Re: [Qemu-devel] [PATCH 39/52] target-m68k: movem

2016-05-06 Thread Richard Henderson

A more verbose commit message is required here.

On 05/04/2016 11:08 AM, Laurent Vivier wrote:

@@ -1724,21 +1726,40 @@ 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);
-}
-if (mask != 1)
-tcg_gen_addi_i32(addr, addr, 4);
-}
+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);


Missing this bit from the manual:

For the MC68020, MC68030, MC68040, and CPU32, if the addressing register is 
also moved to memory, the value written is the initial register value 
decremented by the size of the operation. The MC68000 and MC68010 write the 
initial register value (not decremented).


You appear to be implementing only the latter.



+} 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);
+   }
+   }


For loads, we surely should be doing something more in order to properly 
emulate the access trap that might occur here.  I seem to recall saving the 
effective address, a CM bit in the exception stack frame, and RTE restarting 
the movem with the saved effective address.



r~



[Qemu-devel] [PATCH 39/52] target-m68k: movem

2016-05-04 Thread Laurent Vivier
Signed-off-by: Laurent Vivier 
---
 target-m68k/translate.c | 51 ++---
 1 file changed, 36 insertions(+), 15 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 9a38235..53c3c41 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1714,6 +1714,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);
@@ -1724,21 +1726,40 @@ 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);
-}
-if (mask != 1)
-tcg_gen_addi_i32(addr, addr, 4);
-}
+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 ((insn & 070) == 030)
+   tcg_gen_mov_i32(AREG(insn, 0), addr);
 }
 }
 
-- 
2.5.5