qzdoom/src/scripting/vm/vmops.h
Christoph Oelckers f9cd2c9af7 - added switch/case processing. Right now it is just a sequence of test/jmp instructions. It may make sense to add a special opcode that can perform the comparisons natively but that's an option for later.
- added a TESTN instruction. This is like TEST but negates the operand. This was added to avoid flooding the constant table with too many case labels. With TEST and TESTN combined, all numbers between -65535 and 65535 can be kept entirely inside the instruction. Numbers outside this range still use a BEQ instruction.
2016-10-23 12:00:25 +02:00

222 lines
8.5 KiB
C

#ifndef xx
#define xx(op, name, mode) OP_##op
#endif
xx(NOP, nop, NOP), // no operation
// Load constants.
xx(LI, li, LI), // load immediate signed 16-bit constant
xx(LK, lk, LKI), // load integer constant
xx(LKF, lk, LKF), // load float constant
xx(LKS, lk, LKS), // load string constant
xx(LKP, lk, LKP), // load pointer constant
xx(LFP, lf, LFP), // load frame pointer
// Load from memory. rA = *(rB + rkC)
xx(LB, lb, RIRPKI), // load byte
xx(LB_R, lb, RIRPRI),
xx(LH, lh, RIRPKI), // load halfword
xx(LH_R, lh, RIRPRI),
xx(LW, lw, RIRPKI), // load word
xx(LW_R, lw, RIRPRI),
xx(LBU, lbu, RIRPKI), // load byte unsigned
xx(LBU_R, lbu, RIRPRI),
xx(LHU, lhu, RIRPKI), // load halfword unsigned
xx(LHU_R, lhu, RIRPRI),
xx(LSP, lsp, RFRPKI), // load single-precision fp
xx(LSP_R, lsp, RFRPRI),
xx(LDP, ldp, RFRPKI), // load double-precision fp
xx(LDP_R, ldp, RFRPRI),
xx(LS, ls, RSRPKI), // load string
xx(LS_R, ls, RSRPRI),
xx(LO, lo, RPRPKI), // load object
xx(LO_R, lo, RPRPRI),
xx(LP, lp, RPRPKI), // load pointer
xx(LP_R, lp, RPRPRI),
xx(LV, lv, RVRPKI), // load vector
xx(LV_R, lv, RVRPRI),
xx(LBIT, lbit, RIRPI8), // rA = !!(*rB & C) -- *rB is a byte
// Store instructions. *(rA + rkC) = rB
xx(SB, sb, RPRIKI), // store byte
xx(SB_R, sb, RPRIRI),
xx(SH, sh, RPRIKI), // store halfword
xx(SH_R, sh, RPRIRI),
xx(SW, sw, RPRIKI), // store word
xx(SW_R, sw, RPRIRI),
xx(SSP, ssp, RPRFKI), // store single-precision fp
xx(SSP_R, ssp, RPRFRI),
xx(SDP, sdp, RPRFKI), // store double-precision fp
xx(SDP_R, sdp, RPRFRI),
xx(SS, ss, RPRSKI), // store string
xx(SS_R, ss, RPRSRI),
xx(SP, sp, RPRPKI), // store pointer
xx(SP_R, sp, RPRPRI),
xx(SV, sv, RPRVKI), // store vector
xx(SV_R, sv, RPRVRI),
xx(SBIT, sbit, RPRII8), // *rA |= C if rB is true, *rA &= ~C otherwise
// Move instructions.
xx(MOVE, mov, RIRI), // dA = dB
xx(MOVEF, mov, RFRF), // fA = fB
xx(MOVES, mov, RSRS), // sA = sB
xx(MOVEA, mov, RPRP), // aA = aB
xx(CAST, cast, CAST), // xA = xB, conversion specified by C
xx(DYNCAST_R, dyncast,RPRPRP), // aA = aB after casting to rkC (specifying a class)
xx(DYNCAST_K, dyncast,RPRPKP),
// Control flow.
xx(TEST, test, RII16), // if (dA != BC) then pc++
xx(TESTN, testn, RII16), // if (dA != -BC) then pc++
xx(JMP, jmp, I24), // pc += ABC -- The ABC fields contain a signed 24-bit offset.
xx(IJMP, ijmp, RII16), // pc += dA + BC -- BC is a signed offset. The target instruction must be a JMP.
xx(PARAM, param, __BCP), // push parameter encoded in BC for function call (B=regtype, C=regnum)
xx(PARAMI, parami, I24), // push immediate, signed integer for function call
xx(CALL, call, RPI8I8), // Call function pkA with parameter count B and expected result count C
xx(CALL_K, call, KPI8I8),
xx(TAIL, tail, RPI8), // Call+Ret in a single instruction
xx(TAIL_K, tail, KPI8),
xx(RESULT, result, __BCP), // Result should go in register encoded in BC (in caller, after CALL)
xx(RET, ret, I8BCP), // Copy value from register encoded in BC to return value A, possibly returning
xx(RETI, reti, I8I16), // Copy immediate from BC to return value A, possibly returning
xx(TRY, try, I24), // When an exception is thrown, start searching for a handler at pc + ABC
xx(UNTRY, untry, I8), // Pop A entries off the exception stack
xx(THROW, throw, THROW), // A == 0: Throw exception object pB
// A == 1: Throw exception object pkB
// A >= 2: Throw VM exception of type BC
xx(CATCH, catch, CATCH), // 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), // if rA >= BC, throw exception
// String instructions.
xx(CONCAT, concat, RSRSRS), // sA = sB.. ... ..sC
xx(LENS, lens, RIRS), // dA = sB.Length
xx(CMPS, cmps, I8RXRX), // if ((skB op skC) != (A & 1)) then pc++
// Integer math.
xx(SLL_RR, sll, RIRIRI), // dA = dkB << diC
xx(SLL_RI, sll, RIRII8),
xx(SLL_KR, sll, RIKIRI),
xx(SRL_RR, srl, RIRIRI), // dA = dkB >> diC -- unsigned
xx(SRL_RI, srl, RIRII8),
xx(SRL_KR, srl, RIKIRI),
xx(SRA_RR, sra, RIRIRI), // dA = dkB >> diC -- signed
xx(SRA_RI, sra, RIRII8),
xx(SRA_KR, sra, RIKIRI),
xx(ADD_RR, add, RIRIRI), // dA = dB + dkC
xx(ADD_RK, add, RIRIKI),
xx(ADDI, addi, RIRIIs), // dA = dB + C -- C is a signed 8-bit constant
xx(SUB_RR, sub, RIRIRI), // dA = dkB - dkC
xx(SUB_RK, sub, RIRIKI),
xx(SUB_KR, sub, RIKIRI),
xx(MUL_RR, mul, RIRIRI), // dA = dB * dkC
xx(MUL_RK, mul, RIRIKI),
xx(DIV_RR, div, RIRIRI), // dA = dkB / dkC (signed)
xx(DIV_RK, div, RIRIKI),
xx(DIV_KR, div, RIKIRI),
xx(DIVU_RR, divu, RIRIRI), // dA = dkB / dkC (unsigned)
xx(DIVU_RK, divu, RIRIKI),
xx(DIVU_KR, divu, RIKIRI),
xx(MOD_RR, mod, RIRIRI), // dA = dkB % dkC (signed)
xx(MOD_RK, mod, RIRIKI),
xx(MOD_KR, mod, RIKIRI),
xx(MODU_RR, modu, RIRIRI), // dA = dkB % dkC (unsigned)
xx(MODU_RK, modu, RIRIKI),
xx(MODU_KR, modu, RIKIRI),
xx(AND_RR, and, RIRIRI), // dA = dB & dkC
xx(AND_RK, and, RIRIKI),
xx(OR_RR, or, RIRIRI), // dA = dB | dkC
xx(OR_RK, or, RIRIKI),
xx(XOR_RR, xor, RIRIRI), // dA = dB ^ dkC
xx(XOR_RK, xor, RIRIKI),
xx(MIN_RR, min, RIRIRI), // dA = min(dB,dkC)
xx(MIN_RK, min, RIRIKI),
xx(MAX_RR, max, RIRIRI), // dA = max(dB,dkC)
xx(MAX_RK, max, RIRIKI),
xx(ABS, abs, RIRI), // dA = abs(dB)
xx(NEG, neg, RIRI), // dA = -dB
xx(NOT, not, RIRI), // dA = ~dB
xx(SEXT, sext, RIRII8), // dA = dB, sign extended by shifting left then right by C
xx(ZAP_R, zap, RIRIRI), // dA = dB, with bytes zeroed where bits in C/dC are one
xx(ZAP_I, zap, RIRII8),
xx(ZAPNOT_R, zapnot, RIRIRI), // dA = dB, with bytes zeroed where bits in C/dC are zero
xx(ZAPNOT_I, zapnot, RIRII8),
xx(EQ_R, beq, CIRR), // if ((dB == dkC) != A) then pc++
xx(EQ_K, beq, CIRK),
xx(LT_RR, blt, CIRR), // if ((dkB < dkC) != A) then pc++
xx(LT_RK, blt, CIRK),
xx(LT_KR, blt, CIKR),
xx(LE_RR, ble, CIRR), // if ((dkB <= dkC) != A) then pc++
xx(LE_RK, ble, CIRK),
xx(LE_KR, ble, CIKR),
xx(LTU_RR, bltu, CIRR), // if ((dkB < dkC) != A) then pc++ -- unsigned
xx(LTU_RK, bltu, CIRK),
xx(LTU_KR, bltu, CIKR),
xx(LEU_RR, bleu, CIRR), // if ((dkB <= dkC) != A) then pc++ -- unsigned
xx(LEU_RK, bleu, CIRK),
xx(LEU_KR, bleu, CIKR),
// Double-precision floating point math.
xx(ADDF_RR, add, RFRFRF), // fA = fB + fkC
xx(ADDF_RK, add, RFRFKF),
xx(SUBF_RR, sub, RFRFRF), // fA = fkB - fkC
xx(SUBF_RK, sub, RFRFKF),
xx(SUBF_KR, sub, RFKFRF),
xx(MULF_RR, mul, RFRFRF), // fA = fB * fkC
xx(MULF_RK, mul, RFRFKF),
xx(DIVF_RR, div, RFRFRF), // fA = fkB / fkC
xx(DIVF_RK, div, RFRFKF),
xx(DIVF_KR, div, RFKFRF),
xx(MODF_RR, mod, RFRFRF), // fA = fkB % fkC
xx(MODF_RK, mod, RFRFKF),
xx(MODF_KR, mod, RFKFRF),
xx(POWF_RR, pow, RFRFRF), // fA = fkB ** fkC
xx(POWF_RK, pow, RFRFKF),
xx(POWF_KR, pow, RFKFRF),
xx(MINF_RR, min, RFRFRF), // fA = min(fB),fkC)
xx(MINF_RK, min, RFRFKF),
xx(MAXF_RR, max, RFRFRF), // fA = max(fB),fkC)
xx(MAXF_RK, max, RFRFKF),
xx(ATAN2, atan2, RFRFRF), // fA = atan2(fB,fC), result is in degrees
xx(FLOP, flop, RFRFI8), // fA = f(fB), where function is selected by C
xx(EQF_R, beq, CFRR), // if ((fB == fkC) != (A & 1)) then pc++
xx(EQF_K, beq, CFRK),
xx(LTF_RR, blt, CFRR), // if ((fkB < fkC) != (A & 1)) then pc++
xx(LTF_RK, blt, CFRK),
xx(LTF_KR, blt, CFKR),
xx(LEF_RR, ble, CFRR), // if ((fkb <= fkC) != (A & 1)) then pc++
xx(LEF_RK, ble, CFRK),
xx(LEF_KR, ble, CFKR),
// Vector math.
xx(NEGV, negv, RVRV), // vA = -vB
xx(ADDV_RR, addv, RVRVRV), // vA = vB + vkC
xx(ADDV_RK, addv, RVRVKV),
xx(SUBV_RR, subv, RVRVRV), // vA = vkB - vkC
xx(SUBV_RK, subv, RVRVKV),
xx(SUBV_KR, subv, RVKVRV),
xx(DOTV_RR, dotv, RVRVRV), // va = vB dot vkC
xx(DOTV_RK, dotv, RVRVKV),
xx(CROSSV_RR, crossv, RVRVRV), // vA = vkB cross vkC
xx(CROSSV_RK, crossv, RVRVKV),
xx(CROSSV_KR, crossv, RVKVRV),
xx(MULVF_RR, mulv, RVRVRV), // vA = vkB * fkC
xx(MULVF_RK, mulv, RVRVKV),
xx(MULVF_KR, mulv, RVKVRV),
xx(LENV, lenv, RFRV), // fA = vB.Length
xx(EQV_R, beqv, CVRR), // if ((vB == vkC) != A) then pc++ (inexact if A & 32)
xx(EQV_K, beqv, CVRK),
// Pointer math.
xx(ADDA_RR, add, RPRPRI), // pA = pB + dkC
xx(ADDA_RK, add, RPRPKI),
xx(SUBA, sub, RIRPRP), // dA = pB - pC
xx(EQA_R, beq, CPRR), // if ((pB == pkC) != A) then pc++
xx(EQA_K, beq, CPRK),
#undef xx