From: sater Date: Fri, 4 Jan 1985 13:55:07 +0000 (+0000) Subject: Initial revision X-Git-Tag: release-5-5~5815 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=dd8505531ba39bd0cc2251eefc684846350b91bd;p=ack.git Initial revision --- diff --git a/doc/ncg.doc b/doc/ncg.doc new file mode 100644 index 000000000..4abfdbad5 --- /dev/null +++ b/doc/ncg.doc @@ -0,0 +1,2944 @@ +.\" $Header$ +.RP +.ND +.TL +The table driven code generator +.br +from the +.br +Amsterdam Compiler Kit +.br +Second Revised Edition +.AU +Hans van Staveren +.AI +Dept. of Mathematics and Computer Science +Vrije Universiteit +Amsterdam, The Netherlands +.AB +The Amsterdam Compiler Kit is a collection of tools +designed to help automate the process of compiler building. +Part of it is a table driven code generator, +called +.I cg , +and a program to check and translate machine description +tables called +.I cgg . +This document provides a description of the internal workings of +.I cg , +and a description of syntax and semantics of the driving table. +This is required reading for those wishing to write a new table. +.AE +.NH 1 +Introduction +.PP +Part of the Amsterdam Compiler Kit is a code generator system consisting +of a code generator generator (\fIcgg\fP for short) and some machine +independent C code. +.I Cgg +reads a machine description table and creates two files, +tables.h and tables.c. +These are then used together with other C code to produce +a code generator for the machine at hand. +.PP +This in turn reads compact EM code and produces +assembly code. +The remainder of this document will first broadly describe +the working of the code generator, +then the machine table will be described after which +some light is shed onto +the internal workings of the code generator. +.PP +The reader is assumed to have at least a vague notion about the +semantics of the intermediary EM code. +Someone wishing to write a table for a new machine +should be thoroughly acquainted with EM code +and the assembly code of the machine at hand. +.NH 1 +What has changed since version 1 ? +.PP +This chapter can be skipped by anyone not familiar with the first version. +It is not needed to understand the current version. +.PP +This paper describes the second version of the code generator system. +Although the code generator itself is for the main part unchanged, +the table format has been drastically redesigned and the opportunities +to make faulty tables are reduced. +The format is now aesthaticly more pleasing (according to \fIme\fP that is), +mainly because the previous version was designed for one line code rules, +which did not work out that way. +.PP +The `SCRATCH' property is now automatically generated by +.I cgg , +.I erase +and +.I setcc +calls and their ilk are now no longer needed +(read: can no longer be forgotten) +and all this because the table now +.I knows +what the machine instructions look like and what arguments they +destroy. +.PP +Checks are now made for register types, so it is no longer possible +to generate a `regind2' token with a floating point register as a base. +In general, if the instructions of the machine are correctly defined, +it is no longer possible to generate code that does not assemble, +which of course does not mean that it is not possible to generate +assembly code that does not do what was intended! +.PP +Checks are made now for missing moves, tests, coercions, etc. +There is a form of procedure call now to reduce table size: +it is no longer necessary to write the code for conditional +instructions six times. +.PP +The inreg() pseudo-function returns other results!! +.NH 1 +Global overview of the workings of the code generator. +.PP +The code generator or +.I cg +tries to generate good code by simulating the stack +of the compiled program and delaying emission of code as long +as possible. +It also keeps track of register contents, which enables it to +eliminate redundant moves, and tries to eliminate redundant tests +by keeping information about condition code status, +if applicable for the machine. +.PP +.I Cg +maintains a `fake stack' containing `tokens' that are built +by executing the pseudo code contained in the code rules given +by the table writer. +One can think of the fake stack as a logical extension of the real +stack the compiled program will have when run. +Alternatively one can think of the real stack as an infinite extension +at the bottom of the fake stack. +Both ways, the concatenation of the real stack and the fake stack +will be the stack as it would have been on a real EM machine (see figure). +.KF +.DS L +.ta 8 16 24 32 40 48 56 64 72 + EM machine target machine + + | | | | + | | | | + | | | | + | | | | + | | | real stack | + | | | | | + | | | | | growing + | EM stack | | | | + | | |_______________| \e|/ + | | | | + | | | | + | | | | + | | | fake stack | + | | | | + |_______________| |_______________| + + +.I + Relation between EM stack, real stack and fake stack. +.R +.DE +.KE +During code generation tokens will be kept on the fake stack as long +as possible but when they are moved to the real stack, +by generating code for the push, +all tokens above\u*\d +.FS +* in this document the stack is assumed to grow downwards, +although the top of the stack will mean the first element that will +be popped. +.FE +the pushed tokens will be pushed also, +so the fake stack will not contain holes. +.PP +The information about the machine that +.I cg +needs has to be given in a machine description table, +with as a major part a list of code rules telling +.I cg +what to do when certain EM-instructions occur +with certain tokens on the fake stack. +Not all possible fake stack possibilities have to be given of course, +there is a possibility for providing rewriting rules, or +.I coercions +as they are called in this document. +.PP +The main loop of +.I cg +is: +.IP 1) +find a pattern of EM instructions starting at the current one to +generate code for. +This pattern will usually be of length one but longer patterns can be used. +Process any pseudo-instructions found. +.IP 2) +Select one of the possibly many stack patterns that go with this +EM pattern on the basis of heuristics, look ahead or both. +The cost fields provided in the token definitions and +instruction definitions are used +to compute costs during look ahead. +.IP 3) +Force the current fake stack contents to match the pattern. +This may involve +copying tokens to registers, making dummy transformations, e.g. to +transform a `local' into an `indexed from register' or might even +cause the move of the complete fake stack contents to the real stack +and then back into registers if no suitable coercions +were provided by the table writer. +.IP 4) +Execute the pseudocode associated with the code rule just selected, +this may cause registers to be allocated, +code to be emitted etc.. +.IP 5) +Put tokens onto the fake stack to reflect the result of the operation. +.IP 6) +Insert some EM instructions into the stream; +this is possible but not common. +.IP 7) +Account for the cost. +The cost is kept in a (space, time) vector and look ahead decisions +are based on a linear combination of these. +The code generator calls on itself recursively during look ahead, +and the recursive incarnations return the costs they made. +The costs the top-level code generator makes is of course irrelevant. +.PP +The table that drives +.I cg +is not read in every time, +but instead is used at compile time +of +.I cg +to set parameters and to load pseudocode tables. +A program called +.I cgg +reads the table and produces large lists of numbers that are +compiled together with machine independent code to produce +a code generator for the machine at hand. +.PP +Part of the information needed is not easily expressed in this table +format and must be supplied in two separate files, +mach.h and mach.c. +Their contents are described later in this document. +.NH 1 +Register variables +.PP +If the machine has more than enough registers to generate code with, +it is possible to reserve some of them for use as register variables. +If it has not, you can skip this section and ignore any references +to register variables in the rest of this document. +.PP +The front ends generate messages to the back ends telling them which +local variables could go into registers. +The information given is the offset of the local, it's size and type +and a scoring number, roughly the number of times it occurs. +.PP +The decision which variable to put in which register is taken by the +machine independent part of +.I cg +with the help of a scoring function provided by the table writer in mach.c. +The types of variables known are +.IP reg_any 12 +Just a variable of some integer type. +Nothing special known about it. +.IP reg_float +A floating point variable. +.IP reg_loop +A loop control variable. +.IP reg_pointer +A pointer variable. +Usually they are better candidates to put in registers. +.PP +If you use register variables in your table you must supply +more functions in mach.c. +These functions are explained later. +.NH 1 +Description of the machine table +.PP +The machine description table consists of the +concatenation of the following sections: +.IP 1) +Constant definitions +.IP 2) +Property definitions +.IP 3) +Register definitions +.IP 4) +Token definitions +.IP 5) +Set definitions +.IP 6) +Instruction definitions +.IP 7) +Move definitions +.IP 8) +Test definitions +.IP 9) +Stack definitions +.IP 10) +Coercions +.IP 11) +Code rules +.PP +This is the order in the table +but the descriptions in this document will use a slightly different +order. +All sections except the first start with an uppercase header word. +Examples may be given in early stages that use knowledge that is explained +in a later stage. +If something is not clear the first time, please read on. +All will clear up in a couple of pages. +.PP +Input is in free format, white space and newlines may be used +at will to improve legibility. +Identifiers used in the table have the same syntax as C identifiers, +upper and lower case considered different, all characters significant. +Here is a list of reserved words; all of these are unavailable as identifiers. +.DS L +.ta 14 28 42 56 +ADDR STACK from reg_any test +COERCIONS STACKINGRULES gen reg_float to +INSTRUCTIONS TESTS highw reg_loop ufit +INT TIMEFACTOR inreg reg_pointer uses +MOVES TOKENS kills regvar with +PATTERNS call leaving return yields +PROPERTIES cost loww reusing +REGISTERS defined move rom +SETS exact pat samesign +SIZEFACTOR example proc sfit +.DE +C style comments are accepted. +.DS +/* this is a comment */ +.DE +If the standard constant facility is not enough the C-preprocessor can +be used to enhance the table format. +.PP +Integers in the table have the normal C-style syntax. +Decimal by default, octal when preceded by a 0 +and hexadecimal when preceded by 0x. +.NH 2 +Constant section +.PP +In the first part of the table some constants can be defined, +most with the syntax +.DS +NAME=value +.DE +value being an integer or string. +Three constants must be defined here: +.IP EM_WSIZE 10 +Number of bytes in a machine word. +This is the number of bytes +a \fBloc\fP instruction will put on the stack. +.IP EM_PSIZE +Number of bytes in a pointer. +This is the number of bytes +a \fBlal\fP instruction will put on the stack. +.IP EM_BSIZE +Number of bytes in the hole between AB and LB. +If the calling sequence just saves PC and LB this +size will be twice the pointersize. +.PP +EM_WSIZE and EM_PSIZE are checked when a program is compiled +with the resulting code generator. +EM_BSIZE is used by +.I cg +to add to the offset of instructions dealing with locals +having positive offsets, +i.e. parameters. +.PP +Other constants can be defined here to be used as mnemonics +later in the table. +.PP +Optional is the definition of a printformat for integers in the code file. +This is given as +.DS +FORMAT = string +.DE +The string must be a valid printf(III) format, +and defaults to "%d" or "%ld" depending on the wordsize of +the machine. For example on the PDP-11 one can use +.DS +FORMAT= "0%o" +.DE +to satisfy the old UNIX assembler that reads octal unless followed by +a period, and the ACK assembler that follows C conventions. +.PP +Tables under control of programs like +.I sccs +or +.I rcs +can put their id-string here, for example +.DS +rcsid="$Header$" +.DE +These strings, like all strings in the table, will eventually +end up in the binary code generator produced. +.PP +Optionally one can give the factors with which the size and time +parts of the cost vector have to be multiplied to ensure they have the +same order of magnitude. +This can be done as +.DS +SIZEFACTOR = C\d3\u/C\d4\u +TIMEFACTOR = C\d1\u/C\d2\u +.DE +Above numbers must be read as rational numbers. +Defaults are 1/1 for both of them. +These constants set the default size/time tradeoff in the code generator, +so if TIMEFACTOR and SIZEFACTOR are both 1 the code generator will choose +at random between two code sequences where one has +cost (10,4) and the other has cost (8,6). +See also the description of the cost field below. +.NH 2 +Property definition +.PP +This part of the table defines the list of properties that can be used +to differentiate between register classes. +It consists of a list of user-defined +identifiers optionally followed by the size +of the property in parentheses, default EM_WSIZE. +Example for the PDP-11: +.DS +.ta 8 16 24 32 40 +PROPERTIES /* The header word for this section */ + +GENREG /* All PDP registers */ +REG /* Normal registers (allocatable) */ +ODDREG /* All odd registers (allocatable) */ +REGPAIR(4) /* Register pairs for division */ +FLTREG(4) /* Floating point registers */ +DBLREG(8) /* Same, double precision */ +GENFREG(4) /* generic floating point */ +GENDREG(8) /* Same, double precision */ +FLTREGPAIR(8) /* register pair for modf */ +DBLREGPAIR(16) /* Same, double precision */ +LOCALBASE /* Guess what */ +STACKPOINTER +PROGRAMCOUNTER +.DE +Registers are allocated by asking for a property, +so if for some reason in later parts of the table +one particular register must be allocated it +has to have a unique property. +.NH 2 +Register definition +.PP +The next part of the tables describes the various registers of the +machine and defines identifiers +to be used in later parts of the tables. +Syntax: +.DS + : REGISTERS + : ':' '.' + : ident [ '(' string ')' ] [ '=' ident [ '+' ident ] ] +.DE +Example for the PDP-11: +.DS L +.ta 8 16 24 32 40 48 56 64 +REGISTERS + +r0,r2,r4 : GENREG,REG. +r1,r3 : GENREG,REG,ODDREG. +r01("r0")=r0+r1 : REGPAIR. +fr0("r0"),fr1("r1"),fr2("r2"),fr3("r3") : GENFREG,FLTREG. +dr0("r0")=fr0,dr1("r1")=fr1, + dr2("r2")=fr2,dr3("r3")=fr3 : GENDREG,DBLREG. +fr01("r0")=fr0+fr1,fr23("r2")=fr2+fr3 : FLTREGPAIR. +dr01("r0")=dr0+dr1,dr23("r2")=dr2+dr3 : DBLREGPAIR. +lb("r5") : GENREG,LOCALBASE. +sp : GENREG,STACKPOINTER. +pc : GENREG,PROGRAMCOUNTER. +.DE +.PP +The names in the left hand lists are names of registers as used +in the table. +They can optionally be followed by a string in parentheses, +their name as far as the assembler is concerned. +The default assembler name is the same as the table name. +A name can also be followed by +.DS += othername +.DE +or +.DS += othername + othername +.DE +which says that the register is composed of the parts +after the '=' sign. +The identifiers at the right hand side of the lists are +names of properties. +The end of each register definition is a period. +.PP +It might seem wise to list every property of a register, +so one might give r0 the extra property MFPTREG named after the not +too well known MFPT instruction on newer PDP-11 types, +but this is not a good idea, +especially since no use can be made of that instruction anyway. +Every extra property means the register set is more unorthogonal +and +.I cg +execution time is influenced by that, +because it has to take into account a larger set of registers +that are not equivalent. +So try to keep the number of different register classes to a minimum. +When faced with the choice between two possible code rules +for a nonfrequent EM sequence, +one being elegant but requiring an extra property, +and the other less elegant, +elegance should probably loose. +.PP +Tables that implement register variables must mark registers to be used +for variable storage here by following the list of properties by one +of the following: +.DS +regvar \fIor\fP regvar(reg_any) +regvar(reg_loop) +regvar(reg_pointer) +regvar(reg_float) +.DE +meaning they are candidates for that type of variable. +All register variables of one type must be of the same size, +and they may have no subregisters. +Such registers are not available for normal code generation. +.NH 2 +Stack token definition +.PP +The next part describes all possible tokens that can reside on +the fake stack during code generation. +Attributes of a token are described as a C struct declaration; +this is followed by the size of the token in bytes, +optionally followed by the cost of the token when used as an addressing mode +and the format to be used on output. +.PP +In general, when writing a table, it is not wise to try +to think of all necessary tokens in advance. +While writing the necessity or advisability for some token +will be seen and it can then be added together with the +stacking rules and coercions needed. +.PP +Tokens should usually be declared for every addressing mode +of the machine at hand and for every size directly usable in +a machine instruction. +Example for the PDP-11 (incomplete): +.DS L +TOKENS + +const2 = { INT num; } 2 cost(2,300) "$" num . +addr_local = { INT ind; } 2 . +addr_external = { ADDR off; } 2 "$" off. + +regdef2 = { GENREG reg; } 2 "*" reg. +regind2 = { GENREG reg; ADDR off; } 2 off "(" reg ")" . +reginddef2 = { GENREG reg; ADDR off; } 2 "*" off "(" reg ")" . +regconst2 = { GENREG reg; ADDR off; } 2 . +relative2 = { ADDR off; } 2 off . +reldef2 = { ADDR off; } 2 "*" off. +.DE +.PP +Types allowed in the struct are ADDR, INT and all register properties. +The type ADDR means a string and an integer, +which is output as string+integer, +and arithmetic on mixed ADDR and INT is possible. +This is the right mode for anything that can be an +assembler address expression. +The type of the register in the token is strict. +At any assignment of an expression of type register to a token attribute +of type register +.I cgg +will check if the set of possible results from the expression is a subset +of the set of permissible values for the token attribute. +.PP +The cost-field is made up by the word +.I cost +followed by two numbers in parentheses, the size and timecosts +of this token when output in the code file. +If omitted, zero cost is assumed. +While generating code, +.I cg +keeps track of a linear combination of these costs together +with the costs of the instructions itself which we will see later. +The coefficients of this linear combination are influenced +by two things: +.IP 1) +The SIZEFACTOR and TIMEFACTOR constants, +as mentioned above. +.IP 2) +A run time option to +.I cg +that can adjust the time/space tradeoff to all positions +from 100% time to 100% space. +.LP +By supplying different code rules in certain situations +it is possible to get a code generator that can adjust it's +code to the need of the moment. +This is probably most useful with small machines, +experience has shown that on the larger micro's and mini's +the difference between time-optimal and space-optimal code +is often small. +.PP +The printformat consists of a list of strings intermixed with +attributes from the token. +Strings are output literally, attributes are printed according +to their type and value. +Tokens without a printformat should never be output, +and +.I cgg +checks for this. +.PP +Notice that tokens need not correspond to addressing modes; +the regconst2 token listed above, +meaning the sum of the contents of the register and the constant, +has no corresponding addressing mode on the PDP-11, +but is included so that a sequence of add constant, load indirect, +can be handled efficiently. +This regconst2 token is needed as part of the path +.DS +REG -> regconst2 -> regind2 +.DE +of which the first and the last "exist" and the middle is needed +only as an intermediate step. +.PP +Tokens with name `LOCAL' or `DLOCAL' are a special case when +register variables are used, this is explained further in the +section on token descriptions. +.NH 2 +Sets +.PP +Usually machines have certain collections of addressing modes that +can be used with certain instructions. +The stack patterns in the table are lists of these collections +and since it is cumbersome to write out these long lists +every time, there is a section here to give names to these +collections. +Please note that it is not forbidden to write out a set +in the remainder of the table, +but for clarity it is usually better not to. +.LP +Example for the PDP-11 (incomplete): +.DS L +.ta 8 16 24 32 40 48 56 64 +SETS + +src2 = GENREG + regdef2 + regind2 + reginddef2 + relative2 + + reldef2 + addr_external + const2 + LOCAL + ILOCAL + + autodec + autoinc . +dst2 = src2 - ( const2 + addr_external ) . +xsrc2 = src2 + ftoint . +src1 = regdef1 + regind1 + reginddef1 + relative1 + reldef1 . +dst1 = src1 . +src1or2 = src1 + src2 . +src4 = relative4 + regdef4 + DLOCAL + regind4 . +dst4 = src4 . +.DE +Permissible in the set construction are all the usual set operators, i.e. +.IP + +set union +.IP - +set difference +.IP * +set intersection +.PP +Normal operator priorities apply, and parentheses can be +used. +Every token identifier is also a set identifier +denoting the singleton collection of tokens containing +just itself. +Every register property as defined above is also a set +matching all registers with that property. +The standard set identifier ALL denotes the collection of +all tokens. +.NH 2 +Instruction definitions +.PP +In the next part of the table the instructions for the machine +are declared together with information about their operands. +Example for the PDP-11(very incomplete): +.DS +.ta 8 16 24 32 40 48 56 64 +INSTRUCTIONS +/* default cost */ + +cost(2,600) + +/* Normal instructions */ + +adc dst2:rw:cc . +add src2:ro,dst2:rw:cc cost(2,450). +ash src2:ro,REG:rw:cc . +ashc src2:ro,REGPAIR+ODDREG:rw . +asl dst2:rw:cc . +asr dst2:rw:cc . +bhis "bcc" label . + +/* floating point instructions */ + +movf "ldf" fsrc,freg . +movf "stf" freg,fdst . +.DE +As the examples show an instruction definition consists of the name +of the instruction, +optionally followed by an assembler mnemonic in +quotes-default is the name itself-and then +a list of operands, +optionally followed by the cost and then a period. +If the cost is omitted the cost just after the word +INSTRUCTIONS is assumed, +if that is also omitted the cost is zero. +The cost must be known by +.I cg +of course if it has multiple +code generation paths to choose from. +.PP +For each operand we have the set of possible token values, +followed by a qualifier that can be +.IP :ro +signifies that this operand is read only, +so it can be replaced by a register with the same contents +if available. +.IP :rw +signifies that the operand is read-write +.IP :wo +signifies that the operand is write only. +.IP :cc +says that after the instruction is finished, the condition codes +are set to this operand. +If none of the operands have the :cc qualifier set, +.I cg +will assume that condition codes were unaffected +(but see below). +.PP +The first three qualifiers are of course mutually exclusive. +The :ro qualifier does not cause any special action in the current +implementation, and the :wo and :rw qualifiers are treated equal. +It must be recommended however to be precise in the specifications, +since later enhancements to the code generator might use them. +.PP +As the last examples show it is not necessary to give one definition +for an instruction. +There are machines that have very unorthogonal instruction sets, +in fact most of them do, +and it is possible to declare each possible combination +of operands. +The +.I cgg +program will check all uses of the instruction to find out which +one was meant. +.PP +Although not in the PDP-11 example above there is a possibility +to describe instructions that have side effects to registers not +in the operand list. +The only thing possible is to say that the instruction is destructive +to some registers or the condition codes, by following the operand list +with the word +.I kills +and a list of the things destroyed. +Example for some hypothetic accumulator machine: +.DS +add source2:ro kills ACCU :cc . +.DE +.PP +The cost fields in the definitions for tokens and instructions +are added together when generating code. +It depends on the machine at hand whether the costs are orthogonal +enough to make use of both these costs, +in extreme cases every combination of instructions and operands +can be given in this section, +all with their own costs. +.NH 2 +Expressions +.PP +Throughout the rest of the table expressions can be used in some +places. +This section will give the syntax and semantics of expressions. +There are four types of expressions: integer, address, register and undefined. +Really the type register is nonexistent as such, +for each register expression +.I cgg +keeps a set of possible values, +and this set can be seen as the real type. +.PP +Type checking is performed by +.I cgg . +An operator with at least one undefined operand returns undefined except +for the defined() function mentioned below. +An undefined expression is interpreted as FALSE when it is needed +as a truth value. +It is the responsibility of the table writer to ensure no undefined +expressions are ever used as initialisers for token attributes. +This is unfortunately almost impossible to check for +.I cgg +so be careful. +.LP +Basic terms in an expression are +.IP number 16 +A number is a constant of type integer. +Also usable is an identifier defined to a number in the constant +definition section. +.IP """string""" +A string within double quotes is a constant of type address. +All the normal C style escapes may be used within the string. +Also usable is an identifier defined to a string in the constant +definition section. +.IP [0-9][bf] +This must be read as a grep-pattern. +It evaluates to a string that is the label name for the +temporary label meant. +More about this in the section on code rules. +.IP REGIDENT +The name of a register is a constant of type register. +.IP $\fIi\fP +A dollarsign followed by a number is the representation of the argument +of EM instruction \fI\fP. +The type of the operand is dependent on the instruction, +sometimes it is integer, +sometimes it is address. +It is undefined when the instruction has no operand. +Watch out for instructions with type-letter w. +They can occur without an operand. +Check for this in your code rule with the defined() pseudo function. +.br +If you cannot imagine the operand of the instruction ever to be +something different from a plain integer, the type is integer, +otherwise it is address. +.br +Those who want to know it exactly, the integer instruction types +are the instructions marked with the +type-letters c,f,l,n,o,s,r,w,z in the EM manual. +.br +.I Cg +makes all necessary conversions for you, +like adding EM_BSIZE to positive arguments of instructions +dealing with locals, +prepending underlines to global names, +converting code labels into a unique representation etc. +Details about this can be found in the section about +machine dependent C code. +.IP %1 +This in general means the token mentioned first in the +stack pattern. +When used inside an expression the token must be a simple register. +Type of this is register. +.IP %1.off +This means attribute "off" of the first stack pattern token. +Type is the same as that of attribute "off". +To use this expression implies a check that all tokens +in the set used have the same attribute in the same place. +.IP %off +This means attribute "off" in the `current' token. +This can only be used when no confusion is possible about which token +was meant, eg. in the optional boolean expressions following token sets +in the move and test rules, in coercions or in the kills section inside +the code rules. +Same check as above. +.IP %1.1 +This is the first subregister of the first token. +Previous comments apply. +.IP %b +A percent sign followed by a lowercase letter +stands for an allocated register. +This is the second allocated register. +.IP %a.2 +The second subregister of the first allocated register. +.PP +All normal C operators apply to integers, +the + operator on addresses behaves as you would expect +and the only operators allowed on register expressions +are == and != . +Furthermore there are some special `functions': +.IP defined(e) 16 +Returns 1 if expression +.I e +is defined, 0 otherwise. +.IP samesign(e1,e2) +Returns 1 if integer expression +.I e1 +and +.I e2 +have the same sign. +.IP sfit(e1,e2) +Returns 1 if integer expression +.I e1 +fits as a signed integer +into a field of +.I e2 +bits, 0 otherwise. +.IP ufit(e1,e2) +Same as above but now for unsigned +.I e1 . +.IP rom($a,n) +Integer expression giving word +.I n +from the \fBrom\fP descriptor +pointed at by EM instruction +number +.I a +in the EM-pattern. +Undefined if that descriptor does not exist. +.IP loww($a) +Returns the lower half of the argument of EM instruction number +.I a . +This is used to split the arguments of a \fBldc\fP instruction. +.IP highw($a) +Same for upper half. +.LP +The next two `functions' are only needed in a table that +implements register variables. +.IP inreg(e) 16 +Returns the status of the local variable with offset +.I e +from the localbase. +Value is an integer, +negative if the local was not allowed as a register +variable, +zero if it was allowed but not assigned to a register, +and the type of the register if it was assigned to a register. +This makes it possible to write +.DS +inreg($1)==reg_pointer +.DE +and similar things. +.IP regvar(e,t) +Type of this is register. +It returns the register the local with offset +.I e +is assigned to. +The table writer guarantees the register is one of type +.I t , +with +.I t +one of reg_any, reg_loop, reg_pointer or reg_float. +If +.I t +is omitted reg_any is assumed. +Undefined if inreg(\fIe\fP)<=0 . +.NH 2 +Token descriptions +.PP +Throughout the rest of the table tokens must be described, +be it as operands of instructions or as stack-replacements. +In all those cases we will speak about a token description. +The possibilities for these will be described here. +.PP +All expressions of type register are token descriptions. +The construct %1 means the token matched first in the stack pattern. +All other token descriptions are those that are built on the spot. +They look like this: +.DS +{ , } +.DE +All expressions are type-checked by +.I cgg , +and the number of initializers is also checked. +.PP +A special case of the last token descriptions occurs when +the token name is `LOCAL' or `DLOCAL' and the table uses register +variables. The first token attribute then must be of type integer and +the token description is automagically replaced by the register chosen +if the LOCAL (wordsize) or DLOCAL (twice the wordsize) was assigned +to a register. +.NH 2 +Code rules +.PP +The largest section of the tables consists of the code generation rules. +They specify EM patterns, stack patterns, code to be generated etc. +Broadly the syntax is +.DS L +code rule : EM-part code-part +EM-part : EM-pattern | procedure-heading +code-part : code-description | procedure-call +code-description : stackpattern kills allocates generates yields leaving +.DE +Ignoring the "procedure"-part for now, the description for the EM-pattern +and the code-description follows. +Almost everything here is optional, the minimum code rule +is: +.DS +pat nop +.DE +that will simply throw away +.I nop +instructions. +.NH 3 +The EM pattern +.PP +The EM pattern consists of a list of EM mnemonics +preceded by the word +.I pat +optionally followed by a boolean expression. +Examples: +.DS +pat \fBloe\fP +.DE +will match a single \fBloe\fP instruction, +.DS +pat \fBloc\fP \fBloc\fP \fBcif\fP $1==2 && $2==8 +.DE +is a pattern that will match +.DS +\fBloc\fP 2 +\fBloc\fP 8 +\fBcif\fP +.DE +and +.DS +pat \fBlol\fP \fBinc\fP \fBstl\fP $1==$3 +.DE +will match for example +.DS +.ta 10m 20m 30m 40m 50m 60m +\fBlol\fP 6 \fBlol\fP -2 \fBlol\fP 4 +\fBinc\fP \fBinc\fP but \fInot\fP \fBinc\fP +\fBstl\fP 6 \fBstl\fP -2 \fBstl\fP -4 +.DE +A missing boolean expression evaluates to TRUE. +.PP +The code generator will match the longest EM pattern on every occasion, +if two patterns of the same length match the first in the table will be chosen, +while all patterns of length greater than or equal to three are considered +to be of the same length. +This rule of three is an unfortunate implementation dependent restriction, +but patterns longer than three EM instructions are luckily not needed +too often. +.PP +Following the EM-pattern there may be more than one code +rule, +.I cg +will choose using heuristics and the cost +information provided with the instruction and token +definitions. +Owing to parsing reasons of the table, the word +.I with +(see below) +is mandatory when there are more code rules attached to one +EM-pattern. +The stack pattern may be empty however. +.NH 3 +The stack pattern +.PP +The optional stack pattern is a list of token sets preceded by the word +.I with . +The token sets are usually represented by set identifiers for clarity. +No boolean expression is allowed here. +The first expression is the one that matches the top of the stack. +.PP +If the pattern is followed by the word STACK +it only matches if there is nothing +else on the fake stack, +and the code generator will stack everything not matched at the start +of the rule. +.PP +The pattern can be preceded with the word +.I exact +following the +.I with +that tells the code generator not to try to coerce to the pattern +but only to use it when it is already present on the fake stack. +There are two reasons for this construction, +correctness and speed. +It is needed for correctness when the pattern contains a register +that is not transparent when data is moved through it. +.LP +Example: on the PDP-11 the shortest code for +.DS +\fBlae\fP a +\fBloi\fP 8 +\fBlae\fP b +\fBsti\fP 8 +.DE +is +.DS +movf _a,fr0 +movf fr0,_b +.DE +if the floating point processor is in double +precision mode and fr0 is free. +Unfortunately this is not correct since a trap can occur on certain +kinds of data. +This could happen if there was a stack pattern for \fBsti\fP\ 8 +like this: +.DS +with DBLREG +.DE +The code generator would then find that coercing the 8-byte global _a +to a floating point register and then storing it to _b was the cheapest, +if the space/time knob was turned far enough to space. +This can be prevented by changing the stack pattern to +.DS +with exact DBLREG +.DE +It is unfortunate that the type information is no longer present, +since if _a really is a floating point number the move could be +made without error. +.PP +The second reason for the +.I exact +construct is speed. +When the code generator has a long list of possible stack patterns +for one EM pattern it can waste much time trying to find coercions +to all of them, while the mere presence of such a long list +indicates that the table writer has given many special cases. +Prepending all the special cases by +.I exact +will stop the code generator from trying to find things +that either cannot be done, +or are too expensive anyway. +.PP +So in general it is wise to prepend all stack patterns that +cannot be made by coercions with +.I exact . +.PP +Using both +.I exact +and STACK in the stack pattern has the effect that the rule will +only be taken if there is nothing else on the fake stack. +.NH 3 +The kills part +.PP +The optional kills part describes certain tokens +that should neither remain on +the fake stack, nor remembered as contents of registers. +This is usually only required with store operations. +The entire fake stack, except for the part matched in the stack pattern, +is searched for tokens matching the expression and they are copied +to the real stack. +Every register that contains the token is marked as empty. +.PP +Syntax is +.DS +kills +thing to kill : token set optionally followed by boolean expression +.DE +Example: +.DS +kills regind2 %reg != lb || %off == $1 +.DE +is a kills part used for example in the \fBinl\fP or \fBstl\fP code rule. +It removes all register offsetted tokens where the register is not the +localbase plus the local in which the store is done. +The necessity for this can be seen from the following example: +.DS +\fBlol\fP 4 +\fBinl\fP 4 +\fBstl\fP 6 +.DE +Without a proper kills part in the rule for \fBinl\fP code would +be generated as here +.DS +inc 4(r5) +mov 4(r5),6(r5) +.DE +so local 6 would be given the new value of local 4 instead of the old +as the EM code prescribed. +.PP +When generating code for an EM-instruction like +.B sti +it is necessary to write a line in the table like +.DS +kills all_except_constant_or_register +.DE +where the long identifier is a set containing all tokens +that can be the destination of some random indirect store. +These indirect stores are the main reason to prevent this +.I kills +line to be deduced automatically by +.I cgg . +.PP +When generating something like a branch instruction it +might be needed to empty the fake stack completely. +This can of course be done with +.DS +kills ALL +.DE +or by ending the stack pattern with the word STACK, which is equivalent, +if the stack pattern does not start with +.I exact . +.PP +It is unfortunate that this part is still present in the table +but it is too much for now to let the +.I cgg +program discover what rules ruin what kind of tokens. +Maybe some day ..... +.NH 3 +The allocates part +.PP +The optional register allocation part describes the registers needed. +Syntax is +.DS +uses +.DE +where itemlist is a list of three kinds of things: +.IP 1) +.I reusing +< a token description >, for example %1. +.br +This will instruct the code generator that all registers +contained in this token can be reused if they are not used +in another token on the fakestack, +so that they are available for allocation in this +.I uses +line +if they were only used in that token. +See example below. +.IP 2) +a register property. +.br +This will allocate a register with that property, +that is marked as empty at this point. +Look ahead can be performed if there is more than one register available. +.IP 3) +a register property with initialization. +.br +This will allocate the register as in 2) but will also +initialize it. +This eases the task of the code generator because it can +find a register already filled with the right value +if it exists. +.LP +Examples: +.DS +uses ODDREG +.DE +will allocate an odd register, while +.DS +uses REG={regind2,lb,$1} +.DE +will allocate a register while simultaneously filling it with +the asked value. +.br +Inside the coercion from xsrc2 to REG in the PDP-11 table +the following line can be found. +.DS +uses reusing %1, REG=%1 +.DE +This tells the code generator that registers contained in %1 can be used +again and asks to fill the register allocated with %1. +So if %1={regind2,r3,"4"} and r3 is not in use elsewhere on the fake stack +the following code might be generated. +.DS +mov 4(r3),r3 +.DE +In the rest of the line the registers allocated can be named by +%a and %b.1,%b.2, i.e. with lower case letters +in order of allocation. +.NH 3 +The generates part +.PP +Code to be generated, also optionally, is specified as +the word +.I gen +followed by a list of items of the following kind: +.IP 1) +An instruction name followed by a comma-separated +list of token descriptions. +.I Cgg +will search the instruction definitions for the machine to find a suitable +instruction. +At code generation time the assembler name of the +instruction will be output followed by a space, +followed by a comma separated list of tokens. +.br +In the table an instruction without operands must be +followed by a period. +The author of +.I cgg +could not get +.I yacc +to be silent without it. +Sorry about this. +.IP 2) +a +.I move +call. +This has the following syntax: +.DS +move , +.DE +Moves are handled specially since that enables the code generator +to keep track of register contents. +Example: +.DS +move r3,{regind2,lb,$1} +.DE +will generate code to move r3 to $1(r5) except when +r3 already was a copy of $1(r5). +Then the code will be omitted. +The rules describing how to move things to each other +can be found in the move definitions section described below. +.IP 3) +For machines that have condition codes, +which alas most of them do, +there are provisions to remember condition code settings +and prevent needless testing. +To set the condition code to a token put in the code the following call: +.DS +test +.DE +This will generate a test if the condition codes +were not already set to that token. +The rules describing how to test things +can be found in the test definitions section described below. +See also the :cc qualifier that can be used at instruction +definition time. +.IP 4) +The +.I return +statement. +Only used when register variables are in use. +This statement causes a call to the machine dependent +C-routine +.I regreturn . +Explanation of this must wait for the description of the +file mach.c below. +.IP 5) +A temporary label of the form : may be placed here. +Expressions of the form [0-9][bf] in this code rule +generate the same string as is used for this label. +The code generator system could probably easily be changed +to make this work for assemblers that do not support this +type of label by generating unique labels itself. +Implementation of this is not contemplated at the moment, +bad luck if your assembler cannot do it. +.NH 3 +Stack replacement +.PP +The optional stack replacement is a possibly empty list +of tokens to be pushed onto the fake stack. +It start with the word +.I yields , +and is followed by a list of token descriptions. +.PP +All tokens matched by the stack pattern at the beginning of the code rule +are first removed and their registers deallocated. +Items are pushed in the order of appearance. +This means that the last item will be on the top of the +stack after the push. +So if the stack pattern contained two sets +and you want to push them back unchanged, +you have to specify as stack replacement +.DS +yields %2 %1 +.DE +and not the other way around. +This is known to cause errors in tables so watch out for +this! +.NH 3 +EM replacement +.PP +In exceptional cases it might be useful to leave part of an EM-pattern +undone. +For example, a \fBsdl\fP instruction might +be split into two \fBstl\fP instructions +when there is no 4-byte quantity on the stack. +The EM replacement part allows +one to express this. +It is activated by the word +.I leaving . +.LP +Example: +.DS +leaving \fBstl\fP $1 \fBstl\fP $1+2 +.DE +The instructions are inserted in the stream so that they can match +the first part of a pattern in the next step. +Note that since the code generator traverses the EM instructions in a strict +linear fashion, +it is impossible to let the EM replacement match later parts of a pattern. +So if there is a pattern +.DS +\fBloc\fP \fBstl\fP $1==0 +.DE +and the input is +.DS +\fBloc\fP 0 \fBsdl\fP 4 +.DE +the \fBloc\fP\ 0 will be processed first, +then the \fBsdl\fP might be split into two \fBstl\fP's but the pattern +cannot match now. +.NH 3 +Examples +.PP +A list of examples for the PDP-11 is given here. +Far from being complete it gives examples of most kinds +of instructions. +.DS +.ta 8 16 24 32 40 48 56 64 +pat loc yields {const2, $1} + +pat ldc yields {const2, loww($1)} + {const2, highw($1)} +.DE +These simple patterns just push one or more tokens onto the fake stack. +.DS +.ta 8 16 24 32 40 48 56 64 +pat lof +with REG yields {regind2,%1,$1} +with exact regconst2 yields {regind2,%1.reg,$1+%1.off} +with exact addr_external yields {relative2,$1+%1.off} +with exact addr_local yields {LOCAL, %1.ind + $1,2} +.DE +This pattern shows the possibility to do different things +depending on the fake stack contents, +there are some rules for some specific cases plus a general rule, +not preceded by +.I exact +that can always be taken after a coercion, +if necessary. +.DS +.ta 8 16 24 32 40 48 56 64 +pat lxl $1>3 +uses REG={LOCAL, SL, 2}, + REG={const2,$1-1} +gen 1: + move {regind2,%a, SL},%a + sob %b,{label,1b} yields %a +.DE +This rule shows register allocation with initialisation, +and the use of a temporary label. +The constant SL used here is defined to be the offset from lb +of the static link, +that is pushed by the Pascal compiler as the last argument of +a function. +.DS +.ta 8 16 24 32 40 48 56 64 +pat stf +with regconst2 xsrc2 + kills allexeptcon + gen move %2,{regind2,%1.reg,$1+%1.off} +with addr_external xsrc2 + kills allexeptcon + gen move %2,{relative2,$1+%1.off} +.DE +This rule shows the use of a +.I kills +part in a store instruction. +The set allexeptcon contains all tokens that can be the destination +of an indirect store. +.DS +.ta 8 16 24 32 40 48 56 64 +pat sde +with exact FLTREG + kills posextern + gen move %1,{relative4,$1} +with exact ftolong + kills posextern + gen setl. + movfi %1.reg,{relative4,$1} + seti. +with src2 src2 + kills posextern + gen move %1, {relative2, $1 } + move %2, {relative2, $1+2} +.DE +The rule for +.B sde +shows the use of the +.I exact +clause in both qualities, +the first is for correctness, +the second for efficiency. +The third rule is taken by default, +resulting in two separate stores, +nothing better exists on the PDP-11. +.DS +.ta 8 16 24 32 40 48 56 64 +pat sbi $1==2 +with src2 REG + gen sub %1,%2 yields %2 +with exact REG src2-REG + gen sub %2,%1 + neg %1 yields %1 +.DE +This rule for +.I sbi +has a normal first part, +and a hand optimized special case as it's second part. +.DS +.ta 8 16 24 32 40 48 56 64 +pat mli $1==2 +with ODDREG src2 + gen mul %2,%1 yields %1 +with src2 ODDREG + gen mul %1,%2 yields %2 +.DE +This shows the general property for rules with commutative +operators, +heuristics or look ahead will have to decide which rule is the best. +.DS +.ta 8 16 24 32 40 48 56 64 +pat loc sli $1==1 && $2==2 +with REG +gen asl %1 yields %1 +.DE +A simple rule involving a longer EM-pattern, +to make use of a specialized instruction available. +.DS +.ta 8 16 24 32 40 48 56 64 +pat loc loc cii $1==1 && $2==2 +with src1or2 +uses reusing %1,REG +gen movb %1,%a yields %a +.DE +A somewhat more complicated example of the same. +Note the +.I reusing +clause. +.DS +.ta 8 16 24 32 40 48 56 64 +pat loc loc loc cii $1>=0 && $2==2 && $3==4 leaving loc $1 loc 0 +.DE +Shows a trivial example of EM-replacement. +This is a rule that could be done by the +peephole optimizer, +if word order in longs was defined in EM. +On a `big-endian' machine the two replacement +instructions would be the other way around. +.DS +.ta 8 16 24 32 40 48 56 64 +pat and $1==2 +with const2 REG + gen bic {const2,~%1.num},%2 yields %2 +with REG const2 + gen bic {const2,~%2.num},%1 yields %1 +with REG REG + gen com %1 + bic %1,%2 yields %2 +.DE +Shows the way you have to twist the table, +if an +.I and -instruction +is not available on your machine. +.DS +.ta 8 16 24 32 40 48 56 64 +pat set $1==2 +with REG +uses REG={const2,1} +gen ash %1,%a yields %a +.DE +Shows the building of a word-size set. +.DS +.ta 8 16 24 32 40 48 56 64 +pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)==0 + leaving adi 2 + +pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)!=0 + leaving adi 2 adp 0-rom($1,1) +.DE +Two rules showing the use of the rom pseudo function, +and some array optimalisation. +.DS +.ta 8 16 24 32 40 48 56 64 +pat bra +with STACK +gen jbr {label, $1} +.DE +A simple jump. +The stack pattern guarantees that everything will be stacked +before the jump is taken. +.DS +.ta 8 16 24 32 40 48 56 64 +pat cal +with STACK +gen jsr pc,{label, $1} +.DE +A simple call. +Same comments as previous rule. +.DS +.ta 8 16 24 32 40 48 56 64 +pat lfr $1==2 yields r0 +pat lfr $1==4 yields r1 r0 +.DE +Shows the return area conventions of the PDP-11 table. +At this point a reminder: +the +.B asp +instruction, and some other instructions must leave +the function return area intact. +See the defining document for EM for exact information. +.DS +.ta 8 16 24 32 40 48 56 64 +pat ret $1==0 +with STACK +gen mov lb,sp + rts pc +.DE +This shows a rule for +.B ret +in a table not using register variables. +In a table with register variables the +.I gen +part would just contain +.I return . +.DS +.ta 8 16 24 32 40 48 56 64 +pat blm +with REG REG +uses REG={const2,$1/2} +gen 1: + mov {autoinc,%2},{autoinc,%1} + sob %a,{label,1b} +.DE +This rule for +.B blm +already uses three registers of the same type. +.I Cgg +contains code to check all your rules +to see if they can be applied from an empty fakestack. +It uses the marriage thesis from Hall, +a thesis from combinatorial mathematics, +to accomplish this. +.DS +.ta 8 16 24 32 40 48 56 64 +pat exg $1==2 +with src2 src2 yields %1 %2 +.DE +This rule shows the exchanging of two elements on the fake stack. +.NH 2 +Code rules using procedures +.PP +To start this chapter it must be admitted at once that the +word procedure is chosen here mainly for it's advertising +value. +It more resembles a glorified goto but this of course can +not be admitted in the glossy brochures. +This document will continue to use the word +procedure. +.PP +The need for procedures was felt after the first version of +the code generator system was made, +mainly because of conditional instructions. +Often the code sequences for +.B tlt , +.B tle , +.B teq , +.B tne , +.B tge +and +.B tgt +were identical apart from one opcode in the code rule. +The code sequence had to be written out six times however. +Not only did this increase the table size and bore the +table writer, it also led to errors when changing the table +since it happened now and then that five out of six +rules were changed. +.PP +In general the procedures in this table format are used to +keep one copy instead of six of the code rules for all +sorts of conditionals and one out of two for things like +increment/decrement. +.PP +And now the syntax, first the procedure definition, +which must indeed be defined before the call because +.I cgg +is one-pass. +The procedure heading replaces the EM-pattern in a code rule +and looks like this: +.DS +proc +.DE +The identifier is used in later calls and the example must +be used if expressions like $1 are used in the code rule. +.DS + : example +.DE +so an example looks just like an EM-pattern, but without +the optional boolean expression. +The example is needed to know the types of $1 expressions. +The current version of +.I cgg +does not check correctness of the example, so be careful. +.PP +A procedure is called with one or two string-parameters, +that are assembler opcodes. +They can be accessed by appending the strings `[1]' or `[2]' +to a table opcode. +The string `*' can be used as an equivalent for `[1]'. +Just in case this is not clear, here is an example for +a procedure to increment/decrement a register. +.DS +.ta 8 16 24 32 40 48 56 64 +incop REG:rw:cc . /* in the INSTRUCTIONS part of course */ + +proc incdec +with REG +gen incop* %1 yields %1 +.DE +The procedure is called with parameter "inc" or "dec". +.PP +The procedure call is given instead of the code-part of the +code rule and looks like this +.DS +call '(' string [ ',' string ] ')' +.DE +which leads to the following large example: +.DS +.ta 8 16 24 32 40 48 56 64 +proc bxx example beq +with src2 src2 STACK +gen cmp %2,%1 + jxx* {label, $1} + +pat blt call bxx("jlt") +pat ble call bxx("jle") +pat beq call bxx("jeq") +pat bne call bxx("jne") +pat bgt call bxx("jgt") +pat bge call bxx("jge") +.DE +.NH 2 +Move definitions +.PP +We now jump back to near the beginning of the table +where the move definitions are found. +The move definitions directly follow the instruction +definitions. +.PP +In certain cases a move is called for, +either explicitly when a +.I move +instruction is used in a code rule, +or implicitly in a register initialization. +The different code rules possible to move data from one +spot to another are described here. +Example for the PDP-11: +.DS +.ta 8 16 24 32 40 48 56 64 +MOVES + +from const2 %num==0 to dst2 +gen clr %2 + +from src2 to dst2 +gen mov %1,%2 + +from FLTREG to longf4-FLTREG +gen movfo %1,%2 + +from longf4-FLTREG to FLTREG +gen movof %1,%2 +.DE +The example shows that the syntax is just +.DS +from to gen +.DE +Source and destination are a token set, optionally followed by +a boolean expression. +The code generator will take the first move that matches, +whenever a move is necessary. +.I Cgg +checks whether all moves called for in the table are present. +.NH 2 +Test definitions +.PP +This part describes the instructions necessary to set the condition codes +to a certain token. +These rules are needed when the +.I test +instruction is used in code rules. +Example for the PDP-11: +.DS +.ta 8 16 24 32 40 48 56 64 +TESTS + +to test src2 +gen tst %1 +.DE +So syntax is just +.DS +to test gen +.DE +Source is the same thing as in the move definition. +.I Cgg +checks whether all tests called for in the table are present. +.NH 2 +Some explanation about the rules behind coercions +.PP +A central part in code generation is taken by the +.I coercions . +It is the responsibility of the table writer to provide +all necessary coercions so that code generation can continue. +The minimal set of coercions are +the coercions to unstack every token expression, +in combination with the rules to stack every token. +It should not be possible to smuggle a table through +.I cgg +without these basic set available. +.PP +If these are present the code generator can always make the necessary +transformations by stacking and unstacking. +Of course for code quality it is usually best to provide extra coercions +to prevent this stacking to take place. +.I Cg +discriminates three types of coercions: +.IP 1) +Unstacking coercions. +This category can use the +.I uses +clause in its code. +.IP 2) +Splitting coercions, these are the coercions that split +larger tokens into smaller ones. +.IP 3) +Transforming coercions, these are the coercions that transform +a token into another of the same size. +This category can use the +.I uses +clause in its code. +.PP +When a stack configuration does not match the stack pattern +.I coercions +are searched for in the following order: +.IP 1) +First tokens are split if necessary to get their sizes right. +.IP 2) +Then transforming coercions are found that will make the pattern match. +.IP 3) +Finally if the stack pattern is longer than the fake stack contents +unstacking coercions will be used to fill up the pattern. +.PP +At any point, when coercions are missing so code generation could not +continue, the offending tokens are stacked. +.NH 2 +Stack definitions +.PP +The next part of the table defines the stacking rules for the machine. +Each token that may reside on the fake stack must have a rule attached +to put it on the real stack. +Example for the PDP-11: +.DS +.ta 8 16 24 32 40 48 56 64 +STACKINGRULES + +from const2 %num==0 to STACK +gen clr {autodec,sp} + +from src2 to STACK +gen mov %1,{autodec,sp} + +from regconst2 to STACK +gen mov %1.reg,{autodec,sp} + add {addr_external, %1.off},{regdef2,sp} + +from DBLREG to STACK +gen movf %1,{autodec,sp} + +from FLTREG to STACK +gen movfo %1,{autodec,sp} + +from regind8 to STACK +uses REG +gen move %1.reg,%a + add {addr_external, 8+%1.off},%a + mov {autodec, %a},{autodec,sp} + mov {autodec, %a},{autodec,sp} + mov {autodec, %a},{autodec,sp} + mov {autodec, %a},{autodec,sp} +.DE +.PP +These examples should be self-explanatory, except maybe for the last one. +It is possible inside a stacking-rule to use a register. +Since however the stacking might also take place at a moment +when no registers are free, it is mandatory that for each token +there is one stackingrule that does not use a register. +The code generator uses the first rule possible. +.NH 2 +Coercions +.PP +The next part of the table defines the coercions that are possible +on the defined tokens. +Example for the PDP-11: +.DS +.ta 8 16 24 32 40 48 56 64 +COERCIONS + +from STACK +uses REG +gen mov {autoinc,sp},%a yields %a + +from STACK +uses DBLREG +gen movf {autoinc,sp},%a yields %a + +from STACK +uses REGPAIR +gen mov {autoinc,sp},%a.1 + mov {autoinc,sp},%a.2 yields %a +.DE +These three coercions just deliver a certain type +of register by popping it from the real stack. +.DS +.ta 8 16 24 32 40 48 56 64 +from LOCAL yields {regind2,lb,%1.ind} + +from DLOCAL yields {regind4,lb,%1.ind} + +from REG yields {regconst2, %1, 0} +.DE +These three are zero-cost rewriting rules. +.DS +.ta 8 16 24 32 40 48 56 64 +from regconst2 %1.off==1 +uses reusing %1,REG=%1.reg +gen inc %a yields %a + +from regconst2 +uses reusing %1,REG=%1.reg +gen add {addr_external, %1.off},%a yields %a + +from addr_local +uses REG +gen mov lb,%a + add {const2, %1.ind},%a yields %a +.DE +The last three are three different cases of the coercion +register+constant to register. +Only in the last case is it always necessary to allocate +an extra register, +since arithmetic on the localbase is unthinkable. +.DS +.ta 8 16 24 32 40 48 56 64 +from xsrc2 +uses reusing %1, REG=%1 yields %a + +from longf4 +uses FLTREG=%1 yields %a + +from double8 +uses DBLREG=%1 yields %a + +from src1 +uses REG={const2,0} +gen bisb %1,%a yields %a +.DE +These examples show the coercion of different +tokens to a register of the needed type. +The last one shows the trouble needed on a PDP-11 to +ensure bytes are not sign-extended. +In EM it is defined that the result of a \fBloi\fP\ 1 +instruction is an integer in the range 0..255. +.DS +.ta 8 16 24 32 40 48 56 64 +from REGPAIR yields %1.2 %1.1 + +from regind4 yields {regind2,%1.reg,2+%1.off} + {regind2,%1.reg,%1.off} + +from relative4 yields {relative2,2+%1.off} + {relative2,%1.off} +.DE +The last examples are splitting rules. +.PP +The examples show that +all coercions change one token on the fake stack into one or more others, +possibly generating code. +The STACK token is supposed to be on the fake stack when it is +really empty, and can only be changed into one other token. +.NH 1 +The files mach.h and mach.c +.PP +The table writer must also supply two files containing +machine dependent declarations and C code. +These files are mach.h and mach.c. +.NH 2 +Types in the code generator +.PP +Three different types of integer coexist in the code generator +and their range depends on the machine at hand. +They are defined depending on the Target EM_WSIZE, or TEM_WSIZE, +and TEM_PSIZE. +The type 'int' is used for things like counters that won't require +more than 16 bits precision. +The type 'word' is used among others to assemble datawords and +is of type 'long' if TEM_WSIZE>2. +The type 'full' is used for addresses and is of type 'long' if +TEM_WSIZE>2 or TEM_PSIZE>2. +.PP +In macro and function definitions in later paragraphs implicit typing +will be used for parameters, that is parameters starting with an 's' +will be of type string, and the letters 'i','w','f' will stand for +int, word and full respectively. +.NH 2 +Global variables to work with +.PP +Some global variables are present in the code generator +that can be manipulated by the routines in mach.h and mach.c. +.LP +The declarations are: +.DS L +.ta 20 +FILE *codefile; /* code is emitted on this stream */ +word part_word; /* words to be output are put together here */ +int part_size; /* number of bytes already put in part_word */ +char str[]; /* Last string read in */ +long argval; /* Last int read and kept */ +.DE +.NH 2 +Macros in mach.h +.PP +In the file mach.h a collection of macros is defined that have +to do with formatting of assembly code for the machine at hand. +Some of these macros can of course be left undefined in which case the +macro calls are left in the source and will be treated as +function calls. +These functions can then be defined in \fImach.c\fR. +.PP +The macros to be defined are: +.IP ex_ap(s) 16 +Must print the magic incantations that will mark the symbol \fI\fR +to be exported to other modules. +This is the translation of the EM \fBexa\fP and \fBexp\fP instructions. +.IP in_ap(s) +Same to import the symbol. +Translation of \fBina\fP and \fBinp\fP. +.IP newplb(s) +Must print the definition of procedure label \fIs\fR. +If left undefined the newilb() macro is used instead. +.IP newilb(s) +Must print the definition of instruction label \fIs\fR. +.IP newdlb(s) +Must print the definition of data label \fIs\fR. +.IP dlbdlb(s1,s2) +Must define data label +.I s1 +to be equal to +.I s2 . +.IP newlbss(s,f) +Must declare a piece of memory initialized to BSS_INIT(see below) +of length +.I f +and with label +.I s . +.IP cst_fmt +Format to be used when converting constant arguments of +EM instructions to string. +Argument to be formatted will be 'full'. +.IP off_fmt +Format to be used for integer part of label+constant, +argument will be 'full'. +.IP fmt_ilb(ip,il,s) +Must use the numbers +.I ip +and +.I il +that are a procedure number +and a label number respectively and copy a string to +.I s +that must be unique for that combination. +This procedure is optional, if it is not given ilb_fmt +must be defined as below. +.IP ilb_fmt +Format to be used for creation of unique instruction labels. +Arguments will be a unique procedure number (int) and the label +number (int). +.IP dlb_fmt +Format to be used for printing numeric data labels. +Argument will be 'int'. +.IP hol_fmt +Format to be used for generation of labels for +space generated by a +.B hol +pseudo. +Argument will be 'int'. +.IP hol_off +Format to be used for printing of the address of an element in +.B hol +space. +Arguments will be the offset in the +.B hol +block (word) and the number of the +.B hol +(int). +.IP con_cst(w) +Must generate output that will assemble into one machine word. +.IP con_ilb(s) +Must generate output that will put the address of the instruction label +into the datastream. +.IP con_dlb(s) +Must generate output that will put the address of the data label +into the datastream. +.IP fmt_id(sf,st) +Must take the string in +.I sf +that is a nonnumeric global label, and transform it into a copy made to +.I st +that will not collide with reserved assembler words and system labels. +This procedure is optional, if it is not given the id_first macro is used +as defined below. +.IP id_first +Must be a character. +This is prepended to all nonnumeric global labels if their length +is shorter than the maximum allowed(currently 8) or if they already +start with that character. +This is to avoid conflicts of user labels with system labels. +.IP BSS_INIT +Must be a constant. +This is the value filled in all the words not initialized explicitly. +This is loader and system dependent. +If omitted no initialization is assumed. +.NH 3 +Example mach.h for the PDP-11 +.DS L +.ta 8 16 24 32 40 48 56 +#define ex_ap(y) fprintf(codefile,"\et.globl %s\en",y) +#define in_ap(y) /* nothing */ + +#define newplb(x) fprintf(codefile,"%s:\en",x) +#define newilb(x) fprintf(codefile,"%s:\en",x) +#define newdlb(x) fprintf(codefile,"%s:\en",x) +#define dlbdlb(x,y) fprintf(codefile,"%s=%s\en",x,y) +#define newlbss(l,x) fprintf(codefile,"%s:.=.+%d.\en",l,x); + +#define cst_fmt "$%d." +#define off_fmt "%d." +#define ilb_fmt "I%02x%x" +#define dlb_fmt "_%d" +#define hol_fmt "hol%d" + +#define hol_off "%d.+hol%d" + +#define con_cst(x) fprintf(codefile,"%d.\en",x) +#define con_ilb(x) fprintf(codefile,"%s\en",x) +#define con_dlb(x) fprintf(codefile,"%s\en",x) + +#define id_first '_' +#define BSS_INIT 0 +.DE +.NH 2 +Functions in mach.c +.PP +In mach.c some functions must be supplied, +mostly manipulating data resulting from pseudoinstructions. +The specifications are given here, +implicit typing of parameters as above. +.IP - +con_part(isz,word) +.br +This function must manipulate the globals +part_word and part_size to append the isz bytes +contained in word to the output stream. +If part_word is full, i.e. part_size==TEM_WSIZE +the function part_flush() may be called to empty the buffer. +This is the function that must go through the trouble of +doing byte order in words correct. +.IP - +con_mult(w_size) +.br +This function must take the string str[] and create an integer +from the string of size w_size and generate code to assemble global +data for that integer. +Only the sizes for which arithmetic is implemented need be +handled, +so if you didn't implement 200-byte integer division +you don't have to implement 200-byte integer global data. +Here one must take care of word order in long integers. +.IP - +con_float() +.br +This function must generate code to assemble a floating +point number of which the size is contained in argval +and the ASCII representation in str[]. +.IP - +prolog(f_nlocals) +.br +This function is called at the start of every procedure. +Function prolog code must be generated, +and room made for local variables for a total of f_nlocals bytes. +.IP - +mes(w_mesno) +.br +This function is called when a +.B mes +pseudo is seen that is not handled by the machine independent part. +Example below shows all you probably have to know about that. +.IP - +segname[] +.br +This is not a function, +but an array of four strings. +These strings are put out whenever the code generator +switches segments. +Segments are SEGTXT, SEGCON, SEGROM and SEGBSS in that order. +.PP +If register variables are used in a table, the program +.I cgg +will define the word REGVARS during compilation of the sources. +So the following functions described here should be bracketed +by #ifdef REGVARS and #endif. +.IP - +regscore(off,size,typ,freq,totyp) long off; +.br +This function should assign a score to a register variable, +the score should preferably be the estimated number of bytes +gained when it is put in a register. +Off and size are the offset and size of the variable, +typ is the type, that is reg_any, reg_pointer, reg_loop or reg_float. +Freq is the count of static occurrences, and totyp +is the type of the register it is planned to go into. +.br +Keep in mind that the gain should be net, that is the cost for +register save/restore sequences and the cost of initialisation +in the case of parameters should already be included. +.IP - +i_regsave() +.br +This function is called at the start of a procedure, just before +register saves are done. +It can be used to initialise some variables if needed. +.IP - +f_regsave() +.br +This function is called at end of the register save sequence. +It can be used to do the real saving if multiple register move +instructions are available. +.IP - +regsave(regstr,off,size) char *regstr; long off; +.br +Should either do the real saving or set up a table to have +it done by f_regsave. +Note that initialisation of parameters should also be done, +or planned here. +.IP - +regreturn() +.br +Should restore saved registers and return. +The function result is already in the function return area by now. +.NH 3 +Example mach.c for the PDP-11 +.PP +As an example of the sort of code expected, +the mach.c for the PDP-11 is presented here. +.DS L +.ta 8 16 24 32 40 48 56 64 +/* + * machine dependent back end routines for the PDP-11 + */ + +con_part(sz,w) register sz; word w; { + + while (part_size % sz) + part_size++; + if (part_size == 2) + part_flush(); + if (sz == 1) { + w &= 0xFF; + if (part_size) + w <<= 8; + part_word |= w; + } else { + assert(sz == 2); + part_word = w; + } + part_size += sz; +} + +con_mult(sz) word sz; { + long l; + + if (sz != 4) + fatal("bad icon/ucon size"); + l = atol(str); + fprintf(codefile,"\et%o;%o\en",(int)(l>>16),(int)l); +} + +con_float() { + double f; + register short *p,i; + + /* + * This code is correct only when the code generator is + * run on a PDP-11 or VAX-11 since it assumes native + * floating point format is PDP-11 format. + */ + + if (argval != 4 && argval != 8) + fatal("bad fcon size"); + f = atof(str); + p = (short *) &f; + i = *p++; + if (argval == 8) { + fprintf(codefile,"\et%o;%o;",i,*p++); + i = *p++; + } + fprintf(codefile,"\et%o;%o\en",i,*p++); +} + +#ifdef REGVARS + +char Rstring[10]; +full lbytes; +struct regadm { + char *ra_str; + long ra_off; +} regadm[2]; +int n_regvars; + +regscore(off,size,typ,score,totyp) long off; { + + /* + * This function is full of magic constants. + * They are a result of experimentation. + */ + + if (size != 2) + return(-1); + score -= 1; /* allow for save/restore */ + if (off>=0) + score -= 2; + if (typ==reg_pointer) + score *= 17; + else if (typ==reg_loop) + score = 10*score+50; /* Guestimate */ + else + score *= 10; + return(score); /* 10 * estimated # of words of profit */ +} + +i_regsave() { + + Rstring[0] = 0; + n_regvars=0; +} + +f_regsave() { + register i; + + if (n_regvars==0 || lbytes==0) { + fprintf(codefile,"mov r5,-(sp)\enmov sp,r5\en"); + if (lbytes == 2) + fprintf(codefile,"tst -(sp)\en"); + else if (lbytes!=0) + fprintf(codefile,"sub $0%o,sp\en",lbytes); + for (i=0;i6) { + fprintf(codefile,"mov $0%o,r0\en",lbytes); + fprintf(codefile,"jsr r5,PR%s\en",Rstring); + } else { + fprintf(codefile,"jsr r5,PR%d%s\en",lbytes,Rstring); + } + } + for (i=0;i=0) + fprintf(codefile,"mov 0%lo(r5),%s\en",regadm[i].ra_off, + regadm[i].ra_str); +} + +regsave(regstr,off,size) char *regstr; long off; { + + fprintf(codefile,"/ Local %ld into %s\en",off,regstr); + strcat(Rstring,regstr); + regadm[n_regvars].ra_str = regstr; + regadm[n_regvars].ra_off = off; + n_regvars++; +} + +regreturn() { + + fprintf(codefile,"jmp RT%s\en",Rstring); +} + +#endif + +prolog(nlocals) full nlocals; { + +#ifndef REGVARS + fprintf(codefile,"mov r5,-(sp)\enmov sp,r5\en"); + if (nlocals == 0) + return; + if (nlocals == 2) + fprintf(codefile,"tst -(sp)\en"); + else + fprintf(codefile,"sub $0%o,sp\en",nlocals); +#else + lbytes = nlocals; +#endif +} + +mes(type) word type; { + int argt ; + + switch ( (int)type ) { + case ms_ext : + for (;;) { + switch ( argt=getarg( + ptyp(sp_cend)|ptyp(sp_pnam)|sym_ptyp) ) { + case sp_cend : + return ; + default: + strarg(argt) ; + fprintf(codefile,".globl %s\en",argstr) ; + break ; + } + } + default : + while ( getarg(any_ptyp) != sp_cend ) ; + break ; + } +} + +char *segname[] = { + ".text", /* SEGTXT */ + ".data", /* SEGCON */ + ".data", /* SEGROM */ + ".bss" /* SEGBSS */ +}; +.DE +.NH 1 +Internal workings of the code generator. +.NH 2 +Description of tables.c and tables.h contents +.PP +In this section the intermediate files will be described +that are produced by +.I cgg +and compiled with machine independent code to produce a code generator. +.NH 3 +Tables.c +.PP +Tables.c contains a large number of initialized array's of all sorts. +Description of each follows: +.br +.in 1i +.ti -0.5i +byte coderules[] +.br +Pseudo code interpreted by the code generator. +Always starts with some opcode followed by operands depending +on the opcode. +Some of the opcodes have an argument encoded in the upper three +bits of the opcode byte. +Integers in this table are between 0 and 32767 and have a one byte +encoding if between 0 and 127. +.ti -0.5i +char wrd_fmt[] +.br +The format used for output of words. +.ti -0.5i +char stregclass[] +.br +Number of computed static register class per register. +Two registers are in the same class if they have the same properties +and don't share a common subregister. +.ti -0.5i +struct reginfo machregs[] +.br +Info per register. +Initialized with representation string, size, +members of the register and set of registers affected when this +one is changed. +Also contains room for run time information, +like contents and reference count. +.ti -0.5i +tkdef_t tokens[] +.br +Information per tokentype. +Initialized with size, cost, type of operands and formatstring. +.ti -0.5i +node_t enodes[] +.br +List of triples representing expressions for the code generator. +.ti -0.5i +string codestrings[] +.br +List of strings. +All strings are put in a list and checked for duplication, +so only one copy per string will reside here. +.ti -0.5i +set_t machsets[] +.br +List of token expression sets. +Bit 0 of the set is used for the SCRATCH property of registers, +bit 1 upto NREG are for the corresponding registers +and bit NREG+1 upto the end are for corresponding tokens. +.ti -0.5i +inst_t tokeninstances[] +.br +List of descriptions for building tokens. +Contains type of rule for building one, +plus operands depending on the type. +.ti -0.5i +move_t moves[] +.br +List of move rules. +Contains token expressions for source and destination +plus index for code rule. +.ti -0.5i +test_t tests[] +.br +List of test rules. +Contains token expressions for source +plus index for code rule. +.ti -0.5i +byte pattern[] +.br +EM patterns. +This is structured internally as chains of patterns, +each chain pointed at by pathash[]. +After each pattern the list of possible code rules is given. +.ti -0.5i +int pathash[256] +.br +Indices into pattern[] for all patterns with a certain low order +byte of the hashing function. +.ti -0.5i +c1_t c1coercs[] +.br +List of rules to stack tokens. +Contains token expressions, +register needed, +cost +and code rule. +.ti -0.5i +c2_t c2coercs[] +.br +List of splitting coercions. +Token expressions, +split factor, +replacements +and code rule. +.ti -0.5i +c3_t c3coercs[] +.br +List of one to one coercions. +Token expressions, +register needed, +replacement +and code rule. +.ti -0.5i +struct reginfo **reglist[] +.br +List of lists of pointers to register information. +For every property the list is here +to find the registers corresponding to it. +.in 0 +.NH 3 +tables.h +.PP +In tables.h various derived constants for the tables are +given. +They are then used to determine array sizes in the actual code generator, +plus loop termination in some cases. +.NH 2 +Other important data structures +.PP +During code generation some other data structures are used +and here is a short description of some of the important ones. +.PP +Tokens are kept in the code generator as a struct consisting of +one integer +.I t_token +which is -1 if the token is a register, +and the number of the token otherwise, +plus an array of +.I TOKENSIZE +unions +.I t_att +of which the first is the register number in case of a register. +.PP +The fakestack is an array of these tokens, +there is a global variable +.I stackheight . +.PP +The results of expressions are kept in a struct +.I result +with elements +.I e_typ , +giving the type of the expression: +.I EV_INT , +.I EV_REG +or +.I EV_ADDR , +and a union +.I e_v +which contains the real result. +.NH 2 +A tour through the sources +.NH 3 +codegen.c +.PP +The file codegen.c contains one large function consisting +of one giant switch statement. +It is the interpreter for the code generator pseudo code +as contained in code rules[]. +This function can call itself recursively when doing look ahead. +Arguments are: +.IP codep 10 +Pointer into code rules, pseudo program counter. +.IP ply +Number of EM pattern look ahead allowed. +.IP toplevel +Boolean telling whether this is the toplevel codegen() or +a deeper incarnation. +.IP costlimit +A cutoff value to limit searches. +If the cost crosses costlimit the incarnation can terminate. +.IP forced +A register number if nonzero. +This is used inside coercions to force the allocate() call to allocate +a register determined by earlier look ahead. +.PP +The instructions inplemented in the switch: +.NH 4 +DO_DLINE +.PP +Prints debugging information if the code generator runs in debug mode. +This information is only generated if +.I cgg +was called with the -d flag. +.NH 4 +DO_NEXTEM +.PP +Matches the next EM pattern and does look ahead if necessary to find the best +code rule associated with this pattern. +Heuristics are used to determine best code rule when possible. +This is done by calling the distance() function. +It can also handle the procedure mechanism. +.NH 4 +DO_COERC +.PP +This sets the code generator in the state to do a from stack coercion. +.NH 4 +DO_XMATCH +.PP +This is done when a match no longer has to be checked. +Used when the nocoercions: trick is used in the table. +.NH 4 +DO_MATCH +.PP +This is the big one inside this function. +It has the task to transform the contents of the current +fake stack to match the pattern given after it. +.PP +Since the code generator does not know combining coercions, +i.e. there is no way to make a big token out of two smaller ones, +the first thing done is to stack every token that is too small. +After that all tokens too big are split if possible to the right size. +.PP +Next the coercions are sought that would transform tokens in place to +the right one, plus the coercions that would pop tokens of the stack. +Each of those might need a register, so a list of registers is generated +and at the end of looking for coercions the function +.I tuples() +is called to generate the list of all possible \fIn\fP-tuples, +where +.I n +equals the number of registers needed. +.PP +Look ahead is now performed if the number of tuples is greater than one. +If no possibility is found within the costlimit, +the fake stack is made smaller by pushing the bottom token, +and this process is repeated until either a way is found or +the fake stack is completely empty and there is still no way +to make the match. +.PP +If there is a way the corresponding coercions are executed +and the code is finished. +.NH 4 +DO_REMOVE +.PP +Here the kills clause is executed, all tokens matched by the +token expression plus boolean expression are pushed. +In the current implementation there is no attempt to move those +tokens to registers, but that is a possible future extension. +.NH 4 +DO_DEALLOCATE +.PP +This one temporarily decrements by one the reference count of all registers +contained in the token given as argument. +.NH 4 +DO_REALLOCATE +.PP +Here all temporary deallocates are made undone. +.NH 4 +DO_ALLOCATE +.PP +This is the part that allocates a register and decides which one to use. +If the +.I forced +argument was given its task is simple, +otherwise some work must be done. +First the list of possible registers is scanned, +all free registers noted and it is noted whether any of those +registers is already +containing the initialization. +If no registers are available some fakestack token is stacked and the +process is repeated. +.PP +After that if an exact match was found, +the list of registers is reduced to one register matching exactly +out of every register class. +Now look ahead is performed if necessary and the register chosen. +If an initialization was given the corresponding move is performed, +otherwise the register is marked empty. +.NH 4 +DO_INSTR +.PP +This prints an instruction and it's operands. +Only done on toplevel. +.NH 4 +DO_MOVE +.PP +Calls the move() function in the code generator to implement the move +instruction in the table. +.NH 4 +DO_TEST +.PP +Calls the test() function in the code generator to implement the test +instruction in the table. +.NH 4 +DO_ERASE +.PP +Marks the register that is its argument as empty. +.NH 4 +DO_TOKREPLACE +.PP +This is the token replacement part. +It is also called if there is no token replacement because it has +some other functions as well. +.PP +First the tokens that will be pushed on the fake stack are computed +and stored in a temporary array. +Then the tokens that were matched in this rule are popped +and their embedded registers have their reference count +decremented. +After that the replacement tokens are pushed. +.PP +Finally all registers allocated in this rule have their reference count +decremented. +If they were not pushed on the fake stack they will be available again +in the next code rule. +.NH 4 +DO_EMREPLACE +.PP +Places replacement EM instructions back into the instruction stream. +.NH 4 +DO_COST +.PP +Accounts for cost as given in the code rule. +.NH 4 +DO_RETURN +.PP +Returns from this level of codegen(). +Is used at the end of coercions, +move rules etc.. +.NH 3 +compute.c +.PP +This module computes the various expressions as given +in the enodes[] array. +Nothing very special happens here, +it is just a recursive function computing leaves +of expressions and applying the operator. +.NH 3 +equiv.c +.PP +In this module the tuples() function is implemented. +It is given the number of registers needed and +a list of register lists and it constructs a list of tuples +where the \fIn\fP'th register comes from the \fIn\fP'th list. +Before the list is constructed however +the dynamic register classes are computed. +Two registers are in the same dynamic class if they are in the +same static class and their contents is the same. +.PP +After that the permute() recursive function is called to +generate the list of tuples. +After construction a generated tuple is added to the list +if it is not already pairwise in the same class +or if the register relations are not the same, +i.e. if the first and second register share a common +subregister in one tuple and not in the other they are considered different. +.NH 3 +fillem.c +.PP +This is the routine that does the reading of EM instructions +and the handling of pseudos. +The mach.c module provided by the table writer is included +at the end of this module. +The routine fillemlines() is called by nextem() at toplevel +to make sure there are enough instruction to match. +It fills the EM instruction buffer up to 5 places from the end to +keep room for EM replacement instructions, +or up to a pseudo. +.PP +The dopseudo() function performs the function of the pseudo last +encountered. +If the pseudo is a +.B rom +the corresponding label is saved with the contents of the +.B rom +to be available to the code generator later. +The rest of the routines are small service routines for either +input or data output. +.NH 3 +gencode.c +.PP +This module contains routines called by codegen() to generate the real +code to the codefile. +The function genstr() gets a string as argument and copies it to codefile. +The prtoken() function interprets the tokenformat as given in +the tokens[] array. +.NH 3 +glosym.c +.PP +This module maintains a list of global symbols that have a +.B rom +pseudo associated. +There are functions to enter a symbol and to find a symbol. +.NH 3 +main.c +.PP +Main routine of the code generator. +Processes arguments and flags. +Flags available are: +.IP -d +Sets debug mode if the code generator was not compiled with +the NDEBUG macro defined. +The flag can be followed by a digit specifying the amount of debugging +wanted, +and by @labelname giving the start of debugging. +Debug mode gives very long output on stderr indicating +all steps of the code generation process including nesting +of the codegen() function. +.IP -p\fIn\fP +Sets the look ahead depth to +.I n , +the +.I p +stands for ply, +a well known word in chess playing programs. +.IP -w\fIn\fP +Sets the weight percentage for size in the cost function to +.I n +percent. +Uses Euclides algorithm to simplify rationals. +.NH 3 +move.c +.PP +Function to implement the move instruction in the tables, +register initialization and the test instruction and associated bookkeeping. +First tests are made to try to prevent the move from really happening. +After that, if there is an after that, +the move rule is found and the code executed. +.NH 3 +nextem.c +.PP +The entry point of this module is nextem(). +It hashes the next three EM instructions, +and uses the low order byte of the hash +as an index into the array pathash[], +to find a chain of patterns in the array +pattern[], +that are all tried for a match. +.PP +The function trypat() does most of the work +checking patterns. +When a pattern is found to match all instructions +the operands of the instruction are placed into the dollar[] array. +Then the boolean expression is tried. +If it matches the function can return, +leaving the operands still in the dollar[] array, +so later in the code rule they can still be used. +.NH 3 +reg.c +.PP +Collection of routines to handle registers. +Reference count routines are here, +chrefcount() and getrefcount(), +plus routines to erase a single register or all of them, +erasereg() and cleanregs(). +.PP +If NDEBUG hasn't been defined, here is also the routine that checks +if the reference count kept with the register information is in +agreement with the number of times it occurs on the fake stack. +.NH 3 +salloc.c +.PP +Module for string allocation and garbage collection. +Contains entry points myalloc(), +a routine calling malloc() and checking whether room is left, +myfree(), just free(), +popstr() a function called from state.c to free all strings +made since the last saved status. +Furthermore there is salloc() which has the size of the string as parameter +and returns a pointer to the allocated space, +while keeping a copy of the pointer for garbage allocation purposes. +.PP +The function garbage_collect is called from codegen() at toplevel +every now and then, +and checks all places where strings may reside to mark strings +as being in use. +Strings not in use are returned to the pool of free space. +.NH 3 +state.c +.PP +Set of routines called to save current status and +restore a previous saved state. +.NH 3 +subr.c +.PP +Random set of leftover routines. +.NH 4 +match +.PP +Computes whether a certain token matches a certain token expression. +Just computes a bitnumber according to the algorithm explained with +machsets[], +and tests the bit and the boolean expression if it is there. +.NH 4 +instance,cinstance +.PP +These two functions compute a token from a description. +They differ very slight, cinstance() is used to compute +the result of a coercion in a certain context +and therefore has more arguments, which it uses instead of +the global information instance() works on. +.NH 4 +eqtoken +.PP +eqtoken computes whether two tokens can be considered identical. +Used to check register contents during moves mainly. +.NH 4 +distance +.PP +This is the heuristic function that computes a distance from +the current fake stack contents to the token pattern in the table. +It likes exact matches most, then matches where at least the sizes are correct +and if the sizes are not correct it likes too large sizes more than too +small, since splitting a token is easier than combining one. +.NH 4 +split +.PP +This function tries to find a splitting coercion +and executes it immediately when found. +The fake stack is shuffled thoroughly when this happens, +so pieces below the token that must be split are saved first. +.NH 4 +docoerc +.PP +This function executes a coercion that was found. +The same shuffling is done, so the top of the stack is again saved. +.NH 4 +stackupto +.PP +This function gets a pointer into the fake stack and must stack +every token including the one pointed at up to the bottom of the fake stack. +The first stacking rule possible is used, +so rules using registers must come first. +.NH 4 +findcoerc +.PP +Looks for a one to one coercion, if found it returns a pointer +to it and leaves a list of possible registers to use in the global +variable curreglist. +This is used by codegen(). +.NH 3 +var.c +.PP +Global variables used by more than one module. +External definitions are in extern.h.