mirror of https://github.com/inolen/redream.git
updated interpreter callbacks to use inline registration like constantpropagationpass
This commit is contained in:
parent
a2691d1e5b
commit
f7049e7166
|
@ -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 <typename R = void, typename A0 = void, typename A1 = void, \
|
||||
int ACCESS_MASK = 0> \
|
||||
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<ValueType<VALUE_##r>::type, ValueType<VALUE_##a0>::type, \
|
||||
ValueType<VALUE_##a1>::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<A0, 0, ACCESS_MASK>::LoadArg(i, r, locals)
|
||||
#define LOAD_ARG1() helper<A1, 1, ACCESS_MASK>::LoadArg(i, r, locals)
|
||||
#define LOAD_ARG2() helper<A1, 2, ACCESS_MASK>::LoadArg(i, r, locals)
|
||||
#define STORE_RESULT(v) helper<R, 3, ACCESS_MASK>::StoreArg(i, r, locals, v)
|
||||
#define NEXT_INSTR (idx + 1)
|
||||
|
||||
template <typename T>
|
||||
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 <typename T, int ARG, IntAccessMask ACCESS_MASK>
|
||||
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 <typename T, int ARG, IntAccessMask ACCESS_MASK>
|
||||
struct helper<
|
||||
T, ARG, ACCESS_MASK,
|
||||
|
@ -165,11 +270,8 @@ struct helper<
|
|||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ACC_IMM
|
||||
//
|
||||
// argument is encoded directly on the instruction
|
||||
//
|
||||
template <typename T, int ARG, IntAccessMask ACCESS_MASK>
|
||||
struct helper<
|
||||
T, ARG, ACCESS_MASK,
|
||||
|
@ -184,17 +286,6 @@ struct helper<
|
|||
}
|
||||
};
|
||||
|
||||
#define CALLBACK(name) \
|
||||
template <typename R = void, typename A0 = void, typename A1 = void, \
|
||||
int ACCESS_MASK = 0> \
|
||||
static uint32_t name(const IntInstr *i, uint32_t idx, Memory *memory, \
|
||||
IntValue *r, uint8_t *locals, void *guest_ctx)
|
||||
#define LOAD_ARG0() helper<A0, 0, ACCESS_MASK>::LoadArg(i, r, locals)
|
||||
#define LOAD_ARG1() helper<A1, 1, ACCESS_MASK>::LoadArg(i, r, locals)
|
||||
#define LOAD_ARG2() helper<A1, 2, ACCESS_MASK>::LoadArg(i, r, locals)
|
||||
#define STORE_RESULT(v) helper<R, 3, ACCESS_MASK>::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<A1 *>(reinterpret_cast<uint8_t *>(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<A0>::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<A0>::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<A0>::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<A0>::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<A0>::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<A0>::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<A0>::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<A0>::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<A0>::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<A1>::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<ValueType<VALUE_##r>::type, ValueType<VALUE_##a0>::type, \
|
||||
ValueType<VALUE_##a1>::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);
|
||||
|
|
|
@ -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)
|
|
@ -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<ValueType<VALUE_##r>::type, ValueType<VALUE_##a0>::type, \
|
||||
ValueType<VALUE_##a1>::type>; \
|
||||
} \
|
||||
} op##_##r##_##a0##_##a1##_init;
|
||||
} cpp_##op##_##r##_##a0##_##a1##_init
|
||||
|
||||
// common helpers for fold functions
|
||||
#define ARG0() instr->arg0()->value<A0>()
|
||||
|
@ -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<A0>::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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue