mirror of
https://github.com/byteworksinc/ORCA-C.git
synced 2024-12-22 07:30:54 +00:00
2d43074d5a
Per the C standards, the % operator should give a remainder after division, such that (a/b)*b + a%b equals a (provided that a/b is representable). As such, the operation of % is defined for cases where either or both of the operands are negative. Since division truncates toward 0, a%b should give a negative result (or 0) in cases where a is negative. Previously, the % operator was essentially behaving like the "mod" operator in Pascal, which is equivalent for positive operands but not if either operand is negative. It would generally give incorrect results in those cases, or in some cases give compile-time or run-time errors. This patch addresses both 16-bit and 32-bit signed computations at run time, and operations in constant expressions. The approach at run time is to call existing division routines, which return the correct remainder, except always as a positive number. The generated code checks the sign of the first operand, and if it is negative negates the remainder. The code generated is somewhat large (especially for the 32-bit case), so it might be sensible to put it in a library function and call that, but for now it's just generated in-line. This avoids introducing a dependency on a new library function, so the generated code remains compatible with older versions of ORCALib (e.g. the GNO one). Fixes #10.
799 lines
51 KiB
Plaintext
799 lines
51 KiB
Plaintext
{-- Misc. pcodes -----------------------------------------------}
|
|
{ }
|
|
{ dc_cns - generate a constant value }
|
|
{ }
|
|
{ GenL1(dc_cns, lval, count); }
|
|
{ GenR1t(dc_cns, rval, count, type); }
|
|
{ Gen2t(dc_cns, ival, count, type); }
|
|
{ GenS(dc_cns, sptr); }
|
|
{ }
|
|
{ Creates COUNT occurrances of the constant lval, 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 }
|
|
{ }
|
|
{ Gen2(pc_lnm, lc, flag) }
|
|
{ }
|
|
{ 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 }
|
|
{ }
|
|
{ }
|
|
{ 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? }
|
|
{ sourceFile - 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_adr - real addition }
|
|
{ }
|
|
{ Gen0(pc_adi) cgByte,cgUByte,cgWord,cgUWord }
|
|
{ Gen0(pc_adl) cgLong,cgULong }
|
|
{ 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 }
|
|
{ }
|
|
{ Gen0(pc_bnd) cgByte,cgUByte,cgWord,cgUWord }
|
|
{ Gen0(pc_bal) cgLong,cgULong }
|
|
{ }
|
|
{ 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 }
|
|
{ }
|
|
{ Gen0(pc_bnt) cgByte,cgUByte,cgWord,cgUWord }
|
|
{ Gen0(pc_bnl) cgLong,cgULong }
|
|
{ }
|
|
{ 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 }
|
|
{ }
|
|
{ Gen0(pc_bor) cgByte,cgUByte,cgWord,cgUWord }
|
|
{ Gen0(pc_blr) cgLong,cgULong }
|
|
{ }
|
|
{ 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 }
|
|
{ }
|
|
{ Gen0(pc_bxr) cgByte,cgUByte,cgWord,cgUWord }
|
|
{ Gen0(pc_blx) cgLong,cgULong }
|
|
{ }
|
|
{ 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 operationd 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_dvr - real divide }
|
|
{ }
|
|
{ Gen0(pc_dvi) cgByte,cgWord }
|
|
{ Gen0(pc_udi) cgUByte,cgUWord }
|
|
{ Gen0(pc_dvl) cgLong }
|
|
{ Gen0(pc_udl) cgULong }
|
|
{ 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 }
|
|
{ }
|
|
{ Gen1t (pc_ind, 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. }
|
|
{ }
|
|
{ }
|
|
{ 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. }
|
|
{ }
|
|
{ }
|
|
{ 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) }
|
|
{ GenLdcReal(val) }
|
|
{ }
|
|
{ Loads a constant value. Special calls for long and 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 }
|
|
{ }
|
|
{ Gen0(pc_mod) cgByte,cgWord }
|
|
{ Gen0(pc_uim) cgUByte,cgUWord }
|
|
{ Gen0(pc_mdl) cgLong }
|
|
{ Gen0(pc_ulm) cgULong }
|
|
{ }
|
|
{ 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_mpr - real multiply }
|
|
{ }
|
|
{ Gen0(pc_mpi) cgByte,cgWord }
|
|
{ Gen0(pc_umi) cgUByte,cgUWord }
|
|
{ Gen0(pc_mpl) cgLong }
|
|
{ Gen0(pc_uml) cgULong }
|
|
{ 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_ngr - real negation }
|
|
{ }
|
|
{ Gen0(pc_ngi) cgByte,cgUByte,cgWord,cgUWord }
|
|
{ Gen0(pc_ngl) cgLong,cgULong }
|
|
{ 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_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_sbr - real subtraction }
|
|
{ }
|
|
{ Gen0(pc_sbi) cgByte,cgUByte,cgWord,cgUWord }
|
|
{ Gen0(pc_sbl) cgLong,cgULong }
|
|
{ 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 }
|
|
{ }
|
|
{ Gen0(pc_shl) cgByte,cgUByte,cgWord,cgUWord }
|
|
{ Gen0(pc_sll) cgLong,cgULong }
|
|
{ }
|
|
{ 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. }
|
|
{ }
|
|
{ }
|
|
{ pc_shr - shift right }
|
|
{ pc_usr - unsigned shift right }
|
|
{ pc_slr - long shift right }
|
|
{ pc_vsr - unsigned long shift right }
|
|
{ }
|
|
{ Gen0(pc_shr) cgByte,cgWord }
|
|
{ Gen0(pc_usr) cgUByte,cgUWord }
|
|
{ Gen0(pc_slr) cgLong }
|
|
{ Gen0(pc_vsr) cgULong }
|
|
{ }
|
|
{ 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 }
|
|
{ orignial 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. }
|
|
{ }
|
|
{ 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(pc_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, and 0 if not. }
|
|
{ }
|
|
{ }
|
|
{ pc_cup - call user procedure }
|
|
{ }
|
|
{ Gen1tName(pc_cup, repair, name, ftype) }
|
|
{ }
|
|
{ Calls a user procedure or function. Ftype is the type. }
|
|
{ Repair is 1 if stack repair should be forced, and 0 if not. }
|
|
{ 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 refering 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 sybol 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. }
|
|
{ }
|