add all loads

This commit is contained in:
water
2020-08-29 21:04:21 -04:00
parent bf7a496bb0
commit a2e04508f6
3 changed files with 1411 additions and 4 deletions
+334 -2
View File
@@ -115,8 +115,12 @@ class IGen {
return instr;
}
// todo - GPR64 -> XMM64 (zext)
// todo - XMM -> GPR64
// todo - XMM128 - XMM128
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// LOADS n' STORES - reg + reg addr
// GOAL Loads
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
/*!
@@ -138,6 +142,42 @@ class IGen {
return instr;
}
static Instruction load8s_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0xf);
instr.set_op2(0xbe);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s8(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, true);
return instr;
}
static Instruction load8s_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0xf);
instr.set_op2(0xbe);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s32(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, true);
return instr;
}
/*!
* movzx dst, BYTE PTR [addr1 + addr2]
* addr1 and addr2 have to be different registers.
@@ -157,6 +197,42 @@ class IGen {
return instr;
}
static Instruction load8u_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0xf);
instr.set_op2(0xb6);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s8(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, true);
return instr;
}
static Instruction load8u_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0xf);
instr.set_op2(0xb6);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s32(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, true);
return instr;
}
/*!
* movsx dst, WORD PTR [addr1 + addr2]
* addr1 and addr2 have to be different registers.
@@ -176,6 +252,41 @@ class IGen {
return instr;
}
static Instruction load16s_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0xf);
instr.set_op2(0xbf);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s8(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, true);
return instr;
}
static Instruction load16s_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0xf);
instr.set_op2(0xbf);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s32(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, true);
return instr;
}
/*!
* movzx dst, WORD PTR [addr1 + addr2]
@@ -196,6 +307,42 @@ class IGen {
return instr;
}
static Instruction load16u_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0xf);
instr.set_op2(0xb7);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s8(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, true);
return instr;
}
static Instruction load16u_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0xf);
instr.set_op2(0xb7);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s32(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, true);
return instr;
}
/*!
* movsxd dst, DWORD PTR [addr1 + addr2]
* addr1 and addr2 have to be different registers.
@@ -213,6 +360,40 @@ class IGen {
return instr;
}
static Instruction load32s_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0x63);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s8(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, true);
return instr;
}
static Instruction load32s_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0x63);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s32(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, true);
return instr;
}
/*!
* movzxd dst, DWORD PTR [addr1 + addr2]
* addr1 and addr2 have to be different registers.
@@ -230,6 +411,40 @@ class IGen {
return instr;
}
static Instruction load32u_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0x8b);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s8(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, false);
return instr;
}
static Instruction load32u_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0x8b);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s32(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, false);
return instr;
}
/*!
* mov dst, QWORD PTR [addr1 + addr2]
* addr1 and addr2 have to be different registers.
@@ -247,8 +462,125 @@ class IGen {
return instr;
}
static Instruction load64_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0x8b);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s8(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, true);
return instr;
}
static Instruction load64_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
assert(dst.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(0x8b);
instr.set_modrm_and_rex_for_reg_plus_reg_plus_s32(dst.hw_id(), addr1.hw_id(), addr2.hw_id(),
offset, true);
return instr;
}
static Instruction load_goal_gpr(Register dst,
Register addr,
Register off,
int offset,
int size,
bool sign_extend) {
switch (size) {
case 1:
if (offset == 0) {
if (sign_extend) {
return load8s_gpr64_gpr64_plus_gpr64(dst, addr, off);
} else {
return load8u_gpr64_gpr64_plus_gpr64(dst, addr, off);
}
} else if (offset >= INT8_MIN && offset <= INT8_MAX) {
if (sign_extend) {
return load8s_gpr64_gpr64_plus_gpr64_plus_s8(dst, addr, off, offset);
} else {
return load8u_gpr64_gpr64_plus_gpr64_plus_s8(dst, addr, off, offset);
}
} else if (offset >= INT32_MIN && offset <= INT32_MAX) {
if (sign_extend) {
return load8s_gpr64_gpr64_plus_gpr64_plus_s32(dst, addr, off, offset);
} else {
return load8u_gpr64_gpr64_plus_gpr64_plus_s32(dst, addr, off, offset);
}
} else {
assert(false);
}
case 2:
if (offset == 0) {
if (sign_extend) {
return load16s_gpr64_gpr64_plus_gpr64(dst, addr, off);
} else {
return load16u_gpr64_gpr64_plus_gpr64(dst, addr, off);
}
} else if (offset >= INT8_MIN && offset <= INT8_MAX) {
if (sign_extend) {
return load16s_gpr64_gpr64_plus_gpr64_plus_s8(dst, addr, off, offset);
} else {
return load16u_gpr64_gpr64_plus_gpr64_plus_s8(dst, addr, off, offset);
}
} else if (offset >= INT32_MIN && offset <= INT32_MAX) {
if (sign_extend) {
return load16s_gpr64_gpr64_plus_gpr64_plus_s32(dst, addr, off, offset);
} else {
return load16u_gpr64_gpr64_plus_gpr64_plus_s32(dst, addr, off, offset);
}
} else {
assert(false);
}
case 4:
if (offset == 0) {
if (sign_extend) {
return load32s_gpr64_gpr64_plus_gpr64(dst, addr, off);
} else {
return load32u_gpr64_gpr64_plus_gpr64(dst, addr, off);
}
} else if (offset >= INT8_MIN && offset <= INT8_MAX) {
if (sign_extend) {
return load32s_gpr64_gpr64_plus_gpr64_plus_s8(dst, addr, off, offset);
} else {
return load32u_gpr64_gpr64_plus_gpr64_plus_s8(dst, addr, off, offset);
}
} else if (offset >= INT32_MIN && offset <= INT32_MAX) {
if (sign_extend) {
return load32s_gpr64_gpr64_plus_gpr64_plus_s32(dst, addr, off, offset);
} else {
return load32u_gpr64_gpr64_plus_gpr64_plus_s32(dst, addr, off, offset);
}
} else {
assert(false);
}
case 8:
default:
assert(false);
}
}
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// LOADS n' STORES - XMM128
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
/*!
* Store a 128-bit xmm into a register, no offset
* Store a 128-bit xmm into an address stored in a register, no offset
*/
static Instruction store128_gpr64_xmm128(Register gpr_addr, Register xmm_value) {
assert(gpr_addr.is_gpr());
+110 -2
View File
@@ -169,6 +169,114 @@ 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) {
bool rex_b = false, rex_r = false, rex_x = false;
bool addr1_ext = false;
bool addr2_ext = false;
if (addr1 >= 8) {
addr1 -= 8;
addr1_ext = true;
}
if (addr2 >= 8) {
addr2 -= 8;
addr2_ext = true;
}
if (reg >= 8) {
reg -= 8;
rex_r = true;
}
ModRM modrm;
modrm.mod = 1; // no disp
modrm.rm = 4; // sib!
modrm.reg_op = reg;
SIB sib;
sib.scale = 0;
Imm imm2(1, offset);
// default addr1 in index
if(addr1 == 4) {
sib.index = addr2;
sib.base = addr1;
rex_x = addr2_ext;
rex_b = addr1_ext;
} else {
// addr1 in index
sib.index = addr1;
sib.base = addr2;
rex_x = addr1_ext;
rex_b = addr2_ext;
}
assert(sib.index != 4);
if(rex_b || rex_w || rex_r || rex_x) {
set(REX(rex_w, rex_r, rex_x, rex_b));
}
set(modrm);
set(sib);
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) {
bool rex_b = false, rex_r = false, rex_x = false;
bool addr1_ext = false;
bool addr2_ext = false;
if (addr1 >= 8) {
addr1 -= 8;
addr1_ext = true;
}
if (addr2 >= 8) {
addr2 -= 8;
addr2_ext = true;
}
if (reg >= 8) {
reg -= 8;
rex_r = true;
}
ModRM modrm;
modrm.mod = 2; // no disp
modrm.rm = 4; // sib!
modrm.reg_op = reg;
SIB sib;
sib.scale = 0;
Imm imm2(4, offset);
// default addr1 in index
if(addr1 == 4) {
sib.index = addr2;
sib.base = addr1;
rex_x = addr2_ext;
rex_b = addr1_ext;
} else {
// addr1 in index
sib.index = addr1;
sib.base = addr2;
rex_x = addr1_ext;
rex_b = addr2_ext;
}
assert(sib.index != 4);
if(rex_b || rex_w || rex_r || rex_x) {
set(REX(rex_w, rex_r, rex_x, rex_b));
}
set(modrm);
set(sib);
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) {
bool rex_b = false, rex_r = false, rex_x = false;
bool addr1_ext = false;
@@ -203,7 +311,7 @@ struct Instruction {
rex_x = addr1_ext;
rex_b = addr2_ext;
modrm.mod = 1;
set(Imm(1, 0));
set_disp(Imm(1, 0));
} else {
// default addr1 in index
@@ -267,7 +375,7 @@ struct Instruction {
if (rm == 5) {
modrm.mod = 1; // 1 byte imm
set(Imm(1, 0));
set_disp(Imm(1, 0));
}
set(modrm);
File diff suppressed because it is too large Load Diff