diff mbox

[for-2.5,15/30] m68k: add more modes to movem

Message ID 1439151229-27747-16-git-send-email-laurent@vivier.eu
State New
Headers show

Commit Message

Laurent Vivier Aug. 9, 2015, 8:13 p.m. UTC
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 52 ++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 39 insertions(+), 13 deletions(-)

Comments

Richard Henderson Aug. 12, 2015, 7:54 a.m. UTC | #1
On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> +    opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD;
> +    incr = opsize_bytes(opsize);
> +    if (!is_load && (insn & 070) == 040) {
> +        for (i = 15; i >= 0; i--, mask >>= 1) {

This has got to be wrong.  Just because it's pre-decrement doesn't mean you 
should skip all of the loads.


r~
Andreas Schwab Aug. 12, 2015, 8:07 a.m. UTC | #2
Richard Henderson <rth@twiddle.net> writes:

> On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>> +    opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD;
>> +    incr = opsize_bytes(opsize);
>> +    if (!is_load && (insn & 070) == 040) {
>> +        for (i = 15; i >= 0; i--, mask >>= 1) {
>
> This has got to be wrong.  Just because it's pre-decrement doesn't mean
> you should skip all of the loads.

Pre-dec only supports reg-to-mem, and is special because mask is bit
reversed.

Andreas.
Richard Henderson Aug. 12, 2015, 3:13 p.m. UTC | #3
On 08/12/2015 01:07 AM, Andreas Schwab wrote:
> Richard Henderson <rth@twiddle.net> writes:
> 
>> On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>>> +    opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD;
>>> +    incr = opsize_bytes(opsize);
>>> +    if (!is_load && (insn & 070) == 040) {
>>> +        for (i = 15; i >= 0; i--, mask >>= 1) {
>>
>> This has got to be wrong.  Just because it's pre-decrement doesn't mean
>> you should skip all of the loads.
> 
> Pre-dec only supports reg-to-mem, and is special because mask is bit
> reversed.

Ah, I'd never noticed that.  A comment to that effect would be good.


r~
diff mbox

Patch

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index f52aca3..d3a3695 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1227,6 +1227,8 @@  DISAS_INSN(movem)
     TCGv reg;
     TCGv tmp;
     int is_load;
+    int opsize;
+    int32_t incr;
 
     mask = read_im16(env, s);
     tmp = gen_lea(env, s, insn, OS_LONG);
@@ -1237,20 +1239,44 @@  DISAS_INSN(movem)
     addr = tcg_temp_new();
     tcg_gen_mov_i32(addr, tmp);
     is_load = ((insn & 0x0400) != 0);
-    for (i = 0; i < 16; i++, mask >>= 1) {
-        if (mask & 1) {
-            if (i < 8)
-                reg = DREG(i, 0);
-            else
-                reg = AREG(i, 0);
-            if (is_load) {
-                tmp = gen_load(s, OS_LONG, addr, 0);
-                tcg_gen_mov_i32(reg, tmp);
-            } else {
-                gen_store(s, OS_LONG, addr, reg);
+    opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD;
+    incr = opsize_bytes(opsize);
+    if (!is_load && (insn & 070) == 040) {
+        for (i = 15; i >= 0; i--, mask >>= 1) {
+            if (mask & 1) {
+                if (i < 8) {
+                    reg = DREG(i, 0);
+                } else {
+                    reg = AREG(i, 0);
+                }
+                gen_store(s, opsize, addr, reg);
+                if (mask != 1) {
+                    tcg_gen_subi_i32(addr, addr, incr);
+                }
+            }
+        }
+        tcg_gen_mov_i32(AREG(insn, 0), addr);
+    } else {
+        for (i = 0; i < 16; i++, mask >>= 1) {
+            if (mask & 1) {
+                if (i < 8) {
+                    reg = DREG(i, 0);
+                } else {
+                    reg = AREG(i, 0);
+                }
+                if (is_load) {
+                    tmp = gen_load(s, opsize, addr, 1);
+                    tcg_gen_mov_i32(reg, tmp);
+                } else {
+                    gen_store(s, opsize, addr, reg);
+                }
+                if (mask != 1 || (insn & 070) == 030) {
+                    tcg_gen_addi_i32(addr, addr, incr);
+                }
             }
-            if (mask != 1)
-                tcg_gen_addi_i32(addr, addr, 4);
+        }
+        if ((insn & 070) == 030) {
+            tcg_gen_mov_i32(AREG(insn, 0), addr);
         }
     }
 }