/* RIC (Russell Intermediate Code) Op codes */ /* The first group has a single string argument */ #define BR 1 /* branch unconditionally */ #define BRT 2 /* branch if value in TL is true. */ #define BRF 3 /* branch if value in TL is false. */ #define CLL 4 /* call routine with given label */ /* Needs to do any cleanup (e.g. stack pops) */ /* necessitated by the preceding ARG instr that */ /* passed the activation record pointer. */ #define LBL 5 /* attach the given label to the next instruction */ #define EXT 6 /* declare the label to be external */ /* All labels that need to be known to the */ /* outside are marked in this way. All labels */ /* not beginning with an 'L' are intended to be */ /* unique, and thus may be made globally visible. */ #define LBA 7 /* supply a label argument to immediately */ /* following instruction */ #define BFN 9 /* begin named function */ /* function temporaries may be reserved on the */ /* stack at this point */ /* FP should be set to point to one below return */ /* address. AR should be set to first (and only) */ /* argument. Other locations are set explicitly. */ /* Locations (incl. AR) are implicitly saved */ /* during a procedure call. */ #define TFB 10 /* trace function entry */ #define TFE 11 /* trace function exit */ #define PRO 12 /* record function entry for profiling */ #define ADT 13 /* character string data. A label for the */ /* location of the data may be supplied by a */ /* preceding LBA instruction OBSOLETE */ #define ERR 14 /* branch to error routine with indicated label */ /* Arguments may have been pushed. */ #define BSF 15 /* begin short function. Identical to BFN, */ /* except that AR should neither be set, nor does */ /* the old value need to be saved. */ /* Arguments to BSF functions are passed */ /* individually using ARG, rather than passing a */ /* a single argument containing the activation */ /* record. If the name of the function does not */ /* start with Ffn, the generated function must be */ /* C callable. (Typically it will be, in any */ /* case.) */ #define LBR 16 /* Attach a symbolic name to the virtual register */ /* declared by the immediately following DCL */ #define DDT 17 /* Generate double precision floating point data. */ /* May be labelled with an LBA instruction. */ /* The argument is actually a string representing */ /* representing a floating point constant. */ /* Such data is read-only. */ #define FDT 18 /* Analogous to FDT, but for single precision */ /* constants. */ #define MAX_LABEL_OP 19 /* The remainder has up to 3 integer arguments. Unless otherwise */ /* specified, they refer to temporary locations (virtual */ /* registers). An offset is a signed integer value. */ /* An object is considered accessible only if there is an */ /* accessible pointer to its beginning. */ /* Pointers in any active temporary or on the stack are accessible */ /* args */ #define DCL 20 /* loc type -- declare temporary location */ /* (i.e. virtual register) */ /* The following types are allowed: */ # define DCL_ADDR 1 # define DCL_INT 2 /* 32 bit integer */ # define DCL_FLOAT 3 # define DCL_DBL_FLOAT 4 /* DCL_ADDR and DCL_INT, are assumed to be the */ /* same size. The distinction is only a hint */ /* to the machine code generator. */ /* DCL_FLOAT is unlikely to be used in the */ /* near future. */ /* In the following, size is a location: */ #define UDC 21 /* loc -- free temporary location */ /* If applied to a predefined location, this */ /* constitutes a declaration that the value it */ /* contains is dead at this point. */ /* Duplicate UDC's for the same location may */ /* occasionally appear. All but the first can be */ /* safely ignored. */ #define ALH 22 /* size loc -- loc := ptr to new heap object */ #define GAR 23 /* i loc -- Get the ith argument (passed with */ /* ARG) into loc */ #define ALS 24 /* size -- allocate new stack object containing */ /* pointer data */ /* Both ALS and ALH are assumed to clear the */ /* allocated space. This is necessary only for */ /* garbage collection, and may frequently be */ /* eliminated by an optimizer */ #define LDI 25 /* index offset loc -- loc := index[offset] */ #define STI 26 /* index offset loc -- index[offset] := loc */ #define CLI 27 /* index offset -- jsr index[offset] */ /* Needs cleanup similar to CLL */ #define LDN 28 /* signed_value loc -- loc := signed_value */ #define RTN 29 /* -- return from function w/ value at loc RL */ #define LDL 30 /* loc -- load value of label provided */ /* by immediately preceding LBA instruction */ /* The label must have been previously defined. */ #define MOV 31 /* loc1 loc2 -- loc2 := loc1 */ #define TAR 32 /* arg put_fn -- save passed argument for trace */ #define PSH 33 /* loc -- push contents of loc onto stack */ /* equivalent to ALS 1; STI SP, 0, loc */ /* #define MVI 34 loc1 loc2 -- *loc2++ := *loc1++ */ #define ADP 35 /* loc1 offset loc2 -- loc2 := &loc1[offset] */ /* Add a (word) offset to a pointer value */ /* Unlike LDI and STI, offset here is a location */ #define CLC 36 /* nargs -- Call to a non-Russell routine or a BSF */ /* style Russell routine. Nargs */ /* is an integer. The routine name is given by */ /* a preceding LBA instruction. The arguments */ /* are supplied in reverse order by prior */ /* ARG instructions. */ #define ALA 37 /* size loc -- loc := ptr to new atomic heap */ /* object. Object should never contain pointer */ /* data. */ #define HINT 38 /* kind arg1 arg2 -- Code generator hint. */ #define OPT 1 /* n -- The next n instructions perform */ /* runtime checks, and may be discarded at */ /* suitably high levels of optimization. */ #define NP 2 /* The following ARG instruction refers to a */ /* pointer to an object that may be on the */ /* heap. The called procedure does not */ /* preserve references to this object. Thus */ /* the ARG instruction may be disregarded for */ /* purposes of static ref. counting */ #define AL 3 /* size atom -- (size is a constant). The */ /* following procedure call (CLC, CLL, CLI) */ /* returns a new object of the indicated */ /* size. If size is != 0 the object may */ /* be deallocated by attaching it directly */ /* to the free list of the indicated size. */ /* If size is = 0, the size of the object */ /* is unknown, and the object could be */ /* statically allocated; rfree should be */ /* called to release it. */ /* Atom is either 0 or 1, and */ /* specifies whether the allocated object is */ /* atomic, and thus should be returned to the */ /* atomic object free list. */ #define DEA 4 /* loc size -- Indicates that */ /* the object pointed to by loc may be freed. */ /* This type of hint is inserted by the */ /* static reference counter for the benefit */ /* of the code generator. */ /* A negative size indicates the object is */ /* atomic; a positive size means composite, */ /* and a 0 size means unknown. */ /* Size is a constant, not a location. */ #define NSC 5 /* The following CLL or CLI instruction */ /* does not result in a saved continuation. */ /* Thus the reference counts of objects */ /* pointed to only by virtual registers */ /* is unchanged across the call. */ /* (This is always the case for CLC calls.) */ #define STSZ 6 /* loc -- The following STI instruction */ /* should store the size of loc if it's known */ /* that loc has exactly one reference, and 0 */ /* otherwise. Loc contains a pointer to a */ /* composite object. */ #define PT 7 /* Analogous to NP, but a single reference is */ /* preserved (passed through) as the function */ /* result. */ #define DEAD 8 /* loc -- The value in loc will not be used */ /* again. (The location itself may be reused.*/ /* Thus UDC would be inappropriate.) */ #define GFU 9 /* GF is about to be updated, or AR is about */ /* to be updated inside a BSF function. */ /* Such a hint always precedes the first such */ /* update in a routine. */ #define LIVE 10 /* loc -- The value in loc should be viewed */ /* as live up to this point. Such a hint is */ /* included whenever a location (other than */ /* GF and AR) could appear to be dead, but a */ /* derived pointer is not. A value in such a */ /* location needs to be retained, so as not */ /* to confuse the garbage collector. */ /* We do not generate such HINTs if it is */ /* known that the value in question is also */ /* stored in an accessible memory location. */ /* Similarly, we do not generate such a HINT */ /* if the derived pointer is only implicit */ /* in an LDI or STI instruction. */ #define ET 11 /* Defines the type of the following item */ /* declared by an EXT. All EXTs that do not */ /* refer to functions are preceded by such a */ /* hint. The second argument is a type */ /* specifier, as for the DCL instruction. */ #define ONS 12 /* The following allocation instruction may */ /* be implemented as a stack allocation. */ /* This is used only if the comipler is not */ /* allowed to generate ALS instructions (-f */ /* or -F flag). Each allocation instruction */ /* preceded by a HINT ONS is eventually */ /* followed by a corresponding HINT ONS; */ /* HINT DEA sequence. All such pairs are */ /* properly nested. There are no branches */ /* into or our of such a pair. */ #define ARG 39 /* n loc -- Pass loc as the nth argument to CLC */ /* ARG instructions always occur in reverse order, */ /* with highest numbered argument first. The */ /* lowest numbered argument is numbered 1. */ /* Also used to pass the activation record pointer */ /* through CLL and CLI calls. */ /* MAY reserve space on the stack. */ /* Integer operations */ #define ADI 40 /* op1 op2 result -- result := (int)op1 + (int)op2 */ #define SBI 41 /* op1 op2 result -- result := (int)op1 - (int)op2 */ #define MLI 42 /* op1 op2 result -- result := (int)op1 * (int)op2 */ #define DVI 43 /* op1 op2 result -- result := (int)op1 / (int)op2 */ #define NGI 44 /* op result -- result := -op */ #define IDT 45 /* data -- generate integer data. May be labeled */ /* with an LBA */ /* Consecutive IDTs w/o intervening LBAs generate */ /* consecutive data. */ /* Data is read-only. */ #define EQI 46 /* op1 op2 result -- result := (int)op1 = (int)op2 */ #define LTI 47 /* op1 op2 result -- result := (int)op1 < (int)op2 */ #define GTI 48 /* op1 op2 result -- result := (int)op1 > (int)op2 */ #define NEI 49 /* op1 op2 result -- result := (int)op1 != (int)op2 */ #define LEI 50 /* op1 op2 result -- result := (int)op1 <= (int)op2 */ #define GEI 51 /* op1 op2 result -- result := (int)op1 >= (int)op2 */ #define SHI 52 /* op1 op2 result -- result := arith_shift(op1, op2) */ #define ABI 53 /* op1 result -- result := abs(op1) */ /* Boolean operations */ #define TRU 60 /* loc -- load the constant true into the */ /* indicated location. */ #define FLS 61 /* loc -- load the constant false into the */ /* indicated location. */ /* The following instructions are assumed to work on */ /* both Booleans and bit vectors: */ #define AND 62 /* op1 op2 result -- result := op1 & op2 */ #define OR 63 /* op1 op2 result -- result := op1 | op2 */ /* The following applies only to Booleans: */ #define NOT 64 /* op result -- result := ~ op */ /* String operations */ #define LDS 70 /* loc -- put a pointer to the string given by the */ /* preceding LBA instruction into loc */ #define LDC 71 /* index offset loc -- loc := index[offset] */ /* Differs from LDI in that offset is a virtual */ /* register (location) and it is a BYTE rather than */ /* word displacement from index. Used to access */ /* individual characters in a string. */ /* Operations on single precision floating point numbers */ #define ADF 80 /* op1 op2 result -- result := (float)op1 + (float)op2 */ #define SBF 81 /* op1 op2 result -- result := (float)op1 - (float)op2 */ #define MLF 82 /* op1 op2 result -- result := (float)op1 * (float)op2 */ #define DVF 83 /* op1 op2 result -- result := (float)op1 / (float)op2 */ #define NGF 84 /* op result -- result := - (float) op */ #define EXF 85 /* op1 result -- result := (int) x s.t. */ /* 2 **(x-1) <= op1 < 2**x */ #define EQF 86 /* op1 op2 result -- result := (float)op1 = (float)op2 */ #define LTF 87 /* op1 op2 result -- result := (float)op1 < (float)op2 */ #define GTF 88 /* op1 op2 result -- result := (float)op1 > (float)op2 */ #define NEF 89 /* op1 op2 result -- result := (float)op1 != (float)op2 */ #define LEF 90 /* op1 op2 result -- result := (float)op1 <= (float)op2 */ #define GEF 91 /* op1 op2 result -- result := (float)op1 >= (float)op2 */ #define SHF 92 /* op1 op2 result -- result := (float)op1 * 2** (int)op2 */ #define N_OP_CODES 100 /* predefined locations */ #define AR 1 /* activation record pointer */ #define SP 2 /* stack pointer */ #define GF 3 /* pointer to global act. rec. */ /* explicitly saved and restored by */ /* intermediate code if it is updated. */ /* Thus it can easily be assigned to a */ /* fixed register. */ #define UN 4 /* location containing "undefined" value */ #define SK 5 /* value sink, nothing comes out ... */ /* An instruction using SK as */ /* destination or an STI SK,... is a */ /* noop */ #define RL 6 /* location for function result */ /* capable of holding max size object */ #define RS 0x30000000 /* result of operation. In-line code only */ /* Can't be legitimate operand to anything */ /* but LDN */ #define TL 8 /* Location tested in conditional branches */ /* Dead after first reference. */ #define C0 10 /* always 0 */ #define C1 11 /* always 1 */ #define C2 12 /* always 2 */ #define C3 13 /* always 3 */ #define C4 14 /* always 4 */ /* T1 and T2 are short term temporaries. They should be */ /* used only in fixed code sequences, not involving */ /* arbitrary embedded code. T1 is mapped to the same */ /* location as RL, and may thus conflict with RS in */ /* inline code sequences. T2 will never be specified as */ /* the result location for an inline code sequence. */ /* T1 is assumed to be predeclared. T2 is not treated */ /* specially by the final code generator. */ /* Since T1 and RL are the same, and will presumably be */ /* mapped to the location used for function results, we */ /* assume that T1 may be clobbered by ALA and ALH. */ #define T1 RL #define T2 16 /* Note: All general locations are expected to be saved and */ /* restored on procedure call. */ #define FIRST_AVAIL_LOC 20 /* Activation record layout (all parts optional): * * 0: static link * 1: 1st arg * ... * locals */ #define AR_SL 0 /* * Function object layout: * * 0: size * 1: ep * 2: ip */ #define FO_SIZE 0 #define FO_EP 1 #define FO_IP 2