|
|
1.1 ! root 1: .de Ls ! 2: .RS ! 3: .nr L 0 1 ! 4: .. ! 5: .de Le ! 6: .RE ! 7: .LP ! 8: .. ! 9: .de Np ! 10: .IP (\\n+L) .25i ! 11: .. ! 12: .ds ar \v'2p'\s18\(->\s0\v'-2p' ! 13: .ds sd \s8\v'.2m'\h'-0.4n' ! 14: .ds su \v'-.2m'\s0 ! 15: .ds ex \fIarg\fP ! 16: .ds e1 \fIarg\*(sd1\*(su\fP ! 17: .ds e2 \fIarg\*(sd2\*(su\fP ! 18: .ds e3 \fIarg\*(sd3\*(su\fP ! 19: .ds e4 \fIarg\*(sd4\*(su\fP ! 20: .ds e5 \fIarg\*(sd5\*(su\fP ! 21: .ds ei \fIarg\*(sdi\*(su\fP ! 22: .ds en \fIarg\*(sdn\*(su\fP ! 23: .ds e0 \fIarg\*(sd0\*(su\fP ! 24: .ds xx \fIexpr\fP ! 25: .ds x1 \fIexpr\*(sd1\*(su\fP ! 26: .ds x2 \fIexpr\*(sd2\*(su\fP ! 27: .ds x3 \fIexpr\*(sd3\*(su\fP ! 28: .ds x4 \fIexpr\*(sd4\*(su\fP ! 29: .ds x5 \fIexpr\*(sd5\*(su\fP ! 30: .ds xi \fIexpr\*(sdi\*(su\fP ! 31: .ds xn \fIexpr\*(sdn\*(su\fP ! 32: .ds x0 \fIexpr\*(sd0\*(su\fP ! 33: .ds v0 \fIvar\fP ! 34: .ds v1 \fIvar\*(sd1\*(su\fP ! 35: .ds v2 \fIvar\*(sd2\*(su\fP ! 36: .ds v3 \fIvar\*(sd3\*(su\fP ! 37: .ds vi \fIvar\*(sdi\*(su\fP ! 38: .ds vn \fIvar\*(sdn\*(su\fP ! 39: .ds ax \fIarg\fP ! 40: .ds a1 \fIarg\*(sd1\*(su\fP ! 41: .ds a2 \fIarg\*(sd2\*(su\fP ! 42: .ds a3 \fIarg\*(sd3\*(su\fP ! 43: .ds a4 \fIarg\*(sd4\*(su\fP ! 44: .ds a5 \fIarg\*(sd5\*(su\fP ! 45: .ds ai \fIarg\*(sdi\*(su\fP ! 46: .ds an \fIarg\*(sdn\*(su\fP ! 47: .ds a0 \fIarg\*(sd0\*(su\fP ! 48: .de St ! 49: .ta 1.0iR +.5i 4i ! 50: .. ! 51: .de S1 ! 52: .ta 0.75i ! 53: .. ! 54: .de Pt ! 55: .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i ! 56: .. ! 57: .TR 83-10d ! 58: .DA "June 1983; Revised July 1983,\^ January 1984,\^ June 1984,\^ and August 1984" ! 59: .Gr ! 60: .TL ! 61: Porting the UNIX Implementation of Icon ! 62: .AU ! 63: William H. Mitchell ! 64: .AB ! 65: This document explains how to port the UNIX implementation of the ! 66: Icon programming language. The Icon system is composed of a translator,\^ ! 67: a linker,\^ and an interpreter. Procedures for porting each system ! 68: component are described in detail. This document is meant to be a ! 69: companion to the Icon ``tour'' (TR 84-11) and the source code for ! 70: the system. ! 71: .AE ! 72: .SH ! 73: Introduction ! 74: .PP ! 75: This document describes how to port the Version 5 Icon interpreter ! 76: to a \*U environment. ! 77: .Un ! 78: There is both an interpreter and a compiler available for Icon; this ! 79: document only addresses porting the interpreter. ! 80: The Icon system has three major components: ! 81: a translator,\^ a linker,\^ and an interpreter. The translator and ! 82: the linker are entirely written in C and porting them is merely a ! 83: matter of setting constant values that are appropriate for the target ! 84: machine. Portions of the interpreter are written in assembly language and ! 85: thus must be written anew for each machine. The interpreter also ! 86: contains a very small amount of C code that must be written on a ! 87: per-machine basis. ! 88: .PP ! 89: The sections of this document that describe the porting of the ! 90: translator and the linker are straightforward,\^ being merely a ! 91: description of a process. While porting the translator and the ! 92: linker is a task of following instructions,\^ porting the interpreter ! 93: is a task of design and programming. The approach taken is to describe ! 94: what function each routine must perform and how it is implemented in ! 95: the VAX\u\(dg\d version of Icon. The porter's job is to determine how to ! 96: .FS ! 97: \u\(dg\dVAX is a trademark of Digital Equipment Corporation. ! 98: .FE ! 99: implement the various routines on the target machine. ! 100: .PP ! 101: In light of ! 102: the increasing popularity of the C language and the availability of C ! 103: compilers for non-UNIX environments,\^ it is quite possible that one may ! 104: desire to port Icon to a non-UNIX environment. ! 105: Because the matter of porting a UNIX program to ! 106: a non-UNIX environment is a problem in itself,\^ it is not addressed in ! 107: this document. Rather,\^ this document assumes that the target ! 108: environment is UNIX. This is not to say that porting Icon to a non-UNIX ! 109: environment is not feasible. Icon is not strongly bound to UNIX,\^ the ! 110: primary association being that Icon is written in C. It is ! 111: anticipated that most C systems that are available for a non-UNIX ! 112: environment will provide most of the UNIX-independent C standard ! 113: functions as part of a library. If such a library is available,\^ ! 114: it should be possible to port Icon without great difficulty. ! 115: .PP ! 116: This document is a companion document of the Icon ! 117: ``tour''\^[1] and should be studied with the source code for ! 118: Version 5.8 of Icon at hand. ! 119: In particular,\^ the porter should be familiar with the information ! 120: contained in the tour. ! 121: .PP ! 122: The sections of this document that describe the VAX assembly language ! 123: code attempt to explain the operation of instructions when the ! 124: operation is not obvious. However,\^ this document does ! 125: assume that the porter has ! 126: a rudimentary familiarity with the basic concepts of the VAX-11 ! 127: architecture\^[2]. ! 128: .SH ! 129: C Compiler Requirements ! 130: .PP ! 131: Because there is no ! 132: standard for the C programming language,\^ it is difficult to say how ! 133: ``standard'' the usage of C in the system is. The system was ! 134: developed using the V7 C compiler,\^ often referred to as the Ritchie ! 135: compiler\^[3]. The system was later ported to the VAX using the \fIPortable ! 136: C Compiler\fP\^[4] and no serious problems were encountered. ! 137: .PP ! 138: In addition to supporting ``full'' C,\^ a few specific requirements and ! 139: non-requirements are made on the C compiler: ! 140: .Ls ! 141: .Np ! 142: The compiler must support both assignment and call-by-value for ! 143: structures. ! 144: .Np ! 145: The compiler need not support bit field operations. ! 146: .Np ! 147: Arguments to C functions must be stored in consecutive,\^ ! 148: ascending memory locations. ! 149: .Np ! 150: There may be problems if \*Msizeof(int)\fP and \*Msizeof(char *)\fP ! 151: are not the same,\^ but no definite problems are known. ! 152: .Np ! 153: It is believed that there are great,\^ perhaps insurmountable ! 154: problems,\^ if \*Msizeof(char *)\fP is not equal to \*Msizeof(int *)\fP. ! 155: .Le ! 156: .SH ! 157: System Testing ! 158: .PP ! 159: The test programs and testing procedures to be used for porting Icon ! 160: are described in \^[5]. ! 161: At various points in this document,\^ the porter is directed ! 162: to test the system component just completed. At such times,\^ the ! 163: porter should refer to \^[5] to determine what should be done. ! 164: .NH 1 ! 165: Porting the Icon Translator ! 166: .NH 2 ! 167: Overview ! 168: .PP ! 169: The Icon translator,\^ known as \*Mitran\fR,\^ is the first ! 170: logical component of the Icon system. The translator takes Icon ! 171: source files as input and produces two \fIucode\fR output files ! 172: for each input file. ! 173: The translator may be run by saying: ! 174: .Ds ! 175: itran hello.icn ! 176: .De ! 177: This produces two ascii files,\^ ! 178: \*Mhello.u1\fR and \*Mhello.u2\fR. \*Mhello.u1\fR ! 179: contains interpretable instructions and data in a printable ! 180: format. \*Mhello.u2\fR contains information about global symbols and ! 181: scope. ! 182: .PP ! 183: The translator is written entirely in C and is the most machine ! 184: independent major system component. No serious ! 185: problems should be encountered in porting it. If difficulties are ! 186: encountered,\^ it probably indicates that there are major problems ! 187: with the C compiler being used. ! 188: .NH 2 ! 189: Porting Procedure ! 190: .PP ! 191: The Icon system contains a number of instances of values that must be ! 192: specified on a per-machine basis. The system also contains assembly ! 193: code and,\^ of course,\^ such code is different on each machine. Rather ! 194: than maintaining a source copy of Icon for each machine that Icon runs ! 195: on,\^ C preprocessor control statements are used to select portions of ! 196: code specific to a certain machine. The source as distributed can ! 197: be compiled on either a VAX and PDP-11* system by defining \*MVAX\fP or ! 198: .FS ! 199: *PDP is a trademark of Digital Equipment Corporation. ! 200: .FE ! 201: \*MPDP11\fP respectively in \*Mh/config.h\fP. The porting source has ! 202: neither \*MVAX\fP or \*MPDP11\fP defined; rather,\^ \*MPORT\fP ! 203: is defined. Where machine specific code is to appear,\^ along with ! 204: sections bracketed by \*M#define\fPs for \*MVAX\fP and \*MPDP11\fP,\^ ! 205: there is a skeletal section bracketed by a \*M#define\fP for ! 206: \*MPORT\fP. The \*MPORT\fP section is to be filled out for the ! 207: target machine. This convention is followed throughout and porting ! 208: Icon is nothing more than filling in all the \*MPORT\fP sections. ! 209: .PP ! 210: The source for the translator is contained in the directory \*Mtran\fP. ! 211: Translator machine dependencies are confined to the file \*Mtran/sym.h\fR. ! 212: A pair of constants define the sizes of two data structures used during the ! 213: translation process. ! 214: Edit the file \*Msym.h\fR and search for the string \*MPORT\fR. ! 215: The code looks something like ! 216: .Ds ! 217: .ta 2.0iR 2.5i ! 218: #ifdef PORT ! 219: #define TSIZE x /* default size of parse tree space */ ! 220: #define SSIZE x /* default size of string space */ ! 221: #endif PORT ! 222: #ifdef VAX ! 223: #define TSIZE 15000 /* size of parse tree space */ ! 224: #define SSIZE 15000 /* default size of string space */ ! 225: #endif VAX ! 226: #ifdef PDP11 ! 227: #define TSIZE 5000 /* default size of parse tree space */ ! 228: #define SSIZE 5000 /* default size of string space */ ! 229: #endif PDP11 ! 230: .De ! 231: The values of \*MTSIZE\fP and \*Mssize\fP are not critical ! 232: and current values have been chosen rather arbitrarily. ! 233: If you are on a large ! 234: machine,\^ use the values of \*MTSIZE\fR and \*MSSIZE\fR specified for ! 235: the VAX; otherwise,\^ use the values specified for the PDP-11. ! 236: .PP ! 237: The translator may now be compiled by issuing the \fImake\fR command ! 238: without any arguments. ! 239: .PP ! 240: It should be noted that although Icon programs are used to create ! 241: some of the translator source files (namely \*Mkeyword.h\fP,\^ \*Mkeyword.c\fP ! 242: \*Moptab.c\fP,\^ and \*Mtoktab.c\fP). These files are machine independent ! 243: and do not need to be remade. If for some reason \*Mmake\fP tries to ! 244: create any of these files,\^ just \*Mtouch\fP the file in question to ! 245: update the last-modified date. Similarly,\^ \*Mparse.c\fP is generated by ! 246: \fIyacc\fP and does not need to be regenerated unless the grammar is ! 247: modified. ! 248: .PP ! 249: When the translator has been successfully compiled using \fImake\fP,\^ ! 250: refer to [5] for testing. ! 251: .PP ! 252: Porting the translator may seem like a trivial task,\^ ! 253: but its successful completion is a definite milestone because ! 254: it is good sign that the C compiler in use is suitable. ! 255: .nr $1 1 ! 256: .nr $2 0 ! 257: .NH 1 ! 258: Porting the Icon Linker ! 259: .NH 2 ! 260: Overview ! 261: .PP ! 262: The Icon linker,\^ known as \*Milink\fP,\^ is the second logical component ! 263: of the Icon system. The linker takes \*Mu1\fP and \*Mu2\fP files ! 264: produced by the translator and binds them together to form an ! 265: \fIinterpretable\fP file. The interpretable file serves as input ! 266: for the Icon interpreter. ! 267: The linker is written entirely in C and is a fairly small and ! 268: simple program. However,\^ the interpretable files produced by ! 269: the linker are not machine independent and because of this,\^ ! 270: porting the linker is more troublesome than porting the ! 271: translator. ! 272: .PP ! 273: Interpretable files contain two distinct types of data: opcodes and ! 274: associated operands that the interpreter ``understands''; and data that ! 275: is directly mapped into run-time data structures. By ``mapping'' it ! 276: is meant that the data is loaded into memory and then C structure ! 277: references are used to access elements of the object at a certain ! 278: location in memory. ! 279: The formats of ! 280: the opcodes and operands must conform to what the interpreter is ! 281: expecting. The data that is directly mapped must conform to the ! 282: format of the C data structures used by the run-time system. ! 283: .PP ! 284: On the VAX,\^ for example,\^ interpreter opcodes are one byte long ! 285: and operands are four bytes long. On the PDP-11,\^ opcodes are ! 286: also one byte long,\^ but operands are only two bytes long. ! 287: Opcode and operand size are fairly arbitrary,\^ but it is important ! 288: that the linker and the interpreter be coordinated. ! 289: .PP ! 290: The mapped data structures are slightly more complicated because ! 291: the linker must conform to the format produced by the C compiler. ! 292: This is not difficult,\^ since the data structures involved have ! 293: a regular form. All are composed of some number of \fIwords\fP ! 294: where each word is the same size in every structure.* ! 295: .FS ! 296: *Literature about the VAX conventionally uses the term \fIword\fP to refer ! 297: to 16-bit quantities and the term \fIlongword\fP to refer to 32-bit ! 298: quantities. In this document,\^ \fIword\fP in a generic context ! 299: refers to the basic unit of the run-time data structures; \fIword\fP ! 300: in a VAX-specific context refers to a 32-bit quantity. ! 301: .FE ! 302: .PP ! 303: The opcodes,\^ operands,\^ and mapped data are accumulated in memory during the ! 304: linking process. This conglomerate is referred to as the \fIcode\fP ! 305: section. Several routines are used to add data to the code ! 306: section. These routines are parameterized so that porting the linker ! 307: to a new machine is merely a matter of setting the parameters ! 308: correctly. Four primitive data units ! 309: compose the code section. These are \fIopcodes\fP,\^ \fIoperands\fP,\^ ! 310: \fIwords\fP,\^ and \fIblocks\fP. ! 311: .IP opcodes ! 312: .br ! 313: are instructions for the ! 314: interpreter. An opcode may direct the interpreter to push a value ! 315: on the stack,\^ branch to a location,\^ perform an arithmetic operation,\^ ! 316: etc. ! 317: .IP operands ! 318: .br ! 319: are associated with some opcodes. For ! 320: example,\^ the \*Mgoto\fP instruction has a location to branch to as ! 321: its single operand. ! 322: .IP words ! 323: .br ! 324: compose mapped data structures. A word is the basic ! 325: unit of the run-time data structures and should consist ! 326: of \*Msizeof(int *)\fP bytes. ! 327: .IP blocks ! 328: .br ! 329: are merely some number of bytes. For example,\^ a \*Mcset\fP constant ! 330: is loaded into the code section as a block of 32 8-bit bytes (256 bits). ! 331: .PP ! 332: Routines in \*Mlink/lcode.c\fP are used to add a unit ! 333: of data of one of the preceding types to the code section. These ! 334: routines are \*Moutop\fP,\^ \*Moutopnd\fP,\^ \*Moutword\fP,\^ and ! 335: \*Moutblock\fP. Each routine adds the appropriate data into ! 336: the code section at the current location (maintained as a pointer),\^ ! 337: and then the location pointer is advanced to the next free location. ! 338: .NH 2 ! 339: Porting Procedure ! 340: .PP ! 341: Edit \*Milink.h\fP and search for the string \*MPORT\fP. Define ! 342: the following constants as described. ! 343: .IP \*MINTSIZE\fP ! 344: .br ! 345: The number of bits in an \*Mint\fP. ! 346: .IP \*MLOGINTSIZE\fP ! 347: .br ! 348: The base 2 log of \*MINTSIZE\fP. ! 349: That is,\^ \*MLOGINTSIZE\fP answers ! 350: the question ``\fIWhat power of 2 is \*MINTSIZE\fR\^?''. ! 351: .IP \*MLONGS\fP ! 352: .br ! 353: Icon has an integer data type. On the VAX and the PDP-11 the range ! 354: of integer values is \-2\u\s-231\s0\d to 2\u\s-231\s0\d-1. On the VAX,\^ ! 355: C \*Mint\fPs and \*Mlong\fPs are both 32 bits wide. On the PDP-11,\^ ! 356: C \*Mint\fPs are 16 bits wide while \*Mlong\fPs are 32 bits wide. ! 357: The PDP-11 Icon system makes an internal distinction between integers ! 358: that ``fit'' in 16 bits and integers that require 32 bits. ! 359: The former are stored in two-word descriptors (the actual value being ! 360: in the second of the two 16-bit words),\^ while the latter have a ! 361: value descriptor that points to a block in the heap that holds the ! 362: two-word,\^ 32-bit value. On the other hand,\^ the VAX uses two 32-bit words ! 363: for descriptors and thus the second word of a descriptor can hold ! 364: the largest possible integer value used by Icon. ! 365: Rather than having an internal distinction between integer ! 366: types on the VAX,\^ integers are always represented by two-word ! 367: integer descriptors. There are places in the code where special ! 368: provisions must be made if C \*Mint\fPs are not the same size ! 369: as C \*Mlong\fPs. ! 370: .sp ! 371: If \*Msizeof(int) != sizeof(long)\fP for the C compiler in use,\^ ! 372: define \*MLONGS\fP. (\*MLONGS\fP need not be given a value,\^ ! 373: \*M#define LONGS\fP is sufficient.) ! 374: If \*MLONGS\fP must be defined,\^ the minimum ! 375: and maximum values that can be represented by an \*Mint\fP must also ! 376: be defined. Define \*MMINSHORT\fP to be the smallest value that an ! 377: \*Mint\fP can hold and define \*MMAXSHORT\fP to be the largest value that ! 378: an \*Mint\fP can hold. ! 379: .IP \*MMAXCODE\fP ! 380: .br ! 381: This is the maximum size in bytes of the code that can be generated for each ! 382: procedure. This value is not critical; 10,\^000 is used for the VAX,\^ ! 383: while 2000 is used for the PDP-11. ! 384: .IP \*Mstrchr\fP\ and\ \*Mstrrchr\fP ! 385: .br ! 386: If you are on a USG UNIX system,\^ \*M#define\fP \*Mindex\fP to be ! 387: \*Mstrchr\fP and \*Mrindex\fP to be \*Mstrrchr\fP. ! 388: .PP ! 389: Edit \*Mdatatype.h\fP and ! 390: search for the \*MPORT\fP section. This section contains ! 391: \*M#define\fPs that are used to set and test flags contained in the ! 392: first word of descriptors. The basic idea in forming these ! 393: constants is to set some bits at the high end of the word,\^ and set some ! 394: other bits at the low end. The number of unused bits in the middle ! 395: depends on the size of a word. ! 396: .PP ! 397: \*MF_NQUAL\fP,\^ \*MF_VAR\fP,\^ \*MF_TVAR\fP,\^ \*MF_PTR\fP,\^ \*MF_NUM\fP,\^ ! 398: \*MF_INT\fP,\^ and \*MF_AGGR\fP should be set to mask values with one ! 399: bit set to 1 in each. For \*MF_NQUAL\fP,\^ the leftmost bit should set,\^ ! 400: for \*MF_VAR\fP,\^ the next to leftmost bit should be set,\^ and so ! 401: forth. The values for the VAX and PDP-11 should be suitable for ! 402: machines with 32-bit and 16-bit words,\^ respectively. ! 403: .PP ! 404: The constants ! 405: \*MOPSIZE\fP,\^ \*MOPNDSIZE\fP,\^ and \*MWORDSIZE\fP control the ! 406: sizes of opcodes,\^ operands,\^ and words in the code section. ! 407: Before setting these constants to values appropriate for the ! 408: target machine,\^ a ``standard'' linker should be built and tested using ! 409: the supplied values (under \*MPORT\fP) for these constants. ! 410: This allows the linker to be checked against output files that ! 411: are known to be correct. The purpose of this is to attempt to ! 412: discover C compiler problems. Compile the linker using \*Mmake\fP and ! 413: refer to ! 414: [5] for the testing procedure. ! 415: .PP ! 416: Once the ``standard'' linker has been checked out,\^ the following ! 417: ``sizing'' parameters in \*Milink.h\fP should be set to values ! 418: appropriate for the target machine. ! 419: .IP \*MOPSIZE\fP ! 420: .br ! 421: This is the size in bytes of interpreter opcodes. The interpreter treats ! 422: opcodes as unsigned quantities. One byte (8 bits) is currently ! 423: large enough to accommodate all opcodes and a value of 1 is recommended ! 424: for \*MOPSIZE\fP. The \*Moutop\fP routine in \*Mlcode.c\fP assumes that ! 425: opcodes are one byte. If a larger size is desired,\^ \*Moutop\fP ! 426: will have to be recoded. It might be wise to use a value other than ! 427: 1 for \*MOPSIZE\fP on machines that are not byte-addressable and have ! 428: ample memory. ! 429: .IP \*MOPNDSIZE\fP ! 430: .br ! 431: This is the size in bytes of operands for interpreter instructions. ! 432: For some instructions,\^ the operand value represents an offset ! 433: from the interpreter program counter and thus,\^ the maximum possible ! 434: offset is limited by the magnitude of values that can be represented ! 435: in \*MOPNDSIZE\fP bytes. Because larger operands occupy more code ! 436: space and smaller operands limit addressing ``distance'',\^ a trade-off ! 437: is involved. On the VAX,\^ operands are four bytes because memory ! 438: space is not very critical. On the PDP-11,\^ operands are two bytes ! 439: because of the limited memory. While it is easy to change the ! 440: value of \*MOPNDSIZE\fP in the linker,\^ the operand size is pervasive ! 441: in the interpreter. If the target machine has a large,\^ perhaps ! 442: virtual address space,\^ use a value such as 4 for \*MOPNDSIZE\fP. A ! 443: value such as 2 may be appropriate for a smaller machine. A value ! 444: of 1 is not advisable under any circumstances. The suggested value ! 445: for \*MOPNDSIZE\fP is \*Msizeof(int)\fP. ! 446: .IP \*MWORDSIZE\fP ! 447: .br ! 448: This should be set to \*Msizeof(int *)\fP on the target machine. The ! 449: various run-time data structures are all composed of a number ! 450: of words each of which contain \*MWORDSIZE\fP bytes. For example,\^ ! 451: the data blocks for user-defined procedures are built in the code ! 452: section by a sequence of calls to \*Moutword\fP. ! 453: .PP ! 454: The \*Mbackpatch\fP routine in \*Mlcode.c\fP needs some ! 455: machine-specific modifications. This routine backpatches forward ! 456: references to ucode labels. In the \fIwhile\fP loop,\^ the operand (which is ! 457: \*MOPNDSIZE\fP bytes long) that is pointed at by \*Mq\fP is loaded ! 458: into the variable \*Mp\fP. Then,\^ the operand is replaced by the ! 459: value of \*Mr\fP. On the VAX,\^ this can be expressed as: ! 460: .Ds ! 461: p = *q; ! 462: *q = r; ! 463: .De ! 464: where \*Mq\fP is an \*Mint *\fP. This is possible because the VAX allows ! 465: word references on an arbitrary boundary. On the PDP-11,\^ such ! 466: references are illegal and the assignments must be made on a byte-wise ! 467: basis. If the target machine allows word accesses on arbitrary ! 468: boundaries,\^ the VAX code may be used (assuming \*MOPNDSIZE\fP is equal to ! 469: \*Msizeof(int)\fP). ! 470: If not,\^ but operands are the same size as \*Mint\fPs,\^ ! 471: the PDP-11 code may be used. ! 472: Other situations may require ingenuity. Be sure to alter the first \*MPORT\fP ! 473: section in \*Mbackpatch\fP to contain an appropriate declaration for ! 474: \*Mq\fP (that section currently contains a declaration for \*Mq\fP and ! 475: a \*Mreturn\fP). ! 476: .PP ! 477: When the linker has been compiled,\^ ! 478: refer to [5] for directions on ! 479: testing. ! 480: .nr $1 2 ! 481: .nr $2 0 ! 482: .NH 1 ! 483: Porting the Icon Interpreter ! 484: .NH 2 ! 485: Introduction ! 486: .PP ! 487: The Icon interpreter,\^ known as \fIiconx\fP,\^ is the third major logical ! 488: component of the system. The interpreter takes ! 489: interpretable files produced by the linker and ``executes'' them. ! 490: The interpreter is run by: ! 491: .Ds ! 492: iconx hello ! 493: .De ! 494: where \*Mhello\fP has been produced by the linker. ! 495: .PP ! 496: Due to the stack manipulations that the interpreter performs,\^ it is ! 497: necessary for a small portion of the interpreter to be written in ! 498: assembly language rather than in C. On the VAX,\^ about 550 lines of ! 499: assembly instructions are required. The coding of these assembly ! 500: instructions is the most difficult part of the ! 501: port. ! 502: .NH 2 ! 503: Source File Layout ! 504: .LP ! 505: The interpreter is divided into four parts: ! 506: .DS ! 507: .ft R ! 508: start-up code ! 509: the main loop ! 510: primary subroutines ! 511: support subroutines ! 512: .DE ! 513: .LP ! 514: The start-up code initializes the interpreter and passes control ! 515: to the main loop. The main loop,\^ referred to as \*Minterp\fP,\^ ! 516: fetches interpreter instructions ! 517: and executes them. An interpreter instruction may be entirely ! 518: performed by \*Minterp\fP or \*Minterp\fP may call a \fIprimary ! 519: subroutine\fP to perform the operation. In turn,\^ a primary subroutine ! 520: may call a number of \fIsupport subroutines\fP. ! 521: Each primary subroutine has a direct correspondence to a source language ! 522: operation of some type or to a stack manipulation. ! 523: .PP ! 524: While the translator and linker sources files are in their own ! 525: directories,\^ the interpreter source files are segregated into several ! 526: directories. ! 527: .nr a \w'\*Moperators\fR'+1m ! 528: .IP \*Miconx\fP (\na)u ! 529: The start-up code and the main interpreter loop reside in this ! 530: directory. Files of particular interest are: \*Mstart.s\fP,\^ which ! 531: is entered when the interpreter is run and does some low-level ! 532: initialization; \*Minit.c\fP,\^ which is called from \*Mstart.s\fP and ! 533: completes initialization of the interpreter; and \*Minterp.s\fP,\^ which ! 534: is the interpreter loop itself. ! 535: .IP \*Mfunctions\fP (\na)u ! 536: This directory contains code for the built-in procedures. ! 537: For example,\^ \*Mwrite.c\fP contains ! 538: the source for the \*Mwrite\fP function. The source for each ! 539: built-in procedure appears in a file of its own. ! 540: .IP \*Moperators\fP (\na)u ! 541: This directory contains code for the Icon operators. The routines in ! 542: this directory ! 543: implement the various Icon source level operators. For ! 544: example,\^ \*Mplus.c\fP is called to perform the \*M+\fP (addition) ! 545: operation,\^ and \*Mbang.c\fP is called to perform the \*M!\fP (element ! 546: generation) operation. As with the built-in procedures,\^ there is ! 547: one operator per file. ! 548: .IP \*Mlib\fP (\na)u ! 549: This directory contains routines that ! 550: do not fit anywhere else. First of all,\^ there is ! 551: code for routines that perform actions similar in nature to those in ! 552: \*Mfunctions\fP and \*Moperators\fP,\^ but that do not have a functional or ! 553: operator syntax. For example,\^ \*Mllist.c\fP creates a list ! 554: that is specified syntactically as ! 555: \*M\^[\*(e0,\^\*(e1,\^\*(El,\^\*(en]\fR,\^ and \*Mfield.c\fP handles record element ! 556: accesses that arise from \*M\*(e1.\*(e2\fR. ! 557: .sp .8 ! 558: \*Mlib\fP also contains routines such as \*Mesusp.s\fP and \*Mefail.s\fP ! 559: that handle stack manipulations during expression evaluation. The ! 560: routines \*Mpret.s\fP and \*Mpfail.s\fP handle procedure return and ! 561: failure respectively. ! 562: .sp .8 ! 563: The directories \*Mfunctions\fP,\^ \*Moperators\fP,\^ and \*Mlib\fP ! 564: compose the primary subroutines mentioned above. ! 565: .IP \*Mrt\fP (\na)u ! 566: The support subroutines are contained in the \*Mrt\fP directory. ! 567: The primary subroutines are autonomous with respect to each other and ! 568: use the \*Mrt\fP routines for common operations. For example,\^ ! 569: \*Mcvstr.c\fP is used to convert a value to a string,\^ \*Mtrace.c\fP ! 570: produces various types of tracing messages,\^ and \*Mgc.c\fP is the ! 571: garbage collector. ! 572: .IP \*Mh\fP (\na)u ! 573: This directory contains a number of header files that are ! 574: \*M#include\fPd in the other files that compose the interpreter. ! 575: Of particular interest is \*Mrt.h\fP,\^ which defines a number of ! 576: constants and data structures. ! 577: .NH 2 ! 578: Overview of the Porting Process ! 579: .PP ! 580: The following steps are to be followed when porting the interpreter. ! 581: .Ls ! 582: .Np ! 583: Determination of layout of procedure,\^ generator,\^ and expression ! 584: markers and associated frame pointers. ! 585: .Np ! 586: Setting of implementation specific constants in \*Mh/rt.h\fP and ! 587: creation of \*Mh/defs.s\fP from \*Mrt.h\fP. ! 588: .Np ! 589: Complete system compilation. ! 590: .Np ! 591: Coding of a ``basis'' of routines for the interpreter,\^ consisting of ! 592: \*Miconx/start.s\fP,\^ \*Mrt/setbound.s\fP,\^ \*Mlib/invoke.s\fP,\^ ! 593: \*Miconx/interp.s\fP,\^ \*Mlib/efail.s\fP,\^ ! 594: \*Mlib/pfail.s\fP. ! 595: .Np ! 596: Testing of the basis routines for the interpreter. ! 597: .Np ! 598: Coding and testing of ! 599: .Ds ! 600: rt/arith.s ! 601: rt/fail.s ! 602: lib/pret.s ! 603: lib/esusp.s ! 604: lib/lsusp.s ! 605: lib/psusp.s ! 606: rt/suspend.s ! 607: functions/display.c ! 608: .De ! 609: in an incremental fashion. Test programs are provided ! 610: to test the system after adding each routine. ! 611: .Np ! 612: Coding of \*Mrt/gcollect.s\fP and \*Mrt/sweep.c\fP. ! 613: Testing of garbage collection. ! 614: .Np ! 615: Complete system testing. ! 616: .Le ! 617: .PP ! 618: This document does not explain how to port the sections of the system ! 619: that are related to co-expressions. The involved files are ! 620: \*Mlib/coact.s\fP,\^ \*Mlib/cofail.s\fP,\^ \*Mlib/coret.s\fP,\^ ! 621: \*Mlib/create.c\fP,\^ and \*Moperators/refresh.c\fP. Icon ! 622: works properly with these sections of code left unimplemented,\^ ! 623: provided no attempt is made to use co-expressions,\^ in which case ! 624: the system notes it as a fatal error. ! 625: .NH 2 ! 626: Porting Procedure ! 627: .SH ! 628: Determination of Frame Layouts ! 629: .PP ! 630: Unfortunately,\^ one of the most far-reaching decisions that must be ! 631: made during the porting process is also one of the first decisions ! 632: that must be made. The decision (actually,\^ a number of decisions) is ! 633: how to layout the procedure,\^ generator,\^ and ! 634: expression frames and what registers should be used as frame ! 635: pointers. The various frames and their usages are explained in ! 636: detail in \^[1] and the portions of this document that describe ! 637: routines that manipulate a particular frame also provide further ! 638: explanations. The porter should have a good ! 639: understanding of what the frames are used for before setting frame ! 640: layouts as they are pervasive throughout the assembly language ! 641: portions of the system. ! 642: .PP ! 643: This document is rather tightly bound to the VAX implementation of ! 644: Icon. Because of this,\^ the stack model that is used is that ! 645: of the VAX. Specifically,\^ the VAX stack starts in high memory and ! 646: grows downward. Thus,\^ when something is pushed on the stack,\^ the ! 647: stack pointer goes down. When something is removed,\^ the stack pointer ! 648: goes up. ! 649: The only time that this convention is departed from is in the use of ! 650: the phrase ``the top of the stack''. The top of the stack is the ! 651: stack word that has the \fIlowest\fP memory address. ! 652: .PP ! 653: The procedure frame layout is the first to be determined. The layout ! 654: is somewhat fixed by the C compiler and target machine,\^ ! 655: so the task is a combination ! 656: of making a decision and also recognizing what has been pre-determined. ! 657: On most machines,\^ the ! 658: task of the porter is more one of recognition than of design. ! 659: .PP ! 660: The first thing to determine is the ! 661: frame layout imposed by the target machine and the C compiler. ! 662: Create a file containing the following ! 663: .Ds ! 664: f() ! 665: { ! 666: x(1,\^2); ! 667: } ! 668: .De ! 669: Compile the file using \fIcc\fP ! 670: in such a manner as to catch the assembly code that is ! 671: generated in a file. The \*M\-S\fP option of \fIcc\fP should cause ! 672: assembly code to be placed in a file. On the VAX,\^ the code ! 673: generated by \*Mx(1,\^2)\fP is ! 674: .Ds ! 675: .ta .7i ! 676: pushl $2 ! 677: pushl $1 ! 678: calls $2,\^_x ! 679: .De ! 680: From this it can be seen that arguments are pushed on the stack ! 681: using the \*Mpushl\fP instruction,\^ and that the \*Mcalls\fP ! 682: instruction does the actual procedure call. The first argument ! 683: to \*Mcalls\fP is the number of arguments that are on the stack. ! 684: When a return is made from a procedure called with a \*Mcalls\fP ! 685: instruction,\^ the arguments are removed from the stack by the return ! 686: mechanism. On some machines,\^ the removal of arguments after a subroutine ! 687: call is left to the programmer (or code generator,\^ in this case). ! 688: This is usually done by adding a value to the stack pointer or ! 689: incrementing the stack pointer several times. ! 690: .PP ! 691: Examine the assembly code produced on the target machine by the ! 692: given C statements. Determine what actions are taken by the machine ! 693: when the appropriate call instruction is performed. It is important ! 694: to completely and totally understand what the target machine does ! 695: when a call is performed. ! 696: Next,\^ determine what sort of procedure frame is used by C routines. ! 697: Compile the following C function using \*M\-S\fP. ! 698: .Ds ! 699: .ta .7i ! 700: f(a,\^b,\^c) ! 701: int a; char b; char *c; ! 702: { ! 703: int x,\^y; ! 704: ! 705: x = a; ! 706: a = 1; ! 707: y = 2; ! 708: } ! 709: .De ! 710: Look at the generated ! 711: code and try to get a feel for what is going on. The things that ! 712: need to be determined are: ! 713: .Ds ! 714: .ft R ! 715: how arguments are accessed ! 716: the format of the C call frame ! 717: register saving and restoring conventions ! 718: .De ! 719: For example,\^ on the VAX,\^ the following code is generated ! 720: for the test procedure. ! 721: .Ds ! 722: .Pt ! 723: .word L12 register save mask,\^ filled in later ! 724: jbr L14 jump to end to make stack space ! 725: L15: ! 726: movl 4(ap),\^-4(fp) x = a ! 727: movl $1,\^4(ap) a = 1 ! 728: movl $2,\^-8(fp) y = 2 ! 729: ret return ! 730: .set L12,\^0x0 set register mask ! 731: L14: ! 732: subl2 $8,\^sp make room for two local variables ! 733: of four bytes each ! 734: jbr L15 jump to start of routine ! 735: .De ! 736: Several inferences can be made. First of all,\^ arguments are accessed ! 737: relative to \*Map\fP,\^ the argument pointer. Secondly,\^ local variables ! 738: are accessed relative to \*Mfp\fP,\^ the frame pointer. On the VAX,\^ ! 739: because of the hardware register save and restoration based on the ! 740: entry mask (the first word of the routine),\^ no subroutine calls are ! 741: required to save registers. ! 742: .PP ! 743: The Icon procedure frame must have the following attributes: ! 744: .Ls ! 745: .Np ! 746: The values on the stack at the time of call to the procedure appear ! 747: as arguments to the procedure. Furthermore,\^ the values must be ! 748: accessible in a deterministic fashion. ! 749: .Np ! 750: Register values are saved in the frame and can be accessed deterministically. ! 751: .Np ! 752: \*M_line\fP and \*M_file\fP appear in the procedure frame just below ! 753: the last word pushed on the stack as part of the C procedure calling ! 754: protocol. ! 755: .Np ! 756: The region for local variables begins at the lower end of the ! 757: ``constant'' portion of the frame. Local variables must be ! 758: be accessible via deterministic means. ! 759: .Np ! 760: The procedure frame created by a C procedure call must be a subset ! 761: of the procedure frame selected. That is,\^ the Icon procedure frame ! 762: must be an augmentation of the C procedure frame. ! 763: .Le ! 764: .LP ! 765: The VAX uses this procedure frame layout: ! 766: .Ds ! 767: .St ! 768: .ft R ! 769: arguments ! 770: 4 number of arguments (\*Mnargs\fR) ! 771: \*Map\fR \*(ar 0 number of words in argument list (\*Mnwords\fR) ! 772: saved \*Mr11\fR (\*Mefp\fR) ! 773: saved \*Mr10\fR (\*Mgfp\fR) ! 774: \*(El ! 775: last saved register ! 776: 16 saved \*Mpc\fR ! 777: 12 saved \*Mfp\fR ! 778: 8 saved \*Map\fR ! 779: 4 program status word and register mask ! 780: \*Mfp\fR \*(ar 0 0 (condition handler address) ! 781: -4 saved value of \*M_line\fR ! 782: -8 saved value of \*M_file\fR ! 783: \*Msp\fR \*(ar Icon local variables ! 784: .De ! 785: .PP ! 786: Actually,\^ on the VAX,\^ most of the decisions are predetermined by ! 787: the VAX architecture. The arguments are present on the stack,\^ so they ! 788: are the high end of the frame. The registers are saved on the stack ! 789: by the \*Mcalls\fP instruction. The values of \*M_line\fP and \*M_file\fP ! 790: naturally fit after the saved registers. The locals then appear on ! 791: the lower end and extend for a variable distance (on a per-procedure ! 792: basis). Note that the first local is at \*M\-16(fp)\fP and the \fIlast\fP ! 793: argument is at \*M8(ap)\fP. ! 794: .PP ! 795: The VAX hardware takes care of saving and restoring registers upon ! 796: subroutine entry and exit. It is quite possible that the target ! 797: machine will not have this capability and the task must be delegated ! 798: to software. This is usually evidenced by a call to a routine with a ! 799: name such as \*Mcsave\fP as the very first thing in the routine and a ! 800: call to a routine with a name such as \*Mcrestore\fP at the end of a ! 801: routine. If this is the case,\^ the actions of ! 802: the saving and restoring routines must be taken into account when determining ! 803: the procedure frame layout. ! 804: .PP ! 805: In addition to determining the procedure frame layout,\^ a procedure ! 806: frame pointer must also be selected. On the VAX,\^ ! 807: the \*Mfp\fP stays constant throughout execution of a C procedure; ! 808: it is used as the procedure frame pointer. For the target machine,\^ ! 809: there should be some register on which references to local variables ! 810: (and perhaps parameters) are based. That register should be used ! 811: as the procedure frame pointer (sometimes referred to as the ! 812: \*Mpfp\fP). ! 813: The \*Mpfp\fP need not point at the lowest word pushed on the stack ! 814: as part of the procedure call; it only needs to be constant while ! 815: a procedure is executing. Of course,\^ the \*Mpfp\fP changes while the ! 816: program is executing; by ``pointing at'' a particular word,\^ it is ! 817: meant that the \*Mpfp\fP always references a certain word in the ! 818: procedure frame marker. An \*Mrt.h\fP constant,\^ \*MFRAMELIMIT\fP,\^ is ! 819: dependent on the number of words between the lowest word of the ! 820: procedure marker and the word that the \*Mpfp\fP points to. Setting ! 821: \*MFRAMELIMIT\fP is described below. ! 822: .PP ! 823: A point about terminology should be stressed. The procedure frame marker is ! 824: bounded by arguments on one end and the Icon local variables on the other. ! 825: A procedure marker,\^ the arguments,\^ the Icon ! 826: local variables,\^ and the stack below ! 827: the local variables compose a procedure frame. ! 828: .\"\^[Note in here about variable size of marker,\^ forced saving of efp,\^ gfp.,\^ ! 829: .\"ap being needed] ! 830: .PP ! 831: Determining the procedure frame layout ! 832: is by no means a deterministic process. It takes work,\^ but once ! 833: it's successfully set,\^ the single hardest task of the port is complete. ! 834: .PP ! 835: Once the procedure frame has been set,\^ the generator frame layout follows ! 836: rather easily. A generator frame is merely an augmented procedure ! 837: frame. The generator frame has two additional pieces of information,\^ ! 838: a saved value of \*M_k_level\fP,\^ and a saved value for the boundary. ! 839: It is recommended that the generator frame ! 840: be identical to a procedure frame except that the two extra words ! 841: required be located between the lowest word that is pushed on the ! 842: stack by the procedure call mechanism and the saved value of \*M_line\fP. ! 843: Thus,\^ on the VAX,\^ the generator frame \fImarker\fP is ! 844: .Ds ! 845: .ft R ! 846: .St ! 847: saved \*Mr11\fR ! 848: saved \*Mr10\fR ! 849: \*(El ! 850: last saved register ! 851: 20 reactivation address ! 852: 16 saved \*Mfp\fR ! 853: 12 saved \*Map\fR ! 854: 8 program status word and register mask ! 855: 4 0 (condition handler address) ! 856: \*Mgfp\fR \*(ar 0 saved value of the boundary ! 857: -4 saved value of \*M_k_level\fR ! 858: -8 saved value of \*M_line\fR ! 859: -12 saved value of \*M_file\fR ! 860: .De ! 861: Note that instead of a saved \*Mpc\fR value,\^ the generator frame marker ! 862: holds a reactivation address. Control passes to this address when ! 863: the generator is reactivated. Reactivation is fully explained in ! 864: later sections. ! 865: .PP ! 866: A generator frame pointer (\*Mgfp\fP) is associated with a generator ! 867: frame. On the VAX,\^ \*Mr10\fP is the \*Mgfp\fP. The choice of a \*Mgfp\fP ! 868: is indirectly determined by the machine architecture and is ! 869: intertwined with the selection of an expression frame pointer. ! 870: The selection of the register to use as the \*Mgfp\fP is discussed below. ! 871: It is recommended that the \*Mgfp\fP point ! 872: at the word containing the saved boundary value. ! 873: .PP ! 874: The third type of frame marker is the expression frame marker. ! 875: Expression frame markers are totally machine independent and contain ! 876: three pieces of information: a saved expression marker address,\^ ! 877: a saved generator marker address,\^ and a failure label that is to ! 878: be given control in certain circumstances. On the VAX,\^ the ! 879: expression marker layout is ! 880: .Ds ! 881: .ft R ! 882: .St ! 883: \*Mefp\fR \*(ar 0 saved \*Mefp\fR value ! 884: -4 saved \*Mgfp\fR value ! 885: -8 failure address ! 886: .De ! 887: This same format should be used on the target machine and there is no ! 888: apparent reason for needing an alternative format. The expression ! 889: frame pointer (\*Mefp\fP) should point at the high word of the ! 890: expression marker. ! 891: .PP ! 892: The registers that should be used for the \*Mgfp\fP and \*Mefp\fP are ! 893: indirectly dependent on the procedure call mechanism. The primary ! 894: requirement for the registers used as the \*Mefp\fP and \*Mgfp\fP is that ! 895: they are saved across procedure calls. The secondary requirement is ! 896: that the \*Mgfp\fP and \*Mefp\fP always be saved in a procedure frame. ! 897: If the target machine has two general purpose registers that are ! 898: always saved in a procedure frame,\^ those two registers are quite ! 899: suitable for the \*Mgfp\fP and \*Mefp\fP. ! 900: .PP ! 901: If the procedure call mechanism does not always save a pair of general ! 902: purpose registers,\^ the problem is more complicated. ! 903: There are stack manipulations that are performed that ! 904: \fIrequire\fP saved values of \*Mefp\fP and \*Mgfp\fP to be present ! 905: in procedure and generator frames. ! 906: For built-in procedures and Icon procedures ! 907: this is no problem because \*Minvoke\fP creates the procedure frame ! 908: for them and can insure that the registers are saved. On the VAX,\^ for the C ! 909: routines that are directly called from \*Minterp\fP,\^ no such ! 910: assurances can be made because the VAX C compiler directs ! 911: only the registers used in a routine to be saved in the C procedure ! 912: frame. This creates a problem because Icon counts on the registers ! 913: being saved. The problem is countered by making the C compiler think ! 914: that certain registers are used in certain routines. Specifically,\^ ! 915: declarations for a pair of \*Mregister int\fP variables are placed at ! 916: the start of appropriate routines. On the VAX,\^ the first two local ! 917: variables declared in a C routine \fIalways\fP get allocated to \*Mr10\fP and ! 918: \*Mr11\fP. Thus,\^ \*Mr10\fP and \*Mr11\fP are used for the \*Mgfp\fP ! 919: and the \*Mefp\fP respectively. If the target machine is like ! 920: the VAX in that it doesn't always save certain registers,\^ a similar ! 921: tactic may need to be used. If this is the case,\^ try compiling a ! 922: routine with a pair of \*Mregister int\fP variables declared and see ! 923: what the compiler does. If the compiler saves the two registers ! 924: assigned to the variables,\^ use those registers for the \*Mgfp\fP and ! 925: the \*Mefp\fP. It is wise to attempt to be sure that the compiler is ! 926: deterministic in making its choice of registers to allocate to the ! 927: variables. Routines that require this ruse to be employed have a line ! 928: containing the string \*MDclSave\fP as the first line of the ! 929: declarations. \*MDclSave\fP is defined in \*Mrt.h\fP and should be ! 930: set to an appropriate value. It may be the case that no registers ! 931: need to be saved. If so,\^ define \*MDclSave\fP,\^ but specify no value. ! 932: This is done for the PDP-11. ! 933: .PP ! 934: It is also necessary to select a register to use as the interpreter ! 935: program counter (\*Mipc\fP). Any general register that is preserved ! 936: across procedure calls is suitable. The VAX uses \*Mr9\fP for ! 937: the \*Mipc\fP. ! 938: .NH 2 ! 939: Machine and System Specific Values ! 940: .PP ! 941: Edit \*Mh/rt.h\fP and search for the first \*MPORT\fP section. ! 942: Define the various constant values as outlined below. ! 943: .IP \*MMAXHEAPSIZE\fP ! 944: .br ! 945: The size of the heap storage region in bytes. The VAX uses 50k and ! 946: the PDP-11 uses 10k. If you have a small machine,\^ use 10k. Larger ! 947: machines should use larger values,\^ such as that for VAX. ! 948: .IP \*MMAXSTRSPACE\fP ! 949: .br ! 950: The size of the string storage region in bytes. As with ! 951: \*MMAXHEAPSIZE\fP,\^ this value is somewhat arbitrary. A value similar ! 952: to that used for the heap size should be used. ! 953: .IP \*MSTACKSIZE\fP ! 954: .br ! 955: The size of co-expression stacks in words. Use 1000 for smaller ! 956: machines,\^ 2000 for larger ones. ! 957: .IP \*MMAXSTACKS\fP ! 958: .br ! 959: The number of co-expression stacks initially allocated. Use 2 for ! 960: smaller machines,\^ 4 for larger ones. ! 961: .IP \*MNUMBUF\fP ! 962: .br ! 963: The number of i/o buffers available. When a file is opened,\^ a buffer ! 964: is assigned to the file if one is available. A value from 5 to ! 965: 10 is recommended. ! 966: .IP \*MINTSIZE\fP ! 967: .IP \*MLOGINTSIZE\fP ! 968: .IP \*MLONGS\fP ! 969: .IP \*MMINSHORT\fP ! 970: .IP \*MMAXSHORT\fP ! 971: .br ! 972: These constants must be set to the values they were given (if any) in ! 973: \*Mlink/ilink.h\fP. ! 974: .IP \*MMINLONG\fP ! 975: .br ! 976: The smallest value that can be represented in a \*Mlong\fP. ! 977: .IP \*MMAXLONG\fP ! 978: .br ! 979: The largest value that can be represented in a \*Mlong\fP. ! 980: .IP \*MLGHUGE\fP ! 981: .br ! 982: The highest base-10 exponent plus 1 representable by a \*Mfloat\fP. ! 983: For example,\^ on the VAX,\^ the highest number representable by a \*Mfloat\fP ! 984: is about 1.7x10\u38\d. Thus,\^ \*MLGHUGE\fP is 39 on the VAX. ! 985: .IP \*MFRAMELIMIT\fP ! 986: .br ! 987: As discussed above,\^ set \*MFRAMELIMIT\fP to the number of words ! 988: between the low word of the procedure frame marker and the word that ! 989: the procedure frame pointer references. ! 990: .IP \*MSTKBASE\fP ! 991: .br ! 992: This value represents the approximate base of the stack when ! 993: execution begins. On machines such as the VAX,\^ where the stack grows ! 994: down from high memory,\^ \*MSTKBASE\fP should have a high value,\^ where ! 995: on machines where the stack grows up from low memory,\^ \*MSTKBASE\fP ! 996: should have a low value. The \fIman\fP page for \fIexec(2)\fP usually ! 997: specifies the initial value for the stack pointer when program ! 998: execution begins. If uncertain,\^ be extreme with the value. ! 999: .IP \*MGRANSIZE\fP ! 1000: .br ! 1001: The granularity of memory allocations. Calls to \fIbrk(2)\fP are ! 1002: used to expand the main memory that is being used. When \fIbrk\fP ! 1003: is given an address to expand to,\^ it rounds it to a multiple of ! 1004: a certain number. That number should be used for \*MGRANSIZE\fP. ! 1005: The \fIman\fP page for \fIbrk(2)\fP should state what value is used ! 1006: on a particular system. ! 1007: .IP \*MDclSave\fP ! 1008: .br ! 1009: Give \*MDclSave\fP the value needed as previously described. ! 1010: .IP \*MEntryPoint(x)\fP ! 1011: .br ! 1012: \*MEntryPoint\fP is a macro that is used to yield the address of the ! 1013: first instruction of the C routine \*Mx\fP that is past any procedure ! 1014: entry protocol instructions. On the VAX,\^ the register mask is two ! 1015: bytes long and thus the first executable instruction of a routine \*Mx\fP ! 1016: is at \*M(char *)x + 2\fP. On the PDP-11,\^ there is a four-byte instruction ! 1017: at the start of each routine that calls the routine \*Mcsv\fP to ! 1018: save registers and establish the procedure frame. Thus for the ! 1019: PDP-11,\^ \*MEntryPoint(x)\fP is \*M(char *)x + 4\fP. Values calculated ! 1020: by \*MEntryPoint\fP are used in \*Minvoke\fP. ! 1021: .IP \*MDummyFcn(name)\fP ! 1022: .br ! 1023: Initially,\^ each of the assembly language ! 1024: portions of the system that must be filled in ! 1025: consist of a single line of the form \*MDummyFcn(name)\fP. ! 1026: \*MDummyFcn\fP should be defined to generate \fIassembly\fP language ! 1027: statements that ! 1028: form a dummy routine with the label \*Mname\fP. This can be as ! 1029: simple as a label and a global declaration. It is advisable to include ! 1030: as part of the definition something that will cause a program abort. ! 1031: A halt instruction usually does the job. Thus,\^ the system can be ! 1032: built and will function normally unless an incomplete routine is ! 1033: called. ! 1034: .IP \*MDummyDcl(x)\fP ! 1035: .br ! 1036: A macro that should expand into an assembly language declaration that ! 1037: allocates a word of storage for a variable named \*Mx\fP. ! 1038: .IP \*MDummyRef(x)\fP ! 1039: .br ! 1040: A macro that should expand into an assembly language reference to the ! 1041: variable \*Mx\fP. ! 1042: .IP \*MGlobal(x)\fP ! 1043: .br ! 1044: A macro that should expand into an assembly language ! 1045: declaration of \*Mx\fP as a global symbol. ! 1046: .IP \*Mfp\fP,\^\ \*Mefp\fP,\^\ \*Mgfp\fP,\^\ \*Mipc\fP ! 1047: .br ! 1048: It is advisable to use \*M#define\fPs for these registers rather than ! 1049: explicitly name them in the code. ! 1050: .IP \*Mcset_display\fP ! 1051: .br ! 1052: This is a rather complicated macro that is used to initialize the ! 1053: values of \*Mcset\fPs such as \*M&cset\fP and \*M&lcase\fP. If the ! 1054: target machine has \*Mint\fPs with 32 or 16 bits,\^ then the VAX or ! 1055: PDP-11 definition (respectively) of \*Mcset_display\fP may be used. ! 1056: If this is not the case,\^ \*Mcset_display\fP will have to be ! 1057: hand-crafted and the various uses of it will have to be altered for ! 1058: the machine in question. Briefly,\^ a \*Mcset_display\fP specifies ! 1059: which of the 256 bits that comprise a cset are to be set to 1. ! 1060: For example,\^ the \*Mcset_display\fP for \*M&cset\fP has all the bits ! 1061: set to 1,\^ while \*M&ascii\fP has the first 128 bits set to 1. ! 1062: \*Mcset\fPs are accessed using the \*Msetb\fP and \*Mtstb\fP macros ! 1063: which are also defined in \*Mrt.h\fP. ! 1064: \*Mcset_display\fPs appear in \*Miconx/init.c\fP,\^ ! 1065: \*Mfunctions/bal.c\fP,\^ and \*Mfunctions/trim.c\fP. It may also be ! 1066: necessary to modify the definitions of \*MCSETSIZE\fP,\^ \*Msetb\fP,\^ ! 1067: and \*Mtstb\fP. ! 1068: .PP ! 1069: Search for the second \*MPORT\fP section. ! 1070: \*MF_NQUAL\fP,\^ \*MF_VAR\fP,\^ \*MF_TVAR\fP,\^ \*MF_PTR\fP,\^ \*MF_NUM\fP,\^ ! 1071: \*MF_INT\fP,\^ and \*MF_AGGR\fP should be given the ! 1072: same values they have in \*Mlink/datatype.h\fP. ! 1073: .PP ! 1074: Once \*Mrt.h\fP has been completed,\^ an analogous file,\^ \*Mh/defs.s\fP ! 1075: must tailored. \*Mdefs.s\fP is a subset of \*Mrt.h\fP that is ! 1076: included in assembly language files. The \*MPORT\fP section of \*Mdefs.s\fP ! 1077: lists a number of constants that must be defined. Use the appropriate ! 1078: values from \*Mrt.h\fP for each constant. If all assemblers used a ! 1079: default radix of 10 for constants,\^ it would be possible to tailor ! 1080: \*Mdefs.s\fP mechanically,\^ but since this is not the case,\^ ! 1081: \*Mdefs.s\fP must be modified by hand. ! 1082: .NH 2 ! 1083: Complete System Compilation ! 1084: .PP ! 1085: In order to determine if there are serious C compiler problems with ! 1086: the interpreter source,\^ the entire system should be made at this ! 1087: point. Do a ! 1088: .Ds ! 1089: make Icon ! 1090: .De ! 1091: in the root directory of the Icon distribution. ! 1092: The entire ! 1093: system should compile without any problems. The resulting ! 1094: interpreter will be completely disfunctional,\^ but if it is built without ! 1095: any problems,\^ it provides further evidence that the C compiler is ! 1096: up to the task. ! 1097: .NH 2 ! 1098: Porting the Assembly Language Routines ! 1099: .PP ! 1100: The porting of the assembly language routines is the most difficult part of ! 1101: porting Icon. This document has a section for each assembly language routine ! 1102: and each routine is described in three ways: ! 1103: .Ds ! 1104: .ft R ! 1105: overview ! 1106: generic operation ! 1107: the routine on the VAX ! 1108: .De ! 1109: .PP ! 1110: The overview section briefly describes the action of the routine ! 1111: and how the routine may be encountered during the course of execution. ! 1112: The generic operation section tells what steps the routine ! 1113: takes to perform its given task. Each major step that the routine takes ! 1114: is described. These steps should be very similar from machine to ! 1115: machine. ! 1116: The section about the routine on the VAX details the ! 1117: operation of the routine on the VAX. This section complements ! 1118: the comments contained in the source code for the routine and should ! 1119: be read with the source code at hand. ! 1120: This section is very machine specific. (Ideally there would be one ! 1121: such section for each existing Icon implementation.) ! 1122: .PP ! 1123: Each routine must be formulated for the target machine. For the most ! 1124: part,\^ the best approach is to take the same steps that are ! 1125: taken on the VAX. It is important to select the right level for ! 1126: modeling the VAX routines. Try to recognize the steps that are ! 1127: made rather than following the operations on a per-instruction basis. ! 1128: The most important thing is to have a good understanding of what actions ! 1129: are performed and how these can be done on the target machine. ! 1130: .PP ! 1131: The first goal is to get a very simple Icon program working. This ! 1132: first program is \*Mtest/hello.icn\fP. It is quite short: ! 1133: .Ds ! 1134: procedure main() ! 1135: write("hello world") ! 1136: end ! 1137: .De ! 1138: The basis of routines mentioned above ! 1139: (\*Mstart.s\fP,\^ \*Msetbound.s\fP,\^ \*Minvoke.s\fP,\^ \*Minterp.s\fP,\^ ! 1140: \*Mefail.s\fP,\^ and \*Mpfail.s\fP) ! 1141: must be implemented for even a very simple Icon program to work. ! 1142: However,\^ all these ! 1143: routines do not need to be written to make \*Mhello\fP \fIbegin\fP to work. ! 1144: .PP ! 1145: Translate and link \*Mhello\fP by running the translator and the ! 1146: linker: ! 1147: .Ds ! 1148: tran/itran hello.icn ! 1149: link/ilink hello.u1 ! 1150: .De ! 1151: This creates an interpretable file named \*Mhello\fP. Just to ! 1152: get the feel of things,\^ run the interpreter on the file: ! 1153: .Ds ! 1154: iconx/iconx hello ! 1155: .De ! 1156: A message of some type and a core dump should be produced. ! 1157: .PP ! 1158: The files \*Mtran/itran\fP,\^ \*Mlink/ilink\fP,\^ and \*Miconx/iconx\fP,\^ ! 1159: are copied into the \*Mbin\fP directory as the last action of ! 1160: .Ds ! 1161: make Icon ! 1162: .De ! 1163: in the root directory. ! 1164: The porter may find it convenient to link ! 1165: these files to the \*Mbin\fP directory and then place the full pathname ! 1166: in his search path. It is necessary to ! 1167: remove \*Mitran\fP,\^ \*Milink\fP,\^ and \*Miconx\fP in the \*Mbin\fP ! 1168: directory before linking them. Also,\^ if the files are linked,\^ the last ! 1169: step of \fImake\fP in the root directory will fail. This failure is ! 1170: inconsequential. ! 1171: .PP ! 1172: As \*Mstart.s\fP et al. are written,\^ try stepping through them to be ! 1173: sure the correct actions are being performed. Most of the assembly ! 1174: language source ! 1175: files are straight line code with a branch or two and it is possible to ! 1176: do a large amount of verification of the assembly code by single stepping ! 1177: through it with a debugger. ! 1178: .PP ! 1179: When a routine has been completed,\^ it may be added to the interpreter ! 1180: by doing a \fImake\fP in the directory containing the routine and ! 1181: then doing another \fImake\fP in the directory \*Miconx\fP.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.