mirror of
https://github.com/open-goal/jak-project
synced 2026-07-07 14:13:45 -04:00
add some stores
This commit is contained in:
@@ -4,15 +4,13 @@
|
||||
|
||||
namespace emitter {
|
||||
|
||||
CodeTester::CodeTester() : m_info(RegisterInfo::make_register_info()) {
|
||||
|
||||
}
|
||||
CodeTester::CodeTester() : m_info(RegisterInfo::make_register_info()) {}
|
||||
|
||||
std::string CodeTester::dump_to_hex_string(bool nospace) {
|
||||
std::string result;
|
||||
char buff[32];
|
||||
for (int i = 0; i < code_buffer_size; i++) {
|
||||
if(nospace) {
|
||||
if (nospace) {
|
||||
sprintf(buff, "%02X", code_buffer[i]);
|
||||
} else {
|
||||
sprintf(buff, "%02x ", code_buffer[i]);
|
||||
@@ -60,14 +58,14 @@ void CodeTester::emit_push_all_gprs(bool exclude_rax) {
|
||||
|
||||
void CodeTester::emit_push_all_xmms() {
|
||||
emit(IGen::sub_gpr64_imm8s(RSP, 8));
|
||||
for(int i = 0; i < 16; i++) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
emit(IGen::sub_gpr64_imm8s(RSP, 16));
|
||||
emit(IGen::store128_gpr64_xmm128(RSP, XMM0 + i));
|
||||
}
|
||||
}
|
||||
|
||||
void CodeTester::emit_pop_all_xmms() {
|
||||
for(int i = 0; i < 16; i++) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
emit(IGen::load128_xmm128_gpr64(XMM0 + i, RSP));
|
||||
emit(IGen::add_gpr64_imm8s(RSP, 16));
|
||||
}
|
||||
@@ -103,4 +101,4 @@ CodeTester::~CodeTester() {
|
||||
munmap(code_buffer, code_buffer_capacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace emitter
|
||||
@@ -26,7 +26,7 @@ class CodeTester {
|
||||
|
||||
Register get_c_abi_arg_reg(int i) {
|
||||
// todo - this should be different for windows.
|
||||
switch(i) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
return RDI;
|
||||
case 1:
|
||||
@@ -40,9 +40,7 @@ class CodeTester {
|
||||
}
|
||||
}
|
||||
|
||||
std::string reg_name(Register x) {
|
||||
return m_info.get_info(x).name;
|
||||
}
|
||||
std::string reg_name(Register x) { return m_info.get_info(x).name; }
|
||||
|
||||
private:
|
||||
int code_buffer_size = 0;
|
||||
@@ -50,5 +48,5 @@ class CodeTester {
|
||||
u8* code_buffer = nullptr;
|
||||
RegisterInfo m_info;
|
||||
};
|
||||
} // namespace goal
|
||||
} // namespace emitter
|
||||
#endif // JAK_CODETESTER_H
|
||||
|
||||
@@ -142,6 +142,21 @@ class IGen {
|
||||
return instr;
|
||||
}
|
||||
|
||||
static Instruction store8_gpr64_gpr64_plus_gpr64(Register addr1, Register addr2, Register value) {
|
||||
assert(value.is_gpr());
|
||||
assert(addr1.is_gpr());
|
||||
assert(addr2.is_gpr());
|
||||
assert(addr1 != addr2);
|
||||
assert(addr1 != RSP);
|
||||
assert(addr2 != RSP);
|
||||
Instruction instr(0x88);
|
||||
instr.set_modrm_and_rex_for_reg_plus_reg_addr(value.hw_id(), addr1.hw_id(), addr2.hw_id());
|
||||
if (value.id() > RBX) {
|
||||
instr.add_rex();
|
||||
}
|
||||
return instr;
|
||||
}
|
||||
|
||||
static Instruction load8s_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
|
||||
Register addr1,
|
||||
Register addr2,
|
||||
@@ -160,6 +175,26 @@ class IGen {
|
||||
return instr;
|
||||
}
|
||||
|
||||
static Instruction store8_gpr64_gpr64_plus_gpr64_plus_s8(Register addr1,
|
||||
Register addr2,
|
||||
Register value,
|
||||
s64 offset) {
|
||||
assert(value.is_gpr());
|
||||
assert(addr1.is_gpr());
|
||||
assert(addr2.is_gpr());
|
||||
assert(addr1 != addr2);
|
||||
assert(addr1 != RSP);
|
||||
assert(addr2 != RSP);
|
||||
assert(offset >= INT8_MIN && offset <= INT8_MAX);
|
||||
Instruction instr(0x88);
|
||||
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s8(value.hw_id(), addr1.hw_id(), addr2.hw_id(),
|
||||
offset, false);
|
||||
if (value.id() > RBX) {
|
||||
instr.add_rex();
|
||||
}
|
||||
return instr;
|
||||
}
|
||||
|
||||
static Instruction load8s_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
|
||||
Register addr1,
|
||||
Register addr2,
|
||||
@@ -178,6 +213,26 @@ class IGen {
|
||||
return instr;
|
||||
}
|
||||
|
||||
static Instruction store8_gpr64_gpr64_plus_gpr64_plus_s32(Register addr1,
|
||||
Register addr2,
|
||||
Register value,
|
||||
s64 offset) {
|
||||
assert(value.is_gpr());
|
||||
assert(addr1.is_gpr());
|
||||
assert(addr2.is_gpr());
|
||||
assert(addr1 != addr2);
|
||||
assert(addr1 != RSP);
|
||||
assert(addr2 != RSP);
|
||||
assert(offset >= INT32_MIN && offset <= INT32_MAX);
|
||||
Instruction instr(0x88);
|
||||
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s32(value.hw_id(), addr1.hw_id(), addr2.hw_id(),
|
||||
offset, false);
|
||||
if (value.id() > RBX) {
|
||||
instr.add_rex();
|
||||
}
|
||||
return instr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* movzx dst, BYTE PTR [addr1 + addr2]
|
||||
* addr1 and addr2 have to be different registers.
|
||||
@@ -252,6 +307,60 @@ class IGen {
|
||||
return instr;
|
||||
}
|
||||
|
||||
static Instruction store16_gpr64_gpr64_plus_gpr64(Register addr1,
|
||||
Register addr2,
|
||||
Register value) {
|
||||
assert(value.is_gpr());
|
||||
assert(addr1.is_gpr());
|
||||
assert(addr2.is_gpr());
|
||||
assert(addr1 != addr2);
|
||||
assert(addr1 != RSP);
|
||||
assert(addr2 != RSP);
|
||||
Instruction instr(0x66);
|
||||
instr.set_op2(0x89);
|
||||
instr.set_modrm_and_rex_for_reg_plus_reg_addr(value.hw_id(), addr1.hw_id(), addr2.hw_id());
|
||||
instr.swap_op0_rex(); // why?????
|
||||
return instr;
|
||||
}
|
||||
|
||||
static Instruction store16_gpr64_gpr64_plus_gpr64_plus_s8(Register addr1,
|
||||
Register addr2,
|
||||
Register value,
|
||||
s64 offset) {
|
||||
assert(value.is_gpr());
|
||||
assert(addr1.is_gpr());
|
||||
assert(addr2.is_gpr());
|
||||
assert(addr1 != addr2);
|
||||
assert(addr1 != RSP);
|
||||
assert(addr2 != RSP);
|
||||
assert(offset >= INT8_MIN && offset <= INT8_MAX);
|
||||
Instruction instr(0x66);
|
||||
instr.set_op2(0x89);
|
||||
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s8(value.hw_id(), addr1.hw_id(), addr2.hw_id(),
|
||||
offset, false);
|
||||
instr.swap_op0_rex(); // why?????
|
||||
return instr;
|
||||
}
|
||||
|
||||
static Instruction store16_gpr64_gpr64_plus_gpr64_plus_s32(Register addr1,
|
||||
Register addr2,
|
||||
Register value,
|
||||
s64 offset) {
|
||||
assert(value.is_gpr());
|
||||
assert(addr1.is_gpr());
|
||||
assert(addr2.is_gpr());
|
||||
assert(addr1 != addr2);
|
||||
assert(addr1 != RSP);
|
||||
assert(addr2 != RSP);
|
||||
assert(offset >= INT32_MIN && offset <= INT32_MAX);
|
||||
Instruction instr(0x66);
|
||||
instr.set_op2(0x89);
|
||||
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s32(value.hw_id(), addr1.hw_id(), addr2.hw_id(),
|
||||
offset, false);
|
||||
instr.swap_op0_rex(); // why?????
|
||||
return instr;
|
||||
}
|
||||
|
||||
static Instruction load16s_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
|
||||
Register addr1,
|
||||
Register addr2,
|
||||
@@ -496,6 +605,41 @@ class IGen {
|
||||
return instr;
|
||||
}
|
||||
|
||||
static Instruction store_goal_gpr(Register addr,
|
||||
Register value,
|
||||
Register off,
|
||||
int offset,
|
||||
int size) {
|
||||
switch (size) {
|
||||
case 1:
|
||||
if (offset == 0) {
|
||||
return store8_gpr64_gpr64_plus_gpr64(addr, off, value);
|
||||
} else if (offset >= INT8_MIN && offset <= INT8_MAX) {
|
||||
return store8_gpr64_gpr64_plus_gpr64_plus_s8(addr, off, value, offset);
|
||||
} else if (offset >= INT32_MIN && offset <= INT32_MAX) {
|
||||
return store8_gpr64_gpr64_plus_gpr64_plus_s32(addr, off, value, offset);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
case 2:
|
||||
if (offset == 0) {
|
||||
return store16_gpr64_gpr64_plus_gpr64(addr, off, value);
|
||||
} else if (offset >= INT8_MIN && offset <= INT8_MAX) {
|
||||
return store16_gpr64_gpr64_plus_gpr64_plus_s8(addr, off, value, offset);
|
||||
} else if (offset >= INT32_MIN && offset <= INT32_MAX) {
|
||||
return store16_gpr64_gpr64_plus_gpr64_plus_s32(addr, off, value, offset);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Load memory at addr + offset, where addr is a GOAL pointer and off is the offset register.
|
||||
* This will pick the appropriate fancy addressing mode instruction.
|
||||
*/
|
||||
static Instruction load_goal_gpr(Register dst,
|
||||
Register addr,
|
||||
Register off,
|
||||
|
||||
+28
-17
@@ -169,7 +169,11 @@ struct Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
void set_modrm_and_rex_for_reg_plus_reg_plus_s8(uint8_t reg, uint8_t addr1, uint8_t addr2, s8 offset, bool rex_w) {
|
||||
void set_modrm_and_rex_for_reg_plus_reg_plus_s8(uint8_t reg,
|
||||
uint8_t addr1,
|
||||
uint8_t addr2,
|
||||
s8 offset,
|
||||
bool rex_w) {
|
||||
bool rex_b = false, rex_r = false, rex_x = false;
|
||||
bool addr1_ext = false;
|
||||
bool addr2_ext = false;
|
||||
@@ -190,8 +194,8 @@ struct Instruction {
|
||||
}
|
||||
|
||||
ModRM modrm;
|
||||
modrm.mod = 1; // no disp
|
||||
modrm.rm = 4; // sib!
|
||||
modrm.mod = 1; // no disp
|
||||
modrm.rm = 4; // sib!
|
||||
modrm.reg_op = reg;
|
||||
|
||||
SIB sib;
|
||||
@@ -200,7 +204,7 @@ struct Instruction {
|
||||
Imm imm2(1, offset);
|
||||
|
||||
// default addr1 in index
|
||||
if(addr1 == 4) {
|
||||
if (addr1 == 4) {
|
||||
sib.index = addr2;
|
||||
sib.base = addr1;
|
||||
rex_x = addr2_ext;
|
||||
@@ -214,7 +218,7 @@ struct Instruction {
|
||||
}
|
||||
assert(sib.index != 4);
|
||||
|
||||
if(rex_b || rex_w || rex_r || rex_x) {
|
||||
if (rex_b || rex_w || rex_r || rex_x) {
|
||||
set(REX(rex_w, rex_r, rex_x, rex_b));
|
||||
}
|
||||
|
||||
@@ -223,7 +227,11 @@ struct Instruction {
|
||||
set_disp(imm2);
|
||||
}
|
||||
|
||||
void set_modrm_and_rex_for_reg_plus_reg_plus_s32(uint8_t reg, uint8_t addr1, uint8_t addr2, s8 offset, bool rex_w) {
|
||||
void set_modrm_and_rex_for_reg_plus_reg_plus_s32(uint8_t reg,
|
||||
uint8_t addr1,
|
||||
uint8_t addr2,
|
||||
s8 offset,
|
||||
bool rex_w) {
|
||||
bool rex_b = false, rex_r = false, rex_x = false;
|
||||
bool addr1_ext = false;
|
||||
bool addr2_ext = false;
|
||||
@@ -244,8 +252,8 @@ struct Instruction {
|
||||
}
|
||||
|
||||
ModRM modrm;
|
||||
modrm.mod = 2; // no disp
|
||||
modrm.rm = 4; // sib!
|
||||
modrm.mod = 2; // no disp
|
||||
modrm.rm = 4; // sib!
|
||||
modrm.reg_op = reg;
|
||||
|
||||
SIB sib;
|
||||
@@ -254,7 +262,7 @@ struct Instruction {
|
||||
Imm imm2(4, offset);
|
||||
|
||||
// default addr1 in index
|
||||
if(addr1 == 4) {
|
||||
if (addr1 == 4) {
|
||||
sib.index = addr2;
|
||||
sib.base = addr1;
|
||||
rex_x = addr2_ext;
|
||||
@@ -268,7 +276,7 @@ struct Instruction {
|
||||
}
|
||||
assert(sib.index != 4);
|
||||
|
||||
if(rex_b || rex_w || rex_r || rex_x) {
|
||||
if (rex_b || rex_w || rex_r || rex_x) {
|
||||
set(REX(rex_w, rex_r, rex_x, rex_b));
|
||||
}
|
||||
|
||||
@@ -277,7 +285,11 @@ struct Instruction {
|
||||
set_disp(imm2);
|
||||
}
|
||||
|
||||
void set_modrm_and_rex_for_reg_plus_reg_addr(uint8_t reg, uint8_t addr1, uint8_t addr2, bool rex_w = false, bool rex_always = false) {
|
||||
void set_modrm_and_rex_for_reg_plus_reg_addr(uint8_t reg,
|
||||
uint8_t addr1,
|
||||
uint8_t addr2,
|
||||
bool rex_w = false,
|
||||
bool rex_always = false) {
|
||||
bool rex_b = false, rex_r = false, rex_x = false;
|
||||
bool addr1_ext = false;
|
||||
bool addr2_ext = false;
|
||||
@@ -298,14 +310,14 @@ struct Instruction {
|
||||
}
|
||||
|
||||
ModRM modrm;
|
||||
modrm.mod = 0; // no disp
|
||||
modrm.rm = 4; // sib!
|
||||
modrm.mod = 0; // no disp
|
||||
modrm.rm = 4; // sib!
|
||||
modrm.reg_op = reg;
|
||||
|
||||
SIB sib;
|
||||
sib.scale = 0;
|
||||
|
||||
if(addr1 == 5 && addr2 == 5) {
|
||||
if (addr1 == 5 && addr2 == 5) {
|
||||
sib.index = addr1;
|
||||
sib.base = addr2;
|
||||
rex_x = addr1_ext;
|
||||
@@ -317,7 +329,7 @@ struct Instruction {
|
||||
// default addr1 in index
|
||||
bool flipped = (addr1 == 4) || (addr2 == 5);
|
||||
|
||||
if(flipped) {
|
||||
if (flipped) {
|
||||
sib.index = addr2;
|
||||
sib.base = addr1;
|
||||
rex_x = addr2_ext;
|
||||
@@ -333,8 +345,7 @@ struct Instruction {
|
||||
assert(sib.index != 4);
|
||||
}
|
||||
|
||||
|
||||
if(rex_b || rex_w || rex_r || rex_x || rex_always) {
|
||||
if (rex_b || rex_w || rex_r || rex_x || rex_always) {
|
||||
set(REX(rex_w, rex_r, rex_x, rex_b));
|
||||
}
|
||||
|
||||
|
||||
@@ -18,19 +18,16 @@ RegisterInfo RegisterInfo::make_register_info() {
|
||||
info.m_info[R10] = {6, true, false, "r10"};
|
||||
info.m_info[R11] = {7, true, false, "r11"};
|
||||
info.m_info[R12] = {-1, true, false, "r12"};
|
||||
info.m_info[R13] = {-1, false, true, "r13"}; // pp?
|
||||
info.m_info[R14] = {-1, false, true, "r14"}; // st?
|
||||
info.m_info[R15] = {-1, false, true, "r15"}; // offset.
|
||||
info.m_info[R13] = {-1, false, true, "r13"}; // pp?
|
||||
info.m_info[R14] = {-1, false, true, "r14"}; // st?
|
||||
info.m_info[R15] = {-1, false, true, "r15"}; // offset.
|
||||
|
||||
info.m_arg_regs = std::array<Register, N_ARGS>({RDI, RSI, RDX, RCX, R8, R9, R10, R11});
|
||||
info.m_saved_gprs = std::array<Register, N_SAVED_GPRS>({RBX, RBP, R10, R11, R12});
|
||||
info.m_saved_xmms = std::array<Register, N_SAVED_XMMS>({XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15});
|
||||
info.m_saved_xmms =
|
||||
std::array<Register, N_SAVED_XMMS>({XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15});
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
} // namespace emitter
|
||||
@@ -51,8 +51,6 @@ enum X86_REG : u8 {
|
||||
XMM15
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Register {
|
||||
public:
|
||||
Register() = default;
|
||||
@@ -75,9 +73,7 @@ class Register {
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
int id() const {
|
||||
return m_id;
|
||||
}
|
||||
int id() const { return m_id; }
|
||||
|
||||
struct hash {
|
||||
auto operator()(const Register& x) const { return std::hash<u8>()(x.m_id); }
|
||||
@@ -109,37 +105,21 @@ class RegisterInfo {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
const Info& get_info(Register r) const {
|
||||
return m_info.at(r.id());
|
||||
}
|
||||
const Info& get_info(Register r) const { return m_info.at(r.id()); }
|
||||
|
||||
Register get_arg_reg(int id) const {
|
||||
return m_arg_regs.at(id);
|
||||
}
|
||||
Register get_arg_reg(int id) const { return m_arg_regs.at(id); }
|
||||
|
||||
Register get_saved_gpr(int id) const {
|
||||
return m_saved_gprs.at(id);
|
||||
}
|
||||
Register get_saved_gpr(int id) const { return m_saved_gprs.at(id); }
|
||||
|
||||
Register get_saved_xmm(int id) const {
|
||||
return m_saved_xmms.at(id);
|
||||
}
|
||||
Register get_saved_xmm(int id) const { return m_saved_xmms.at(id); }
|
||||
|
||||
Register get_process_reg() const {
|
||||
return R13;
|
||||
}
|
||||
Register get_process_reg() const { return R13; }
|
||||
|
||||
Register get_st_reg() const {
|
||||
return R14;
|
||||
}
|
||||
Register get_st_reg() const { return R14; }
|
||||
|
||||
Register get_offset_reg() const {
|
||||
return R15;
|
||||
}
|
||||
Register get_offset_reg() const { return R15; }
|
||||
|
||||
Register get_ret_reg() const {
|
||||
return RAX;
|
||||
}
|
||||
Register get_ret_reg() const { return RAX; }
|
||||
|
||||
private:
|
||||
RegisterInfo() = default;
|
||||
|
||||
@@ -85,7 +85,6 @@ Interpreter::Interpreter() {
|
||||
load_goos_library();
|
||||
}
|
||||
|
||||
|
||||
Interpreter::~Interpreter() {
|
||||
// There are some circular references that prevent shared_ptrs from cleaning up if we
|
||||
// don't do this.
|
||||
|
||||
@@ -167,4 +167,3 @@ TEST(CodeTester, push_pop_all_the_things) {
|
||||
tester.emit_return();
|
||||
tester.execute();
|
||||
}
|
||||
|
||||
|
||||
+440
-46
@@ -139,8 +139,8 @@ TEST(Emitter, load8s_gpr64_goal_ptr_gpr64) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -208,8 +208,8 @@ TEST(Emitter, load8s_gpr64_gpr64_gpr64_s8) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -277,8 +277,8 @@ TEST(Emitter, load8s_gpr64_gpr64_gpr64_s32) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -352,8 +352,8 @@ TEST(Emitter, load8u_gpr64_goal_ptr_gpr64) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -421,8 +421,8 @@ TEST(Emitter, load8u_gpr64_gpr64_gpr64_s8) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -490,8 +490,8 @@ TEST(Emitter, load8u_gpr64_gpr64_gpr64_s32) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -565,8 +565,8 @@ TEST(Emitter, load16s_gpr64_goal_ptr_gpr64) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -634,8 +634,8 @@ TEST(Emitter, load16s_gpr64_gpr64_plus_gpr64_plus_s8) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -703,8 +703,8 @@ TEST(Emitter, load16s_gpr64_gpr64_plus_gpr64_plus_s32) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -778,8 +778,8 @@ TEST(Emitter, load16u_gpr64_goal_ptr_gpr64) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -847,8 +847,8 @@ TEST(Emitter, load16u_gpr64_gpr64_plus_gpr64_plus_s8) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -916,8 +916,8 @@ TEST(Emitter, load16u_gpr64_gpr64_plus_gpr64_plus_s32) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -952,7 +952,6 @@ TEST(Emitter, load32s_gpr64_goal_ptr_gpr64) {
|
||||
tester.emit(IGen::load32s_gpr64_gpr64_plus_gpr64(RAX, RBX, RSI));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(), "48 63 04 1e");
|
||||
|
||||
|
||||
int iter = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (i == RSP) {
|
||||
@@ -980,8 +979,8 @@ TEST(Emitter, load32s_gpr64_goal_ptr_gpr64) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -1049,8 +1048,8 @@ TEST(Emitter, load32s_gpr64_gpr64_plus_gpr64_plus_s8) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -1118,8 +1117,8 @@ TEST(Emitter, load32s_gpr64_gpr64_plus_gpr64_plus_s32) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -1154,7 +1153,6 @@ TEST(Emitter, load32u_gpr64_goal_ptr_gpr64) {
|
||||
tester.emit(IGen::load32u_gpr64_gpr64_plus_gpr64(RAX, RBX, RSI));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(), "8b 04 1e");
|
||||
|
||||
|
||||
int iter = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (i == RSP) {
|
||||
@@ -1182,8 +1180,8 @@ TEST(Emitter, load32u_gpr64_goal_ptr_gpr64) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -1251,8 +1249,8 @@ TEST(Emitter, load32u_gpr64_gpr64_plus_gpr64_plus_s8) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -1320,8 +1318,8 @@ TEST(Emitter, load32u_gpr64_gpr64_plus_gpr64_plus_s32) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -1356,7 +1354,6 @@ TEST(Emitter, load64_gpr64_goal_ptr_gpr64) {
|
||||
tester.emit(IGen::load64_gpr64_gpr64_plus_gpr64(RAX, RBX, RSI));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(), "48 8b 04 1e");
|
||||
|
||||
|
||||
int iter = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (i == RSP) {
|
||||
@@ -1384,8 +1381,8 @@ TEST(Emitter, load64_gpr64_goal_ptr_gpr64) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -1412,7 +1409,6 @@ TEST(Emitter, load64_gpr64_goal_ptr_gpr64) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(Emitter, load64_gpr64_gpr64_plus_gpr64_plus_s8) {
|
||||
CodeTester tester;
|
||||
tester.init_code_buffer(512);
|
||||
@@ -1454,8 +1450,8 @@ TEST(Emitter, load64_gpr64_gpr64_plus_gpr64_plus_s8) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -1523,8 +1519,8 @@ TEST(Emitter, load64_gpr64_gpr64_plus_gpr64_plus_s32) {
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
|
||||
// fill k with junk
|
||||
if(k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter&1)?0:UINT64_MAX));
|
||||
if (k != i && k != j) {
|
||||
tester.emit(IGen::mov_gpr64_u64(k, (iter & 1) ? 0 : UINT64_MAX));
|
||||
}
|
||||
|
||||
// load into k
|
||||
@@ -1549,4 +1545,402 @@ TEST(Emitter, load64_gpr64_gpr64_plus_gpr64_plus_s32) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Emitter, store8_gpr64_gpr64_plus_gpr64) {
|
||||
CodeTester tester;
|
||||
tester.init_code_buffer(512);
|
||||
|
||||
tester.clear();
|
||||
tester.emit(IGen::store8_gpr64_gpr64_plus_gpr64(RAX, RCX, RDX));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(), "88 14 01");
|
||||
|
||||
int iter = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (i == RSP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 16; j++) {
|
||||
if (j == RSP || j == i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int k = 0; k < 16; k++) {
|
||||
if (k == RSP || k == j || k == i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tester.clear();
|
||||
tester.emit_push_all_gprs(true);
|
||||
// push args to the stack
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(2)));
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(1)));
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(0)));
|
||||
|
||||
// pop args into appropriate register
|
||||
tester.emit(IGen::pop_gpr64(i)); // i will have offset 0
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
tester.emit(IGen::pop_gpr64(k)); // k will have the value to store.
|
||||
|
||||
// store!
|
||||
tester.emit(IGen::store8_gpr64_gpr64_plus_gpr64(i, j, k));
|
||||
|
||||
// return!
|
||||
tester.emit_pop_all_gprs(true);
|
||||
tester.emit_return();
|
||||
|
||||
// prepare the memory:
|
||||
s8 memory[8] = {0, 0, -3, -2, -1, 0, 0, 0};
|
||||
|
||||
// run!
|
||||
tester.execute((u64)memory, 3, 7, 0);
|
||||
EXPECT_EQ(memory[2], -3);
|
||||
EXPECT_EQ(memory[3], 7);
|
||||
EXPECT_EQ(memory[4], -1);
|
||||
|
||||
if (memory[3] != 7) {
|
||||
fmt::print("test {}, {}, {}\n", tester.reg_name(i), tester.reg_name(j),
|
||||
tester.reg_name(k));
|
||||
printf("%s\n", tester.dump_to_hex_string().c_str());
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Emitter, store8_gpr64_gpr64_plus_gpr64_plus_s8) {
|
||||
CodeTester tester;
|
||||
tester.init_code_buffer(512);
|
||||
|
||||
tester.clear();
|
||||
tester.emit(IGen::store8_gpr64_gpr64_plus_gpr64_plus_s8(RAX, RCX, RDX, 12));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(), "88 54 01 0c");
|
||||
|
||||
auto instr = IGen::store8_gpr64_gpr64_plus_gpr64_plus_s8(RAX, RCX, RDX, -3);
|
||||
u8 buff[256];
|
||||
instr.emit(buff);
|
||||
EXPECT_EQ(*(s8*)(buff + instr.offset_of_disp()), -3);
|
||||
|
||||
int iter = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (i == RSP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 16; j++) {
|
||||
if (j == RSP || j == i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int k = 0; k < 16; k++) {
|
||||
if (k == RSP || k == j || k == i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tester.clear();
|
||||
tester.emit_push_all_gprs(true);
|
||||
// push args to the stack
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(2)));
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(1)));
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(0)));
|
||||
|
||||
// pop args into appropriate register
|
||||
tester.emit(IGen::pop_gpr64(i)); // i will have offset 0
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
tester.emit(IGen::pop_gpr64(k)); // k will have the value to store.
|
||||
|
||||
// store
|
||||
tester.emit(IGen::store8_gpr64_gpr64_plus_gpr64_plus_s8(i, j, k, -3));
|
||||
|
||||
// return!
|
||||
tester.emit_pop_all_gprs(true);
|
||||
tester.emit_return();
|
||||
|
||||
// prepare the memory:
|
||||
s8 memory[8] = {0, 0, -3, -2, -1, 0, 0, 0};
|
||||
|
||||
// run!
|
||||
tester.execute((u64)memory, 6, 7, 0);
|
||||
EXPECT_EQ(memory[2], -3);
|
||||
EXPECT_EQ(memory[3], 7);
|
||||
EXPECT_EQ(memory[4], -1);
|
||||
|
||||
if (memory[3] != 7) {
|
||||
fmt::print("test {}, {}, {}\n", tester.reg_name(i), tester.reg_name(j),
|
||||
tester.reg_name(k));
|
||||
printf("%s\n", tester.dump_to_hex_string().c_str());
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Emitter, store8_gpr64_gpr64_plus_gpr64_plus_s32) {
|
||||
CodeTester tester;
|
||||
tester.init_code_buffer(512);
|
||||
|
||||
tester.clear();
|
||||
tester.emit(IGen::store8_gpr64_gpr64_plus_gpr64_plus_s32(RAX, RCX, RDX, 12));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(), "88 94 01 0c 00 00 00");
|
||||
|
||||
auto instr = IGen::store8_gpr64_gpr64_plus_gpr64_plus_s32(RAX, RCX, RDX, -3);
|
||||
u8 buff[256];
|
||||
instr.emit(buff);
|
||||
EXPECT_EQ(*(s32*)(buff + instr.offset_of_disp()), -3);
|
||||
|
||||
int iter = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (i == RSP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 16; j++) {
|
||||
if (j == RSP || j == i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int k = 0; k < 16; k++) {
|
||||
if (k == RSP || k == j || k == i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tester.clear();
|
||||
tester.emit_push_all_gprs(true);
|
||||
// push args to the stack
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(2)));
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(1)));
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(0)));
|
||||
|
||||
// pop args into appropriate register
|
||||
tester.emit(IGen::pop_gpr64(i)); // i will have offset 0
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
tester.emit(IGen::pop_gpr64(k)); // k will have the value to store.
|
||||
|
||||
// store
|
||||
tester.emit(IGen::store8_gpr64_gpr64_plus_gpr64_plus_s32(i, j, k, -3));
|
||||
|
||||
// return!
|
||||
tester.emit_pop_all_gprs(true);
|
||||
tester.emit_return();
|
||||
|
||||
// prepare the memory:
|
||||
s8 memory[8] = {0, 0, -3, -2, -1, 0, 0, 0};
|
||||
|
||||
// run!
|
||||
tester.execute((u64)memory, 6, 7, 0);
|
||||
EXPECT_EQ(memory[2], -3);
|
||||
EXPECT_EQ(memory[3], 7);
|
||||
EXPECT_EQ(memory[4], -1);
|
||||
|
||||
if (memory[3] != 7) {
|
||||
fmt::print("test {}, {}, {}\n", tester.reg_name(i), tester.reg_name(j),
|
||||
tester.reg_name(k));
|
||||
printf("%s\n", tester.dump_to_hex_string().c_str());
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Emitter, store16_gpr64_gpr64_plus_gpr64) {
|
||||
CodeTester tester;
|
||||
tester.init_code_buffer(512);
|
||||
|
||||
tester.clear();
|
||||
tester.emit(IGen::store16_gpr64_gpr64_plus_gpr64(RCX, RAX, R8));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(), "66 44 89 04 08");
|
||||
|
||||
int iter = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (i == RSP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 16; j++) {
|
||||
if (j == RSP || j == i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int k = 0; k < 16; k++) {
|
||||
if (k == RSP || k == j || k == i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tester.clear();
|
||||
tester.emit_push_all_gprs(true);
|
||||
// push args to the stack
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(2)));
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(1)));
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(0)));
|
||||
|
||||
// pop args into appropriate register
|
||||
tester.emit(IGen::pop_gpr64(i)); // i will have offset 0
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
tester.emit(IGen::pop_gpr64(k)); // k will have the value to store.
|
||||
|
||||
// store!
|
||||
tester.emit(IGen::store16_gpr64_gpr64_plus_gpr64(i, j, k));
|
||||
|
||||
// return!
|
||||
tester.emit_pop_all_gprs(true);
|
||||
tester.emit_return();
|
||||
|
||||
// prepare the memory:
|
||||
s16 memory[8] = {0, 0, -3, -2, -1, 0, 0, 0};
|
||||
|
||||
// run!
|
||||
tester.execute((u64)memory, 6, 7, 0);
|
||||
EXPECT_EQ(memory[2], -3);
|
||||
EXPECT_EQ(memory[3], 7);
|
||||
EXPECT_EQ(memory[4], -1);
|
||||
|
||||
if (memory[3] != 7) {
|
||||
fmt::print("test {}, {}, {}\n", tester.reg_name(i), tester.reg_name(j),
|
||||
tester.reg_name(k));
|
||||
printf("%s\n", tester.dump_to_hex_string().c_str());
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Emitter, store16_gpr64_gpr64_plus_gpr64_plus_s8) {
|
||||
CodeTester tester;
|
||||
tester.init_code_buffer(512);
|
||||
|
||||
tester.clear();
|
||||
tester.emit(IGen::store16_gpr64_gpr64_plus_gpr64_plus_s8(RAX, RCX, R8, 12));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(), "66 44 89 44 01 0c");
|
||||
|
||||
auto instr = IGen::store16_gpr64_gpr64_plus_gpr64_plus_s8(RAX, RCX, RDX, -3);
|
||||
u8 buff[256];
|
||||
instr.emit(buff);
|
||||
EXPECT_EQ(*(s8*)(buff + instr.offset_of_disp()), -3);
|
||||
|
||||
int iter = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (i == RSP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 16; j++) {
|
||||
if (j == RSP || j == i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int k = 0; k < 16; k++) {
|
||||
if (k == RSP || k == j || k == i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tester.clear();
|
||||
tester.emit_push_all_gprs(true);
|
||||
// push args to the stack
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(2)));
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(1)));
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(0)));
|
||||
|
||||
// pop args into appropriate register
|
||||
tester.emit(IGen::pop_gpr64(i)); // i will have offset 0
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
tester.emit(IGen::pop_gpr64(k)); // k will have the value to store.
|
||||
|
||||
// store
|
||||
tester.emit(IGen::store16_gpr64_gpr64_plus_gpr64_plus_s8(i, j, k, -3));
|
||||
|
||||
// return!
|
||||
tester.emit_pop_all_gprs(true);
|
||||
tester.emit_return();
|
||||
|
||||
// prepare the memory:
|
||||
s16 memory[8] = {0, 0, -3, -2, -1, 0, 0, 0};
|
||||
|
||||
// run!
|
||||
tester.execute((u64)memory, 6 + 3, 7, 0);
|
||||
EXPECT_EQ(memory[2], -3);
|
||||
EXPECT_EQ(memory[3], 7);
|
||||
EXPECT_EQ(memory[4], -1);
|
||||
|
||||
if (memory[3] != 7) {
|
||||
fmt::print("test {}, {}, {}\n", tester.reg_name(i), tester.reg_name(j),
|
||||
tester.reg_name(k));
|
||||
printf("%s\n", tester.dump_to_hex_string().c_str());
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Emitter, store16_gpr64_gpr64_plus_gpr64_plus_s32) {
|
||||
CodeTester tester;
|
||||
tester.init_code_buffer(512);
|
||||
|
||||
tester.clear();
|
||||
tester.emit(IGen::store16_gpr64_gpr64_plus_gpr64_plus_s32(RAX, RCX, R8, 12));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(), "66 44 89 84 01 0c 00 00 00");
|
||||
|
||||
auto instr = IGen::store16_gpr64_gpr64_plus_gpr64_plus_s32(RAX, RCX, RDX, -3);
|
||||
u8 buff[256];
|
||||
instr.emit(buff);
|
||||
EXPECT_EQ(*(s8*)(buff + instr.offset_of_disp()), -3);
|
||||
|
||||
int iter = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (i == RSP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 16; j++) {
|
||||
if (j == RSP || j == i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int k = 0; k < 16; k++) {
|
||||
if (k == RSP || k == j || k == i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tester.clear();
|
||||
tester.emit_push_all_gprs(true);
|
||||
// push args to the stack
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(2)));
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(1)));
|
||||
tester.emit(IGen::push_gpr64(tester.get_c_abi_arg_reg(0)));
|
||||
|
||||
// pop args into appropriate register
|
||||
tester.emit(IGen::pop_gpr64(i)); // i will have offset 0
|
||||
tester.emit(IGen::pop_gpr64(j)); // j will have offset 1
|
||||
tester.emit(IGen::pop_gpr64(k)); // k will have the value to store.
|
||||
|
||||
// store
|
||||
tester.emit(IGen::store16_gpr64_gpr64_plus_gpr64_plus_s32(i, j, k, -3));
|
||||
|
||||
// return!
|
||||
tester.emit_pop_all_gprs(true);
|
||||
tester.emit_return();
|
||||
|
||||
// prepare the memory:
|
||||
s16 memory[8] = {0, 0, -3, -2, -1, 0, 0, 0};
|
||||
|
||||
// run!
|
||||
tester.execute((u64)memory, 6 + 3, 7, 0);
|
||||
EXPECT_EQ(memory[2], -3);
|
||||
EXPECT_EQ(memory[3], 7);
|
||||
EXPECT_EQ(memory[4], -1);
|
||||
|
||||
if (memory[3] != 7) {
|
||||
fmt::print("test {}, {}, {}\n", tester.reg_name(i), tester.reg_name(j),
|
||||
tester.reg_name(k));
|
||||
printf("%s\n", tester.dump_to_hex_string().c_str());
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,6 @@
|
||||
//
|
||||
using namespace emitter;
|
||||
|
||||
|
||||
|
||||
TEST(EmitterSlow, xmm32_move) {
|
||||
std::vector<u32> u32_constants = {0, INT32_MAX, UINT32_MAX, 17};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user