diff --git a/src/cpu/backend/interpreter/interpreter_callbacks.cc b/src/cpu/backend/interpreter/interpreter_callbacks.cc index a6d7854b..afae5758 100644 --- a/src/cpu/backend/interpreter/interpreter_callbacks.cc +++ b/src/cpu/backend/interpreter/interpreter_callbacks.cc @@ -8,9 +8,120 @@ using namespace dreavm::cpu::backend::interpreter; using namespace dreavm::cpu::ir; using namespace dreavm::emu; +// callbacks for each IR operation. callback functions are generated per +// operation, per signature, per access mask. +#define MAX_CALLBACKS_PER_OP \ + (VALUE_NUM * VALUE_NUM * VALUE_NUM * NUM_ACC_COMBINATIONS) +#define MAX_CALLBACKS (MAX_CALLBACKS_PER_OP * NUM_OPCODES) + +static IntFn int_cbs[MAX_CALLBACKS]; + +// OP_SELECT and OP_BRANCH_COND are the only instructions using arg2, and +// arg2's type always matches arg1's. because of this, arg2 isn't considered +// when generating the lookup table. +#define CALLBACK_IDX(op, result_sig, arg0_sig, arg1_sig, access_mask) \ + (MAX_CALLBACKS_PER_OP * op + (((result_sig * VALUE_NUM * VALUE_NUM) + \ + (arg0_sig * VALUE_NUM) + arg1_sig) * \ + NUM_ACC_COMBINATIONS) + \ + access_mask) + +// declare a templated callback for an IR operation. note, declaring a +// callback does not actually register it. callbacks must be registered +// for a particular signature with REGISTER_CALLBACK. +#define CALLBACK(name) \ + template \ + static uint32_t name(const IntInstr *i, uint32_t idx, Memory *memory, \ + IntValue *r, uint8_t *locals, void *guest_ctx) + +// generate NUM_ACC_COMBINATIONS callbacks for each operation, excluding access +// masks where (mask & 0x3), (mask >> 2) & 0x3, or (mask >> 4) & 0x3 are equal +// to 3, as they're not valid access masks +// FIXME if ConstantPropagationPass is working 100%, more of these combinations +// can be removed +#define REGISTER_CALLBACK_C(op, fn, r, a0, a1, c) \ + int_cbs[CALLBACK_IDX(OP_##op, VALUE_##r, VALUE_##a0, VALUE_##a1, c)] = \ + &fn::type, ValueType::type, \ + ValueType::type, c>; + +#define REGISTER_CALLBACK(op, fn, r, a0, a1) \ + static struct _int_##op##_##r##_##a0##_##a1##_init { \ + _int_##op##_##r##_##a0##_##a1##_init() { \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 0) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 1) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 2) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 4) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 5) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 6) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 8) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 9) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 10) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 16) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 17) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 18) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 20) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 21) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 22) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 24) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 25) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 26) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 32) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 33) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 34) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 36) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 37) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 38) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 40) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 41) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 42) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 64) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 65) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 66) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 68) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 69) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 70) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 72) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 73) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 74) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 80) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 81) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 82) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 84) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 85) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 86) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 88) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 89) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 90) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 96) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 97) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 98) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 100) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 101) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 102) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 104) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 105) \ + REGISTER_CALLBACK_C(op, fn, r, a0, a1, 106) \ + } \ + } int_##op##_##r##_##a0##_##a1##_init + +IntFn dreavm::cpu::backend::interpreter::GetCallback( + Opcode op, const IntSig &sig, IntAccessMask access_mask) { + IntFn fn = + int_cbs[CALLBACK_IDX(op, GetArgSignature(sig, 3), GetArgSignature(sig, 0), + GetArgSignature(sig, 1), access_mask)]; + CHECK_NOTNULL(fn); + return fn; +} + // // helpers for loading / storing arguments // +#define LOAD_ARG0() helper::LoadArg(i, r, locals) +#define LOAD_ARG1() helper::LoadArg(i, r, locals) +#define LOAD_ARG2() helper::LoadArg(i, r, locals) +#define STORE_RESULT(v) helper::StoreArg(i, r, locals, v) +#define NEXT_INSTR (idx + 1) + template static inline T GetValue(const IntValue &v); template <> @@ -127,11 +238,8 @@ struct helper { const uint8_t *l, T v); }; -// // ACC_REG -// // argument is located in a virtual register, arg->i32 specifies the register -// template struct helper< T, ARG, ACCESS_MASK, @@ -146,11 +254,8 @@ struct helper< } }; -// // ACC_LCL -// // argument is located on the stack, arg->i32 specifies the stack offset -// template struct helper< T, ARG, ACCESS_MASK, @@ -165,11 +270,8 @@ struct helper< } }; -// // ACC_IMM -// // argument is encoded directly on the instruction -// template struct helper< T, ARG, ACCESS_MASK, @@ -184,17 +286,6 @@ struct helper< } }; -#define CALLBACK(name) \ - template \ - static uint32_t name(const IntInstr *i, uint32_t idx, Memory *memory, \ - IntValue *r, uint8_t *locals, void *guest_ctx) -#define LOAD_ARG0() helper::LoadArg(i, r, locals) -#define LOAD_ARG1() helper::LoadArg(i, r, locals) -#define LOAD_ARG2() helper::LoadArg(i, r, locals) -#define STORE_RESULT(v) helper::StoreArg(i, r, locals, v) -#define NEXT_INSTR (idx + 1) - // // interpreter callbacks // @@ -202,6 +293,12 @@ CALLBACK(PRINTF) { std::cout << LOAD_ARG0() << std::endl; return NEXT_INSTR; } +REGISTER_CALLBACK(PRINTF, PRINTF, V, I8, V); +REGISTER_CALLBACK(PRINTF, PRINTF, V, I16, V); +REGISTER_CALLBACK(PRINTF, PRINTF, V, I32, V); +REGISTER_CALLBACK(PRINTF, PRINTF, V, I64, V); +REGISTER_CALLBACK(PRINTF, PRINTF, V, F32, V); +REGISTER_CALLBACK(PRINTF, PRINTF, V, F64, V); CALLBACK(LOAD_CONTEXT) { A0 offset = LOAD_ARG0(); @@ -209,6 +306,12 @@ CALLBACK(LOAD_CONTEXT) { STORE_RESULT(v); return NEXT_INSTR; } +REGISTER_CALLBACK(LOAD_CONTEXT, LOAD_CONTEXT, I8, I32, V); +REGISTER_CALLBACK(LOAD_CONTEXT, LOAD_CONTEXT, I16, I32, V); +REGISTER_CALLBACK(LOAD_CONTEXT, LOAD_CONTEXT, I32, I32, V); +REGISTER_CALLBACK(LOAD_CONTEXT, LOAD_CONTEXT, I64, I32, V); +REGISTER_CALLBACK(LOAD_CONTEXT, LOAD_CONTEXT, F32, I32, V); +REGISTER_CALLBACK(LOAD_CONTEXT, LOAD_CONTEXT, F64, I32, V); CALLBACK(STORE_CONTEXT) { A0 offset = LOAD_ARG0(); @@ -216,6 +319,12 @@ CALLBACK(STORE_CONTEXT) { *reinterpret_cast(reinterpret_cast(guest_ctx) + offset) = v; return NEXT_INSTR; } +REGISTER_CALLBACK(STORE_CONTEXT, STORE_CONTEXT, V, I32, I8); +REGISTER_CALLBACK(STORE_CONTEXT, STORE_CONTEXT, V, I32, I16); +REGISTER_CALLBACK(STORE_CONTEXT, STORE_CONTEXT, V, I32, I32); +REGISTER_CALLBACK(STORE_CONTEXT, STORE_CONTEXT, V, I32, I64); +REGISTER_CALLBACK(STORE_CONTEXT, STORE_CONTEXT, V, I32, F32); +REGISTER_CALLBACK(STORE_CONTEXT, STORE_CONTEXT, V, I32, F64); CALLBACK(LOAD_I8) { uint32_t addr = (uint32_t)LOAD_ARG0(); @@ -223,41 +332,42 @@ CALLBACK(LOAD_I8) { STORE_RESULT(v); return NEXT_INSTR; } - CALLBACK(LOAD_I16) { uint32_t addr = (uint32_t)LOAD_ARG0(); R v = memory->R16(addr); STORE_RESULT(v); return NEXT_INSTR; } - CALLBACK(LOAD_I32) { uint32_t addr = (uint32_t)LOAD_ARG0(); R v = memory->R32(addr); STORE_RESULT(v); return NEXT_INSTR; } - CALLBACK(LOAD_I64) { uint32_t addr = (uint32_t)LOAD_ARG0(); R v = memory->R64(addr); STORE_RESULT(v); return NEXT_INSTR; } - CALLBACK(LOAD_F32) { uint32_t addr = (uint32_t)LOAD_ARG0(); R v = memory->RF32(addr); STORE_RESULT(v); return NEXT_INSTR; } - CALLBACK(LOAD_F64) { uint32_t addr = (uint32_t)LOAD_ARG0(); R v = memory->RF64(addr); STORE_RESULT(v); return NEXT_INSTR; } +REGISTER_CALLBACK(LOAD, LOAD_I8, I8, I32, V); +REGISTER_CALLBACK(LOAD, LOAD_I16, I16, I32, V); +REGISTER_CALLBACK(LOAD, LOAD_I32, I32, I32, V); +REGISTER_CALLBACK(LOAD, LOAD_I64, I64, I32, V); +REGISTER_CALLBACK(LOAD, LOAD_F32, F32, I32, V); +REGISTER_CALLBACK(LOAD, LOAD_F64, F64, I32, V); CALLBACK(STORE_I8) { uint32_t addr = (uint32_t)LOAD_ARG0(); @@ -265,53 +375,65 @@ CALLBACK(STORE_I8) { memory->W8(addr, v); return NEXT_INSTR; } - CALLBACK(STORE_I16) { uint32_t addr = (uint32_t)LOAD_ARG0(); A1 v = LOAD_ARG1(); memory->W16(addr, v); return NEXT_INSTR; } - CALLBACK(STORE_I32) { uint32_t addr = (uint32_t)LOAD_ARG0(); A1 v = LOAD_ARG1(); memory->W32(addr, v); return NEXT_INSTR; } - CALLBACK(STORE_I64) { uint32_t addr = (uint32_t)LOAD_ARG0(); A1 v = LOAD_ARG1(); memory->W64(addr, v); return NEXT_INSTR; } - CALLBACK(STORE_F32) { uint32_t addr = (uint32_t)LOAD_ARG0(); A1 v = LOAD_ARG1(); memory->WF32(addr, v); return NEXT_INSTR; } - CALLBACK(STORE_F64) { uint32_t addr = (uint32_t)LOAD_ARG0(); A1 v = LOAD_ARG1(); memory->WF64(addr, v); return NEXT_INSTR; } +REGISTER_CALLBACK(STORE, STORE_I8, V, I32, I8); +REGISTER_CALLBACK(STORE, STORE_I16, V, I32, I16); +REGISTER_CALLBACK(STORE, STORE_I32, V, I32, I32); +REGISTER_CALLBACK(STORE, STORE_I64, V, I32, I64); +REGISTER_CALLBACK(STORE, STORE_F32, V, I32, F32); +REGISTER_CALLBACK(STORE, STORE_F64, V, I32, F64); CALLBACK(CAST) { A0 v = LOAD_ARG0(); STORE_RESULT((R)v); return NEXT_INSTR; } +REGISTER_CALLBACK(CAST, CAST, F32, I32, V); +REGISTER_CALLBACK(CAST, CAST, F64, I32, V); +REGISTER_CALLBACK(CAST, CAST, F64, I64, V); +REGISTER_CALLBACK(CAST, CAST, I32, F32, V); +REGISTER_CALLBACK(CAST, CAST, I64, F64, V); CALLBACK(SEXT) { A0 v = LOAD_ARG0(); STORE_RESULT((R)v); return NEXT_INSTR; } +REGISTER_CALLBACK(SEXT, SEXT, I16, I8, V); +REGISTER_CALLBACK(SEXT, SEXT, I32, I8, V); +REGISTER_CALLBACK(SEXT, SEXT, I64, I8, V); +REGISTER_CALLBACK(SEXT, SEXT, I32, I16, V); +REGISTER_CALLBACK(SEXT, SEXT, I64, I16, V); +REGISTER_CALLBACK(SEXT, SEXT, I64, I32, V); CALLBACK(ZEXT) { using U0 = typename std::make_unsigned::type; @@ -319,6 +441,12 @@ CALLBACK(ZEXT) { STORE_RESULT((R)(U0)v); return NEXT_INSTR; } +REGISTER_CALLBACK(ZEXT, ZEXT, I16, I8, V); +REGISTER_CALLBACK(ZEXT, ZEXT, I32, I8, V); +REGISTER_CALLBACK(ZEXT, ZEXT, I64, I8, V); +REGISTER_CALLBACK(ZEXT, ZEXT, I32, I16, V); +REGISTER_CALLBACK(ZEXT, ZEXT, I64, I16, V); +REGISTER_CALLBACK(ZEXT, ZEXT, I64, I32, V); CALLBACK(TRUNCATE) { using U0 = typename std::make_unsigned::type; @@ -326,6 +454,12 @@ CALLBACK(TRUNCATE) { STORE_RESULT((R)(U0)v); return NEXT_INSTR; } +REGISTER_CALLBACK(TRUNCATE, TRUNCATE, I8, I16, V); +REGISTER_CALLBACK(TRUNCATE, TRUNCATE, I8, I32, V); +REGISTER_CALLBACK(TRUNCATE, TRUNCATE, I16, I32, V); +REGISTER_CALLBACK(TRUNCATE, TRUNCATE, I8, I64, V); +REGISTER_CALLBACK(TRUNCATE, TRUNCATE, I16, I64, V); +REGISTER_CALLBACK(TRUNCATE, TRUNCATE, I32, I64, V); CALLBACK(SELECT) { A0 cond = LOAD_ARG0(); @@ -334,6 +468,10 @@ CALLBACK(SELECT) { STORE_RESULT(cond ? t : f); return NEXT_INSTR; } +REGISTER_CALLBACK(SELECT, SELECT, I8, I8, I8); +REGISTER_CALLBACK(SELECT, SELECT, I16, I8, I16); +REGISTER_CALLBACK(SELECT, SELECT, I32, I8, I32); +REGISTER_CALLBACK(SELECT, SELECT, I64, I8, I64); CALLBACK(EQ) { A0 lhs = LOAD_ARG0(); @@ -341,6 +479,12 @@ CALLBACK(EQ) { STORE_RESULT((int8_t)(lhs == rhs)); return NEXT_INSTR; } +REGISTER_CALLBACK(EQ, EQ, I8, I8, I8); +REGISTER_CALLBACK(EQ, EQ, I8, I16, I16); +REGISTER_CALLBACK(EQ, EQ, I8, I32, I32); +REGISTER_CALLBACK(EQ, EQ, I8, I64, I64); +REGISTER_CALLBACK(EQ, EQ, I8, F32, F32); +REGISTER_CALLBACK(EQ, EQ, I8, F64, F64); CALLBACK(NE) { A0 lhs = LOAD_ARG0(); @@ -348,6 +492,12 @@ CALLBACK(NE) { STORE_RESULT((int8_t)(lhs != rhs)); return NEXT_INSTR; } +REGISTER_CALLBACK(NE, NE, I8, I8, I8); +REGISTER_CALLBACK(NE, NE, I8, I16, I16); +REGISTER_CALLBACK(NE, NE, I8, I32, I32); +REGISTER_CALLBACK(NE, NE, I8, I64, I64); +REGISTER_CALLBACK(NE, NE, I8, F32, F32); +REGISTER_CALLBACK(NE, NE, I8, F64, F64); CALLBACK(SGE) { A0 lhs = LOAD_ARG0(); @@ -355,6 +505,12 @@ CALLBACK(SGE) { STORE_RESULT((int8_t)(lhs >= rhs)); return NEXT_INSTR; } +REGISTER_CALLBACK(SGE, SGE, I8, I8, I8); +REGISTER_CALLBACK(SGE, SGE, I8, I16, I16); +REGISTER_CALLBACK(SGE, SGE, I8, I32, I32); +REGISTER_CALLBACK(SGE, SGE, I8, I64, I64); +REGISTER_CALLBACK(SGE, SGE, I8, F32, F32); +REGISTER_CALLBACK(SGE, SGE, I8, F64, F64); CALLBACK(SGT) { A0 lhs = LOAD_ARG0(); @@ -362,6 +518,12 @@ CALLBACK(SGT) { STORE_RESULT((int8_t)(lhs > rhs)); return NEXT_INSTR; } +REGISTER_CALLBACK(SGT, SGT, I8, I8, I8); +REGISTER_CALLBACK(SGT, SGT, I8, I16, I16); +REGISTER_CALLBACK(SGT, SGT, I8, I32, I32); +REGISTER_CALLBACK(SGT, SGT, I8, I64, I64); +REGISTER_CALLBACK(SGT, SGT, I8, F32, F32); +REGISTER_CALLBACK(SGT, SGT, I8, F64, F64); CALLBACK(UGE) { using U0 = typename std::make_unsigned::type; @@ -371,6 +533,10 @@ CALLBACK(UGE) { STORE_RESULT((int8_t)(lhs >= rhs)); return NEXT_INSTR; } +REGISTER_CALLBACK(UGE, UGE, I8, I8, I8); +REGISTER_CALLBACK(UGE, UGE, I8, I16, I16); +REGISTER_CALLBACK(UGE, UGE, I8, I32, I32); +REGISTER_CALLBACK(UGE, UGE, I8, I64, I64); CALLBACK(UGT) { using U0 = typename std::make_unsigned::type; @@ -380,6 +546,10 @@ CALLBACK(UGT) { STORE_RESULT((int8_t)(lhs > rhs)); return NEXT_INSTR; } +REGISTER_CALLBACK(UGT, UGT, I8, I8, I8); +REGISTER_CALLBACK(UGT, UGT, I8, I16, I16); +REGISTER_CALLBACK(UGT, UGT, I8, I32, I32); +REGISTER_CALLBACK(UGT, UGT, I8, I64, I64); CALLBACK(SLE) { A0 lhs = LOAD_ARG0(); @@ -387,6 +557,12 @@ CALLBACK(SLE) { STORE_RESULT((int8_t)(lhs <= rhs)); return NEXT_INSTR; } +REGISTER_CALLBACK(SLE, SLE, I8, I8, I8); +REGISTER_CALLBACK(SLE, SLE, I8, I16, I16); +REGISTER_CALLBACK(SLE, SLE, I8, I32, I32); +REGISTER_CALLBACK(SLE, SLE, I8, I64, I64); +REGISTER_CALLBACK(SLE, SLE, I8, F32, F32); +REGISTER_CALLBACK(SLE, SLE, I8, F64, F64); CALLBACK(SLT) { A0 lhs = LOAD_ARG0(); @@ -394,6 +570,12 @@ CALLBACK(SLT) { STORE_RESULT((int8_t)(lhs < rhs)); return NEXT_INSTR; } +REGISTER_CALLBACK(SLT, SLT, I8, I8, I8); +REGISTER_CALLBACK(SLT, SLT, I8, I16, I16); +REGISTER_CALLBACK(SLT, SLT, I8, I32, I32); +REGISTER_CALLBACK(SLT, SLT, I8, I64, I64); +REGISTER_CALLBACK(SLT, SLT, I8, F32, F32); +REGISTER_CALLBACK(SLT, SLT, I8, F64, F64); CALLBACK(ULE) { using U0 = typename std::make_unsigned::type; @@ -403,6 +585,10 @@ CALLBACK(ULE) { STORE_RESULT((int8_t)(lhs <= rhs)); return NEXT_INSTR; } +REGISTER_CALLBACK(ULE, ULE, I8, I8, I8); +REGISTER_CALLBACK(ULE, ULE, I8, I16, I16); +REGISTER_CALLBACK(ULE, ULE, I8, I32, I32); +REGISTER_CALLBACK(ULE, ULE, I8, I64, I64); CALLBACK(ULT) { using U0 = typename std::make_unsigned::type; @@ -412,6 +598,10 @@ CALLBACK(ULT) { STORE_RESULT((int8_t)(lhs < rhs)); return NEXT_INSTR; } +REGISTER_CALLBACK(ULT, ULT, I8, I8, I8); +REGISTER_CALLBACK(ULT, ULT, I8, I16, I16); +REGISTER_CALLBACK(ULT, ULT, I8, I32, I32); +REGISTER_CALLBACK(ULT, ULT, I8, I64, I64); CALLBACK(ADD) { A0 lhs = LOAD_ARG0(); @@ -419,6 +609,12 @@ CALLBACK(ADD) { STORE_RESULT(lhs + rhs); return NEXT_INSTR; } +REGISTER_CALLBACK(ADD, ADD, I8, I8, I8); +REGISTER_CALLBACK(ADD, ADD, I16, I16, I16); +REGISTER_CALLBACK(ADD, ADD, I32, I32, I32); +REGISTER_CALLBACK(ADD, ADD, I64, I64, I64); +REGISTER_CALLBACK(ADD, ADD, F32, F32, F32); +REGISTER_CALLBACK(ADD, ADD, F64, F64, F64); CALLBACK(SUB) { A0 lhs = LOAD_ARG0(); @@ -426,6 +622,12 @@ CALLBACK(SUB) { STORE_RESULT(lhs - rhs); return NEXT_INSTR; } +REGISTER_CALLBACK(SUB, SUB, I8, I8, I8); +REGISTER_CALLBACK(SUB, SUB, I16, I16, I16); +REGISTER_CALLBACK(SUB, SUB, I32, I32, I32); +REGISTER_CALLBACK(SUB, SUB, I64, I64, I64); +REGISTER_CALLBACK(SUB, SUB, F32, F32, F32); +REGISTER_CALLBACK(SUB, SUB, F64, F64, F64); CALLBACK(SMUL) { A0 lhs = LOAD_ARG0(); @@ -433,6 +635,12 @@ CALLBACK(SMUL) { STORE_RESULT(lhs * rhs); return NEXT_INSTR; } +REGISTER_CALLBACK(SMUL, SMUL, I8, I8, I8); +REGISTER_CALLBACK(SMUL, SMUL, I16, I16, I16); +REGISTER_CALLBACK(SMUL, SMUL, I32, I32, I32); +REGISTER_CALLBACK(SMUL, SMUL, I64, I64, I64); +REGISTER_CALLBACK(SMUL, SMUL, F32, F32, F32); +REGISTER_CALLBACK(SMUL, SMUL, F64, F64, F64); CALLBACK(UMUL) { using U0 = typename std::make_unsigned::type; @@ -442,6 +650,10 @@ CALLBACK(UMUL) { STORE_RESULT((A0)(lhs * rhs)); return NEXT_INSTR; } +REGISTER_CALLBACK(UMUL, UMUL, I8, I8, I8); +REGISTER_CALLBACK(UMUL, UMUL, I16, I16, I16); +REGISTER_CALLBACK(UMUL, UMUL, I32, I32, I32); +REGISTER_CALLBACK(UMUL, UMUL, I64, I64, I64); CALLBACK(DIV) { A0 lhs = LOAD_ARG0(); @@ -449,54 +661,71 @@ CALLBACK(DIV) { STORE_RESULT(lhs / rhs); return NEXT_INSTR; } +REGISTER_CALLBACK(DIV, DIV, I8, I8, I8); +REGISTER_CALLBACK(DIV, DIV, I16, I16, I16); +REGISTER_CALLBACK(DIV, DIV, I32, I32, I32); +REGISTER_CALLBACK(DIV, DIV, I64, I64, I64); +REGISTER_CALLBACK(DIV, DIV, F32, F32, F32); +REGISTER_CALLBACK(DIV, DIV, F64, F64, F64); CALLBACK(NEG) { A0 v = LOAD_ARG0(); STORE_RESULT(-v); return NEXT_INSTR; } +REGISTER_CALLBACK(NEG, NEG, I8, I8, V); +REGISTER_CALLBACK(NEG, NEG, I16, I16, V); +REGISTER_CALLBACK(NEG, NEG, I32, I32, V); +REGISTER_CALLBACK(NEG, NEG, I64, I64, V); +REGISTER_CALLBACK(NEG, NEG, F32, F32, V); +REGISTER_CALLBACK(NEG, NEG, F64, F64, V); CALLBACK(SQRTF) { A0 v = LOAD_ARG0(); STORE_RESULT(sqrtf(v)); return NEXT_INSTR; } - CALLBACK(SQRT) { A0 v = LOAD_ARG0(); STORE_RESULT(sqrt(v)); return NEXT_INSTR; } +REGISTER_CALLBACK(SQRT, SQRTF, F32, F32, V); +REGISTER_CALLBACK(SQRT, SQRT, F64, F64, V); CALLBACK(ABSF) { A0 v = LOAD_ARG0(); STORE_RESULT(fabs(v)); return NEXT_INSTR; } +REGISTER_CALLBACK(ABS, ABSF, F32, F32, V); +REGISTER_CALLBACK(ABS, ABSF, F64, F64, V); CALLBACK(SINF) { A0 v = LOAD_ARG0(); STORE_RESULT(sinf(v)); return NEXT_INSTR; } - CALLBACK(SIN) { A0 v = LOAD_ARG0(); STORE_RESULT(sin(v)); return NEXT_INSTR; } +REGISTER_CALLBACK(SIN, SINF, F32, F32, V); +REGISTER_CALLBACK(SIN, SIN, F64, F64, V); CALLBACK(COSF) { A0 v = LOAD_ARG0(); STORE_RESULT(cosf(v)); return NEXT_INSTR; } - CALLBACK(COS) { A0 v = LOAD_ARG0(); STORE_RESULT(cos(v)); return NEXT_INSTR; } +REGISTER_CALLBACK(COS, COSF, F32, F32, V); +REGISTER_CALLBACK(COS, COS, F64, F64, V); CALLBACK(AND) { A0 lhs = LOAD_ARG0(); @@ -504,6 +733,10 @@ CALLBACK(AND) { STORE_RESULT(lhs & rhs); return NEXT_INSTR; } +REGISTER_CALLBACK(AND, AND, I8, I8, I8); +REGISTER_CALLBACK(AND, AND, I16, I16, I16); +REGISTER_CALLBACK(AND, AND, I32, I32, I32); +REGISTER_CALLBACK(AND, AND, I64, I64, I64); CALLBACK(OR) { A0 lhs = LOAD_ARG0(); @@ -511,6 +744,10 @@ CALLBACK(OR) { STORE_RESULT(lhs | rhs); return NEXT_INSTR; } +REGISTER_CALLBACK(OR, OR, I8, I8, I8); +REGISTER_CALLBACK(OR, OR, I16, I16, I16); +REGISTER_CALLBACK(OR, OR, I32, I32, I32); +REGISTER_CALLBACK(OR, OR, I64, I64, I64); CALLBACK(XOR) { A0 lhs = LOAD_ARG0(); @@ -518,12 +755,20 @@ CALLBACK(XOR) { STORE_RESULT(lhs ^ rhs); return NEXT_INSTR; } +REGISTER_CALLBACK(XOR, XOR, I8, I8, I8); +REGISTER_CALLBACK(XOR, XOR, I16, I16, I16); +REGISTER_CALLBACK(XOR, XOR, I32, I32, I32); +REGISTER_CALLBACK(XOR, XOR, I64, I64, I64); CALLBACK(NOT) { A0 v = LOAD_ARG0(); STORE_RESULT(~v); return NEXT_INSTR; } +REGISTER_CALLBACK(NOT, NOT, I8, I8, V); +REGISTER_CALLBACK(NOT, NOT, I16, I16, V); +REGISTER_CALLBACK(NOT, NOT, I32, I32, V); +REGISTER_CALLBACK(NOT, NOT, I64, I64, V); CALLBACK(SHL) { A0 v = LOAD_ARG0(); @@ -531,6 +776,10 @@ CALLBACK(SHL) { STORE_RESULT(v << n); return NEXT_INSTR; } +REGISTER_CALLBACK(SHL, SHL, I8, I8, I32); +REGISTER_CALLBACK(SHL, SHL, I16, I16, I32); +REGISTER_CALLBACK(SHL, SHL, I32, I32, I32); +REGISTER_CALLBACK(SHL, SHL, I64, I64, I32); CALLBACK(ASHR) { A0 v = LOAD_ARG0(); @@ -538,6 +787,10 @@ CALLBACK(ASHR) { STORE_RESULT(v >> n); return NEXT_INSTR; } +REGISTER_CALLBACK(ASHR, ASHR, I8, I8, I32); +REGISTER_CALLBACK(ASHR, ASHR, I16, I16, I32); +REGISTER_CALLBACK(ASHR, ASHR, I32, I32, I32); +REGISTER_CALLBACK(ASHR, ASHR, I64, I64, I32); CALLBACK(LSHR) { using U0 = typename std::make_unsigned::type; @@ -546,12 +799,20 @@ CALLBACK(LSHR) { STORE_RESULT((A0)((U0)v >> n)); return NEXT_INSTR; } +REGISTER_CALLBACK(LSHR, LSHR, I8, I8, I32); +REGISTER_CALLBACK(LSHR, LSHR, I16, I16, I32); +REGISTER_CALLBACK(LSHR, LSHR, I32, I32, I32); +REGISTER_CALLBACK(LSHR, LSHR, I64, I64, I32); CALLBACK(BRANCH) { using U0 = typename std::make_unsigned::type; U0 addr = (U0)LOAD_ARG0(); return addr; } +REGISTER_CALLBACK(BRANCH, BRANCH, V, I8, V); +REGISTER_CALLBACK(BRANCH, BRANCH, V, I16, V); +REGISTER_CALLBACK(BRANCH, BRANCH, V, I32, V); +REGISTER_CALLBACK(BRANCH, BRANCH, V, I64, V); CALLBACK(BRANCH_COND) { using U1 = typename std::make_unsigned::type; @@ -564,11 +825,16 @@ CALLBACK(BRANCH_COND) { return addr; } } +REGISTER_CALLBACK(BRANCH_COND, BRANCH_COND, V, I8, I8); +REGISTER_CALLBACK(BRANCH_COND, BRANCH_COND, V, I8, I16); +REGISTER_CALLBACK(BRANCH_COND, BRANCH_COND, V, I8, I32); +REGISTER_CALLBACK(BRANCH_COND, BRANCH_COND, V, I8, I64); CALLBACK(BRANCH_INDIRECT) { uint32_t addr = (uint32_t)LOAD_ARG0(); return addr; } +REGISTER_CALLBACK(BRANCH_INDIRECT, BRANCH_INDIRECT, V, I32, V); CALLBACK(CALL_EXTERNAL) { A0 addr = LOAD_ARG0(); @@ -576,105 +842,4 @@ CALLBACK(CALL_EXTERNAL) { func(guest_ctx); return NEXT_INSTR; } - -// -// callback lookup table generation -// -// callback functions are generated for each instruction, for each possible -// permutation of arguments. each argument has a data type, as well as its -// access type. -// -// NOTE: OP_SELECT and OP_BRANCH_COND are the only instructions using arg2, and -// arg2's type always matches arg1's. because of this, and in order to save -// some memory, arg2 isn't considering when generating the lookup table. -// -#define MAX_CALLBACKS_PER_OP \ - (VALUE_NUM * VALUE_NUM * VALUE_NUM * NUM_ACC_COMBINATIONS) -#define MAX_CALLBACKS (MAX_CALLBACKS_PER_OP * NUM_OPCODES) -#define CALLBACK_IDX(op, result_sig, arg0_sig, arg1_sig, access_mask) \ - (MAX_CALLBACKS_PER_OP * op + (((result_sig * VALUE_NUM * VALUE_NUM) + \ - (arg0_sig * VALUE_NUM) + arg1_sig) * \ - NUM_ACC_COMBINATIONS) + \ - access_mask) - -static IntFn int_cbs[MAX_CALLBACKS]; - -IntFn dreavm::cpu::backend::interpreter::GetCallback( - Opcode op, const IntSig &sig, IntAccessMask access_mask) { - IntFn fn = - int_cbs[CALLBACK_IDX(op, GetArgSignature(sig, 3), GetArgSignature(sig, 0), - GetArgSignature(sig, 1), access_mask)]; - CHECK_NOTNULL(fn); - return fn; -} - -static void InitCallbacks() { -// Generate NUM_ACC_COMBINATIONS callbacks for each op, excluding access masks -// where (mask & 0x3), (mask >> 2) & 0x3, or (mask >> 4) & 0x3 are equal to 3, -// as they're invalid. -#define INT_CALLBACK_C(op, func, r, a0, a1, c) \ - int_cbs[CALLBACK_IDX(op, VALUE_##r, VALUE_##a0, VALUE_##a1, c)] = \ - &func::type, ValueType::type, \ - ValueType::type, c>; -#define INT_CALLBACK(op, func, r, a0, a1) \ - INT_CALLBACK_C(op, func, r, a0, a1, 0) \ - INT_CALLBACK_C(op, func, r, a0, a1, 1) \ - INT_CALLBACK_C(op, func, r, a0, a1, 2) \ - INT_CALLBACK_C(op, func, r, a0, a1, 4) \ - INT_CALLBACK_C(op, func, r, a0, a1, 5) \ - INT_CALLBACK_C(op, func, r, a0, a1, 6) \ - INT_CALLBACK_C(op, func, r, a0, a1, 8) \ - INT_CALLBACK_C(op, func, r, a0, a1, 9) \ - INT_CALLBACK_C(op, func, r, a0, a1, 10) \ - INT_CALLBACK_C(op, func, r, a0, a1, 16) \ - INT_CALLBACK_C(op, func, r, a0, a1, 17) \ - INT_CALLBACK_C(op, func, r, a0, a1, 18) \ - INT_CALLBACK_C(op, func, r, a0, a1, 20) \ - INT_CALLBACK_C(op, func, r, a0, a1, 21) \ - INT_CALLBACK_C(op, func, r, a0, a1, 22) \ - INT_CALLBACK_C(op, func, r, a0, a1, 24) \ - INT_CALLBACK_C(op, func, r, a0, a1, 25) \ - INT_CALLBACK_C(op, func, r, a0, a1, 26) \ - INT_CALLBACK_C(op, func, r, a0, a1, 32) \ - INT_CALLBACK_C(op, func, r, a0, a1, 33) \ - INT_CALLBACK_C(op, func, r, a0, a1, 34) \ - INT_CALLBACK_C(op, func, r, a0, a1, 36) \ - INT_CALLBACK_C(op, func, r, a0, a1, 37) \ - INT_CALLBACK_C(op, func, r, a0, a1, 38) \ - INT_CALLBACK_C(op, func, r, a0, a1, 40) \ - INT_CALLBACK_C(op, func, r, a0, a1, 41) \ - INT_CALLBACK_C(op, func, r, a0, a1, 42) \ - INT_CALLBACK_C(op, func, r, a0, a1, 64) \ - INT_CALLBACK_C(op, func, r, a0, a1, 65) \ - INT_CALLBACK_C(op, func, r, a0, a1, 66) \ - INT_CALLBACK_C(op, func, r, a0, a1, 68) \ - INT_CALLBACK_C(op, func, r, a0, a1, 69) \ - INT_CALLBACK_C(op, func, r, a0, a1, 70) \ - INT_CALLBACK_C(op, func, r, a0, a1, 72) \ - INT_CALLBACK_C(op, func, r, a0, a1, 73) \ - INT_CALLBACK_C(op, func, r, a0, a1, 74) \ - INT_CALLBACK_C(op, func, r, a0, a1, 80) \ - INT_CALLBACK_C(op, func, r, a0, a1, 81) \ - INT_CALLBACK_C(op, func, r, a0, a1, 82) \ - INT_CALLBACK_C(op, func, r, a0, a1, 84) \ - INT_CALLBACK_C(op, func, r, a0, a1, 85) \ - INT_CALLBACK_C(op, func, r, a0, a1, 86) \ - INT_CALLBACK_C(op, func, r, a0, a1, 88) \ - INT_CALLBACK_C(op, func, r, a0, a1, 89) \ - INT_CALLBACK_C(op, func, r, a0, a1, 90) \ - INT_CALLBACK_C(op, func, r, a0, a1, 96) \ - INT_CALLBACK_C(op, func, r, a0, a1, 97) \ - INT_CALLBACK_C(op, func, r, a0, a1, 98) \ - INT_CALLBACK_C(op, func, r, a0, a1, 100) \ - INT_CALLBACK_C(op, func, r, a0, a1, 101) \ - INT_CALLBACK_C(op, func, r, a0, a1, 102) \ - INT_CALLBACK_C(op, func, r, a0, a1, 104) \ - INT_CALLBACK_C(op, func, r, a0, a1, 105) \ - INT_CALLBACK_C(op, func, r, a0, a1, 106) -#include "cpu/backend/interpreter/interpreter_callbacks.inc" -#undef INT_CALLBACK -} - -static struct _cb_init { - _cb_init() { InitCallbacks(); } -} cb_init; +REGISTER_CALLBACK(CALL_EXTERNAL, CALL_EXTERNAL, V, I64, V); diff --git a/src/cpu/backend/interpreter/interpreter_callbacks.inc b/src/cpu/backend/interpreter/interpreter_callbacks.inc deleted file mode 100644 index 823d778f..00000000 --- a/src/cpu/backend/interpreter/interpreter_callbacks.inc +++ /dev/null @@ -1,189 +0,0 @@ -INT_CALLBACK(OP_PRINTF, PRINTF, V, I8, V) -INT_CALLBACK(OP_PRINTF, PRINTF, V, I16, V) -INT_CALLBACK(OP_PRINTF, PRINTF, V, I32, V) -INT_CALLBACK(OP_PRINTF, PRINTF, V, I64, V) -INT_CALLBACK(OP_PRINTF, PRINTF, V, F32, V) -INT_CALLBACK(OP_PRINTF, PRINTF, V, F64, V) -INT_CALLBACK(OP_LOAD_CONTEXT, LOAD_CONTEXT, I8, I32, V) -INT_CALLBACK(OP_LOAD_CONTEXT, LOAD_CONTEXT, I16, I32, V) -INT_CALLBACK(OP_LOAD_CONTEXT, LOAD_CONTEXT, I32, I32, V) -INT_CALLBACK(OP_LOAD_CONTEXT, LOAD_CONTEXT, I64, I32, V) -INT_CALLBACK(OP_LOAD_CONTEXT, LOAD_CONTEXT, F32, I32, V) -INT_CALLBACK(OP_LOAD_CONTEXT, LOAD_CONTEXT, F64, I32, V) -INT_CALLBACK(OP_STORE_CONTEXT, STORE_CONTEXT, V, I32, I8) -INT_CALLBACK(OP_STORE_CONTEXT, STORE_CONTEXT, V, I32, I16) -INT_CALLBACK(OP_STORE_CONTEXT, STORE_CONTEXT, V, I32, I32) -INT_CALLBACK(OP_STORE_CONTEXT, STORE_CONTEXT, V, I32, I64) -INT_CALLBACK(OP_STORE_CONTEXT, STORE_CONTEXT, V, I32, F32) -INT_CALLBACK(OP_STORE_CONTEXT, STORE_CONTEXT, V, I32, F64) -INT_CALLBACK(OP_LOAD, LOAD_I8, I8, I32, V) -INT_CALLBACK(OP_LOAD, LOAD_I16, I16, I32, V) -INT_CALLBACK(OP_LOAD, LOAD_I32, I32, I32, V) -INT_CALLBACK(OP_LOAD, LOAD_I64, I64, I32, V) -INT_CALLBACK(OP_LOAD, LOAD_F32, F32, I32, V) -INT_CALLBACK(OP_LOAD, LOAD_F64, F64, I32, V) -INT_CALLBACK(OP_STORE, STORE_I8, V, I32, I8) -INT_CALLBACK(OP_STORE, STORE_I16, V, I32, I16) -INT_CALLBACK(OP_STORE, STORE_I32, V, I32, I32) -INT_CALLBACK(OP_STORE, STORE_I64, V, I32, I64) -INT_CALLBACK(OP_STORE, STORE_F32, V, I32, F32) -INT_CALLBACK(OP_STORE, STORE_F64, V, I32, F64) -INT_CALLBACK(OP_CAST, CAST, F32, I32, V) -INT_CALLBACK(OP_CAST, CAST, F64, I32, V) -INT_CALLBACK(OP_CAST, CAST, F64, I64, V) -INT_CALLBACK(OP_CAST, CAST, I32, F32, V) -INT_CALLBACK(OP_CAST, CAST, I64, F64, V) -INT_CALLBACK(OP_SEXT, SEXT, I16, I8, V) -INT_CALLBACK(OP_SEXT, SEXT, I32, I8, V) -INT_CALLBACK(OP_SEXT, SEXT, I64, I8, V) -INT_CALLBACK(OP_SEXT, SEXT, I32, I16, V) -INT_CALLBACK(OP_SEXT, SEXT, I64, I16, V) -INT_CALLBACK(OP_SEXT, SEXT, I64, I32, V) -INT_CALLBACK(OP_ZEXT, ZEXT, I16, I8, V) -INT_CALLBACK(OP_ZEXT, ZEXT, I32, I8, V) -INT_CALLBACK(OP_ZEXT, ZEXT, I64, I8, V) -INT_CALLBACK(OP_ZEXT, ZEXT, I32, I16, V) -INT_CALLBACK(OP_ZEXT, ZEXT, I64, I16, V) -INT_CALLBACK(OP_ZEXT, ZEXT, I64, I32, V) -INT_CALLBACK(OP_TRUNCATE, TRUNCATE, I8, I16, V) -INT_CALLBACK(OP_TRUNCATE, TRUNCATE, I8, I32, V) -INT_CALLBACK(OP_TRUNCATE, TRUNCATE, I16, I32, V) -INT_CALLBACK(OP_TRUNCATE, TRUNCATE, I8, I64, V) -INT_CALLBACK(OP_TRUNCATE, TRUNCATE, I16, I64, V) -INT_CALLBACK(OP_TRUNCATE, TRUNCATE, I32, I64, V) -INT_CALLBACK(OP_SELECT, SELECT, I8, I8, I8) -INT_CALLBACK(OP_SELECT, SELECT, I16, I8, I16) -INT_CALLBACK(OP_SELECT, SELECT, I32, I8, I32) -INT_CALLBACK(OP_SELECT, SELECT, I64, I8, I64) -INT_CALLBACK(OP_EQ, EQ, I8, I8, I8) -INT_CALLBACK(OP_EQ, EQ, I8, I16, I16) -INT_CALLBACK(OP_EQ, EQ, I8, I32, I32) -INT_CALLBACK(OP_EQ, EQ, I8, I64, I64) -INT_CALLBACK(OP_EQ, EQ, I8, F32, F32) -INT_CALLBACK(OP_EQ, EQ, I8, F64, F64) -INT_CALLBACK(OP_NE, NE, I8, I8, I8) -INT_CALLBACK(OP_NE, NE, I8, I16, I16) -INT_CALLBACK(OP_NE, NE, I8, I32, I32) -INT_CALLBACK(OP_NE, NE, I8, I64, I64) -INT_CALLBACK(OP_NE, NE, I8, F32, F32) -INT_CALLBACK(OP_NE, NE, I8, F64, F64) -INT_CALLBACK(OP_SGE, SGE, I8, I8, I8) -INT_CALLBACK(OP_SGE, SGE, I8, I16, I16) -INT_CALLBACK(OP_SGE, SGE, I8, I32, I32) -INT_CALLBACK(OP_SGE, SGE, I8, I64, I64) -INT_CALLBACK(OP_SGE, SGE, I8, F32, F32) -INT_CALLBACK(OP_SGE, SGE, I8, F64, F64) -INT_CALLBACK(OP_SGT, SGT, I8, I8, I8) -INT_CALLBACK(OP_SGT, SGT, I8, I16, I16) -INT_CALLBACK(OP_SGT, SGT, I8, I32, I32) -INT_CALLBACK(OP_SGT, SGT, I8, I64, I64) -INT_CALLBACK(OP_SGT, SGT, I8, F32, F32) -INT_CALLBACK(OP_SGT, SGT, I8, F64, F64) -INT_CALLBACK(OP_UGE, UGE, I8, I8, I8) -INT_CALLBACK(OP_UGE, UGE, I8, I16, I16) -INT_CALLBACK(OP_UGE, UGE, I8, I32, I32) -INT_CALLBACK(OP_UGE, UGE, I8, I64, I64) -INT_CALLBACK(OP_UGT, UGT, I8, I8, I8) -INT_CALLBACK(OP_UGT, UGT, I8, I16, I16) -INT_CALLBACK(OP_UGT, UGT, I8, I32, I32) -INT_CALLBACK(OP_UGT, UGT, I8, I64, I64) -INT_CALLBACK(OP_SLE, SLE, I8, I8, I8) -INT_CALLBACK(OP_SLE, SLE, I8, I16, I16) -INT_CALLBACK(OP_SLE, SLE, I8, I32, I32) -INT_CALLBACK(OP_SLE, SLE, I8, I64, I64) -INT_CALLBACK(OP_SLE, SLE, I8, F32, F32) -INT_CALLBACK(OP_SLE, SLE, I8, F64, F64) -INT_CALLBACK(OP_SLT, SLT, I8, I8, I8) -INT_CALLBACK(OP_SLT, SLT, I8, I16, I16) -INT_CALLBACK(OP_SLT, SLT, I8, I32, I32) -INT_CALLBACK(OP_SLT, SLT, I8, I64, I64) -INT_CALLBACK(OP_SLT, SLT, I8, F32, F32) -INT_CALLBACK(OP_SLT, SLT, I8, F64, F64) -INT_CALLBACK(OP_ULE, ULE, I8, I8, I8) -INT_CALLBACK(OP_ULE, ULE, I8, I16, I16) -INT_CALLBACK(OP_ULE, ULE, I8, I32, I32) -INT_CALLBACK(OP_ULE, ULE, I8, I64, I64) -INT_CALLBACK(OP_ULT, ULT, I8, I8, I8) -INT_CALLBACK(OP_ULT, ULT, I8, I16, I16) -INT_CALLBACK(OP_ULT, ULT, I8, I32, I32) -INT_CALLBACK(OP_ULT, ULT, I8, I64, I64) -INT_CALLBACK(OP_ADD, ADD, I8, I8, I8) -INT_CALLBACK(OP_ADD, ADD, I16, I16, I16) -INT_CALLBACK(OP_ADD, ADD, I32, I32, I32) -INT_CALLBACK(OP_ADD, ADD, I64, I64, I64) -INT_CALLBACK(OP_ADD, ADD, F32, F32, F32) -INT_CALLBACK(OP_ADD, ADD, F64, F64, F64) -INT_CALLBACK(OP_SUB, SUB, I8, I8, I8) -INT_CALLBACK(OP_SUB, SUB, I16, I16, I16) -INT_CALLBACK(OP_SUB, SUB, I32, I32, I32) -INT_CALLBACK(OP_SUB, SUB, I64, I64, I64) -INT_CALLBACK(OP_SUB, SUB, F32, F32, F32) -INT_CALLBACK(OP_SUB, SUB, F64, F64, F64) -INT_CALLBACK(OP_SMUL, SMUL, I8, I8, I8) -INT_CALLBACK(OP_SMUL, SMUL, I16, I16, I16) -INT_CALLBACK(OP_SMUL, SMUL, I32, I32, I32) -INT_CALLBACK(OP_SMUL, SMUL, I64, I64, I64) -INT_CALLBACK(OP_SMUL, SMUL, F32, F32, F32) -INT_CALLBACK(OP_SMUL, SMUL, F64, F64, F64) -INT_CALLBACK(OP_UMUL, UMUL, I8, I8, I8) -INT_CALLBACK(OP_UMUL, UMUL, I16, I16, I16) -INT_CALLBACK(OP_UMUL, UMUL, I32, I32, I32) -INT_CALLBACK(OP_UMUL, UMUL, I64, I64, I64) -INT_CALLBACK(OP_DIV, DIV, I8, I8, I8) -INT_CALLBACK(OP_DIV, DIV, I16, I16, I16) -INT_CALLBACK(OP_DIV, DIV, I32, I32, I32) -INT_CALLBACK(OP_DIV, DIV, I64, I64, I64) -INT_CALLBACK(OP_DIV, DIV, F32, F32, F32) -INT_CALLBACK(OP_DIV, DIV, F64, F64, F64) -INT_CALLBACK(OP_NEG, NEG, I8, I8, V) -INT_CALLBACK(OP_NEG, NEG, I16, I16, V) -INT_CALLBACK(OP_NEG, NEG, I32, I32, V) -INT_CALLBACK(OP_NEG, NEG, I64, I64, V) -INT_CALLBACK(OP_NEG, NEG, F32, F32, V) -INT_CALLBACK(OP_NEG, NEG, F64, F64, V) -INT_CALLBACK(OP_SQRT, SQRTF, F32, F32, V) -INT_CALLBACK(OP_SQRT, SQRT, F64, F64, V) -INT_CALLBACK(OP_ABS, ABSF, F32, F32, V) -INT_CALLBACK(OP_ABS, ABSF, F64, F64, V) -INT_CALLBACK(OP_SIN, SINF, F32, F32, V) -INT_CALLBACK(OP_SIN, SIN, F64, F64, V) -INT_CALLBACK(OP_COS, COSF, F32, F32, V) -INT_CALLBACK(OP_COS, COS, F64, F64, V) -INT_CALLBACK(OP_AND, AND, I8, I8, I8) -INT_CALLBACK(OP_AND, AND, I16, I16, I16) -INT_CALLBACK(OP_AND, AND, I32, I32, I32) -INT_CALLBACK(OP_AND, AND, I64, I64, I64) -INT_CALLBACK(OP_OR, OR, I8, I8, I8) -INT_CALLBACK(OP_OR, OR, I16, I16, I16) -INT_CALLBACK(OP_OR, OR, I32, I32, I32) -INT_CALLBACK(OP_OR, OR, I64, I64, I64) -INT_CALLBACK(OP_XOR, XOR, I8, I8, I8) -INT_CALLBACK(OP_XOR, XOR, I16, I16, I16) -INT_CALLBACK(OP_XOR, XOR, I32, I32, I32) -INT_CALLBACK(OP_XOR, XOR, I64, I64, I64) -INT_CALLBACK(OP_NOT, NOT, I8, I8, V) -INT_CALLBACK(OP_NOT, NOT, I16, I16, V) -INT_CALLBACK(OP_NOT, NOT, I32, I32, V) -INT_CALLBACK(OP_NOT, NOT, I64, I64, V) -INT_CALLBACK(OP_SHL, SHL, I8, I8, I32) -INT_CALLBACK(OP_SHL, SHL, I16, I16, I32) -INT_CALLBACK(OP_SHL, SHL, I32, I32, I32) -INT_CALLBACK(OP_SHL, SHL, I64, I64, I32) -INT_CALLBACK(OP_ASHR, ASHR, I8, I8, I32) -INT_CALLBACK(OP_ASHR, ASHR, I16, I16, I32) -INT_CALLBACK(OP_ASHR, ASHR, I32, I32, I32) -INT_CALLBACK(OP_ASHR, ASHR, I64, I64, I32) -INT_CALLBACK(OP_LSHR, LSHR, I8, I8, I32) -INT_CALLBACK(OP_LSHR, LSHR, I16, I16, I32) -INT_CALLBACK(OP_LSHR, LSHR, I32, I32, I32) -INT_CALLBACK(OP_LSHR, LSHR, I64, I64, I32) -INT_CALLBACK(OP_BRANCH, BRANCH, V, I8, V) -INT_CALLBACK(OP_BRANCH, BRANCH, V, I16, V) -INT_CALLBACK(OP_BRANCH, BRANCH, V, I32, V) -INT_CALLBACK(OP_BRANCH, BRANCH, V, I64, V) -INT_CALLBACK(OP_BRANCH_COND, BRANCH_COND, V, I8, I8) -INT_CALLBACK(OP_BRANCH_COND, BRANCH_COND, V, I8, I16) -INT_CALLBACK(OP_BRANCH_COND, BRANCH_COND, V, I8, I32) -INT_CALLBACK(OP_BRANCH_COND, BRANCH_COND, V, I8, I64) -INT_CALLBACK(OP_BRANCH_INDIRECT, BRANCH_INDIRECT, V, I32, V) -INT_CALLBACK(OP_CALL_EXTERNAL, CALL_EXTERNAL, V, I64, V) diff --git a/src/cpu/ir/passes/constant_propagation_pass.cc b/src/cpu/ir/passes/constant_propagation_pass.cc index 5b3ba585..a69c9116 100644 --- a/src/cpu/ir/passes/constant_propagation_pass.cc +++ b/src/cpu/ir/passes/constant_propagation_pass.cc @@ -21,9 +21,9 @@ int fold_masks[NUM_OPCODES]; #define CALLBACK_IDX(op, a0, a1) \ ((op)*VALUE_NUM * VALUE_NUM) + ((a0)*VALUE_NUM) + (a1) -// declare a templated fold callback for an IR operation. note, declaring a -// fold callback does not actually register it. fold callbacks must be -// registered for any signature it is to be ran on. +// declare a templated callback for an IR operation. note, declaring a +// callback does not actually register it. callbacks must be registered +// for a particular signature with REGISTER_FOLD. #define FOLD(op, mask) \ static struct _##op##_init { \ _##op##_init() { fold_masks[OP_##op] = mask; } \ @@ -33,17 +33,13 @@ int fold_masks[NUM_OPCODES]; // registers a fold callback for the specified signature #define REGISTER_FOLD(op, r, a0, a1) \ - static struct _##op##_##r##_##a0##_##a1##_init { \ - _##op##_##r##_##a0##_##a1##_init() { \ - int idx = CALLBACK_IDX(OP_##op, VALUE_##a0, VALUE_##a1); \ - CHECK(fold_cbs[idx] == nullptr) << "Registered duplicate callback for " \ - << Opnames[OP_##op] << "_" << #r << "_" \ - << #a0 << "_" << #a1; \ - fold_cbs[idx] = \ + static struct _cpp_##op##_##r##_##a0##_##a1##_init { \ + _cpp_##op##_##r##_##a0##_##a1##_init() { \ + fold_cbs[CALLBACK_IDX(OP_##op, VALUE_##a0, VALUE_##a1)] = \ &Handle##op::type, ValueType::type, \ ValueType::type>; \ } \ - } op##_##r##_##a0##_##a1##_init; + } cpp_##op##_##r##_##a0##_##a1##_init // common helpers for fold functions #define ARG0() instr->arg0()->value() @@ -107,80 +103,80 @@ FOLD(SELECT, ARG0_CNST) { instr->result()->ReplaceRefsWith(ARG0() ? instr->arg1() : instr->arg2()); block->RemoveInstr(instr); } -REGISTER_FOLD(SELECT, I8, I8, I8) -REGISTER_FOLD(SELECT, I16, I16, I16) -REGISTER_FOLD(SELECT, I32, I32, I32) -REGISTER_FOLD(SELECT, I64, I64, I64) +REGISTER_FOLD(SELECT, I8, I8, I8); +REGISTER_FOLD(SELECT, I16, I16, I16); +REGISTER_FOLD(SELECT, I32, I32, I32); +REGISTER_FOLD(SELECT, I64, I64, I64); FOLD(EQ, ARG0_CNST | ARG1_CNST) { RESULT(ARG0() == ARG1()); } -REGISTER_FOLD(EQ, I8, I8, I8) -REGISTER_FOLD(EQ, I8, I16, I16) -REGISTER_FOLD(EQ, I8, I32, I32) -REGISTER_FOLD(EQ, I8, I64, I64) -REGISTER_FOLD(EQ, I8, F32, F32) -REGISTER_FOLD(EQ, I8, F64, F64) +REGISTER_FOLD(EQ, I8, I8, I8); +REGISTER_FOLD(EQ, I8, I16, I16); +REGISTER_FOLD(EQ, I8, I32, I32); +REGISTER_FOLD(EQ, I8, I64, I64); +REGISTER_FOLD(EQ, I8, F32, F32); +REGISTER_FOLD(EQ, I8, F64, F64); FOLD(NE, ARG0_CNST | ARG1_CNST) { RESULT(ARG0() != ARG1()); } -REGISTER_FOLD(NE, I8, I8, I8) -REGISTER_FOLD(NE, I8, I16, I16) -REGISTER_FOLD(NE, I8, I32, I32) -REGISTER_FOLD(NE, I8, I64, I64) -REGISTER_FOLD(NE, I8, F32, F32) -REGISTER_FOLD(NE, I8, F64, F64) +REGISTER_FOLD(NE, I8, I8, I8); +REGISTER_FOLD(NE, I8, I16, I16); +REGISTER_FOLD(NE, I8, I32, I32); +REGISTER_FOLD(NE, I8, I64, I64); +REGISTER_FOLD(NE, I8, F32, F32); +REGISTER_FOLD(NE, I8, F64, F64); FOLD(SGE, ARG0_CNST | ARG1_CNST) { RESULT(ARG0() >= ARG1()); } -REGISTER_FOLD(SGE, I8, I8, I8) -REGISTER_FOLD(SGE, I8, I16, I16) -REGISTER_FOLD(SGE, I8, I32, I32) -REGISTER_FOLD(SGE, I8, I64, I64) -REGISTER_FOLD(SGE, I8, F32, F32) -REGISTER_FOLD(SGE, I8, F64, F64) +REGISTER_FOLD(SGE, I8, I8, I8); +REGISTER_FOLD(SGE, I8, I16, I16); +REGISTER_FOLD(SGE, I8, I32, I32); +REGISTER_FOLD(SGE, I8, I64, I64); +REGISTER_FOLD(SGE, I8, F32, F32); +REGISTER_FOLD(SGE, I8, F64, F64); FOLD(ADD, ARG0_CNST | ARG1_CNST) { RESULT(ARG0() + ARG1()); } -REGISTER_FOLD(ADD, I8, I8, I8) -REGISTER_FOLD(ADD, I16, I16, I16) -REGISTER_FOLD(ADD, I32, I32, I32) -REGISTER_FOLD(ADD, I64, I64, I64) -REGISTER_FOLD(ADD, F32, F32, F32) -REGISTER_FOLD(ADD, F64, F64, F64) +REGISTER_FOLD(ADD, I8, I8, I8); +REGISTER_FOLD(ADD, I16, I16, I16); +REGISTER_FOLD(ADD, I32, I32, I32); +REGISTER_FOLD(ADD, I64, I64, I64); +REGISTER_FOLD(ADD, F32, F32, F32); +REGISTER_FOLD(ADD, F64, F64, F64); FOLD(SUB, ARG0_CNST | ARG1_CNST) { RESULT(ARG0() - ARG1()); } -REGISTER_FOLD(SUB, I8, I8, I8) -REGISTER_FOLD(SUB, I16, I16, I16) -REGISTER_FOLD(SUB, I32, I32, I32) -REGISTER_FOLD(SUB, I64, I64, I64) -REGISTER_FOLD(SUB, F32, F32, F32) -REGISTER_FOLD(SUB, F64, F64, F64) +REGISTER_FOLD(SUB, I8, I8, I8); +REGISTER_FOLD(SUB, I16, I16, I16); +REGISTER_FOLD(SUB, I32, I32, I32); +REGISTER_FOLD(SUB, I64, I64, I64); +REGISTER_FOLD(SUB, F32, F32, F32); +REGISTER_FOLD(SUB, F64, F64, F64); FOLD(AND, ARG0_CNST | ARG1_CNST) { RESULT(ARG0() & ARG1()); } -REGISTER_FOLD(AND, I8, I8, I8) -REGISTER_FOLD(AND, I16, I16, I16) -REGISTER_FOLD(AND, I32, I32, I32) -REGISTER_FOLD(AND, I64, I64, I64) +REGISTER_FOLD(AND, I8, I8, I8); +REGISTER_FOLD(AND, I16, I16, I16); +REGISTER_FOLD(AND, I32, I32, I32); +REGISTER_FOLD(AND, I64, I64, I64); FOLD(OR, ARG0_CNST | ARG1_CNST) { RESULT(ARG0() | ARG1()); } -REGISTER_FOLD(OR, I8, I8, I8) -REGISTER_FOLD(OR, I16, I16, I16) -REGISTER_FOLD(OR, I32, I32, I32) -REGISTER_FOLD(OR, I64, I64, I64) +REGISTER_FOLD(OR, I8, I8, I8); +REGISTER_FOLD(OR, I16, I16, I16); +REGISTER_FOLD(OR, I32, I32, I32); +REGISTER_FOLD(OR, I64, I64, I64); FOLD(XOR, ARG0_CNST | ARG1_CNST) { RESULT(ARG0() ^ ARG1()); } -REGISTER_FOLD(XOR, I8, I8, I8) -REGISTER_FOLD(XOR, I16, I16, I16) -REGISTER_FOLD(XOR, I32, I32, I32) -REGISTER_FOLD(XOR, I64, I64, I64) +REGISTER_FOLD(XOR, I8, I8, I8); +REGISTER_FOLD(XOR, I16, I16, I16); +REGISTER_FOLD(XOR, I32, I32, I32); +REGISTER_FOLD(XOR, I64, I64, I64); FOLD(SHL, ARG0_CNST | ARG1_CNST) { RESULT(ARG0() << ARG1()); } -REGISTER_FOLD(SHL, I8, I8, I32) -REGISTER_FOLD(SHL, I16, I16, I32) -REGISTER_FOLD(SHL, I32, I32, I32) -REGISTER_FOLD(SHL, I64, I64, I32) +REGISTER_FOLD(SHL, I8, I8, I32); +REGISTER_FOLD(SHL, I16, I16, I32); +REGISTER_FOLD(SHL, I32, I32, I32); +REGISTER_FOLD(SHL, I64, I64, I32); FOLD(LSHR, ARG0_CNST | ARG1_CNST) { using U0 = typename std::make_unsigned::type; RESULT((A0)((U0)ARG0() >> ARG1())); } -REGISTER_FOLD(LSHR, I8, I8, I32) -REGISTER_FOLD(LSHR, I16, I16, I32) -REGISTER_FOLD(LSHR, I32, I32, I32) -REGISTER_FOLD(LSHR, I64, I64, I32) +REGISTER_FOLD(LSHR, I8, I8, I32); +REGISTER_FOLD(LSHR, I16, I16, I32); +REGISTER_FOLD(LSHR, I32, I32, I32); +REGISTER_FOLD(LSHR, I64, I64, I32); diff --git a/src/cpu/ir/passes/validate_instruction_pass.cc b/src/cpu/ir/passes/validate_instruction_pass.cc index a2caa3b1..7a7e3207 100644 --- a/src/cpu/ir/passes/validate_instruction_pass.cc +++ b/src/cpu/ir/passes/validate_instruction_pass.cc @@ -16,22 +16,10 @@ void ValidateInstructionPass::Run(IRBuilder &builder) { void ValidateInstructionPass::ValidateInstr(Instr *instr) { // after constant propagation, there shouldn't be more than a single constant // argument for most instructions - Opcode op = instr->op(); - if (op != OP_STORE_CONTEXT && op != OP_BRANCH_COND && op != OP_SELECT) { - int num_constants = 0; - if (instr->arg0() && instr->arg0()->constant()) { - num_constants++; - } - if (instr->arg1() && instr->arg1()->constant()) { - num_constants++; - } - if (instr->arg2() && instr->arg2()->constant()) { - num_constants++; - } - if (num_constants > 1) { - LOG(FATAL) << "More than one constant argument detected for " - << Opnames[op] << " instruction"; - } + if (instr->op() != OP_STORE_CONTEXT && instr->arg0() && + instr->arg0()->constant() && instr->arg1() && instr->arg1()->constant()) { + LOG(FATAL) << "More than one constant argument detected for " + << Opnames[instr->op()] << " instruction"; } // result (reg or local) should be equal to one of the incoming arguments