summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gen_x86.c99
-rw-r--r--gen_x86.h12
-rw-r--r--m68k_to_x86.c55
3 files changed, 150 insertions, 16 deletions
diff --git a/gen_x86.c b/gen_x86.c
index e7817d8..ebc06d6 100644
--- a/gen_x86.c
+++ b/gen_x86.c
@@ -43,7 +43,10 @@
#define OP2_JCC 0x80
#define OP2_SETCC 0x90
#define OP2_BT 0xA3
+#define OP2_BTS 0xAB
+#define OP2_BTR 0xB3
#define OP2_BTX_I 0xBA
+#define OP2_BTC 0xBB
#define OP2_MOVSX 0xBE
#define OP_EX_ADDI 0x0
@@ -1082,7 +1085,7 @@ uint8_t * setcc_rdisp8(uint8_t * out, uint8_t cc, uint8_t dst, int8_t disp)
return out;
}
-uint8_t * bt_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
+uint8_t * bit_rr(uint8_t * out, uint8_t op2, uint8_t src, uint8_t dst, uint8_t size)
{
if (size == SZ_W) {
*(out++) = PRE_SIZE;
@@ -1103,12 +1106,12 @@ uint8_t * bt_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
out++;
}
*(out++) = PRE_2BYTE;
- *(out++) = OP2_BT;
+ *(out++) = op2;
*(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)
+uint8_t * bit_rrdisp8(uint8_t * out, uint8_t op2, uint8_t src, uint8_t dst_base, int8_t dst_disp, uint8_t size)
{
if (size == SZ_W) {
*(out++) = PRE_SIZE;
@@ -1129,13 +1132,13 @@ uint8_t * bt_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_di
out++;
}
*(out++) = PRE_2BYTE;
- *(out++) = OP2_BT;
+ *(out++) = op2;
*(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)
+uint8_t * bit_ir(uint8_t * out, uint8_t op_ex, uint8_t val, uint8_t dst, uint8_t size)
{
if (size == SZ_W) {
*(out++) = PRE_SIZE;
@@ -1153,12 +1156,12 @@ uint8_t * bt_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size)
}
*(out++) = PRE_2BYTE;
*(out++) = OP2_BTX_I;
- *(out++) = MODE_REG_DIRECT | dst | (OP_EX_BT << 3);
+ *(out++) = MODE_REG_DIRECT | dst | (op_ex << 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)
+uint8_t * bit_irdisp8(uint8_t * out, uint8_t op_ex, uint8_t val, uint8_t dst_base, int8_t dst_disp, uint8_t size)
{
if (size == SZ_W) {
*(out++) = PRE_SIZE;
@@ -1176,12 +1179,92 @@ uint8_t * bt_irdisp8(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t dst_di
}
*(out++) = PRE_2BYTE;
*(out++) = OP2_BTX_I;
- *(out++) = MODE_REG_DISPLACE8 | dst_base | (OP_EX_BT << 3);
+ *(out++) = MODE_REG_DISPLACE8 | dst_base | (op_ex << 3);
*(out++) = dst_disp;
*(out++) = val;
return out;
}
+uint8_t * bt_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
+{
+ return bit_rr(out, OP2_BT, src, dst, size);
+}
+
+uint8_t * bt_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_disp, uint8_t size)
+{
+ return bit_rrdisp8(out, OP2_BT, src, dst_base, dst_disp, size);
+}
+
+uint8_t * bt_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size)
+{
+ return bit_ir(out, OP_EX_BT, val, dst, size);
+}
+
+uint8_t * bt_irdisp8(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t dst_disp, uint8_t size)
+{
+ return bit_irdisp8(out, OP_EX_BT, val, dst_base, dst_disp, size);
+}
+
+uint8_t * bts_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
+{
+ return bit_rr(out, OP2_BT, src, dst, size);
+}
+
+uint8_t * bts_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_disp, uint8_t size)
+{
+ return bit_rrdisp8(out, OP2_BT, src, dst_base, dst_disp, size);
+}
+
+uint8_t * bts_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size)
+{
+ return bit_ir(out, OP_EX_BTS, val, dst, size);
+}
+
+uint8_t * bts_irdisp8(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t dst_disp, uint8_t size)
+{
+ return bit_irdisp8(out, OP_EX_BTS, val, dst_base, dst_disp, size);
+}
+
+uint8_t * btr_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
+{
+ return bit_rr(out, OP2_BTR, src, dst, size);
+}
+
+uint8_t * btr_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_disp, uint8_t size)
+{
+ return bit_rrdisp8(out, OP2_BTR, src, dst_base, dst_disp, size);
+}
+
+uint8_t * btr_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size)
+{
+ return bit_ir(out, OP_EX_BTR, val, dst, size);
+}
+
+uint8_t * btr_irdisp8(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t dst_disp, uint8_t size)
+{
+ return bit_irdisp8(out, OP_EX_BTR, val, dst_base, dst_disp, size);
+}
+
+uint8_t * btc_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
+{
+ return bit_rr(out, OP2_BTC, src, dst, size);
+}
+
+uint8_t * btc_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_disp, uint8_t size)
+{
+ return bit_rrdisp8(out, OP2_BTC, src, dst_base, dst_disp, size);
+}
+
+uint8_t * btc_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size)
+{
+ return bit_ir(out, OP_EX_BTC, val, dst, size);
+}
+
+uint8_t * btc_irdisp8(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t dst_disp, uint8_t size)
+{
+ return bit_irdisp8(out, OP_EX_BTC, val, dst_base, dst_disp, size);
+}
+
uint8_t * jcc(uint8_t * out, uint8_t cc, uint8_t * dest)
{
ptrdiff_t disp = dest-(out+2);
diff --git a/gen_x86.h b/gen_x86.h
index ff58a2b..7c80aa1 100644
--- a/gen_x86.h
+++ b/gen_x86.h
@@ -148,6 +148,18 @@ uint8_t * bt_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size);
uint8_t * bt_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_disp, uint8_t size);
uint8_t * bt_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size);
uint8_t * bt_irdisp8(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t dst_disp, uint8_t size);
+uint8_t * bts_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size);
+uint8_t * bts_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_disp, uint8_t size);
+uint8_t * bts_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size);
+uint8_t * bts_irdisp8(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t dst_disp, uint8_t size);
+uint8_t * btr_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size);
+uint8_t * btr_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_disp, uint8_t size);
+uint8_t * btr_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size);
+uint8_t * btr_irdisp8(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t dst_disp, uint8_t size);
+uint8_t * btc_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size);
+uint8_t * btc_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_disp, uint8_t size);
+uint8_t * btc_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size);
+uint8_t * btc_irdisp8(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t dst_disp, uint8_t size);
uint8_t * jcc(uint8_t * out, uint8_t cc, uint8_t *dest);
uint8_t * jmp(uint8_t * out, uint8_t *dest);
uint8_t * jmp_r(uint8_t * out, uint8_t dst);
diff --git a/m68k_to_x86.c b/m68k_to_x86.c
index 2689c59..24b6410 100644
--- a/m68k_to_x86.c
+++ b/m68k_to_x86.c
@@ -2075,20 +2075,39 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
case M68K_LSR:
dst = translate_shift(dst, inst, &src_op, &dst_op, opts, shr_ir, shr_irdisp8, shr_clr, shr_clrdisp8, shl_ir, shl_irdisp8);
break;
- /*case M68K_BCHG:
+ case M68K_BCHG:
case M68K_BCLR:
case M68K_BSET:
- break;*/
case M68K_BTST:
dst = cycles(dst, inst->extra.size == OPSIZE_BYTE ? 4 : 6);
if (src_op.mode == MODE_IMMED) {
if (inst->extra.size == OPSIZE_BYTE) {
src_op.disp &= 0x7;
}
- if (dst_op.mode == MODE_REG_DIRECT) {
- dst = bt_ir(dst, src_op.disp, dst_op.base, SZ_D);
+ if (inst->op == M68K_BTST) {
+ if (dst_op.mode == MODE_REG_DIRECT) {
+ dst = bt_ir(dst, src_op.disp, dst_op.base, SZ_D);
+ } else {
+ dst = bt_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, SZ_D);
+ }
+ } else if (inst->op == M68K_BSET) {
+ if (dst_op.mode == MODE_REG_DIRECT) {
+ dst = bts_ir(dst, src_op.disp, dst_op.base, SZ_D);
+ } else {
+ dst = bts_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, SZ_D);
+ }
+ } else if (inst->op == M68K_BCLR) {
+ if (dst_op.mode == MODE_REG_DIRECT) {
+ dst = btr_ir(dst, src_op.disp, dst_op.base, SZ_D);
+ } else {
+ dst = btr_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, SZ_D);
+ }
} else {
- dst = bt_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, SZ_D);
+ if (dst_op.mode == MODE_REG_DIRECT) {
+ dst = btc_ir(dst, src_op.disp, dst_op.base, SZ_D);
+ } else {
+ dst = btc_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, SZ_D);
+ }
}
} else {
if (src_op.mode == MODE_REG_DISPLACE8) {
@@ -2104,10 +2123,30 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
if (inst->extra.size == OPSIZE_BYTE) {
dst = and_ir(dst, 0x7, src_op.base, SZ_B);
}
- if (dst_op.mode == MODE_REG_DIRECT) {
- dst = bt_rr(dst, src_op.base, dst_op.base, SZ_D);
+ if (inst->op == M68K_BTST) {
+ if (dst_op.mode == MODE_REG_DIRECT) {
+ dst = bt_rr(dst, src_op.base, dst_op.base, SZ_D);
+ } else {
+ dst = bt_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, SZ_D);
+ }
+ } else if (inst->op == M68K_BSET) {
+ if (dst_op.mode == MODE_REG_DIRECT) {
+ dst = bts_rr(dst, src_op.base, dst_op.base, SZ_D);
+ } else {
+ dst = bts_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, SZ_D);
+ }
+ } else if (inst->op == M68K_BCLR) {
+ if (dst_op.mode == MODE_REG_DIRECT) {
+ dst = btr_rr(dst, src_op.base, dst_op.base, SZ_D);
+ } else {
+ dst = btr_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, SZ_D);
+ }
} else {
- dst = bt_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, SZ_D);
+ if (dst_op.mode == MODE_REG_DIRECT) {
+ dst = btc_rr(dst, src_op.base, dst_op.base, SZ_D);
+ } else {
+ dst = btc_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, SZ_D);
+ }
}
}
//x86 sets the carry flag to the value of the bit tested