ORCA-C/CGI.Comments
Stephen Heumann daff1754b2 Make volatile loads from IO/softswitches access exactly the byte(s) specified.
Previously, one-byte loads were typically done by reading a 16-bit value and then masking off the upper 8 bits. This is a problem when accessing softswitches or slot IO locations, because reading the subsequent byte may have some undesired effect. Now, ORCA/C will do an 8-bit read for such cases, if the volatile qualifier is used.

There were also a couple optimizations that could occasionally result in not all the bytes of a larger value actually being read. These are now disabled for volatile loads that may access softswitches or IO.

These changes should make ORCA/C more suitable for writing low-level software like device drivers.
2022-05-23 21:10:29 -05:00

854 lines
54 KiB
Plaintext

{-- Misc. pcodes -----------------------------------------------}
{ }
{ dc_cns - generate a constant value }
{ }
{ GenL1(dc_cns, lval, count); }
{ GenQ1(dc_cns, qval, count); }
{ GenR1t(dc_cns, rval, count, type); }
{ Gen2t(dc_cns, ival, count, type); }
{ GenS(dc_cns, sptr); }
{ }
{ Creates COUNT occurrences of the constant lval, qval, rval }
{ or ival, based on the type. In Gen2t can accept byte or }
{ word types. In the case of GenS, the operand is a string }
{ constant, and no repeat count is allowed. }
{ }
{ }
{ dc_glb - generate global label }
{ }
{ Gen2Name(dc_glb, r, q, lab) }
{ }
{ Creates a global label in the current segment with the name }
{ LAB^. If Q is 1, the label is marked as private to the }
{ current segment, otherwise it is marked as public. R bytes }
{ of space are reserved. }
{ }
{ }
{ dc_dst - generate global storage }
{ }
{ Gen1(dc_dst, q) }
{ }
{ Creates q bytes of storage (initialized to 0) at the }
{ current location. }
{ }
{ }
{ pc_lnm - line number }
{ }
{ Gen2Name(pc_lnm, lc, flag, nil) }
{ Gen2Name(pc_lnm, lc, flag, pointer(filename)) }
{ }
{ Sets the current line number for the traceback facility and }
{ debugger. This p-code should only be generated after the }
{ pc_ent and pc_nam (if any), and should not be generated }
{ outside of a subroutine. Lc is the line number, while flag }
{ indicates the type of debugging action on this line: }
{ }
{ 0 - step/trace }
{ 1 - break point }
{ 2 - auto-go }
{ }
{ If filename is not nil, it is a pointer to a GS/OS output }
{ string giving the source file name. This is used to change }
{ the file name within a function that spans multiple files. }
{ }
{ }
{ pc_mov - move memory }
{ }
{ Gen2(pc_mov, banks, bytes) }
{ }
{ The top of stack contains a source address, and TOS-1 has a }
{ destination address. The destination address is removed, }
{ and BYTES bytes are moved from the source to the }
{ destination. BANKS is the number of full banks to move; it }
{ is used when 64K or more must be moved. The memory areas }
{ must not overlap. }
{ }
{ }
{ pc_nam - subroutine name }
{ }
{ GenS(pc_nam, str) }
{ }
{ Sets the subroutine name for the traceback facility, }
{ debugger, and profiler. Str is a pointer to the subroutine }
{ name. The following global variables should be set to }
{ appropriate values when this p-code is used: }
{ }
{ debugFlag - are we generating debug code? }
{ profileFlag - are we profiling? }
{ traceBack - are we doing tracebacks? }
{ debugSourceFileGS - current source file name }
{ }
{ }
{ pc_nat - native code generation }
{ }
{ Gen0(pc_nat) }
{ }
{ Generate a native code instruction. The parameters are set }
{ in a special section in asm.pas. }
{ }
{ s - operation code }
{ q - operand value }
{ r - addressing mode }
{ lab - label name }
{ flags - shift flags }
{ }
{-- Pcodes involved expressions --------------------------------}
{ }
{ pc_adi - integer addition }
{ pc_adl - long addition }
{ pc_adq - long long addition }
{ pc_adr - real addition }
{ }
{ Gen0(pc_adi) cgByte,cgUByte,cgWord,cgUWord }
{ Gen0(pc_adl) cgLong,cgULong }
{ Gen0(pc_adq) cgQuad,cgUQuad }
{ Gen0(pc_adr) cgReal,cgDouble,cgComp,cgExtended }
{ }
{ The two values on the top of the evaluation stack are }
{ removed and added. The result is placed back on the stack. }
{ }
{ }
{ pc_and - logical and }
{ pc_lnd - long logical and }
{ }
{ Gen0(pc_and) cgByte,cgUByte,cgWord,cgUWord }
{ Gen0(pc_lnd) cgLong,cgULong }
{ }
{ The two values on the top of the evaluation stack are }
{ removed and anded. The result is placed back on the stack. }
{ Zero is treated as false, and any other value as true. The }
{ and is a logical and. See pc_bnd for a bitwise and. }
{ }
{ If the first operand is false, the second operand is not }
{ evaluated. }
{ }
{ }
{ pc_bnd - bitwise and }
{ pc_bal - long bitwise and }
{ pc_baq - long long bitwise and }
{ }
{ Gen0(pc_bnd) cgByte,cgUByte,cgWord,cgUWord }
{ Gen0(pc_bal) cgLong,cgULong }
{ Gen0(pc_baq) cgQuad,cgUQuad }
{ }
{ The two values on the top of the evaluation stack are }
{ removed and anded. The result is placed back on the stack. }
{ }
{ }
{ pc_bno - binary operand no-operation }
{ }
{ Gen0t(pc_bno, type) }
{ }
{ The left operand is evaluated and discarded, followed by }
{ the evaluation of the right operand. The type is the type }
{ of the right operand; it is used in case a pc_pop is }
{ attached to remove a result left on the stack. This }
{ instruction is used by C for the comma operator and for }
{ parameter lists for function and procedure calls, and by }
{ pc_tri to hold the two expressions. }
{ }
{ }
{ pc_bnt - bitwise negation }
{ pc_bnl - long bitwise negation }
{ pc_bnq - long long bitwise negation }
{ }
{ Gen0(pc_bnt) cgByte,cgUByte,cgWord,cgUWord }
{ Gen0(pc_bnl) cgLong,cgULong }
{ Gen0(pc_bnq) cgQuad,cgUQuad }
{ }
{ The value on the top of the evaluation stack is removed, }
{ exclusive ored with $FFFF, and replaced. (One's compliment.)}
{ }
{ }
{ pc_bor - bitwise or }
{ pc_blr - long bitwise or }
{ pc_bqr - long long bitwise or }
{ }
{ Gen0(pc_bor) cgByte,cgUByte,cgWord,cgUWord }
{ Gen0(pc_blr) cgLong,cgULong }
{ Gen0(pc_bqr) cgQuad,cgUQuad }
{ }
{ The two values on the top of the evaluation stack are }
{ removed and ored. The result is placed back on the stack. }
{ }
{ }
{ pc_bxr - exclusive or }
{ pc_blx - long exclusive or }
{ pc_bqx - long long exclusive or }
{ }
{ Gen0(pc_bxr) cgByte,cgUByte,cgWord,cgUWord }
{ Gen0(pc_blx) cgLong,cgULong }
{ Gen0(pc_bqx) cgQuad,cgUQuad }
{ }
{ The two values on the top of the evaluation stack are }
{ removed and exclusive ored. The result is placed back on }
{ the stack. }
{ }
{ }
{ pc_cbf - copy bit field }
{ }
{ Gen2t(pc_cbf, disp, size, type) }
{ }
{ An integer is removed from the top of the evaluation stack }
{ and saved at the address on the evaluation stack. The }
{ address is removed, but the integer remains intact. The }
{ value is saved DISP bits past the address, and is treated as }
{ a SIZE bit value. Extra bits are dropped. }
{ }
{ }
{ pc_cop - copy to a local variable }
{ }
{ Gen2t(pc_cop, label, disp, type) }
{ }
{ Saves the value on the top of the evaluation stack to DISP }
{ bytes past the local label LABEL. TYPE is the type of the }
{ value being saved. }
{ }
{ }
{ pc_cnv - convert from one scalar type to another }
{ pc_cnn - convert from one scalar type to another }
{ }
{ Gen2(pc_cnv, from, to) }
{ Gen2(pc_cnn, from, to) }
{ }
{ Converts from one scalar type to another. The from and to }
{ parameters are ordinal values of type baseTypeEnum. The }
{ table below shows what from values (along the left edge) and }
{ to values (along the top) are allowed, and what action is }
{ taken for each combination. CgDouble, cgComp or cgExtended }
{ may be used anywhere that cgReal is used, with the same }
{ results. }
{ }
{ The pc_cnn form converts the value at tos-1. The value at }
{ tos is assumed to be the same size as the result type. }
{ }
{ cgByte cgUByte cgWord cgUWord cgLong cgULong cgReal }
{ cgByte extend extend float }
{ cgUByte padd padd float }
{ cgWord extend extend float }
{ cgUWord extend extend float }
{ cgLong discard discard discard discard float }
{ cgULong discard discard discard discard float }
{ cgReal trunc trunc trunc trunc trunc trunc }
{ }
{ The meaning of the operations shown in the table is: }
{ }
{ (blank) No action is taken, but the instruction is }
{ accepted by the code generator. }
{ extend The value is sign extended to the proper length.}
{ padd The value is padded on the left with zero bits }
{ to extend it to the proper length. }
{ discard Extra bits are discarded to reach the proper }
{ length, starting with the most significant bit. }
{ float An integer value is converted to a real value. }
{ trunc A real value is converted to the largest }
{ integer value that is less than or equal to the }
{ real value. }
{ }
{ }
{ pc_cpi - copy indirect }
{ }
{ Gen0t(pc_cpi, type) }
{ }
{ Two values are removed from the evaluation stack. The first }
{ is of type TYPE, while the second is a pointer. The first }
{ value is stored at the location pointed to by the pointer. }
{ The value is then placed back on the stack. }
{ }
{ }
{ pc_cpo - copy to a global variable }
{ }
{ Gen1tName (pc_cpo, disp, type, name) }
{ }
{ Saves the value on the top of the evaluation stack to the }
{ global label NAME. DISP is a fixed displacement past the }
{ names label to load from. (Used for records.) TYPE is }
{ the type of the value being loaded. }
{ }
{ }
{ pc_dec - decrement }
{ }
{ Gen1t(pc_dec, val, type) }
{ }
{ The value on the top of the stack is removed, decremented by }
{ VAL and returned to the stack. Type may be cgByte, cgUByte, }
{ cgWord, cgUWord, cgLong or cgULong. In all cases, the }
{ amount to decrement by is a positive signed integer. }
{ }
{ }
{ pc_dvi - integer divide }
{ pc_udi - unsigned integer divide }
{ pc_dvl - long integer divide }
{ pc_udl - unsigned long divide }
{ pc_dvq - long long integer divide }
{ pc_udq - unsigned long long divide }
{ pc_dvr - real divide }
{ }
{ Gen0(pc_dvi) cgByte,cgWord }
{ Gen0(pc_udi) cgUByte,cgUWord }
{ Gen0(pc_dvl) cgLong }
{ Gen0(pc_udl) cgULong }
{ Gen0(pc_dvq) cgQuad }
{ Gen0(pc_udq) cgUQuad }
{ Gen0(pc_dvr) cgReal,cgDouble,cgComp,cgExtended }
{ }
{ The two values on the top of the evaluation stack are }
{ removed and divided. The result is placed back on the }
{ stack. The result type is the same as the argument type. }
{ }
{ }
{ pc_equ,pc_geq,pc_grt,pc_leq,pc_les,pc_neq - compares }
{ }
{ Gen0t(pc_equ, type) }
{ }
{ The two values on the top of the evaluation stack are }
{ removed and compared. A boolean result is placed back on }
{ the stack. }
{ }
{ }
{ pc_gil - increment and load from a global variable }
{ pc_gli - load a global variable, then inc the original }
{ pc_gdl - decrement and load from a global variable }
{ pc_gld - load a global variable, then dec the original }
{ }
{ Gen2tName (pc_gli, inc, disp, type, name) }
{ }
{ Loads a value from the global label NAME and places it on }
{ the evaluation stack. DISP is a fixed displacement past the }
{ names label to load from. (Used for records.) TYPE is }
{ the type of the value being loaded. }
{ }
{ In addition to loading the value, these instructions also }
{ increment or decrement the value, as indicated in the }
{ comment by the instruction name. The operand is incremented }
{ or decremented by INC. INC must be 1 for one and two byte }
{ operands. }
{ }
{ }
{ pc_iil - increment and load indirect }
{ pc_ili - load indirect, then inc the original }
{ pc_idl - decrement and load indirect }
{ pc_ild - load indirect, then dec the original }
{ }
{ Gen0t (pc_ili, type) }
{ }
{ Loads a value from the indirect address on the top of the }
{ stack, performing either an increment or decrement in the }
{ process. TYPE may be cgByte, cgUByte, cgWord or cgUWord. }
{ }
{ }
{ pc_inc - increment }
{ }
{ Gen1t(pc_inc, val, type) }
{ }
{ The value on the top of the stack is removed, incremented by }
{ VAL and returned to the stack. Type may be cgByte, cgUByte, }
{ cgWord, cgUWord, cgLong or cgULong. In all cases, the }
{ amount to increment by is a positive signed integer. }
{ }
{ }
{ pc_ind - load indirect }
{ }
{ Gen2t (pc_ind, volatile, disp, type) }
{ }
{ A value of type TYPE is loaded from DISP bytes past the }
{ address that is on the evaluation stack. The address is }
{ removed from the stack and replaced with the value. }
{ VOLATILE is non-zero for a volatile load, or 0 otherwise. }
{ }
{ }
{ pc_ior - logical or }
{ pc_lor - long logical or }
{ }
{ Gen0(pc_ior) cgByte,cgUByte,cgWord,cgUWord }
{ Gen0(pc_lor) cgLong,cgULong }
{ }
{ The two values on the top of the evaluation stack are }
{ removed and ored. The result is placed back on the stack. }
{ Zero is treated as false, and any other value as true. The }
{ or is a logical or. See pc_bor for a bitwise or. }
{ }
{ }
{ pc_ixa - integer indexed address }
{ }
{ Gen0t(pc_ixa, type) }
{ }
{ TOS is an integer, which is added to TOS-1, which is a long }
{ integer. This instruction is generally used for computing }
{ short array indexes. }
{ }
{ TYPE can be cgWord or cgUWord; the type indicates whether }
{ the addition is signed or unsigned. }
{ }
{ }
{ pc_lad - load the address of a subroutine }
{ }
{ Gen0Name(pc_lad, name); }
{ }
{ Loads the address of the subroutine NAME. }
{ }
{ }
{ pc_lao - load a global address }
{ }
{ Gen1Name(pc_lao, disp, name); }
{ }
{ Loads the address of DISP bytes past the global variable }
{ NAME onto the stack. }
{ }
{ }
{ pc_lbf - load bit field }
{ pc_lbu - load unsigned bit field }
{ }
{ Gen2t(pc_lbf, disp, size, type) }
{ Gen2t(pc_lbu, disp, size, type) }
{ }
{ A bit field SIZE bits wide is loaded from DISP bits past the }
{ address on the top of the evaluation stack. The address is }
{ removed from the evaluation stack in the process. pc_lbf }
{ loads a signed value, while pc_lbu loads an unsigned value. }
{ }
{ }
{ pc_lca - load a string constant address }
{ }
{ GenS(pc_lca, str) }
{ }
{ Loads the address of a string onto the stack. Str is a }
{ pointer to a string constant. No null terminator is added; }
{ it should be explicitly included in str if desired. }
{ }
{ }
{ pc_lda - load a local address }
{ }
{ Gen2(pc_lda, label, disp) }
{ }
{ Loads the address of DISP bytes past the local label LABEL. }
{ }
{ }
{ pc_ldc - load a constant }
{ }
{ Gen1t(pc_ldc, val, type) }
{ GenLdcLong(val) }
{ GenLdcQuad(val) }
{ GenLdcReal(val) }
{ }
{ Loads a constant value. Special calls for long, quad & real }
{ values are provided due to the unique parameter requirements.}
{ }
{ }
{ pc_ldo - load from a global variable }
{ }
{ Gen1tName (pc_ldo, disp, type, name) }
{ }
{ Loads a value from the global label NAME and places it on }
{ the evaluation stack. DISP is a fixed displacement past the }
{ names label to load from. (Used for records.) TYPE is }
{ the type of the value being loaded. }
{ }
{ }
{ pc_lil - increment and load from a local variable }
{ pc_lli - load a local variable, then inc the original }
{ pc_ldl - decrement and load from a local variable }
{ pc_lld - load a local variable, then dec the original }
{ }
{ Gen2t(pc_lli, label, inc, type) }
{ }
{ Loads a value from the local label LABEL and places it on }
{ the evaluation stack. TYPE is the type of the value being }
{ loaded. INC is the number to increment or decrement by. }
{ }
{ In addition to loading the value, these instructions also }
{ increment or decrement the value, as indicated in the }
{ comment by the instruction name. The operand is incremented }
{ or decremented by INC. INC must be 1 for one and two byte }
{ operands. }
{ }
{ }
{ pc_lod - load from a local variable }
{ }
{ Gen2t(pc_lod, label, disp, type) }
{ }
{ Loads a value from DISP bytes past the local label LABEL and }
{ places it on the evaluation stack. TYPE is the type is the }
{ value being loaded. }
{ }
{ }
{ pc_mod - integer remainder }
{ pc_uim - unsigned integer modulus/remainder }
{ pc_mdl - long remainder }
{ pc_ulm - unsigned long modulus/remainder }
{ pc_mdq - long long remainder }
{ pc_uqm - unsigned long long modulus/remainder }
{ }
{ Gen0(pc_mod) cgByte,cgWord }
{ Gen0(pc_uim) cgUByte,cgUWord }
{ Gen0(pc_mdl) cgLong }
{ Gen0(pc_ulm) cgULong }
{ Gen0(pc_mdq) cgQuad }
{ Gen0(pc_uqm) cgUQuad }
{ }
{ The two values on the top of the evaluation stack are }
{ removed and the remainder after division is calculated. }
{ The result is placed back on the stack. The result, like }
{ the arguments, is an integer. }
{ }
{ }
{ pc_mpi - integer multiply }
{ pc_umi - unsigned integer multiply }
{ pc_mpl - long integer multiply }
{ pc_uml - unsigned long multiply }
{ pc_mpq - long long integer multiply }
{ pc_umq - unsigned long long multiply }
{ pc_mpr - real multiply }
{ }
{ Gen0(pc_mpi) cgByte,cgWord }
{ Gen0(pc_umi) cgUByte,cgUWord }
{ Gen0(pc_mpl) cgLong }
{ Gen0(pc_uml) cgULong }
{ Gen0(pc_mpq) cgQuad }
{ Gen0(pc_umq) cgUQuad }
{ Gen0(pc_mpr) cgReal,cgDouble,cgComp,cgExtended }
{ }
{ The two values on the top of the evaluation stack are }
{ removed and multiplied. The result is placed back on the }
{ stack. The result type is the same as the argument type. }
{ }
{ }
{ pc_ngi - integer negation }
{ pc_ngl - long negation }
{ pc_ngq - long long negation }
{ pc_ngr - real negation }
{ }
{ Gen0(pc_ngi) cgByte,cgUByte,cgWord,cgUWord }
{ Gen0(pc_ngl) cgLong,cgULong }
{ Gen0(pc_ngq) cgQuad,cgUQuad }
{ Gen0(pc_ngr) cgReal,cgDouble,cgComp,cgExtended }
{ }
{ The value on the top of the evaluation stack is removed, }
{ subtracted from 0, and replaced. (Two's compliment.) }
{ }
{ }
{ Gen0(pc_nop) }
{ }
{ This operand is a leaf node. It does nothing. It is used }
{ to create a null expression tree for functions and }
{ procedures that have no parameters. }
{ }
{ }
{ pc_not - logical negation }
{ }
{ Gen0(pc_not) }
{ }
{ The value on the top of the evaluation stack is removed, }
{ logically negated, and replaced. }
{ }
{ }
{ pc_pop - pop a value from the stack }
{ }
{ Gen0t(pc_pop, type) }
{ }
{ The value on the top of the evaluation stack is removed. }
{ }
{ }
{ pc_psh - push bytes on the stack }
{ }
{ Gen0(pc_psh) }
{ }
{ Removes the size (a word) and the source address (a long) }
{ from the evaluation stack, and pushes size bytes from the }
{ source address onto the stack. }
{ }
{ }
{ pc_rbo - reverse byte order }
{ }
{ Gen0(pc_rbo) cgWord,cgUWord }
{ }
{ The value on the top of the evaluation stack is removed, has }
{ the order of its constituent bytes reversed, and is replaced.}
{ }
{ }
{ pc_sbf - save bit field }
{ }
{ Gen2t(pc_sbf, disp, size, type) }
{ }
{ An integer is removed from the top of the evaluation stack }
{ and saved at the address on the evaluation stack. The }
{ value is saved DISP bits past the address, and is treated as }
{ a SIZE bit value. Extra bits are dropped. }
{ }
{ }
{ pc_sbi - integer subtraction }
{ pc_sbl - long subtraction }
{ pc_sbq - long long subtraction }
{ pc_sbr - real subtraction }
{ }
{ Gen0(pc_sbi) cgByte,cgUByte,cgWord,cgUWord }
{ Gen0(pc_sbl) cgLong,cgULong }
{ Gen0(pc_sbq) cgQuad,cgUQuad }
{ Gen0(pc_sbr) cgReal,cgDouble,cgComp,cgExtended }
{ }
{ The two values on the top of the evaluation stack are }
{ removed. TOS-1 - TOS is placed back on the stack. }
{ }
{ }
{ pc_shl - shift left }
{ pc_sll - shift left long }
{ pc_slq - shift left long long }
{ }
{ Gen0(pc_shl) cgByte,cgUByte,cgWord,cgUWord }
{ Gen0(pc_sll) cgLong,cgULong }
{ Gen0(pc_slq) cgQuad,cgUQuad (tos-1) / cgWord (tos) }
{ }
{ The value at tos-1 is shifted left by the number of bits }
{ specified by tos. The result is an integer, which replaces }
{ the operands on the stack. The right bit positions are }
{ filled with zeros. For pc_slq, only the value at tos-1 is }
{ cgQuad/cgUQuad; the shift count at tos is cgWord or cgUWord. }
{ }
{ }
{ pc_shr - shift right }
{ pc_usr - unsigned shift right }
{ pc_slr - long shift right }
{ pc_vsr - unsigned long shift right }
{ pc_sqr - long long shift right }
{ pc_wsr - unsigned long long shift right }
{ }
{ Gen0(pc_shr) cgByte,cgWord }
{ Gen0(pc_usr) cgUByte,cgUWord }
{ Gen0(pc_slr) cgLong }
{ Gen0(pc_vsr) cgULong }
{ Gen0(pc_sqr) cgQuad (tos-1) / cgWord (tos) }
{ Gen0(pc_wsr) cgUQuad (tos-1) / cgWord (tos) }
{ }
{ The value at tos-1 is shifted right by the number of bits }
{ specified by tos. The result is an integer, which replaces }
{ the operands on the stack. This is a signed shift: the }
{ leftmost bit position is filled in with a copy of the }
{ original leftmost bit. }
{ }
{ Pc_usr is the unsigned form. The operation is the same, }
{ except that the leftmost bit is replaced with a zero. }
{ Pc_vsr is used for unsigned long operations, and pc_wsr is }
{ used for unsigned long long operations. }
{ }
{ }
{ pc_stk - stack an operand }
{ }
{ Gen0t(pc_stk, type) }
{ }
{ The value on top of the evaluation stack is to be left there }
{ as a parameter to a subsequent procedure or function call. }
{ This p-code "caps" the expression tree, giving the code }
{ generator something to do with the expression result. }
{ }
{ }
{ pc_sro - store to a global variable }
{ }
{ Gen1tName (pc_sro, disp, type, name) }
{ }
{ Saves the value from the top of the evaluation stack to the }
{ global label NAME. DISP is a fixed displacement past the }
{ names label to load from. (Used for records.) TYPE is }
{ the type of the value being loaded. }
{ }
{ }
{ pc_sto - store indirect }
{ }
{ Gen0t(pc_sto, type) }
{ }
{ Two values are removed from the evaluation stack. TOS is of }
{ type TYPE, while TOS-1 is a pointer. The value is stored at }
{ the location pointed to by the pointer. }
{ }
{ }
{ pc_str - store to a local variable }
{ }
{ Gen2t(pc_str, label, disp, type) }
{ }
{ Saves the value on the top of the evaluation stack to DISP }
{ bytes past the local label LABEL. TYPE is the type of the }
{ value being saved. }
{ }
{ }
{ pc_tri - C trinary operator }
{ }
{ Gen0t(pc_tri, type) }
{ }
{ Implements the C trinary operator. TOS is the false }
{ expression, TOS-1 the true expression, and TOS-2 the }
{ condition expression. The condition expression is }
{ evaluated. If it is non-zero, the true expression is }
{ evaluated. If it is zero, the false expression is }
{ evaluated. The result type of the true and false }
{ expressions must be the same. }
{ }
{ Internally, pc_bno is used for the right operand; the }
{ operands for pc_bno are the two expressions. }
{ }
{-- Flow of control --------------------------------------------}
{ }
{ dc_lab - define a label }
{ }
{ Gen1(dc_lab, lab) }
{ }
{ Defines label number lab at the current location. }
{ }
{ }
{ pc_add - address }
{ }
{ Gen1(pc_add, lab) }
{ }
{ Generates a two-byte address that points to the label lab. }
{ This is used to create branch tables for pc_xjp }
{ instructions. }
{ }
{ }
{ pc_fjp - jump if false }
{ }
{ Gen1(pc_fjp, lab) }
{ }
{ A boolean value is removed from the top of the evaluation }
{ stack. If the value is false, execution continues with the }
{ instruction after the label lab; otherwise execution }
{ continues with the instruction after this one. }
{ }
{ }
{ pc_tjp - jump if true }
{ }
{ Gen1(pc_tjp, lab) }
{ }
{ A boolean value is removed from the top of the evaluation }
{ stack. If the value is true, execution continues with the }
{ instruction after the label lab; otherwise execution }
{ continues with the instruction after this one. }
{ }
{ }
{ pc_ujp - jump }
{ }
{ Gen1(pc_ujp, lab) }
{ }
{ Execution continues with the instruction after the label lab.}
{ }
{ }
{ pc_xjp - indexed jump }
{ }
{ Gen1(pc_xjp, val) }
{ }
{ The top of stack contains an integer, which is removed. If }
{ it is less than zero or greater than VAL, it is replaced by }
{ VAL. The result is then used to index into a jump table, }
{ formed using pc_add instructions, which follows immediately }
{ after the pc_xjp instruction. }
{ }
{-- Pcodes involved with calling and defining procedures -------}
{ }
{ dc_str - start a segment }
{ }
{ Gen2Name(dc_str, p1, p2, name) }
{ }
{ Starts a new object segment with the name name^. P1 is the }
{ segment kind, while p2 is the length code (1 for data, 0 for }
{ code segments). }
{ }
{ }
{ dc_pin - procedure entry point }
{ }
{ Gen0(dc_pin) }
{ }
{ A code segment does not have to be entered at the first byte }
{ when called. This directive is used one time in each code }
{ segment to indicate the actual entry point. }
{ }
{ }
{ dc_enp - end a segment }
{ }
{ Gen0(dc_enp) }
{ }
{ This directive closes the current segment. }
{ }
{ }
{ pc_ent - enter a subroutine }
{ }
{ Gen0(pc_ent) }
{ }
{ This pcode is used at the beginning of every subroutine. It }
{ marks the beginning of a new stack frame definition. }
{ Subsequent dc_loc and dc_prm cause space to be allocated }
{ from this stack frame. }
{ }
{ }
{ pc_ret - return from a subroutine }
{ }
{ Gen0t(pc_ret, type) }
{ }
{ This pcode is used to return from a function or a procedure. }
{ The type is the type of the function, and is used to tell }
{ the code generator what type of value to return. The value }
{ to return is assumed to be stored defaultStackSize bytes }
{ into the stack frame. }
{ }
{ }
{ pc_cui - call user procedure, indirect }
{ }
{ Gen1t(pc_cui, repair, ftype) }
{ }
{ Calls a user procedure or function through the address on }
{ the top of the evaluation stack. FTYPE is the return type. }
{ Repair is 1 if stack repair should be forced, -1 if stack }
{ repair and checking should be disabled, or 0 if the regular }
{ settings should be used. }
{ }
{ }
{ pc_cup - call user procedure }
{ }
{ Gen1tName(pc_cup, repair, ftype, name) }
{ }
{ Calls a user procedure or function. Ftype is the type. }
{ Repair is 1 if stack repair should be forced, -1 if stack }
{ repair and checking should be disabled, or 0 if the regular }
{ settings should be used. NAME is the name of the procedure. }
{ }
{ }
{ dc_loc - define local label }
{ }
{ Gen2(dc_loc, label, size) }
{ }
{ Defines a local label using the label parameter as a label }
{ number. Size bytes are reserved on the stack frame. Label }
{ numbers should be assigned by the compiler, starting with }
{ number 1. Label 0 is reserved for referring to the return }
{ value of a function (if any). }
{ }
{ }
{ dc_prm - define parameter }
{ }
{ Gen3(dc_prm, label, size, disp) }
{ }
{ Defines a label used to refer to a parameter. See dc_loc }
{ for a discussion of the label and size parameters. The disp }
{ parameter is the number of bytes of parameter that will be }
{ pushed after this one; i.e., the disp from the return addr }
{ to this parameter. }
{ }
{ }
{ pc_tl1 - call a tool }
{ }
{ GenTool(pc_tl1, toolNum, retSize, dispatcher) }
{ }
{ Calls a tool. The tool number is toolNum; the tool is }
{ called at location dispatcher. The tool returns a result }
{ that is retSize bytes long. }
{ }
{ }
{ dc_sym - generate a symbol table }
{ }
{ Gen1Name(dc_sym, doGLobals, pointer(table) }
{ }
{ Generates a symbol table for the debugger. TABLE is the }
{ address of the symbol table, which will be passed back to a }
{ subroutine called GenSymbols, which must be supplied by the }
{ compiler. DOGLOBALS is a flag the compiler can set for its }
{ own purposes. C uses the flag to note that the symbol }
{ table being created is for main, so global symbols should be }
{ included. }
{ }