summaryrefslogtreecommitdiff
path: root/gen_x86.c
diff options
context:
space:
mode:
authorMike Pavone <pavone@retrodev.com>2012-12-19 20:23:59 -0800
committerMike Pavone <pavone@retrodev.com>2012-12-19 20:23:59 -0800
commit5ad499fa36c4c71585b1fee5ff4059b743149eb7 (patch)
treee4db06033959280d5c5aeead823f813b0e9a1f1f /gen_x86.c
parent7ee7471794207e37114ced2e1181b8448f5a78dd (diff)
Add support for BTST instruction (untested), absolute addressing mode for instructions other than move (untested) and fix decoding of MOVEM.
Diffstat (limited to 'gen_x86.c')
-rw-r--r--gen_x86.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/gen_x86.c b/gen_x86.c
index 9f10429..dbe58ca 100644
--- a/gen_x86.c
+++ b/gen_x86.c
@@ -40,6 +40,8 @@
#define OP2_JCC 0x80
#define OP2_SETCC 0x90
+#define OP2_BT 0xA3
+#define OP2_BTX_I 0xBA
#define OP_EX_ADDI 0x0
#define OP_EX_ORI 0x1
@@ -59,6 +61,11 @@
#define OP_EX_SAL 0x6 //identical to SHL
#define OP_EX_SAR 0x7
+#define OP_EX_BT 0x4
+#define OP_EX_BTS 0x5
+#define OP_EX_BTR 0x6
+#define OP_EX_BTC 0x7
+
#define BIT_IMMED_RAX 0x4
#define BIT_DIR 0x2
#define BIT_SIZE 0x1
@@ -880,6 +887,106 @@ uint8_t * setcc_rind(uint8_t * out, uint8_t cc, uint8_t dst)
return out;
}
+uint8_t * bt_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
+{
+ if (size == SZ_W) {
+ *(out++) = PRE_SIZE;
+ }
+ if (size == SZ_Q || src >= R8 || dst >= R8) {
+ *out = PRE_REX;
+ if (size == SZ_Q) {
+ *out |= REX_QUAD;
+ }
+ if (src >= R8) {
+ *out |= REX_REG_FIELD;
+ src -= (R8 - X86_R8);
+ }
+ if (dst >= R8) {
+ *out |= REX_RM_FIELD;
+ dst -= (R8 - X86_R8);
+ }
+ out++;
+ }
+ *(out++) = PRE_2BYTE;
+ *(out++) = OP2_BT;
+ *(out++) = MODE_REG_DIRECT | dst | (src << 3);
+ return out;
+}
+
+uint8_t * bt_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_disp, uint8_t size)
+{
+ if (size == SZ_W) {
+ *(out++) = PRE_SIZE;
+ }
+ if (size == SZ_Q || src >= R8 || dst_base >= R8) {
+ *out = PRE_REX;
+ if (size == SZ_Q) {
+ *out |= REX_QUAD;
+ }
+ if (src >= R8) {
+ *out |= REX_REG_FIELD;
+ src -= (R8 - X86_R8);
+ }
+ if (dst_base >= R8) {
+ *out |= REX_RM_FIELD;
+ dst_base -= (R8 - X86_R8);
+ }
+ out++;
+ }
+ *(out++) = PRE_2BYTE;
+ *(out++) = OP2_BT;
+ *(out++) = MODE_REG_DISPLACE8 | dst_base | (src << 3);
+ *(out++) = dst_disp;
+ return out;
+}
+
+uint8_t * bt_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size)
+{
+ if (size == SZ_W) {
+ *(out++) = PRE_SIZE;
+ }
+ if (size == SZ_Q || dst >= R8) {
+ *out = PRE_REX;
+ if (size == SZ_Q) {
+ *out |= REX_QUAD;
+ }
+ if (dst >= R8) {
+ *out |= REX_RM_FIELD;
+ dst -= (R8 - X86_R8);
+ }
+ out++;
+ }
+ *(out++) = PRE_2BYTE;
+ *(out++) = OP2_BTX_I;
+ *(out++) = MODE_REG_DIRECT | dst | (OP_EX_BT << 3);
+ *(out++) = val;
+ return out;
+}
+
+uint8_t * bt_irdisp8(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t dst_disp, uint8_t size)
+{
+ if (size == SZ_W) {
+ *(out++) = PRE_SIZE;
+ }
+ if (size == SZ_Q || dst_base >= R8) {
+ *out = PRE_REX;
+ if (size == SZ_Q) {
+ *out |= REX_QUAD;
+ }
+ if (dst_base >= R8) {
+ *out |= REX_RM_FIELD;
+ dst_base -= (R8 - X86_R8);
+ }
+ out++;
+ }
+ *(out++) = PRE_2BYTE;
+ *(out++) = OP2_BTX_I;
+ *(out++) = MODE_REG_DISPLACE8 | dst_base | (OP_EX_BT << 3);
+ *(out++) = dst_disp;
+ *(out++) = val;
+ return out;
+}
+
uint8_t * jcc(uint8_t * out, uint8_t cc, uint8_t * dest)
{
ptrdiff_t disp = dest-(out+2);