mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 07:12:02 +00:00
- removed all constant versions of vector instructions. The vector code does not use compound constants so there's no need to have instructions for them.
- fixed: The code generator had no good safeguards for exceeding the maximum amount of registers. All there was was a handful of pitiful asserts which in production code do nothing at all but generate broken output. Even worse, the VM was hardwired to at most 255 constants per type per function by storing the constant count in a byte! This has been extended to 65535, but since many instructions only have a byte available for the constant index, a workaround had to be added to do a two-instruction setup if larger indices are needed.
This commit is contained in:
parent
1c2c26eb08
commit
e93961da96
7 changed files with 336 additions and 321 deletions
|
@ -1993,7 +1993,7 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build)
|
|||
|
||||
if (regtype == REGT_INT)
|
||||
{
|
||||
build->Emit(OP_ADDI, value.RegNum, value.RegNum, (Token == TK_Incr) ? 1 : -1);
|
||||
build->Emit(OP_ADDI, value.RegNum, value.RegNum, uint8_t((Token == TK_Incr) ? 1 : -1));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2077,7 +2077,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build)
|
|||
ExpEmit assign(build, regtype);
|
||||
if (regtype == REGT_INT)
|
||||
{
|
||||
build->Emit(OP_ADDI, assign.RegNum, out.RegNum, (Token == TK_Incr) ? 1 : -1);
|
||||
build->Emit(OP_ADDI, assign.RegNum, out.RegNum, uint8_t((Token == TK_Incr) ? 1 : -1));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2094,7 +2094,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build)
|
|||
if (regtype == REGT_INT)
|
||||
{
|
||||
build->Emit(OP_MOVE, out.RegNum, pointer.RegNum);
|
||||
build->Emit(OP_ADDI, pointer.RegNum, pointer.RegNum, (Token == TK_Incr) ? 1 : -1);
|
||||
build->Emit(OP_ADDI, pointer.RegNum, pointer.RegNum, uint8_t((Token == TK_Incr) ? 1 : -1));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2108,7 +2108,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
if (regtype == REGT_INT)
|
||||
{
|
||||
build->Emit(OP_ADDI, pointer.RegNum, pointer.RegNum, (Token == TK_Incr) ? 1 : -1);
|
||||
build->Emit(OP_ADDI, pointer.RegNum, pointer.RegNum, uint8_t((Token == TK_Incr) ? 1 : -1));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -814,10 +814,10 @@ public:
|
|||
VM_UBYTE NumRegF;
|
||||
VM_UBYTE NumRegS;
|
||||
VM_UBYTE NumRegA;
|
||||
VM_UBYTE NumKonstD;
|
||||
VM_UBYTE NumKonstF;
|
||||
VM_UBYTE NumKonstS;
|
||||
VM_UBYTE NumKonstA;
|
||||
VM_UHALF NumKonstD;
|
||||
VM_UHALF NumKonstF;
|
||||
VM_UHALF NumKonstS;
|
||||
VM_UHALF NumKonstA;
|
||||
VM_UHALF MaxParam; // Maximum number of parameters this function has on the stack at once
|
||||
VM_UBYTE NumArgs; // Number of arguments this function takes
|
||||
FString PrintableName; // so that the VM can print meaningful info if something in this function goes wrong.
|
||||
|
|
|
@ -36,6 +36,19 @@
|
|||
#include "info.h"
|
||||
#include "m_argv.h"
|
||||
#include "thingdef.h"
|
||||
#include "doomerrors.h"
|
||||
|
||||
struct VMRemap
|
||||
{
|
||||
BYTE altOp, kReg, kType;
|
||||
};
|
||||
|
||||
|
||||
#define xx(op, name, mode, alt, kreg, ktype) {OP_##alt, kreg, ktype }
|
||||
VMRemap opRemap[NUM_OPS] = {
|
||||
#include "vmops.h"
|
||||
};
|
||||
#undef xx
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -523,10 +536,75 @@ size_t VMFunctionBuilder::GetAddress()
|
|||
|
||||
size_t VMFunctionBuilder::Emit(int opcode, int opa, int opb, int opc)
|
||||
{
|
||||
static BYTE opcodes[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP };
|
||||
|
||||
assert(opcode >= 0 && opcode < NUM_OPS);
|
||||
assert(opa >= 0 && opa <= 255);
|
||||
assert(opb >= 0 && opb <= 255);
|
||||
assert(opc >= 0 && opc <= 255);
|
||||
assert(opa >= 0);
|
||||
assert(opb >= 0);
|
||||
assert(opc >= 0);
|
||||
|
||||
|
||||
// The following were just asserts, meaning this would silently create broken code if there was an overflow
|
||||
// if this happened in a release build. Not good.
|
||||
// These are critical errors that need to be reported to the user.
|
||||
// In addition, the limit of 256 constants can easily be exceeded with arrays so this had to be extended to
|
||||
// 65535 by adding some checks here that map byte-limited instructions to alternatives that can handle larger indices.
|
||||
// (See vmops.h for the remapping info.)
|
||||
|
||||
// Note: OP_CMPS also needs treatment, but I do not expect constant overflow to become an issue with strings, so for now there is no handling.
|
||||
|
||||
if (opa > 255)
|
||||
{
|
||||
if (opRemap[opcode].kReg != 1 || opa > 32767)
|
||||
{
|
||||
I_Error("Register limit exceeded");
|
||||
}
|
||||
int regtype = opRemap[opcode].kType;
|
||||
ExpEmit emit(this, regtype);
|
||||
Emit(opcodes[regtype], emit.RegNum, opa);
|
||||
opcode = opRemap[opcode].altOp;
|
||||
opa = emit.RegNum;
|
||||
emit.Free(this);
|
||||
}
|
||||
if (opb > 255)
|
||||
{
|
||||
if (opRemap[opcode].kReg != 2 || opb > 32767)
|
||||
{
|
||||
I_Error("Register limit exceeded");
|
||||
}
|
||||
int regtype = opRemap[opcode].kType;
|
||||
ExpEmit emit(this, regtype);
|
||||
Emit(opcodes[regtype], emit.RegNum, opb);
|
||||
opcode = opRemap[opcode].altOp;
|
||||
opb = emit.RegNum;
|
||||
emit.Free(this);
|
||||
}
|
||||
if (opc > 255)
|
||||
{
|
||||
if (opcode == OP_PARAM && (opb & REGT_KONST) && opc <= 32767)
|
||||
{
|
||||
int regtype = opb & REGT_TYPE;
|
||||
opb = regtype;
|
||||
ExpEmit emit(this, regtype);
|
||||
Emit(opcodes[regtype], emit.RegNum, opc);
|
||||
opc = emit.RegNum;
|
||||
emit.Free(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (opRemap[opcode].kReg != 4 || opc > 32767)
|
||||
{
|
||||
I_Error("Register limit exceeded");
|
||||
}
|
||||
int regtype = opRemap[opcode].kType;
|
||||
ExpEmit emit(this, regtype);
|
||||
Emit(opcodes[regtype], emit.RegNum, opc);
|
||||
opcode = opRemap[opcode].altOp;
|
||||
opc = emit.RegNum;
|
||||
emit.Free(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (opcode == OP_PARAM)
|
||||
{
|
||||
int chg;
|
||||
|
@ -784,6 +862,8 @@ void FFunctionBuildList::Build()
|
|||
}
|
||||
|
||||
// Emit code
|
||||
try
|
||||
{
|
||||
item.Code->Emit(&buildit);
|
||||
buildit.MakeFunction(sfunc);
|
||||
sfunc->NumArgs = 0;
|
||||
|
@ -802,6 +882,12 @@ void FFunctionBuildList::Build()
|
|||
sfunc->PrintableName = item.PrintableName;
|
||||
sfunc->Unsafe = ctx.Unsafe;
|
||||
}
|
||||
catch (CRecoverableError &err)
|
||||
{
|
||||
// catch errors from the code generator and pring something meaningful.
|
||||
item.Code->ScriptPosition.Message(MSG_ERROR, "%s in %s", err.GetMessage(), item.PrintableName);
|
||||
}
|
||||
}
|
||||
delete item.Code;
|
||||
if (dump != nullptr)
|
||||
{
|
||||
|
|
|
@ -147,7 +147,7 @@
|
|||
|
||||
const VMOpInfo OpInfo[NUM_OPS] =
|
||||
{
|
||||
#define xx(op, name, mode) { #name, mode }
|
||||
#define xx(op, name, mode, alt, kreg, ktype) { #name, mode }
|
||||
#include "vmops.h"
|
||||
};
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret)
|
|||
#if COMPGOTO
|
||||
static const void * const ops[256] =
|
||||
{
|
||||
#define xx(op,sym,mode) &&op
|
||||
#define xx(op,sym,mode,alt,kreg,ktype) &&op
|
||||
#include "vmops.h"
|
||||
};
|
||||
#endif
|
||||
|
@ -425,12 +425,6 @@ begin:
|
|||
DoCast(reg, f, a, B, C);
|
||||
}
|
||||
NEXTOP;
|
||||
OP(DYNCAST_R):
|
||||
// UNDONE
|
||||
NEXTOP;
|
||||
OP(DYNCAST_K):
|
||||
// UNDONE
|
||||
NEXTOP;
|
||||
|
||||
OP(TEST):
|
||||
ASSERTD(a);
|
||||
|
@ -1315,42 +1309,23 @@ begin:
|
|||
OP(ADDV2_RR):
|
||||
ASSERTF(a+1); ASSERTF(B+1); ASSERTF(C+1);
|
||||
fcp = ®.f[C];
|
||||
Do_ADDV2:
|
||||
fbp = ®.f[B];
|
||||
reg.f[a] = fbp[0] + fcp[0];
|
||||
reg.f[a+1] = fbp[1] + fcp[1];
|
||||
NEXTOP;
|
||||
OP(ADDV2_RK):
|
||||
fcp = &konstf[C];
|
||||
goto Do_ADDV2;
|
||||
|
||||
OP(SUBV2_RR):
|
||||
ASSERTF(a+1); ASSERTF(B+1); ASSERTF(C+1);
|
||||
fbp = ®.f[B];
|
||||
fcp = ®.f[C];
|
||||
Do_SUBV2:
|
||||
reg.f[a] = fbp[0] - fcp[0];
|
||||
reg.f[a+1] = fbp[1] - fcp[1];
|
||||
NEXTOP;
|
||||
OP(SUBV2_RK):
|
||||
ASSERTF(a+1); ASSERTF(B+1); ASSERTKF(C+1);
|
||||
fbp = ®.f[B];
|
||||
fcp = &konstf[C];
|
||||
goto Do_SUBV2;
|
||||
OP(SUBV2_KR):
|
||||
ASSERTF(A+1); ASSERTKF(B+1); ASSERTF(C+1);
|
||||
fbp = &konstf[B];
|
||||
fcp = ®.f[C];
|
||||
goto Do_SUBV2;
|
||||
|
||||
OP(DOTV2_RR):
|
||||
ASSERTF(a); ASSERTF(B+1); ASSERTF(C+1);
|
||||
reg.f[a] = reg.f[B] * reg.f[C] + reg.f[B+1] * reg.f[C+1];
|
||||
NEXTOP;
|
||||
OP(DOTV2_RK):
|
||||
ASSERTF(a); ASSERTF(B+1); ASSERTKF(C+1);
|
||||
reg.f[a] = reg.f[B] * konstf[C] + reg.f[B+1] * konstf[C+1];
|
||||
NEXTOP;
|
||||
|
||||
OP(MULVF2_RR):
|
||||
ASSERTF(a+1); ASSERTF(B+1); ASSERTF(C);
|
||||
|
@ -1414,50 +1389,30 @@ begin:
|
|||
OP(ADDV3_RR):
|
||||
ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C+2);
|
||||
fcp = ®.f[C];
|
||||
Do_ADDV3:
|
||||
fbp = ®.f[B];
|
||||
reg.f[a] = fbp[0] + fcp[0];
|
||||
reg.f[a+1] = fbp[1] + fcp[1];
|
||||
reg.f[a+2] = fbp[2] + fcp[2];
|
||||
NEXTOP;
|
||||
OP(ADDV3_RK):
|
||||
fcp = &konstf[C];
|
||||
goto Do_ADDV3;
|
||||
|
||||
OP(SUBV3_RR):
|
||||
ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C+2);
|
||||
fbp = ®.f[B];
|
||||
fcp = ®.f[C];
|
||||
Do_SUBV3:
|
||||
reg.f[a] = fbp[0] - fcp[0];
|
||||
reg.f[a+1] = fbp[1] - fcp[1];
|
||||
reg.f[a+2] = fbp[2] - fcp[2];
|
||||
NEXTOP;
|
||||
OP(SUBV3_RK):
|
||||
ASSERTF(a+2); ASSERTF(B+2); ASSERTKF(C+2);
|
||||
fbp = ®.f[B];
|
||||
fcp = &konstf[C];
|
||||
goto Do_SUBV3;
|
||||
OP(SUBV3_KR):
|
||||
ASSERTF(A+2); ASSERTKF(B+2); ASSERTF(C+2);
|
||||
fbp = &konstf[B];
|
||||
fcp = ®.f[C];
|
||||
goto Do_SUBV3;
|
||||
|
||||
OP(DOTV3_RR):
|
||||
ASSERTF(a); ASSERTF(B+2); ASSERTF(C+2);
|
||||
reg.f[a] = reg.f[B] * reg.f[C] + reg.f[B+1] * reg.f[C+1] + reg.f[B+2] * reg.f[C+2];
|
||||
NEXTOP;
|
||||
OP(DOTV3_RK):
|
||||
ASSERTF(a); ASSERTF(B+2); ASSERTKF(C+2);
|
||||
reg.f[a] = reg.f[B] * konstf[C] + reg.f[B+1] * konstf[C+1] + reg.f[B+2] * konstf[C+2];
|
||||
NEXTOP;
|
||||
|
||||
OP(CROSSV_RR):
|
||||
ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C+2);
|
||||
fbp = ®.f[B];
|
||||
fcp = ®.f[C];
|
||||
Do_CROSSV:
|
||||
{
|
||||
double t[3];
|
||||
t[2] = fbp[0] * fcp[1] - fbp[1] * fcp[0];
|
||||
|
@ -1466,46 +1421,24 @@ begin:
|
|||
reg.f[a] = t[0]; reg.f[a+1] = t[1]; reg.f[a+2] = t[2];
|
||||
}
|
||||
NEXTOP;
|
||||
OP(CROSSV_RK):
|
||||
ASSERTF(a+2); ASSERTF(B+2); ASSERTKF(C+2);
|
||||
fbp = ®.f[B];
|
||||
fcp = &konstf[C];
|
||||
goto Do_CROSSV;
|
||||
OP(CROSSV_KR):
|
||||
ASSERTF(a+2); ASSERTKF(B+2); ASSERTF(C+2);
|
||||
fbp = ®.f[B];
|
||||
fcp = &konstf[C];
|
||||
goto Do_CROSSV;
|
||||
|
||||
OP(MULVF3_RR):
|
||||
ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C);
|
||||
fc = reg.f[C];
|
||||
fbp = ®.f[B];
|
||||
Do_MULV3:
|
||||
reg.f[a] = fbp[0] * fc;
|
||||
reg.f[a+1] = fbp[1] * fc;
|
||||
reg.f[a+2] = fbp[2] * fc;
|
||||
NEXTOP;
|
||||
OP(MULVF3_RK):
|
||||
ASSERTF(a+2); ASSERTF(B+2); ASSERTKF(C);
|
||||
fc = konstf[C];
|
||||
fbp = ®.f[B];
|
||||
goto Do_MULV3;
|
||||
|
||||
OP(DIVVF3_RR):
|
||||
ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C);
|
||||
fc = reg.f[C];
|
||||
fbp = ®.f[B];
|
||||
Do_DIVV3:
|
||||
reg.f[a] = fbp[0] / fc;
|
||||
reg.f[a+1] = fbp[1] / fc;
|
||||
reg.f[a+2] = fbp[2] / fc;
|
||||
NEXTOP;
|
||||
OP(DIVVF3_RK):
|
||||
ASSERTF(a+2); ASSERTF(B+2); ASSERTKF(C);
|
||||
fc = konstf[C];
|
||||
fbp = ®.f[B];
|
||||
goto Do_DIVV3;
|
||||
|
||||
OP(LENV3):
|
||||
ASSERTF(a); ASSERTF(B+2);
|
||||
|
|
|
@ -86,10 +86,10 @@ void VMScriptFunction::Alloc(int numops, int numkonstd, int numkonstf, int numko
|
|||
{
|
||||
assert(Code == NULL);
|
||||
assert(numops > 0);
|
||||
assert(numkonstd >= 0 && numkonstd <= 255);
|
||||
assert(numkonstf >= 0 && numkonstf <= 255);
|
||||
assert(numkonsts >= 0 && numkonsts <= 255);
|
||||
assert(numkonsta >= 0 && numkonsta <= 255);
|
||||
assert(numkonstd >= 0 && numkonstd <= 65535);
|
||||
assert(numkonstf >= 0 && numkonstf <= 65535);
|
||||
assert(numkonsts >= 0 && numkonsts <= 65535);
|
||||
assert(numkonsta >= 0 && numkonsta <= 65535);
|
||||
void *mem = M_Malloc(numops * sizeof(VMOP) +
|
||||
numkonstd * sizeof(int) +
|
||||
numkonstf * sizeof(double) +
|
||||
|
|
|
@ -1,251 +1,247 @@
|
|||
#ifndef xx
|
||||
#define xx(op, name, mode) OP_##op
|
||||
#define xx(op, name, mode, alt, kreg, ktype) OP_##op
|
||||
#endif
|
||||
|
||||
xx(NOP, nop, NOP), // no operation
|
||||
// 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), // 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(LK_R, lk, RIRII8), // load integer constant indexed
|
||||
xx(LKF_R, lk, RFRII8), // load float constant indexed
|
||||
xx(LKS_R, lk, RSRII8), // load string constant indexed
|
||||
xx(LKP_R, lk, RPRII8), // load pointer constant indexed
|
||||
xx(LFP, lf, LFP), // load frame pointer
|
||||
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
|
||||
|
||||
// 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(LV2, lv2, RVRPKI), // load vector2
|
||||
xx(LV2_R, lv2, RVRPRI),
|
||||
xx(LV3, lv3, RVRPKI), // load vector3
|
||||
xx(LV3_R, lv3, RVRPRI),
|
||||
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), // rA = !!(*rB & C) -- *rB is a byte
|
||||
xx(LBIT, lbit, RIRPI8, NOP, 0, 0), // 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(SV2, sv2, RPRVKI), // store vector2
|
||||
xx(SV2_R, sv2, RPRVRI),
|
||||
xx(SV3, sv3, RPRVKI), // store vector3
|
||||
xx(SV3_R, sv3, RPRVRI),
|
||||
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), // *rA |= C if rB is true, *rA &= ~C otherwise
|
||||
xx(SBIT, sbit, RPRII8, NOP, 0, 0), // *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(MOVEV2, mov2, RFRF), // fA = fB (2 elements)
|
||||
xx(MOVEV3, mov3, RFRF), // fA = fB (3 elements)
|
||||
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),
|
||||
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
|
||||
|
||||
// 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(VTBL, vtbl, RPRPI8), // dereferences a virtual method table.
|
||||
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
|
||||
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), // A == 0: continue search on next try
|
||||
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), // if rA >= BC, throw exception
|
||||
xx(BOUND, bound, RII16, NOP, 0, 0), // 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++
|
||||
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), // 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),
|
||||
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), // 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),
|
||||
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), // vA = -vB
|
||||
xx(ADDV2_RR, addv2, RVRVRV), // vA = vB + vkC
|
||||
xx(ADDV2_RK, addv2, RVRVKV),
|
||||
xx(SUBV2_RR, subv2, RVRVRV), // vA = vkB - vkC
|
||||
xx(SUBV2_RK, subv2, RVRVKV),
|
||||
xx(SUBV2_KR, subv2, RVKVRV),
|
||||
xx(DOTV2_RR, dotv2, RVRVRV), // va = vB dot vkC
|
||||
xx(DOTV2_RK, dotv2, RVRVKV),
|
||||
xx(MULVF2_RR, mulv2, RVRVRF), // vA = vkB * fkC
|
||||
xx(MULVF2_RK, mulv2, RVRVKF),
|
||||
xx(DIVVF2_RR, divv2, RVRVRF), // vA = vkB / fkC
|
||||
xx(DIVVF2_RK, divv2, RVRVKF),
|
||||
xx(LENV2, lenv2, RFRV), // fA = vB.Length
|
||||
xx(EQV2_R, beqv2, CVRR), // if ((vB == vkC) != A) then pc++ (inexact if A & 32)
|
||||
xx(EQV2_K, beqv2, CVRK),
|
||||
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), // vA = -vB
|
||||
xx(ADDV3_RR, addv3, RVRVRV), // vA = vB + vkC
|
||||
xx(ADDV3_RK, addv3, RVRVKV),
|
||||
xx(SUBV3_RR, subv3, RVRVRV), // vA = vkB - vkC
|
||||
xx(SUBV3_RK, subv3, RVRVKV),
|
||||
xx(SUBV3_KR, subv3, RVKVRV),
|
||||
xx(DOTV3_RR, dotv3, RVRVRV), // va = vB dot vkC
|
||||
xx(DOTV3_RK, dotv3, RVRVKV),
|
||||
xx(CROSSV_RR, crossv, RVRVRV), // vA = vkB cross vkC
|
||||
xx(CROSSV_RK, crossv, RVRVKV),
|
||||
xx(CROSSV_KR, crossv, RVKVRV),
|
||||
xx(MULVF3_RR, mulv3, RVRVRF), // vA = vkB * fkC
|
||||
xx(MULVF3_RK, mulv3, RVRVKF),
|
||||
xx(DIVVF3_RR, divv3, RVRVRF), // vA = vkB / fkC
|
||||
xx(DIVVF3_RK, divv3, RVRVKF),
|
||||
xx(LENV3, lenv3, RFRV), // fA = vB.Length
|
||||
xx(EQV3_R, beqv3, CVRR), // if ((vB == vkC) != A) then pc++ (inexact if A & 33)
|
||||
xx(EQV3_K, beqv3, CVRK),
|
||||
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), // 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),
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue