mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-15 15:01:42 +00:00
14f2c39e58
- improved the class pointer to string cast to print the actual type it describes and not the class pointer's own type. - fixed: The 'is' operator created non-working code when checking the inheritance of a class pointer, it only worked for objects.
255 lines
14 KiB
C
255 lines
14 KiB
C
#ifndef xx
|
|
#define xx(op, name, mode, alt, kreg, ktype) OP_##op
|
|
#endif
|
|
|
|
// first row is the opcode
|
|
// second row is the disassembly name
|
|
// third row is the disassembly flags
|
|
// fourth row is the alternative opcode if all 256 constant registers are exhausted.
|
|
// fifth row is the constant register index in the opcode
|
|
// sixth row is the constant register type.
|
|
// OP_PARAM and OP_CMPS need special treatment because they encode this information in the instruction.
|
|
|
|
xx(NOP, nop, NOP, NOP, 0, 0), // no operation
|
|
|
|
// Load constants.
|
|
xx(LI, li, LI, NOP, 0, 0), // load immediate signed 16-bit constant
|
|
xx(LK, lk, LKI, NOP, 0, 0), // load integer constant
|
|
xx(LKF, lk, LKF, NOP, 0, 0), // load float constant
|
|
xx(LKS, lk, LKS, NOP, 0, 0), // load string constant
|
|
xx(LKP, lk, LKP, NOP, 0, 0), // load pointer constant
|
|
xx(LK_R, lk, RIRII8, NOP, 0, 0), // load integer constant indexed
|
|
xx(LKF_R, lk, RFRII8, NOP, 0, 0), // load float constant indexed
|
|
xx(LKS_R, lk, RSRII8, NOP, 0, 0), // load string constant indexed
|
|
xx(LKP_R, lk, RPRII8, NOP, 0, 0), // load pointer constant indexed
|
|
xx(LFP, lf, LFP, NOP, 0, 0), // load frame pointer
|
|
xx(META, meta, RPRP, NOP, 0, 0), // load a class's meta class address
|
|
|
|
// Load from memory. rA = *(rB + rkC)
|
|
xx(LB, lb, RIRPKI, LB_R, 4, REGT_INT), // load byte
|
|
xx(LB_R, lb, RIRPRI, NOP, 0, 0),
|
|
xx(LH, lh, RIRPKI, LH_R, 4, REGT_INT), // load halfword
|
|
xx(LH_R, lh, RIRPRI, NOP, 0, 0),
|
|
xx(LW, lw, RIRPKI, LW_R, 4, REGT_INT), // load word
|
|
xx(LW_R, lw, RIRPRI, NOP, 0, 0),
|
|
xx(LBU, lbu, RIRPKI, LBU_R, 4, REGT_INT), // load byte unsigned
|
|
xx(LBU_R, lbu, RIRPRI, NOP, 0, 0),
|
|
xx(LHU, lhu, RIRPKI, LHU_R, 4, REGT_INT), // load halfword unsigned
|
|
xx(LHU_R, lhu, RIRPRI, NOP, 0, 0),
|
|
xx(LSP, lsp, RFRPKI, LSP_R, 4, REGT_INT), // load single-precision fp
|
|
xx(LSP_R, lsp, RFRPRI, NOP, 0, 0),
|
|
xx(LDP, ldp, RFRPKI, LDP_R, 4, REGT_INT), // load double-precision fp
|
|
xx(LDP_R, ldp, RFRPRI, NOP, 0, 0),
|
|
xx(LS, ls, RSRPKI, LS_R, 4, REGT_INT), // load string
|
|
xx(LS_R, ls, RSRPRI, NOP, 0, 0),
|
|
xx(LO, lo, RPRPKI, LO_R, 4, REGT_INT), // load object
|
|
xx(LO_R, lo, RPRPRI, NOP, 0, 0),
|
|
xx(LP, lp, RPRPKI, LP_R, 4, REGT_INT), // load pointer
|
|
xx(LP_R, lp, RPRPRI, NOP, 0, 0),
|
|
xx(LV2, lv2, RVRPKI, LV2_R, 4, REGT_INT), // load vector2
|
|
xx(LV2_R, lv2, RVRPRI, NOP, 0, 0),
|
|
xx(LV3, lv3, RVRPKI, LV3_R, 4, REGT_INT), // load vector3
|
|
xx(LV3_R, lv3, RVRPRI, NOP, 0, 0),
|
|
|
|
xx(LBIT, lbit, RIRPI8, NOP, 0, 0), // rA = !!(*rB & C) -- *rB is a byte
|
|
|
|
// Store instructions. *(rA + rkC) = rB
|
|
xx(SB, sb, RPRIKI, SB_R, 4, REGT_INT), // store byte
|
|
xx(SB_R, sb, RPRIRI, NOP, 0, 0),
|
|
xx(SH, sh, RPRIKI, SH_R, 4, REGT_INT), // store halfword
|
|
xx(SH_R, sh, RPRIRI, NOP, 0, 0),
|
|
xx(SW, sw, RPRIKI, SW_R, 4, REGT_INT), // store word
|
|
xx(SW_R, sw, RPRIRI, NOP, 0, 0),
|
|
xx(SSP, ssp, RPRFKI, SSP_R, 4, REGT_INT), // store single-precision fp
|
|
xx(SSP_R, ssp, RPRFRI, NOP, 0, 0),
|
|
xx(SDP, sdp, RPRFKI, SDP_R, 4, REGT_INT), // store double-precision fp
|
|
xx(SDP_R, sdp, RPRFRI, NOP, 0, 0),
|
|
xx(SS, ss, RPRSKI, SS_R, 4, REGT_INT), // store string
|
|
xx(SS_R, ss, RPRSRI, NOP, 0, 0),
|
|
xx(SP, sp, RPRPKI, SP_R, 4, REGT_INT), // store pointer
|
|
xx(SP_R, sp, RPRPRI, NOP, 0, 0),
|
|
xx(SV2, sv2, RPRVKI, SV2_R, 4, REGT_INT), // store vector2
|
|
xx(SV2_R, sv2, RPRVRI, NOP, 0, 0),
|
|
xx(SV3, sv3, RPRVKI, SV3_R, 4, REGT_INT), // store vector3
|
|
xx(SV3_R, sv3, RPRVRI, NOP, 0, 0),
|
|
|
|
xx(SBIT, sbit, RPRII8, NOP, 0, 0), // *rA |= C if rB is true, *rA &= ~C otherwise
|
|
|
|
// Move instructions.
|
|
xx(MOVE, mov, RIRI, NOP, 0, 0), // dA = dB
|
|
xx(MOVEF, mov, RFRF, NOP, 0, 0), // fA = fB
|
|
xx(MOVES, mov, RSRS, NOP, 0, 0), // sA = sB
|
|
xx(MOVEA, mov, RPRP, NOP, 0, 0), // aA = aB
|
|
xx(MOVEV2, mov2, RFRF, NOP, 0, 0), // fA = fB (2 elements)
|
|
xx(MOVEV3, mov3, RFRF, NOP, 0, 0), // fA = fB (3 elements)
|
|
xx(CAST, cast, CAST, NOP, 0, 0), // xA = xB, conversion specified by C
|
|
xx(CASTB, castb, CAST, NOP, 0, 0), // xA = !!xB, type specified by C
|
|
xx(DYNCAST_R, dyncast, RPRPRP, NOP, 0, 0), // aA = dyn_cast<aC>(aB);
|
|
xx(DYNCAST_K, dyncast, RPRPKP, NOP, 0, 0), // aA = dyn_cast<aKC>(aB);
|
|
xx(DYNCASTC_R, dyncastc, RPRPRP, NOP, 0, 0), // aA = dyn_cast<aC>(aB); for class types
|
|
xx(DYNCASTC_K, dyncastc, RPRPKP, NOP, 0, 0), // aA = dyn_cast<aKC>(aB);
|
|
|
|
// Control flow.
|
|
xx(TEST, test, RII16, NOP, 0, 0), // if (dA != BC) then pc++
|
|
xx(TESTN, testn, RII16, NOP, 0, 0), // if (dA != -BC) then pc++
|
|
xx(JMP, jmp, I24, NOP, 0, 0), // pc += ABC -- The ABC fields contain a signed 24-bit offset.
|
|
xx(IJMP, ijmp, RII16, NOP, 0, 0), // pc += dA + BC -- BC is a signed offset. The target instruction must be a JMP.
|
|
xx(PARAM, param, __BCP, NOP, 0, 0), // push parameter encoded in BC for function call (B=regtype, C=regnum)
|
|
xx(PARAMI, parami, I24, NOP, 0, 0), // push immediate, signed integer for function call
|
|
xx(CALL, call, RPI8I8, NOP, 0, 0), // Call function pkA with parameter count B and expected result count C
|
|
xx(CALL_K, call, KPI8I8, CALL, 1, REGT_POINTER),
|
|
xx(VTBL, vtbl, RPRPI8, NOP, 0, 0), // dereferences a virtual method table.
|
|
xx(TAIL, tail, RPI8, NOP, 0, 0), // Call+Ret in a single instruction
|
|
xx(TAIL_K, tail, KPI8, TAIL, 1, REGT_POINTER),
|
|
xx(RESULT, result, __BCP, NOP, 0, 0), // Result should go in register encoded in BC (in caller, after CALL)
|
|
xx(RET, ret, I8BCP, NOP, 0, 0), // Copy value from register encoded in BC to return value A, possibly returning
|
|
xx(RETI, reti, I8I16, NOP, 0, 0), // Copy immediate from BC to return value A, possibly returning
|
|
xx(TRY, try, I24, NOP, 0, 0), // When an exception is thrown, start searching for a handler at pc + ABC
|
|
xx(UNTRY, untry, I8, NOP, 0, 0), // Pop A entries off the exception stack
|
|
xx(THROW, throw, THROW, NOP, 0, 0), // A == 0: Throw exception object pB
|
|
// A == 1: Throw exception object pkB
|
|
// A >= 2: Throw VM exception of type BC
|
|
xx(CATCH, catch, CATCH, NOP, 0, 0), // A == 0: continue search on next try
|
|
// A == 1: continue execution at instruction immediately following CATCH (catches any exception)
|
|
// A == 2: (pB == <type of exception thrown>) then pc++ ; next instruction must JMP to another CATCH
|
|
// A == 3: (pkB == <type of exception thrown>) then pc++ ; next instruction must JMP to another CATCH
|
|
// for A > 0, exception is stored in pC
|
|
xx(BOUND, bound, RII16, NOP, 0, 0), // if rA >= BC, throw exception
|
|
xx(BOUND_K, bound, LKI, NOP, 0, 0), // if rA >= const[BC], throw exception
|
|
xx(BOUND_R, bound, RIRI, NOP, 0, 0), // if rA >= rB, throw exception
|
|
|
|
// String instructions.
|
|
xx(CONCAT, concat, RSRSRS, NOP, 0, 0), // sA = sB..sC
|
|
xx(LENS, lens, RIRS, NOP, 0, 0), // dA = sB.Length
|
|
xx(CMPS, cmps, I8RXRX, NOP, 0, 0), // if ((skB op skC) != (A & 1)) then pc++
|
|
|
|
// Integer math.
|
|
xx(SLL_RR, sll, RIRIRI, NOP, 0, 0), // dA = dkB << diC
|
|
xx(SLL_RI, sll, RIRII8, NOP, 0, 0),
|
|
xx(SLL_KR, sll, RIKIRI, SLL_RR, 2, REGT_INT),
|
|
xx(SRL_RR, srl, RIRIRI, NOP, 0, 0), // dA = dkB >> diC -- unsigned
|
|
xx(SRL_RI, srl, RIRII8, NOP, 0, 0),
|
|
xx(SRL_KR, srl, RIKIRI, SRL_RR, 2, REGT_INT),
|
|
xx(SRA_RR, sra, RIRIRI, NOP, 0, 0), // dA = dkB >> diC -- signed
|
|
xx(SRA_RI, sra, RIRII8, NOP, 0, 0),
|
|
xx(SRA_KR, sra, RIKIRI, SRA_RR, 2, REGT_INT),
|
|
xx(ADD_RR, add, RIRIRI, NOP, 0, 0), // dA = dB + dkC
|
|
xx(ADD_RK, add, RIRIKI, ADD_RR, 4, REGT_INT),
|
|
xx(ADDI, addi, RIRIIs, NOP, 0, 0), // dA = dB + C -- C is a signed 8-bit constant
|
|
xx(SUB_RR, sub, RIRIRI, NOP, 0, 0), // dA = dkB - dkC
|
|
xx(SUB_RK, sub, RIRIKI, SUB_RR, 4, REGT_INT),
|
|
xx(SUB_KR, sub, RIKIRI, SUB_RR, 2, REGT_INT),
|
|
xx(MUL_RR, mul, RIRIRI, NOP, 0, 0), // dA = dB * dkC
|
|
xx(MUL_RK, mul, RIRIKI, MUL_RR, 4, REGT_INT),
|
|
xx(DIV_RR, div, RIRIRI, NOP, 0, 0), // dA = dkB / dkC (signed)
|
|
xx(DIV_RK, div, RIRIKI, DIV_RR, 4, REGT_INT),
|
|
xx(DIV_KR, div, RIKIRI, DIV_RR, 2, REGT_INT),
|
|
xx(DIVU_RR, divu, RIRIRI, NOP, 0, 0), // dA = dkB / dkC (unsigned)
|
|
xx(DIVU_RK, divu, RIRIKI, DIVU_RR,4, REGT_INT),
|
|
xx(DIVU_KR, divu, RIKIRI, DIVU_RR,2, REGT_INT),
|
|
xx(MOD_RR, mod, RIRIRI, NOP, 0, 0), // dA = dkB % dkC (signed)
|
|
xx(MOD_RK, mod, RIRIKI, MOD_RR, 4, REGT_INT),
|
|
xx(MOD_KR, mod, RIKIRI, MOD_RR, 2, REGT_INT),
|
|
xx(MODU_RR, modu, RIRIRI, NOP, 0, 0), // dA = dkB % dkC (unsigned)
|
|
xx(MODU_RK, modu, RIRIKI, MODU_RR,4, REGT_INT),
|
|
xx(MODU_KR, modu, RIKIRI, MODU_RR,2, REGT_INT),
|
|
xx(AND_RR, and, RIRIRI, NOP, 0, 0), // dA = dB & dkC
|
|
xx(AND_RK, and, RIRIKI, AND_RR, 4, REGT_INT),
|
|
xx(OR_RR, or, RIRIRI, NOP, 0, 0), // dA = dB | dkC
|
|
xx(OR_RK, or, RIRIKI, OR_RR, 4, REGT_INT),
|
|
xx(XOR_RR, xor, RIRIRI, NOP, 0, 0), // dA = dB ^ dkC
|
|
xx(XOR_RK, xor, RIRIKI, XOR_RR, 4, REGT_INT),
|
|
xx(MIN_RR, min, RIRIRI, NOP, 0, 0), // dA = min(dB,dkC)
|
|
xx(MIN_RK, min, RIRIKI, MIN_RR, 4, REGT_INT),
|
|
xx(MAX_RR, max, RIRIRI, NOP, 0, 0), // dA = max(dB,dkC)
|
|
xx(MAX_RK, max, RIRIKI, MAX_RR, 4, REGT_INT),
|
|
xx(ABS, abs, RIRI, NOP, 0, 0), // dA = abs(dB)
|
|
xx(NEG, neg, RIRI, NOP, 0, 0), // dA = -dB
|
|
xx(NOT, not, RIRI, NOP, 0, 0), // dA = ~dB
|
|
xx(SEXT, sext, RIRII8, NOP, 0, 0), // dA = dB, sign extended by shifting left then right by C
|
|
xx(ZAP_R, zap, RIRIRI, NOP, 0, 0), // dA = dB, with bytes zeroed where bits in C/dC are one
|
|
xx(ZAP_I, zap, RIRII8, NOP, 0, 0),
|
|
xx(ZAPNOT_R, zapnot, RIRIRI, NOP, 0, 0), // dA = dB, with bytes zeroed where bits in C/dC are zero
|
|
xx(ZAPNOT_I, zapnot, RIRII8, NOP, 0, 0),
|
|
xx(EQ_R, beq, CIRR, NOP, 0, 0), // if ((dB == dkC) != A) then pc++
|
|
xx(EQ_K, beq, CIRK, EQ_R, 4, REGT_INT),
|
|
xx(LT_RR, blt, CIRR, NOP, 0, 0), // if ((dkB < dkC) != A) then pc++
|
|
xx(LT_RK, blt, CIRK, LT_RR, 4, REGT_INT),
|
|
xx(LT_KR, blt, CIKR, LT_RR, 2, REGT_INT),
|
|
xx(LE_RR, ble, CIRR, NOP, 0, 0), // if ((dkB <= dkC) != A) then pc++
|
|
xx(LE_RK, ble, CIRK, LE_RR, 4, REGT_INT),
|
|
xx(LE_KR, ble, CIKR, LE_RR, 2, REGT_INT),
|
|
xx(LTU_RR, bltu, CIRR, NOP, 0, 0), // if ((dkB < dkC) != A) then pc++ -- unsigned
|
|
xx(LTU_RK, bltu, CIRK, LTU_RR, 4, REGT_INT),
|
|
xx(LTU_KR, bltu, CIKR, LTU_RR, 2, REGT_INT),
|
|
xx(LEU_RR, bleu, CIRR, NOP, 0, 0), // if ((dkB <= dkC) != A) then pc++ -- unsigned
|
|
xx(LEU_RK, bleu, CIRK, LEU_RR, 4, REGT_INT),
|
|
xx(LEU_KR, bleu, CIKR, LEU_RR, 2, REGT_INT),
|
|
|
|
// Double-precision floating point math.
|
|
xx(ADDF_RR, add, RFRFRF, NOP, 0, 0), // fA = fB + fkC
|
|
xx(ADDF_RK, add, RFRFKF, ADDF_RR,4, REGT_FLOAT),
|
|
xx(SUBF_RR, sub, RFRFRF, NOP, 0, 0), // fA = fkB - fkC
|
|
xx(SUBF_RK, sub, RFRFKF, SUBF_RR,4, REGT_FLOAT),
|
|
xx(SUBF_KR, sub, RFKFRF, SUBF_RR,2, REGT_FLOAT),
|
|
xx(MULF_RR, mul, RFRFRF, NOP, 0, 0), // fA = fB * fkC
|
|
xx(MULF_RK, mul, RFRFKF, MULF_RR,4, REGT_FLOAT),
|
|
xx(DIVF_RR, div, RFRFRF, NOP, 0, 0), // fA = fkB / fkC
|
|
xx(DIVF_RK, div, RFRFKF, DIVF_RR,4, REGT_FLOAT),
|
|
xx(DIVF_KR, div, RFKFRF, DIVF_RR,2, REGT_FLOAT),
|
|
xx(MODF_RR, mod, RFRFRF, NOP, 0, 0), // fA = fkB % fkC
|
|
xx(MODF_RK, mod, RFRFKF, MODF_RR,4, REGT_FLOAT),
|
|
xx(MODF_KR, mod, RFKFRF, MODF_RR,4, REGT_FLOAT),
|
|
xx(POWF_RR, pow, RFRFRF, NOP, 0, 0), // fA = fkB ** fkC
|
|
xx(POWF_RK, pow, RFRFKF, POWF_RR,4, REGT_FLOAT),
|
|
xx(POWF_KR, pow, RFKFRF, POWF_RR,2, REGT_FLOAT),
|
|
xx(MINF_RR, min, RFRFRF, NOP, 0, 0), // fA = min(fB),fkC)
|
|
xx(MINF_RK, min, RFRFKF, MINF_RR,4, REGT_FLOAT),
|
|
xx(MAXF_RR, max, RFRFRF, NOP, 0, 0), // fA = max(fB),fkC)
|
|
xx(MAXF_RK, max, RFRFKF, MAXF_RR,4, REGT_FLOAT),
|
|
xx(ATAN2, atan2, RFRFRF, NOP, 0, 0), // fA = atan2(fB,fC), result is in degrees
|
|
xx(FLOP, flop, RFRFI8, NOP, 0, 0), // fA = f(fB), where function is selected by C
|
|
xx(EQF_R, beq, CFRR, NOP, 0, 0), // if ((fB == fkC) != (A & 1)) then pc++
|
|
xx(EQF_K, beq, CFRK, EQF_R, 4, REGT_FLOAT),
|
|
xx(LTF_RR, blt, CFRR, NOP, 0, 0), // if ((fkB < fkC) != (A & 1)) then pc++
|
|
xx(LTF_RK, blt, CFRK, LTF_RR, 4, REGT_FLOAT),
|
|
xx(LTF_KR, blt, CFKR, LTF_RR, 2, REGT_FLOAT),
|
|
xx(LEF_RR, ble, CFRR, NOP, 0, 0), // if ((fkb <= fkC) != (A & 1)) then pc++
|
|
xx(LEF_RK, ble, CFRK, LEF_RR, 4, REGT_FLOAT),
|
|
xx(LEF_KR, ble, CFKR, LEF_RR, 2, REGT_FLOAT),
|
|
|
|
// Vector math. (2D)
|
|
xx(NEGV2, negv2, RVRV, NOP, 0, 0), // vA = -vB
|
|
xx(ADDV2_RR, addv2, RVRVRV, NOP, 0, 0), // vA = vB + vkC
|
|
xx(SUBV2_RR, subv2, RVRVRV, NOP, 0, 0), // vA = vkB - vkC
|
|
xx(DOTV2_RR, dotv2, RVRVRV, NOP, 0, 0), // va = vB dot vkC
|
|
xx(MULVF2_RR, mulv2, RVRVRF, NOP, 0, 0), // vA = vkB * fkC
|
|
xx(MULVF2_RK, mulv2, RVRVKF, MULVF2_RR,4, REGT_FLOAT),
|
|
xx(DIVVF2_RR, divv2, RVRVRF, NOP, 0, 0), // vA = vkB / fkC
|
|
xx(DIVVF2_RK, divv2, RVRVKF, DIVVF2_RR,4, REGT_FLOAT),
|
|
xx(LENV2, lenv2, RFRV, NOP, 0, 0), // fA = vB.Length
|
|
xx(EQV2_R, beqv2, CVRR, NOP, 0, 0), // if ((vB == vkC) != A) then pc++ (inexact if A & 32)
|
|
xx(EQV2_K, beqv2, CVRK, NOP, 0, 0), // this will never be used.
|
|
|
|
// Vector math (3D)
|
|
xx(NEGV3, negv3, RVRV, NOP, 0, 0), // vA = -vB
|
|
xx(ADDV3_RR, addv3, RVRVRV, NOP, 0, 0), // vA = vB + vkC
|
|
xx(SUBV3_RR, subv3, RVRVRV, NOP, 0, 0), // vA = vkB - vkC
|
|
xx(DOTV3_RR, dotv3, RVRVRV, NOP, 0, 0), // va = vB dot vkC
|
|
xx(CROSSV_RR, crossv, RVRVRV, NOP, 0, 0), // vA = vkB cross vkC
|
|
xx(MULVF3_RR, mulv3, RVRVRF, NOP, 0, 0), // vA = vkB * fkC
|
|
xx(MULVF3_RK, mulv3, RVRVKF, MULVF3_RR,4, REGT_FLOAT),
|
|
xx(DIVVF3_RR, divv3, RVRVRF, NOP, 0, 0), // vA = vkB / fkC
|
|
xx(DIVVF3_RK, divv3, RVRVKF, DIVVF3_RR,4, REGT_FLOAT),
|
|
xx(LENV3, lenv3, RFRV, NOP, 0, 0), // fA = vB.Length
|
|
xx(EQV3_R, beqv3, CVRR, NOP, 0, 0), // if ((vB == vkC) != A) then pc++ (inexact if A & 33)
|
|
xx(EQV3_K, beqv3, CVRK, NOP, 0, 0), // this will never be used.
|
|
|
|
// Pointer math.
|
|
xx(ADDA_RR, add, RPRPRI, NOP, 0, 0), // pA = pB + dkC
|
|
xx(ADDA_RK, add, RPRPKI, ADDA_RR,4, REGT_POINTER),
|
|
xx(SUBA, sub, RIRPRP, NOP, 0, 0), // dA = pB - pC
|
|
xx(EQA_R, beq, CPRR, NOP, 0, 0), // if ((pB == pkC) != A) then pc++
|
|
xx(EQA_K, beq, CPRK, EQA_R, 4, REGT_POINTER),
|
|
|
|
#undef xx
|