add some stores

This commit is contained in:
water
2020-08-29 22:41:46 -04:00
parent a2e04508f6
commit 5100aa6a30
11 changed files with 635 additions and 117 deletions
View File
+5 -7
View File
@@ -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
+3 -5
View File
@@ -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
+144
View File
@@ -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
View File
@@ -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));
}
+6 -9
View File
@@ -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
+9 -29
View File
@@ -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;
-1
View File
@@ -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.
-1
View File
@@ -167,4 +167,3 @@ TEST(CodeTester, push_pop_all_the_things) {
tester.emit_return();
tester.execute();
}
+440 -46
View File
@@ -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++;
}
}
}
}
-2
View File
@@ -11,8 +11,6 @@
//
using namespace emitter;
TEST(EmitterSlow, xmm32_move) {
std::vector<u32> u32_constants = {0, INT32_MAX, UINT32_MAX, 17};