[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 02/12] target-m68k: Split gen_lea and gen_ea
From: |
Laurent Vivier |
Subject: |
[Qemu-devel] [PULL 02/12] target-m68k: Split gen_lea and gen_ea |
Date: |
Sat, 24 Dec 2016 12:40:23 +0100 |
From: Richard Henderson <address@hidden>
Provide gen_lea_mode and gen_ea_mode, where the mode can be
specified manually, rather than taken from the instruction.
Signed-off-by: Richard Henderson <address@hidden>
Message-Id: <address@hidden>
---
target/m68k/translate.c | 112 +++++++++++++++++++++++++-----------------------
1 file changed, 59 insertions(+), 53 deletions(-)
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index a9066dc..aaa221e 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -697,37 +697,37 @@ static void gen_partset_reg(int opsize, TCGv reg, TCGv
val)
/* Generate code for an "effective address". Does not adjust the base
register for autoincrement addressing modes. */
-static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
- int opsize)
+static TCGv gen_lea_mode(CPUM68KState *env, DisasContext *s,
+ int mode, int reg0, int opsize)
{
TCGv reg;
TCGv tmp;
uint16_t ext;
uint32_t offset;
- switch ((insn >> 3) & 7) {
+ switch (mode) {
case 0: /* Data register direct. */
case 1: /* Address register direct. */
return NULL_QREG;
case 2: /* Indirect register */
case 3: /* Indirect postincrement. */
- return AREG(insn, 0);
+ return get_areg(s, reg0);
case 4: /* Indirect predecrememnt. */
- reg = AREG(insn, 0);
+ reg = get_areg(s, reg0);
tmp = tcg_temp_new();
tcg_gen_subi_i32(tmp, reg, opsize_bytes(opsize));
return tmp;
case 5: /* Indirect displacement. */
- reg = AREG(insn, 0);
+ reg = get_areg(s, reg0);
tmp = tcg_temp_new();
ext = read_im16(env, s);
tcg_gen_addi_i32(tmp, reg, (int16_t)ext);
return tmp;
case 6: /* Indirect index + displacement. */
- reg = AREG(insn, 0);
+ reg = get_areg(s, reg0);
return gen_lea_indexed(env, s, reg);
case 7: /* Other */
- switch (insn & 7) {
+ switch (reg0) {
case 0: /* Absolute short. */
offset = (int16_t)read_im16(env, s);
return tcg_const_i32(offset);
@@ -749,39 +749,26 @@ static TCGv gen_lea(CPUM68KState *env, DisasContext *s,
uint16_t insn,
return NULL_QREG;
}
-/* Helper function for gen_ea. Reuse the computed address between the
- for read/write operands. */
-static inline TCGv gen_ea_once(CPUM68KState *env, DisasContext *s,
- uint16_t insn, int opsize, TCGv val,
- TCGv *addrp, ea_what what)
+static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
+ int opsize)
{
- TCGv tmp;
-
- if (addrp && what == EA_STORE) {
- tmp = *addrp;
- } else {
- tmp = gen_lea(env, s, insn, opsize);
- if (IS_NULL_QREG(tmp))
- return tmp;
- if (addrp)
- *addrp = tmp;
- }
- return gen_ldst(s, opsize, tmp, val, what);
+ int mode = extract32(insn, 3, 3);
+ int reg0 = REG(insn, 0);
+ return gen_lea_mode(env, s, mode, reg0, opsize);
}
-/* Generate code to load/store a value from/into an EA. If VAL > 0 this is
+/* Generate code to load/store a value from/into an EA. If WHAT > 0 this is
a write otherwise it is a read (0 == sign extend, -1 == zero extend).
ADDRP is non-null for readwrite operands. */
-static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
- int opsize, TCGv val, TCGv *addrp, ea_what what)
+static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0,
+ int opsize, TCGv val, TCGv *addrp, ea_what what)
{
- TCGv reg;
- TCGv result;
- uint32_t offset;
+ TCGv reg, tmp, result;
+ int32_t offset;
- switch ((insn >> 3) & 7) {
+ switch (mode) {
case 0: /* Data register direct. */
- reg = DREG(insn, 0);
+ reg = cpu_dregs[reg0];
if (what == EA_STORE) {
gen_partset_reg(opsize, reg, val);
return store_dummy;
@@ -789,7 +776,7 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s,
uint16_t insn,
return gen_extend(reg, opsize, what == EA_LOADS);
}
case 1: /* Address register direct. */
- reg = AREG(insn, 0);
+ reg = get_areg(s, reg0);
if (what == EA_STORE) {
tcg_gen_mov_i32(reg, val);
return store_dummy;
@@ -797,45 +784,56 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s,
uint16_t insn,
return gen_extend(reg, opsize, what == EA_LOADS);
}
case 2: /* Indirect register */
- reg = AREG(insn, 0);
+ reg = get_areg(s, reg0);
return gen_ldst(s, opsize, reg, val, what);
case 3: /* Indirect postincrement. */
- reg = AREG(insn, 0);
+ reg = get_areg(s, reg0);
result = gen_ldst(s, opsize, reg, val, what);
if (what == EA_STORE || !addrp) {
TCGv tmp = tcg_temp_new();
tcg_gen_addi_i32(tmp, reg, opsize_bytes(opsize));
- delay_set_areg(s, REG(insn, 0), tmp, true);
+ delay_set_areg(s, reg0, tmp, true);
}
return result;
case 4: /* Indirect predecrememnt. */
- {
- TCGv tmp;
- if (addrp && what == EA_STORE) {
- tmp = *addrp;
- } else {
- tmp = gen_lea(env, s, insn, opsize);
- if (IS_NULL_QREG(tmp))
- return tmp;
- if (addrp)
- *addrp = tmp;
+ if (addrp && what == EA_STORE) {
+ tmp = *addrp;
+ } else {
+ tmp = gen_lea_mode(env, s, mode, reg0, opsize);
+ if (IS_NULL_QREG(tmp)) {
+ return tmp;
}
- result = gen_ldst(s, opsize, tmp, val, what);
- if (what == EA_STORE || !addrp) {
- delay_set_areg(s, REG(insn, 0), tmp, false);
+ if (addrp) {
+ *addrp = tmp;
}
}
+ result = gen_ldst(s, opsize, tmp, val, what);
+ if (what == EA_STORE || !addrp) {
+ delay_set_areg(s, reg0, tmp, false);
+ }
return result;
case 5: /* Indirect displacement. */
case 6: /* Indirect index + displacement. */
- return gen_ea_once(env, s, insn, opsize, val, addrp, what);
+ do_indirect:
+ if (addrp && what == EA_STORE) {
+ tmp = *addrp;
+ } else {
+ tmp = gen_lea_mode(env, s, mode, reg0, opsize);
+ if (IS_NULL_QREG(tmp)) {
+ return tmp;
+ }
+ if (addrp) {
+ *addrp = tmp;
+ }
+ }
+ return gen_ldst(s, opsize, tmp, val, what);
case 7: /* Other */
- switch (insn & 7) {
+ switch (reg0) {
case 0: /* Absolute short. */
case 1: /* Absolute long. */
case 2: /* pc displacement */
case 3: /* pc index+displacement. */
- return gen_ea_once(env, s, insn, opsize, val, addrp, what);
+ goto do_indirect;
case 4: /* Immediate. */
/* Sign extend values for consistency. */
switch (opsize) {
@@ -868,6 +866,14 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s,
uint16_t insn,
return NULL_QREG;
}
+static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
+ int opsize, TCGv val, TCGv *addrp, ea_what what)
+{
+ int mode = extract32(insn, 3, 3);
+ int reg0 = REG(insn, 0);
+ return gen_ea_mode(env, s, mode, reg0, opsize, val, addrp, what);
+}
+
typedef struct {
TCGCond tcond;
bool g1;
--
2.7.4
- [Qemu-devel] [PULL 00/12] M68k for 2.9 patches, Laurent Vivier, 2016/12/24
- [Qemu-devel] [PULL 03/12] target-m68k: add cmpm, Laurent Vivier, 2016/12/24
- [Qemu-devel] [PULL 04/12] target-m68k: add 64bit mull, Laurent Vivier, 2016/12/24
- [Qemu-devel] [PULL 06/12] target-m68k: add abcd/sbcd/nbcd, Laurent Vivier, 2016/12/24
- [Qemu-devel] [PULL 05/12] target-m68k: add 680x0 divu/divs variants, Laurent Vivier, 2016/12/24
- [Qemu-devel] [PULL 12/12] target-m68k: free TCG variables that are not, Laurent Vivier, 2016/12/24
- [Qemu-devel] [PULL 02/12] target-m68k: Split gen_lea and gen_ea,
Laurent Vivier <=
- [Qemu-devel] [PULL 11/12] target-m68k: add rol/ror/roxl/roxr instructions, Laurent Vivier, 2016/12/24
- [Qemu-devel] [PULL 07/12] target-m68k: add cas/cas2 ops, Laurent Vivier, 2016/12/24
- [Qemu-devel] [PULL 01/12] target-m68k: Delay autoinc writeback, Laurent Vivier, 2016/12/24
- [Qemu-devel] [PULL 08/12] target-m68k: Implement 680x0 movem, Laurent Vivier, 2016/12/24
- [Qemu-devel] [PULL 09/12] target-m68k: Do not cpu_abort on undefined insns, Laurent Vivier, 2016/12/24
- [Qemu-devel] [PULL 10/12] target-m68k: Inline shifts, Laurent Vivier, 2016/12/24
- Re: [Qemu-devel] [PULL 00/12] M68k for 2.9 patches, Peter Maydell, 2016/12/27