PiDP-8/I SoftwareCheck-in [573aba2f6a]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Rewrote the "Inline Assembly in the Native CC8 Compiler" section in the CC8 user manual after learning more about its behavior and limitations.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 573aba2f6a1b9dc64781e259c226b62e1e13d788ff7f807335e40c6cd0cbedee
User & Date: tangent 2019-02-13 18:52:54
Context
2019-02-13
19:12
Added more detail about file I/O limitations to the LIBC user documentation section of the CC8 manual. (What used to be the "stdio" section is now broken up into several sections at the same level.) check-in: 23f92ab553 user: tangent tags: trunk
18:52
Rewrote the "Inline Assembly in the Native CC8 Compiler" section in the CC8 user manual after learning more about its behavior and limitations. check-in: 573aba2f6a user: tangent tags: trunk
06:13
Documented the new ./configure --boot-tape-* options, and updated some of the other configuration option docs in README.md. check-in: f5a05c7790 user: tangent tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to doc/cc8-manual.md.

    70     70   
    71     71   
    72     72   ## Requirements
    73     73   
    74     74   The CC8 system generally assumes the availability of:
    75     75   
    76     76   *   [At least 12 kWords of core](#memory) at run time for programs
    77         -    compiled with CC8.  The stages of the native OS/8 CC8 compiler require
    78         -    20 kWords to compile programs.
           77  +    compiled with CC8.  The [native OS/8 CC8 compiler passes](#ncpass)
           78  +    require 20 kWords to compile programs.
    79     79   
    80     80       CC8 provides no built-in way to use more memory than this, so you
    81     81       will probably have to resort to [inline assembly](#asm) or FORTRAN
    82     82       II library linkage to get access to more than 16 kWords of core.
    83     83   
    84     84   *   A PDP-8/e or higher class processor.  The CC8 compiler code and its
    85     85       [LIBC implementation](#libc) make liberal use of the MQ register
................................................................................
   255    255   the `os8-run` documentation to understand this process better.
   256    256   
   257    257   If you change the OS/8 CC8 source code, saying `make` at the PiDP-8/I
   258    258   build root will update `bin/v3d.rk05` with new binaries automatically.
   259    259   
   260    260   Because the CC8 native compiler is compiled by the CC8 *cross*-compiler,
   261    261   the [standard memory layout](#memory) applies to both.  Among other
   262         -things, this means each phase of the native compiler requires
          262  +things, this means each pass of the native compiler requires
   263    263   approximately 20 kWords of core.
   264    264   
   265         -The phases are:
          265  +<a id="ncpass"></a>The compiler passes are:
   266    266   
   267    267   1.  `c8.c` &rarr; `c8.sb` &rarr; `CC.SV`: The compiler driver: accepts
   268    268       the input file name from the user, and calls the first proper
   269         -    compiler stage, `CC1`.
          269  +    compiler pass, `CC1`.
   270    270   
   271    271   2.  `n8.c` &rarr; `n8.sb` &rarr; `CC1.SV`: The parser/tokeniser section
   272    272       of the compiler.
   273    273   
   274    274   3.  `p8.c` &rarr; `p8.sb` &rarr; `CC2.SV`: The token to SABR code
   275    275       converter section of the compiler.
   276    276   
   277    277   `CC.SV` contains extremely rudimentary preprocessor features
   278    278   documented [below](#os8pp).
   279    279   
   280    280   There is also `libc.c` &rarr; `libc.sb` &rarr; `LIBC.RL`, the [C
   281    281   library](#libc) linked to any program built with CC8, including the
   282         -stages above, but also to your own programs.
          282  +passes above, but also to your own programs.
   283    283   
   284    284   All of these binaries end up on the automatically-built OS/8 boot disk:
   285    285   `CC?.SV` on `SYS:`, and everything else on `DSK:`, based on the defaults
   286    286   our OS/8 distribution is configured to use when seeking out files.
   287    287   
   288    288   Input programs should go on `DSK:`. Compiler outputs are also placed on
   289    289   `DSK:`.
................................................................................
   399    399           It also means that if you take a program that the cross-compiler
   400    400           handles correctly and just copy it straight into OS/8 and try to
   401    401           compile it, it probably still has the `#include <libc.h>` line and
   402    402           possibly one for `init.h` as well. *Such code will fail to compile.*
   403    403           You must strip such lines out when copying C files into OS/8.
   404    404   
   405    405           (The native compiler emits startup code automatically, and it
   406         -        hard-codes the LIBC call table in the `CC2` compiler stage,
   407         -        implemented in `p8.c`, so it doesn’t need `#include` to make these
   408         -        things work.)
          406  +        hard-codes the LIBC call table in the [final compiler
          407  +        pass](#ncpass), implemented in `p8.c`, so it doesn’t need
          408  +        `#include` to make these things work.)
   409    409   
   410    410       *   [Broken](#os8asm) handling of [inline assmembly](#asm) via `#asm`.
   411    411   
   412    412       *   No support for `#if`, `#ifdef`, etc.
   413    413   
   414    414   5.  Variables are implicitly `static`, even when local.
   415    415   
................................................................................
  1578   1578   [ub]:     https://en.wikipedia.org/wiki/Undefined_behavior
  1579   1579   [zp]:     https://homepage.divms.uiowa.edu/~jones/pdp8/man/mri.html#pagezero
  1580   1580   
  1581   1581   
  1582   1582   <a id="asm"></a>
  1583   1583   ## Inline Assembly Code
  1584   1584   
  1585         -The [cross-compiler](#cross) allows [SABR][sabr] assembly code between
  1586         -`#asm` and `#endasm` markers in the C source code:
         1585  +Both the [cross-compiler](#cross) and the [native compiler](#native)
         1586  +allow inline [SABR][sabr] assembly code between `#asm` and `#endasm`
         1587  +markers in the C source code:
  1587   1588   
  1588   1589       #asm
  1589   1590           TAD (42      / add 42 to AC
  1590   1591       #endasm
  1591   1592   
  1592   1593   Such code is copied literally from the input C source file into the
  1593   1594   compiler’s SABR output file, so it must be written with that context in
................................................................................
  1601   1602   body in assembly:
  1602   1603   
  1603   1604       add48(a)
  1604   1605       int a
  1605   1606       {
  1606   1607           a;          /* load 'a' into AC; explained below */
  1607   1608       #asm
  1608         -        TAD (48
         1609  +        TAD (D48
  1609   1610       #endasm
  1610   1611       }
  1611   1612   
  1612   1613   Doing it this way saves you from having to understand the way the CC8
  1613   1614   software stack works, which we’ve chosen not to document here yet, apart
  1614   1615   from [its approximate location in core memory](#memory). All you need to
  1615   1616   know is that parameters are passed on the stack and *somehow* extracted
................................................................................
  1700   1701   main program and the C library. This constitutes a compile time linkage
  1701   1702   system to allow for standard and vararg functions to be called in the
  1702   1703   library.
  1703   1704   
  1704   1705   **TODO:** Explain this.
  1705   1706   
  1706   1707   
  1707         -### <a id="os8asm"></a>Inline Assembly and the OS/8 CC8 Compiler
  1708         -
  1709         -The native CC8 compiler does not properly do any of the above.
  1710         -
  1711         -There is a start at handling of `#asm` in this compiler, but it isn’t
  1712         -properly integrated into the code generation stage. Instead, the
  1713         -preprocessing stage just gathers up what it finds and dumps it to a
  1714         -temporary file, which the code generation stage unceremoniously dumps in
  1715         -at the *end* of the resulting `CC.SB` output file.
  1716         -
  1717         -Furthermore, this process is currently limited to 1&nbsp;kiB of total
  1718         -text: if the preprocessor gathers any more than that, it’s likely to
  1719         -crash the preprocessor.
  1720         -
  1721         -Since such code is not injected inline into the output SABR code at a
  1722         -corresponding point to where it’s coded in the C source file, it’s not
  1723         -even clear to us how you’d call such code. It may be possible to declare
  1724         -an assembly subroutine this way, but we currently don’t know how you’d
  1725         -call an assembly function that has no prototype in the C code.
  1726         -
  1727         -At this time, we recommend that only low-level experimenters attempt to
  1728         -use this feature of the native OS/8 CC8 compiler.
         1708  +### <a id="os8asm"></a>Inline Assembly in the Native CC8 Compiler
         1709  +
         1710  +#### Limitations
         1711  +
         1712  +The native compiler has some significant limitations in the way it
         1713  +handles inline assembly.
         1714  +
         1715  +The primary one is that snippets of inline assembly are gathered by the
         1716  +[first pass](#ncpass) of the compiler in a core memory buffer that’s
         1717  +only 1024 characters in size. If the total amount of inline assembly in
         1718  +your program exceeds this amount, `CC.SV` will overrun this buffer and
         1719  +produce corrupt output.
         1720  +
         1721  +It’s difficult to justify increasing the size of that buffer, because
         1722  +it’s already over [&frac14; the space given](#udf) in CC8 to global
         1723  +variables.
         1724  +
         1725  +It all has to be gathered in one pass, because this 1&nbsp;kWord buffer
         1726  +is written to a text file (`CASM.TX`) at the end of the [first compiler
         1727  +pass](#ncpass), where it waits for the final compiler pass to read it
         1728  +back in to be inserted into the output SABR code.  Since LIBC’s
         1729  +[`fopen()`](#fopen) is limited to a [single output file at a
         1730  +time](#stdio) and it cannot append to an existing file, it’s got one
         1731  +shot to write everything it collected.
         1732  +
         1733  +This is one reason the CC8 LIBC has to be cross-compiled: its inline
         1734  +assembly is over 6&times; the size of this buffer.
         1735  +
         1736  +
         1737  +#### Incompatibilities
         1738  +
         1739  +The only known incompatibility between the compilers in the way they
         1740  +handle inline assembly is that the native compiler inserts a `DECIM`
         1741  +directive early in its SABR output, so all constants in inline assembly
         1742  +that aren’t specifically given a radix are treated as decimal numbers:
         1743  +
         1744  +    #asm
         1745  +        TAD (42
         1746  +    #endasm
         1747  +
         1748  +That instruction adds 42 decimal to AC when compiled with the native
         1749  +compiler, but it adds 34 decimal (42₈) with the cross-compiler because
         1750  +the cross-compiler leaves SABR in its default octal mode!
         1751  +
         1752  +If you want code to work with both, use the SABR-specific `D` and `K`
         1753  +prefix feature on constants:
         1754  +
         1755  +    #asm
         1756  +        TAD (D42      / add 42 *decimal* to AC
         1757  +    #endasm
         1758  +
         1759  +We cannot recommend using the `DECIM` and `OCTAL` SABR pseudo-ops in
         1760  +code that has to work with both compilers because there’s no way to tell
         1761  +what directive to give at the end of the `#asm` block to restore prior
         1762  +behavior. If you switch the mode without switching it back properly,
         1763  +SABR code emitted by the compiler itself will be misinterpreted.
         1764  +
         1765  +There’s a `DECIM` directive high up in the implementation of LIBC, but
         1766  +that’s fine since it knows it will be compiled by the cross-compiler
         1767  +only.
  1729   1768   
  1730   1769   
  1731   1770   ### <a id="opdef"></a>Predefined OPDEFs
  1732   1771   
  1733   1772   In addition to the op-codes predefined for SABR — which you can find in
  1734   1773   [Appendix C of the OS/8 Handbook, 1974 edition][os8hac] — the following
  1735   1774   `OPDEF` directives are inserted at the top of every SABR file output