qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support
@ 2009-05-29 22:41 Laurent Vivier
  2009-05-29 22:41 ` [Qemu-devel] [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32() Laurent Vivier
                   ` (2 more replies)
  0 siblings, 3 replies; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel

This series of patches is a port to Qemu 0.10 of Andreas Schwab M68K patch
to support Motorola 680x0 CPU family.

It has been tested with some commands from a debian m68k lenny disk.

Commands like "uname", "date", "ls", "more", "grep" work well.

[PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32()
[PATCH 02/17] m68k: add tcg_gen_debug_insn_start()
[PATCH 03/17] m68k: define m680x0 CPUs and features
[PATCH 04/17] m68k: add missing accessing modes for some instructions.
[PATCH 05/17] m68k: add Motorola 680x0 family common instructions.
[PATCH 06/17] m68k: add Scc instruction with memory operand.
[PATCH 07/17] m68k: add DBcc instruction. 
[PATCH 08/17] m68k: modify movem instruction to manage word
[PATCH 09/17] m68k: add 64bit divide.
[PATCH 10/17] m68k: add 32bit and 64bit multiply
[PATCH 11/17] m68k: add word data size for suba/adda
[PATCH 12/17] m68k: add fpu
[PATCH 13/17] m68k: add "byte", "word" and memory shift
[PATCH 14/17] m68k: add "byte", "word" and memory rotate.
[PATCH 15/17] m68k: add bitfield_mem, bitfield_reg
[PATCH 16/17] m68k: add variable offset/width to bitfield_reg/bitfield_mem
[PATCH 17/17] m68k: add cas 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32()
  2009-05-29 22:41 [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support Laurent Vivier
@ 2009-05-29 22:41 ` Laurent Vivier
  2009-05-29 22:41   ` [Qemu-devel] [PATCH 02/17] m68k: add tcg_gen_debug_insn_start() Laurent Vivier
  2009-05-30 17:31 ` [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support François Revol
  2009-09-21  2:56 ` Rob Landley
  2 siblings, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c |   43 ++++++++++++++++++++-----------------------
 1 files changed, 20 insertions(+), 23 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 422f0a4..521891f 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -172,9 +172,6 @@ typedef void (*disas_proc)(DisasContext *, uint16_t);
   static void disas_##name (DisasContext *s, uint16_t insn)
 #endif
 
-/* FIXME: Remove this.  */
-#define gen_im32(val) tcg_const_i32(val)
-
 /* Generate a load from the specified address.  Narrow values are
    sign extended to full register width.  */
 static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int sign)
@@ -340,7 +337,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
         if ((ext & 0x80) == 0) {
             /* base not suppressed */
             if (IS_NULL_QREG(base)) {
-                base = gen_im32(offset + bd);
+                base = tcg_const_i32(offset + bd);
                 bd = 0;
             }
             if (!IS_NULL_QREG(add)) {
@@ -356,7 +353,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
                 add = tmp;
             }
         } else {
-            add = gen_im32(bd);
+            add = tcg_const_i32(bd);
         }
         if ((ext & 3) != 0) {
             /* memory indirect */
@@ -537,16 +534,16 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize)
         case 0: /* Absolute short.  */
             offset = ldsw_code(s->pc);
             s->pc += 2;
-            return gen_im32(offset);
+            return tcg_const_i32(offset);
         case 1: /* Absolute long.  */
             offset = read_im32(s);
-            return gen_im32(offset);
+            return tcg_const_i32(offset);
         case 2: /* pc displacement  */
             tmp = tcg_temp_new();
             offset = s->pc;
             offset += ldsw_code(s->pc);
             s->pc += 2;
-            return gen_im32(offset);
+            return tcg_const_i32(offset);
         case 3: /* pc index+displacement.  */
             return gen_lea_indexed(s, opsize, NULL_QREG);
         case 4: /* Immediate.  */
@@ -1211,16 +1208,16 @@ DISAS_INSN(arith_im)
         break;
     case 2: /* subi */
         tcg_gen_mov_i32(dest, src1);
-        gen_helper_xflag_lt(QREG_CC_X, dest, gen_im32(im));
+        gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im));
         tcg_gen_subi_i32(dest, dest, im);
-        gen_update_cc_add(dest, gen_im32(im));
+        gen_update_cc_add(dest, tcg_const_i32(im));
         s->cc_op = CC_OP_SUB;
         break;
     case 3: /* addi */
         tcg_gen_mov_i32(dest, src1);
         tcg_gen_addi_i32(dest, dest, im);
-        gen_update_cc_add(dest, gen_im32(im));
-        gen_helper_xflag_lt(QREG_CC_X, dest, gen_im32(im));
+        gen_update_cc_add(dest, tcg_const_i32(im));
+        gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im));
         s->cc_op = CC_OP_ADD;
         break;
     case 5: /* eori */
@@ -1230,7 +1227,7 @@ DISAS_INSN(arith_im)
     case 6: /* cmpi */
         tcg_gen_mov_i32(dest, src1);
         tcg_gen_subi_i32(dest, dest, im);
-        gen_update_cc_add(dest, gen_im32(im));
+        gen_update_cc_add(dest, tcg_const_i32(im));
         s->cc_op = CC_OP_SUB;
         break;
     default:
@@ -1326,8 +1323,8 @@ DISAS_INSN(clr)
     default:
         abort();
     }
-    DEST_EA(insn, opsize, gen_im32(0), NULL);
-    gen_logic_cc(s, gen_im32(0));
+    DEST_EA(insn, opsize, tcg_const_i32(0), NULL);
+    gen_logic_cc(s, tcg_const_i32(0));
 }
 
 static TCGv gen_get_ccr(DisasContext *s)
@@ -1591,7 +1588,7 @@ DISAS_INSN(jump)
     }
     if ((insn & 0x40) == 0) {
         /* jsr */
-        gen_push(s, gen_im32(s->pc));
+        gen_push(s, tcg_const_i32(s->pc));
     }
     gen_jmp(s, tmp);
 }
@@ -1619,7 +1616,7 @@ DISAS_INSN(addsubq)
             tcg_gen_addi_i32(dest, dest, val);
         }
     } else {
-        src2 = gen_im32(val);
+        src2 = tcg_const_i32(val);
         if (insn & 0x0100) {
             gen_helper_xflag_lt(QREG_CC_X, dest, src2);
             tcg_gen_subi_i32(dest, dest, val);
@@ -1668,7 +1665,7 @@ DISAS_INSN(branch)
     }
     if (op == 1) {
         /* bsr */
-        gen_push(s, gen_im32(s->pc));
+        gen_push(s, tcg_const_i32(s->pc));
     }
     gen_flush_cc_op(s);
     if (op > 1) {
@@ -1759,7 +1756,7 @@ DISAS_INSN(mov3q)
     val = (insn >> 9) & 7;
     if (val == 0)
         val = -1;
-    src = gen_im32(val);
+    src = tcg_const_i32(val);
     gen_logic_cc(s, src);
     DEST_EA(insn, OS_LONG, src, NULL);
 }
@@ -1885,7 +1882,7 @@ DISAS_INSN(shift_im)
     tmp = (insn >> 9) & 7;
     if (tmp == 0)
         tmp = 8;
-    shift = gen_im32(tmp);
+    shift = tcg_const_i32(tmp);
     /* No need to flush flags becuse we know we will set C flag.  */
     if (insn & 0x100) {
         gen_helper_shl_cc(reg, cpu_env, reg, shift);
@@ -2193,7 +2190,7 @@ DISAS_INSN(fpu)
         switch ((ext >> 10) & 7) {
         case 4: /* FPCR */
             /* Not implemented.  Always return zero.  */
-            tmp32 = gen_im32(0);
+            tmp32 = tcg_const_i32(0);
             break;
         case 1: /* FPIAR */
         case 2: /* FPSR */
@@ -2594,7 +2591,7 @@ DISAS_INSN(mac)
         /* Skip the accumulate if the value is already saturated.  */
         l1 = gen_new_label();
         tmp = tcg_temp_new();
-        gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc));
+        gen_op_and32(tmp, QREG_MACSR, tcg_const_i32(MACSR_PAV0 << acc));
         gen_op_jmp_nz32(tmp, l1);
     }
 #endif
@@ -2628,7 +2625,7 @@ DISAS_INSN(mac)
             /* Skip the accumulate if the value is already saturated.  */
             l1 = gen_new_label();
             tmp = tcg_temp_new();
-            gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc));
+            gen_op_and32(tmp, QREG_MACSR, tcg_const_i32(MACSR_PAV0 << acc));
             gen_op_jmp_nz32(tmp, l1);
         }
 #endif
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 02/17] m68k: add tcg_gen_debug_insn_start()
  2009-05-29 22:41 ` [Qemu-devel] [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32() Laurent Vivier
@ 2009-05-29 22:41   ` Laurent Vivier
  2009-05-29 22:41     ` [Qemu-devel] [PATCH 03/17] m68k: define m680x0 CPUs and features Laurent Vivier
  0 siblings, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

This patch add debug info by writing the PC of the corresponing CPU
instruction of an TCG opcode.

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 521891f..dc34a2a 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2950,6 +2950,9 @@ static void disas_m68k_insn(CPUState * env, DisasContext *s)
 {
     uint16_t insn;
 
+    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
+        tcg_gen_debug_insn_start(s->pc);
+
     insn = lduw_code(s->pc);
     s->pc += 2;
 
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 03/17] m68k: define m680x0 CPUs and features
  2009-05-29 22:41   ` [Qemu-devel] [PATCH 02/17] m68k: add tcg_gen_debug_insn_start() Laurent Vivier
@ 2009-05-29 22:41     ` Laurent Vivier
  2009-05-29 22:41       ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Laurent Vivier
  0 siblings, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

This patch defines four new Motorola 680x0 family CPUs:

- M68K_CPUID_M68000,
- M68K_CPUID_M68020,
- M68K_CPUID_M68040,
- M68K_CPUID_M68060

And six new features:

- M68K_FEATURE_SCALED_INDEX, scaled address index register
- M68K_FEATURE_LONG_MULDIV, 32bit multiply/divide
- M68K_FEATURE_QUAD_MULDIV, 64bit multiply/divide
- M68K_FEATURE_BCCL, long conditional branches
- M68K_FEATURE_BITFIELD, bit field instructions
- M68K_FEATURE_FPU, FPU instructions

Following patches implement them...

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.h    |   13 ++++++++++---
 target-m68k/helper.c |   33 +++++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index feffb6b..eb18e9e 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -181,6 +181,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr);
    ISA revisions mentioned.  */
 
 enum m68k_features {
+    M68K_FEATURE_M68000,
     M68K_FEATURE_CF_ISA_A,
     M68K_FEATURE_CF_ISA_B, /* (ISA B or C).  */
     M68K_FEATURE_CF_ISA_APLUSC, /* BIT/BITREV, FF1, STRLDSR (ISA A+ or C).  */
@@ -191,7 +192,13 @@ enum m68k_features {
     M68K_FEATURE_CF_EMAC_B, /* Revision B EMAC (dual accumulate).  */
     M68K_FEATURE_USP, /* User Stack Pointer.  (ISA A+, B or C).  */
     M68K_FEATURE_EXT_FULL, /* 68020+ full extension word.  */
-    M68K_FEATURE_WORD_INDEX /* word sized address index registers.  */
+    M68K_FEATURE_WORD_INDEX, /* word sized address index registers.  */
+    M68K_FEATURE_SCALED_INDEX, /* scaled address index registers.  */
+    M68K_FEATURE_LONG_MULDIV,	/* 32 bit multiply/divide. */
+    M68K_FEATURE_QUAD_MULDIV,	/* 64 bit multiply/divide. */
+    M68K_FEATURE_BCCL,		/* Long conditional branches.  */
+    M68K_FEATURE_BITFIELD,	/* Bit field insns.  */
+    M68K_FEATURE_FPU
 };
 
 static inline int m68k_feature(CPUM68KState *env, int feature)
@@ -204,8 +211,8 @@ void m68k_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
 void register_m68k_insns (CPUM68KState *env);
 
 #ifdef CONFIG_USER_ONLY
-/* Linux uses 8k pages.  */
-#define TARGET_PAGE_BITS 13
+/* Linux uses 4k pages.  */
+#define TARGET_PAGE_BITS 12
 #else
 /* Smallest TLB entry size is 1k.  */
 #define TARGET_PAGE_BITS 10
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index af9ce22..a22dc97 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -33,6 +33,10 @@
 #define SIGNBIT (1u << 31)
 
 enum m68k_cpuid {
+    M68K_CPUID_M68000,
+    M68K_CPUID_M68020,
+    M68K_CPUID_M68040,
+    M68K_CPUID_M68060,
     M68K_CPUID_M5206,
     M68K_CPUID_M5208,
     M68K_CPUID_CFV4E,
@@ -47,6 +51,10 @@ struct m68k_def_t {
 };
 
 static m68k_def_t m68k_cpu_defs[] = {
+    {"m68000", M68K_CPUID_M68000},
+    {"m68020", M68K_CPUID_M68020},
+    {"m68040", M68K_CPUID_M68040},
+    {"m68060", M68K_CPUID_M68060},
     {"m5206", M68K_CPUID_M5206},
     {"m5208", M68K_CPUID_M5208},
     {"cfv4e", M68K_CPUID_CFV4E},
@@ -107,12 +115,30 @@ static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
         return -1;
 
     switch (def->id) {
+    case M68K_CPUID_M68020:
+    case M68K_CPUID_M68040:
+        m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV);
+    case M68K_CPUID_M68060:
+        m68k_set_feature(env, M68K_FEATURE_BRAL);
+        m68k_set_feature(env, M68K_FEATURE_BCCL);
+        m68k_set_feature(env, M68K_FEATURE_BITFIELD);
+        m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
+        m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV);
+        m68k_set_feature(env, M68K_FEATURE_FPU);
+    case M68K_CPUID_M68000:
+        m68k_set_feature(env, M68K_FEATURE_M68000);
+        m68k_set_feature(env, M68K_FEATURE_USP);
+        m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+        break;
     case M68K_CPUID_M5206:
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
         break;
     case M68K_CPUID_M5208:
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
         m68k_set_feature(env, M68K_FEATURE_BRAL);
         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
         m68k_set_feature(env, M68K_FEATURE_USP);
@@ -120,16 +146,19 @@ static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
     case M68K_CPUID_CFV4E:
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
         m68k_set_feature(env, M68K_FEATURE_BRAL);
         m68k_set_feature(env, M68K_FEATURE_CF_FPU);
         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
         m68k_set_feature(env, M68K_FEATURE_USP);
         break;
     case M68K_CPUID_ANY:
+        m68k_set_feature(env, M68K_FEATURE_M68000);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
         m68k_set_feature(env, M68K_FEATURE_BRAL);
+        m68k_set_feature(env, M68K_FEATURE_BCCL);
         m68k_set_feature(env, M68K_FEATURE_CF_FPU);
         /* MAC and EMAC are mututally exclusive, so pick EMAC.
            It's mostly backwards compatible.  */
@@ -137,7 +166,11 @@ static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
         m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
         m68k_set_feature(env, M68K_FEATURE_USP);
         m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
         m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+        m68k_set_feature(env, M68K_FEATURE_BITFIELD);
+        m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV);
+        m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV);
         break;
     }
 
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions.
  2009-05-29 22:41     ` [Qemu-devel] [PATCH 03/17] m68k: define m680x0 CPUs and features Laurent Vivier
@ 2009-05-29 22:41       ` Laurent Vivier
  2009-05-29 22:41         ` [Qemu-devel] [PATCH 05/17] m68k: add Motorola 680x0 family common instructions Laurent Vivier
  2009-05-31  2:06         ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Stuart Brady
  0 siblings, 2 replies; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

This patch modifies following instructions to allow them to manage data
size other than "long", by adding "byte" and "word" data size: "addsub",
"arith_im", "addsubq", "or", "eor", "and".

This patch modifies following instructions to use EA to access data:
"neg", "not".

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.h       |   10 ++-
 target-m68k/helper.c    |   74 ++++++++++++-----
 target-m68k/translate.c |  202 +++++++++++++++++++++++++++--------------------
 3 files changed, 177 insertions(+), 109 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index eb18e9e..240d75f 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -131,11 +131,17 @@ enum {
     CC_OP_DYNAMIC, /* Use env->cc_op  */
     CC_OP_FLAGS, /* CC_DEST = CVZN, CC_SRC = unused */
     CC_OP_LOGIC, /* CC_DEST = result, CC_SRC = unused */
+    CC_OP_ADDB,   /* CC_DEST = result, CC_SRC = source */
+    CC_OP_ADDW,   /* CC_DEST = result, CC_SRC = source */
     CC_OP_ADD,   /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SUBB,   /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SUBW,   /* CC_DEST = result, CC_SRC = source */
     CC_OP_SUB,   /* CC_DEST = result, CC_SRC = source */
-    CC_OP_CMPB,  /* CC_DEST = result, CC_SRC = source */
-    CC_OP_CMPW,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_ADDXB,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_ADDXW,  /* CC_DEST = result, CC_SRC = source */
     CC_OP_ADDX,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SUBXB,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SUBXW,  /* CC_DEST = result, CC_SRC = source */
     CC_OP_SUBX,  /* CC_DEST = result, CC_SRC = source */
     CC_OP_SHIFT, /* CC_DEST = result, CC_SRC = carry */
 };
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index a22dc97..bcd73d5 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -256,6 +256,33 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
         flags |= CCF_V; \
     } while (0)
 
+#define SET_FLAGS_ADD(type, utype) do { \
+    SET_NZ((type)dest); \
+    if ((utype) dest < (utype) src) \
+        flags |= CCF_C; \
+    tmp = dest - src; \
+    if ((1u << (sizeof(type) * 8 - 1)) & (src ^ dest) & (tmp ^ src)) \
+        flags |= CCF_V; \
+    } while (0)
+
+#define SET_FLAGS_ADDX(type, utype) do { \
+    SET_NZ((type)dest); \
+    if ((utype) dest <= (utype) src) \
+        flags |= CCF_C; \
+    tmp = dest - src - 1; \
+    if ((1u << (sizeof(type) * 8 - 1)) & (src ^ dest) & (tmp ^ src)) \
+        flags |= CCF_V; \
+    } while (0)
+
+#define SET_FLAGS_SUBX(type, utype) do { \
+    SET_NZ((type)dest); \
+    tmp = dest + src + 1; \
+    if ((utype) dest <= (utype) src) \
+        flags |= CCF_C; \
+    if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
+        flags |= CCF_V; \
+    } while (0)
+
     flags = 0;
     src = env->cc_src;
     dest = env->cc_dest;
@@ -266,38 +293,41 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
     case CC_OP_LOGIC:
         SET_NZ(dest);
         break;
+    case CC_OP_ADDB:
+        SET_FLAGS_ADD(int8_t, uint8_t);
+        break;
+    case CC_OP_ADDW:
+        SET_FLAGS_ADD(int16_t, uint16_t);
+        break;
     case CC_OP_ADD:
-        SET_NZ(dest);
-        if (dest < src)
-            flags |= CCF_C;
-        tmp = dest - src;
-        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
-            flags |= CCF_V;
+        SET_FLAGS_ADD(int32_t, uint32_t);
+        break;
+    case CC_OP_SUBB:
+        SET_FLAGS_SUB(int8_t, uint8_t);
+        break;
+    case CC_OP_SUBW:
+        SET_FLAGS_SUB(int16_t, uint16_t);
         break;
     case CC_OP_SUB:
         SET_FLAGS_SUB(int32_t, uint32_t);
         break;
-    case CC_OP_CMPB:
-        SET_FLAGS_SUB(int8_t, uint8_t);
+    case CC_OP_ADDXB:
+        SET_FLAGS_ADDX(int8_t, uint8_t);
         break;
-    case CC_OP_CMPW:
-        SET_FLAGS_SUB(int16_t, uint16_t);
+    case CC_OP_ADDXW:
+        SET_FLAGS_ADDX(int16_t, uint16_t);
         break;
     case CC_OP_ADDX:
-        SET_NZ(dest);
-        if (dest <= src)
-            flags |= CCF_C;
-        tmp = dest - src - 1;
-        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
-            flags |= CCF_V;
+        SET_FLAGS_ADDX(int32_t, uint32_t);
+        break;
+    case CC_OP_SUBXB:
+        SET_FLAGS_SUBX(int8_t, uint8_t);
+        break;
+    case CC_OP_SUBXW:
+        SET_FLAGS_SUBX(int16_t, uint16_t);
         break;
     case CC_OP_SUBX:
-        SET_NZ(dest);
-        tmp = dest + src + 1;
-        if (tmp <= src)
-            flags |= CCF_C;
-        if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
-            flags |= CCF_V;
+        SET_FLAGS_SUBX(int32_t, uint32_t);
         break;
     case CC_OP_SHIFT:
         SET_NZ(dest);
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index dc34a2a..1bf7169 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -264,6 +264,22 @@ static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
     }
 }
 
+/* Read a 8-bit immediat constant */
+static inline uint32_t read_im8(DisasContext *s)
+{
+    uint32_t im;
+    im = ldsb_code(s->pc + 1);
+    s->pc += 2;
+    return im;
+}
+/* Read a 16-bit immediat constant */
+static inline uint32_t read_im16(DisasContext *s)
+{
+    uint32_t im;
+    im = ldsw_code(s->pc);
+    s->pc += 2;
+    return im;
+}
 /* Read a 32-bit immediate constant.  */
 static inline uint32_t read_im32(DisasContext *s)
 {
@@ -440,6 +456,25 @@ static inline int opsize_bytes(int opsize)
     }
 }
 
+static inline int insn_opsize(int insn, int pos)
+{
+    switch ((insn >> pos) & 3) {
+    case 0: return OS_BYTE;
+    case 1: return OS_WORD;
+    case 2: return OS_LONG;
+    default: abort();
+    }
+}
+
+#define SET_CC_OP(opsize, op) do { \
+    switch (opsize) { \
+    case OS_BYTE: s->cc_op = CC_OP_##op##B; break; \
+    case OS_WORD: s->cc_op = CC_OP_##op##W; break; \
+    case OS_LONG: s->cc_op = CC_OP_##op; break; \
+    default: abort(); \
+    } \
+} while (0)
+
 /* Assign value to a register.  If the width is less than the register width
    only the low part of the register is set.  */
 static void gen_partset_reg(int opsize, TCGv reg, TCGv val)
@@ -977,31 +1012,33 @@ DISAS_INSN(addsub)
     TCGv tmp;
     TCGv addr;
     int add;
+    int opsize;
 
     add = (insn & 0x4000) != 0;
+    opsize = insn_opsize(insn, 6);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     if (insn & 0x100) {
-        SRC_EA(tmp, OS_LONG, 0, &addr);
+        SRC_EA(tmp, opsize, -1, &addr);
         src = reg;
     } else {
         tmp = reg;
-        SRC_EA(src, OS_LONG, 0, NULL);
+        SRC_EA(src, opsize, -1, NULL);
     }
     if (add) {
         tcg_gen_add_i32(dest, tmp, src);
         gen_helper_xflag_lt(QREG_CC_X, dest, src);
-        s->cc_op = CC_OP_ADD;
+        SET_CC_OP(opsize, ADD);
     } else {
         gen_helper_xflag_lt(QREG_CC_X, tmp, src);
         tcg_gen_sub_i32(dest, tmp, src);
-        s->cc_op = CC_OP_SUB;
+        SET_CC_OP(opsize, SUB);
     }
     gen_update_cc_add(dest, src);
     if (insn & 0x100) {
-        DEST_EA(insn, OS_LONG, dest, &addr);
+        DEST_EA(insn, opsize, dest, &addr);
     } else {
-        tcg_gen_mov_i32(reg, dest);
+        gen_partset_reg(opsize, reg, dest);
     }
 }
 
@@ -1192,10 +1229,24 @@ DISAS_INSN(arith_im)
     TCGv src1;
     TCGv dest;
     TCGv addr;
+    int opsize;
 
     op = (insn >> 9) & 7;
-    SRC_EA(src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
-    im = read_im32(s);
+    opsize = insn_opsize(insn, 6);
+    switch (opsize) {
+    case OS_BYTE:
+        im = read_im8(s);
+        break;
+    case OS_WORD:
+        im = read_im16(s);
+        break;
+    case OS_LONG:
+        im = read_im32(s);
+        break;
+    default:
+       abort();
+    }
+    SRC_EA(src1, opsize, -1, (op == 6) ? NULL : &addr);
     dest = tcg_temp_new();
     switch (op) {
     case 0: /* ori */
@@ -1211,14 +1262,14 @@ DISAS_INSN(arith_im)
         gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im));
         tcg_gen_subi_i32(dest, dest, im);
         gen_update_cc_add(dest, tcg_const_i32(im));
-        s->cc_op = CC_OP_SUB;
+        SET_CC_OP(opsize, SUB);
         break;
     case 3: /* addi */
         tcg_gen_mov_i32(dest, src1);
         tcg_gen_addi_i32(dest, dest, im);
         gen_update_cc_add(dest, tcg_const_i32(im));
         gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im));
-        s->cc_op = CC_OP_ADD;
+	SET_CC_OP(opsize, ADD);
         break;
     case 5: /* eori */
         tcg_gen_xori_i32(dest, src1, im);
@@ -1228,13 +1279,13 @@ DISAS_INSN(arith_im)
         tcg_gen_mov_i32(dest, src1);
         tcg_gen_subi_i32(dest, dest, im);
         gen_update_cc_add(dest, tcg_const_i32(im));
-        s->cc_op = CC_OP_SUB;
+        SET_CC_OP(opsize, SUB);
         break;
     default:
         abort();
     }
     if (op != 6) {
-        DEST_EA(insn, OS_LONG, dest, &addr);
+        DEST_EA(insn, opsize, dest, &addr);
     }
 }
 
@@ -1310,19 +1361,7 @@ DISAS_INSN(clr)
 {
     int opsize;
 
-    switch ((insn >> 6) & 3) {
-    case 0: /* clr.b */
-        opsize = OS_BYTE;
-        break;
-    case 1: /* clr.w */
-        opsize = OS_WORD;
-        break;
-    case 2: /* clr.l */
-        opsize = OS_LONG;
-        break;
-    default:
-        abort();
-    }
+    opsize = insn_opsize(insn, 6);
     DEST_EA(insn, opsize, tcg_const_i32(0), NULL);
     gen_logic_cc(s, tcg_const_i32(0));
 }
@@ -1350,17 +1389,20 @@ DISAS_INSN(move_from_ccr)
 
 DISAS_INSN(neg)
 {
-    TCGv reg;
     TCGv src1;
+    TCGv dest;
+    TCGv addr;
+    int opsize;
 
-    reg = DREG(insn, 0);
-    src1 = tcg_temp_new();
-    tcg_gen_mov_i32(src1, reg);
-    tcg_gen_neg_i32(reg, src1);
-    s->cc_op = CC_OP_SUB;
-    gen_update_cc_add(reg, src1);
-    gen_helper_xflag_lt(QREG_CC_X, tcg_const_i32(0), src1);
-    s->cc_op = CC_OP_SUB;
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(src1, opsize, -1, &addr);
+    dest = tcg_temp_new();
+    tcg_gen_neg_i32(dest, src1);
+    DEST_EA(insn, opsize, dest, &addr);
+    SET_CC_OP(opsize, SUB);
+    gen_update_cc_add(src1, dest);
+    gen_helper_xflag_lt(QREG_CC_X, tcg_const_i32(0), dest);
+    SET_CC_OP(opsize, SUB);
 }
 
 static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
@@ -1407,11 +1449,17 @@ DISAS_INSN(move_to_ccr)
 
 DISAS_INSN(not)
 {
-    TCGv reg;
+    TCGv src1;
+    TCGv dest;
+    TCGv addr;
+    int opsize;
 
-    reg = DREG(insn, 0);
-    tcg_gen_not_i32(reg, reg);
-    gen_logic_cc(s, reg);
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(src1, opsize, -1, &addr);
+    dest = tcg_temp_new();
+    tcg_gen_not_i32(dest, src1);
+    DEST_EA(insn, opsize, dest, &addr);
+    gen_logic_cc(s, dest);
 }
 
 DISAS_INSN(swap)
@@ -1466,20 +1514,8 @@ DISAS_INSN(tst)
     int opsize;
     TCGv tmp;
 
-    switch ((insn >> 6) & 3) {
-    case 0: /* tst.b */
-        opsize = OS_BYTE;
-        break;
-    case 1: /* tst.w */
-        opsize = OS_WORD;
-        break;
-    case 2: /* tst.l */
-        opsize = OS_LONG;
-        break;
-    default:
-        abort();
-    }
-    SRC_EA(tmp, opsize, 1, NULL);
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(tmp, opsize, -1, NULL);
     gen_logic_cc(s, tmp);
 }
 
@@ -1600,8 +1636,14 @@ DISAS_INSN(addsubq)
     TCGv dest;
     int val;
     TCGv addr;
+    int opsize;
 
-    SRC_EA(src1, OS_LONG, 0, &addr);
+    if ((insn & 070) == 010) {
+        /* Operation on address register is always long.  */
+        opsize = OS_LONG;
+    } else
+        opsize = insn_opsize(insn, 6);
+    SRC_EA(src1, opsize, -1, &addr);
     val = (insn >> 9) & 7;
     if (val == 0)
         val = 8;
@@ -1620,11 +1662,11 @@ DISAS_INSN(addsubq)
         if (insn & 0x0100) {
             gen_helper_xflag_lt(QREG_CC_X, dest, src2);
             tcg_gen_subi_i32(dest, dest, val);
-            s->cc_op = CC_OP_SUB;
+            SET_CC_OP(opsize, SUB);
         } else {
             tcg_gen_addi_i32(dest, dest, val);
             gen_helper_xflag_lt(QREG_CC_X, dest, src2);
-            s->cc_op = CC_OP_ADD;
+            SET_CC_OP(opsize, ADD);
         }
         gen_update_cc_add(dest, src2);
     }
@@ -1712,17 +1754,19 @@ DISAS_INSN(or)
     TCGv dest;
     TCGv src;
     TCGv addr;
+    int opsize;
 
+    opsize = insn_opsize(insn, 6);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     if (insn & 0x100) {
-        SRC_EA(src, OS_LONG, 0, &addr);
+        SRC_EA(src, opsize, -1, &addr);
         tcg_gen_or_i32(dest, src, reg);
-        DEST_EA(insn, OS_LONG, dest, &addr);
+        DEST_EA(insn, opsize, dest, &addr);
     } else {
-        SRC_EA(src, OS_LONG, 0, NULL);
+        SRC_EA(src, opsize, -1, NULL);
         tcg_gen_or_i32(dest, src, reg);
-        tcg_gen_mov_i32(reg, dest);
+        gen_partset_reg(opsize, reg, dest);
     }
     gen_logic_cc(s, dest);
 }
@@ -1763,34 +1807,18 @@ DISAS_INSN(mov3q)
 
 DISAS_INSN(cmp)
 {
-    int op;
     TCGv src;
     TCGv reg;
     TCGv dest;
     int opsize;
 
-    op = (insn >> 6) & 3;
-    switch (op) {
-    case 0: /* cmp.b */
-        opsize = OS_BYTE;
-        s->cc_op = CC_OP_CMPB;
-        break;
-    case 1: /* cmp.w */
-        opsize = OS_WORD;
-        s->cc_op = CC_OP_CMPW;
-        break;
-    case 2: /* cmp.l */
-        opsize = OS_LONG;
-        s->cc_op = CC_OP_SUB;
-        break;
-    default:
-        abort();
-    }
-    SRC_EA(src, opsize, 1, NULL);
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(src, opsize, -1, NULL);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     tcg_gen_sub_i32(dest, reg, src);
     gen_update_cc_add(dest, src);
+    SET_CC_OP(opsize, SUB);
 }
 
 DISAS_INSN(cmpa)
@@ -1810,7 +1838,7 @@ DISAS_INSN(cmpa)
     dest = tcg_temp_new();
     tcg_gen_sub_i32(dest, reg, src);
     gen_update_cc_add(dest, src);
-    s->cc_op = CC_OP_SUB;
+    SET_CC_OP(opsize, SUB);
 }
 
 DISAS_INSN(eor)
@@ -1819,13 +1847,15 @@ DISAS_INSN(eor)
     TCGv reg;
     TCGv dest;
     TCGv addr;
+    int opsize;
 
-    SRC_EA(src, OS_LONG, 0, &addr);
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(src, opsize, -1, &addr);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     tcg_gen_xor_i32(dest, src, reg);
     gen_logic_cc(s, dest);
-    DEST_EA(insn, OS_LONG, dest, &addr);
+    DEST_EA(insn, opsize, dest, &addr);
 }
 
 DISAS_INSN(and)
@@ -1834,17 +1864,19 @@ DISAS_INSN(and)
     TCGv reg;
     TCGv dest;
     TCGv addr;
+    int opsize;
 
+    opsize = insn_opsize(insn, 6);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     if (insn & 0x100) {
-        SRC_EA(src, OS_LONG, 0, &addr);
+        SRC_EA(src, opsize, -1, &addr);
         tcg_gen_and_i32(dest, src, reg);
-        DEST_EA(insn, OS_LONG, dest, &addr);
+        DEST_EA(insn, opsize, dest, &addr);
     } else {
-        SRC_EA(src, OS_LONG, 0, NULL);
+        SRC_EA(src, opsize, -1, NULL);
         tcg_gen_and_i32(dest, src, reg);
-        tcg_gen_mov_i32(reg, dest);
+        gen_partset_reg(opsize, reg, dest);
     }
     gen_logic_cc(s, dest);
 }
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 05/17] m68k: add Motorola 680x0 family common instructions.
  2009-05-29 22:41       ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Laurent Vivier
@ 2009-05-29 22:41         ` Laurent Vivier
  2009-05-29 22:41           ` [Qemu-devel] [PATCH 06/17] m68k: add Scc instruction with memory operand Laurent Vivier
  2009-05-31  2:06         ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Stuart Brady
  1 sibling, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

This patch declares existing ISA instructions belonging to previously
defined 680x0 familty new features:

- modify gen_lea_indexed() to manage scaled index,

- declare M68000 instructions: arith_im, bitop_reg, arith_im, bitop_im,
move, negx, move_from_sr, lea, clr, neg, move_to_ccr, not, pea, swap,
ext, tas, tst, illegal, trap, link, unlk, nop, stop, rte, rts, jump,
addsubq, scc, branch, moveq, or, divw, addsub, subx, cmp, cmpa, eor,
and, mulw, addx, shift_im, shift_reg.

- declare FPU instructions: fbcc, frestore, fsave,

- declare long branch instructions: branch.

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c |   89 ++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 85 insertions(+), 4 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 1bf7169..cd46651 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -327,6 +327,9 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
     if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
         return NULL_QREG;
 
+    if (!m68k_feature(s->env, M68K_FEATURE_SCALED_INDEX))
+        ext &= ~(3 << 9);
+
     if (ext & 0x100) {
         /* full extension word format */
         if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))
@@ -335,7 +338,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
         if ((ext & 0x30) > 0x10) {
             /* base displacement */
             if ((ext & 0x30) == 0x20) {
-                bd = (int16_t)lduw_code(s->pc);
+                bd = ldsw_code(s->pc);
                 s->pc += 2;
             } else {
                 bd = read_im32(s);
@@ -384,7 +387,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
             if ((ext & 3) > 1) {
                 /* outer displacement */
                 if ((ext & 3) == 2) {
-                    od = (int16_t)lduw_code(s->pc);
+                    od = ldsw_code(s->pc);
                     s->pc += 2;
                 } else {
                     od = read_im32(s);
@@ -2859,85 +2862,149 @@ void register_m68k_insns (CPUM68KState *env)
         register_opcode(disas_##name, 0x##opcode, 0x##mask); \
     } while(0)
     INSN(undef,     0000, 0000, CF_ISA_A);
+    INSN(undef,     0000, 0000, M68000);
     INSN(arith_im,  0080, fff8, CF_ISA_A);
+    INSN(arith_im,  0000, ff00, M68000);
+    INSN(undef,     00c0, ffc0, M68000);
     INSN(bitrev,    00c0, fff8, CF_ISA_APLUSC);
     INSN(bitop_reg, 0100, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 0100, f1c0, M68000);
     INSN(bitop_reg, 0140, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 0140, f1c0, M68000);
     INSN(bitop_reg, 0180, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 0180, f1c0, M68000);
     INSN(bitop_reg, 01c0, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 01c0, f1c0, M68000);
     INSN(arith_im,  0280, fff8, CF_ISA_A);
+    INSN(arith_im,  0200, ff00, M68000);
+    INSN(undef,     02c0, ffc0, M68000);
     INSN(byterev,   02c0, fff8, CF_ISA_APLUSC);
     INSN(arith_im,  0480, fff8, CF_ISA_A);
+    INSN(arith_im,  0400, ff00, M68000);
+    INSN(undef,     04c0, ffc0, M68000);
+    INSN(arith_im,  0600, ff00, M68000);
+    INSN(undef,     06c0, ffc0, M68000);
     INSN(ff1,       04c0, fff8, CF_ISA_APLUSC);
     INSN(arith_im,  0680, fff8, CF_ISA_A);
     INSN(bitop_im,  0800, ffc0, CF_ISA_A);
+    INSN(bitop_im,  0800, ffc0, M68000);
     INSN(bitop_im,  0840, ffc0, CF_ISA_A);
+    INSN(bitop_im,  0840, ffc0, M68000);
     INSN(bitop_im,  0880, ffc0, CF_ISA_A);
+    INSN(bitop_im,  0880, ffc0, M68000);
     INSN(bitop_im,  08c0, ffc0, CF_ISA_A);
+    INSN(bitop_im,  08c0, ffc0, M68000);
     INSN(arith_im,  0a80, fff8, CF_ISA_A);
+    INSN(arith_im,  0a00, ff00, M68000);
+    INSN(undef,     0ac0, ffc0, M68000);
     INSN(arith_im,  0c00, ff38, CF_ISA_A);
+    INSN(arith_im,  0c00, ff00, M68000);
+    INSN(undef,     0cc0, ffc0, M68000);
     INSN(move,      1000, f000, CF_ISA_A);
+    INSN(move,      1000, f000, M68000);
     INSN(move,      2000, f000, CF_ISA_A);
+    INSN(move,      2000, f000, M68000);
     INSN(move,      3000, f000, CF_ISA_A);
+    INSN(move,      3000, f000, M68000);
     INSN(strldsr,   40e7, ffff, CF_ISA_APLUSC);
     INSN(negx,      4080, fff8, CF_ISA_A);
+    INSN(negx,      4080, fff8, M68000);
+    INSN(undef,     40c0, ffc0, M68000);
     INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
+    INSN(move_from_sr, 40c0, fff8, M68000);
     INSN(lea,       41c0, f1c0, CF_ISA_A);
+    INSN(lea,       41c0, f1c0, M68000);
     INSN(clr,       4200, ff00, CF_ISA_A);
+    INSN(clr,       4200, ff00, M68000);
     INSN(undef,     42c0, ffc0, CF_ISA_A);
+    INSN(undef,     42c0, ffc0, M68000);
     INSN(move_from_ccr, 42c0, fff8, CF_ISA_A);
     INSN(neg,       4480, fff8, CF_ISA_A);
+    INSN(neg,       4400, ff00, M68000);
+    INSN(undef,     44c0, ffc0, M68000);
     INSN(move_to_ccr, 44c0, ffc0, CF_ISA_A);
+    INSN(move_to_ccr, 44c0, ffc0, M68000);
     INSN(not,       4680, fff8, CF_ISA_A);
+    INSN(not,       4600, ff00, M68000);
+    INSN(undef,     46c0, ffc0, M68000);
     INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
     INSN(pea,       4840, ffc0, CF_ISA_A);
+    INSN(pea,       4840, ffc0, M68000);
     INSN(swap,      4840, fff8, CF_ISA_A);
+    INSN(swap,      4840, fff8, M68000);
     INSN(movem,     48c0, fbc0, CF_ISA_A);
     INSN(ext,       4880, fff8, CF_ISA_A);
+    INSN(ext,       4880, fff8, M68000);
     INSN(ext,       48c0, fff8, CF_ISA_A);
+    INSN(ext,       48c0, fff8, M68000);
     INSN(ext,       49c0, fff8, CF_ISA_A);
+    INSN(ext,       49c0, fff8, M68000);
     INSN(tst,       4a00, ff00, CF_ISA_A);
+    INSN(tst,       4a00, ff00, M68000);
     INSN(tas,       4ac0, ffc0, CF_ISA_B);
+    INSN(tas,       4ac0, ffc0, M68000);
     INSN(halt,      4ac8, ffff, CF_ISA_A);
     INSN(pulse,     4acc, ffff, CF_ISA_A);
     INSN(illegal,   4afc, ffff, CF_ISA_A);
+    INSN(illegal,   4afc, ffff, M68000);
     INSN(mull,      4c00, ffc0, CF_ISA_A);
     INSN(divl,      4c40, ffc0, CF_ISA_A);
     INSN(sats,      4c80, fff8, CF_ISA_B);
     INSN(trap,      4e40, fff0, CF_ISA_A);
+    INSN(trap,      4e40, fff0, M68000);
     INSN(link,      4e50, fff8, CF_ISA_A);
+    INSN(link,      4e50, fff8, M68000);
     INSN(unlk,      4e58, fff8, CF_ISA_A);
+    INSN(unlk,      4e58, fff8, M68000);
     INSN(move_to_usp, 4e60, fff8, USP);
     INSN(move_from_usp, 4e68, fff8, USP);
     INSN(nop,       4e71, ffff, CF_ISA_A);
+    INSN(nop,       4e71, ffff, M68000);
     INSN(stop,      4e72, ffff, CF_ISA_A);
+    INSN(stop,      4e72, ffff, M68000);
     INSN(rte,       4e73, ffff, CF_ISA_A);
+    INSN(rte,       4e73, ffff, M68000);
     INSN(rts,       4e75, ffff, CF_ISA_A);
+    INSN(rts,       4e75, ffff, M68000);
     INSN(movec,     4e7b, ffff, CF_ISA_A);
     INSN(jump,      4e80, ffc0, CF_ISA_A);
+    INSN(jump,      4e80, ffc0, M68000);
     INSN(jump,      4ec0, ffc0, CF_ISA_A);
-    INSN(addsubq,   5180, f1c0, CF_ISA_A);
+    INSN(jump,      4ec0, ffc0, M68000);
+    INSN(addsubq,   5080, f0c0, CF_ISA_A);
+    INSN(addsubq,   5000, f080, M68000);
+    INSN(addsubq,   5080, f0c0, M68000);
     INSN(scc,       50c0, f0f8, CF_ISA_A);
-    INSN(addsubq,   5080, f1c0, CF_ISA_A);
+    INSN(scc,       50c0, f0f8, M68000);
     INSN(tpf,       51f8, fff8, CF_ISA_A);
 
     /* Branch instructions.  */
     INSN(branch,    6000, f000, CF_ISA_A);
+    INSN(branch,    6000, f000, M68000);
     /* Disable long branch instructions, then add back the ones we want.  */
     INSN(undef,     60ff, f0ff, CF_ISA_A); /* All long branches.  */
+    INSN(undef,     60ff, f0ff, M68000); /* All long branches.  */
     INSN(branch,    60ff, f0ff, CF_ISA_B);
     INSN(undef,     60ff, ffff, CF_ISA_B); /* bra.l */
     INSN(branch,    60ff, ffff, BRAL);
+    INSN(branch,    60ff, f0ff, BCCL);
 
     INSN(moveq,     7000, f100, CF_ISA_A);
+    INSN(moveq,     7000, f100, M68000);
     INSN(mvzs,      7100, f100, CF_ISA_B);
     INSN(or,        8000, f000, CF_ISA_A);
+    INSN(or,        8000, f000, M68000);
     INSN(divw,      80c0, f0c0, CF_ISA_A);
+    INSN(divw,      80c0, f0c0, M68000);
     INSN(addsub,    9000, f000, CF_ISA_A);
+    INSN(addsub,    9000, f000, M68000);
+    INSN(undef,     90c0, f0c0, CF_ISA_A);
     INSN(subx,      9180, f1f8, CF_ISA_A);
+    INSN(subx,      9100, f138, M68000);
     INSN(suba,      91c0, f1c0, CF_ISA_A);
 
     INSN(undef_mac, a000, f000, CF_ISA_A);
+    INSN(undef_mac, a000, f000, M68000);
     INSN(mac,       a000, f100, CF_EMAC);
     INSN(from_mac,  a180, f9b0, CF_EMAC);
     INSN(move_mac,  a110, f9fc, CF_EMAC);
@@ -2956,19 +3023,33 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(cmpa,      b0c0, f1c0, CF_ISA_B); /* cmpa.w */
     INSN(cmp,       b080, f1c0, CF_ISA_A);
     INSN(cmpa,      b1c0, f1c0, CF_ISA_A);
+    INSN(cmp,       b000, f100, M68000);
+    INSN(cmpa,      b0c0, f0c0, M68000);
     INSN(eor,       b180, f1c0, CF_ISA_A);
+    INSN(eor,       b180, f1c0, M68000);
     INSN(and,       c000, f000, CF_ISA_A);
+    INSN(and,       c000, f000, M68000);
     INSN(mulw,      c0c0, f0c0, CF_ISA_A);
+    INSN(mulw,      c0c0, f0c0, M68000);
     INSN(addsub,    d000, f000, CF_ISA_A);
+    INSN(addsub,    d000, f000, M68000);
+    INSN(undef,     d0c0, f0c0, CF_ISA_A);
     INSN(addx,      d180, f1f8, CF_ISA_A);
+    INSN(addx,      d100, f138, M68000);
     INSN(adda,      d1c0, f1c0, CF_ISA_A);
     INSN(shift_im,  e080, f0f0, CF_ISA_A);
     INSN(shift_reg, e0a0, f0f0, CF_ISA_A);
+    INSN(shift_im,    e080, f0f0, M68000);
+    INSN(shift_reg,   e0a0, f0f0, M68000);
     INSN(undef_fpu, f000, f000, CF_ISA_A);
+    INSN(undef_fpu, f000, f000, M68000);
     INSN(fpu,       f200, ffc0, CF_FPU);
     INSN(fbcc,      f280, ffc0, CF_FPU);
     INSN(frestore,  f340, ffc0, CF_FPU);
     INSN(fsave,     f340, ffc0, CF_FPU);
+    INSN(fbcc,      f280, ffc0, FPU);
+    INSN(frestore,  f340, ffc0, FPU);
+    INSN(fsave,     f340, ffc0, FPU);
     INSN(intouch,   f340, ffc0, CF_ISA_A);
     INSN(cpushl,    f428, ff38, CF_ISA_A);
     INSN(wddata,    fb00, ff00, CF_ISA_A);
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 06/17] m68k: add Scc instruction with memory operand.
  2009-05-29 22:41         ` [Qemu-devel] [PATCH 05/17] m68k: add Motorola 680x0 family common instructions Laurent Vivier
@ 2009-05-29 22:41           ` Laurent Vivier
  2009-05-29 22:41             ` [Qemu-devel] [PATCH 07/17] m68k: add DBcc instruction Laurent Vivier
  0 siblings, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

This patch defines Scc instruction for M68000 feature accessing
destination operand using an effective address (existing Scc instruction
manages only data registers).

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index cd46651..d08e1c8 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -906,6 +906,23 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
     s->is_jmp = DISAS_TB_JUMP;
 }
 
+DISAS_INSN(scc_mem)
+{
+    int l1;
+    int cond;
+    TCGv dest;
+
+    l1 = gen_new_label();
+    cond = (insn >> 8) & 0xf;
+    dest = tcg_temp_local_new();
+    tcg_gen_movi_i32(dest, 0);
+    gen_jmpcc(s, cond ^ 1, l1);
+    tcg_gen_movi_i32(dest, 0xff);
+    gen_set_label(l1);
+    DEST_EA(insn, OS_BYTE, dest, NULL);
+    tcg_temp_free(dest);
+}
+
 DISAS_INSN(undef_mac)
 {
     gen_exception(s, s->pc - 2, EXCP_LINEA);
@@ -2975,6 +2992,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(addsubq,   5000, f080, M68000);
     INSN(addsubq,   5080, f0c0, M68000);
     INSN(scc,       50c0, f0f8, CF_ISA_A);
+    INSN(scc_mem,   50c0, f0c0, M68000);
     INSN(scc,       50c0, f0f8, M68000);
     INSN(tpf,       51f8, fff8, CF_ISA_A);
 
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 07/17] m68k: add DBcc instruction.
  2009-05-29 22:41           ` [Qemu-devel] [PATCH 06/17] m68k: add Scc instruction with memory operand Laurent Vivier
@ 2009-05-29 22:41             ` Laurent Vivier
  2009-05-29 22:41               ` [Qemu-devel] [PATCH 08/17] m68k: modify movem instruction to manage word Laurent Vivier
  2009-05-30 22:00               ` [Qemu-devel] Re: [PATCH 07/17] m68k: add DBcc instruction Andreas Schwab
  0 siblings, 2 replies; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

Define DBcc instruction and attach it to M68000 feature.

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index d08e1c8..f2a0c92 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -923,6 +923,31 @@ DISAS_INSN(scc_mem)
     tcg_temp_free(dest);
 }
 
+DISAS_INSN(dbcc)
+{
+    int l1;
+    TCGv reg;
+    TCGv tmp;
+    int16_t offset;
+    uint32_t base;
+
+    reg = DREG(insn, 0);
+    base = s->pc;
+    offset = ldsw_code(s->pc);
+    s->pc += 2;
+    l1 = gen_new_label();
+    gen_jmpcc(s, (insn >> 8) & 0xf, l1);
+
+    tmp = tcg_temp_new();
+    tcg_gen_ext16s_i32(tmp, reg);
+    tcg_gen_addi_i32(tmp, tmp, -1);
+    gen_partset_reg(OS_WORD, reg, tmp);
+    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
+    gen_jmp_tb(s, 1, base + offset);
+    gen_set_label(l1);
+    gen_jmp_tb(s, 0, s->pc);
+}
+
 DISAS_INSN(undef_mac)
 {
     gen_exception(s, s->pc - 2, EXCP_LINEA);
@@ -2994,6 +3019,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(scc,       50c0, f0f8, CF_ISA_A);
     INSN(scc_mem,   50c0, f0c0, M68000);
     INSN(scc,       50c0, f0f8, M68000);
+    INSN(dbcc,      50c8, f0f8, M68000);
     INSN(tpf,       51f8, fff8, CF_ISA_A);
 
     /* Branch instructions.  */
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 08/17] m68k: modify movem instruction to manage word
  2009-05-29 22:41             ` [Qemu-devel] [PATCH 07/17] m68k: add DBcc instruction Laurent Vivier
@ 2009-05-29 22:41               ` Laurent Vivier
  2009-05-29 22:41                 ` [Qemu-devel] [PATCH 09/17] m68k: add 64bit divide Laurent Vivier
  2009-05-30 22:00               ` [Qemu-devel] Re: [PATCH 07/17] m68k: add DBcc instruction Andreas Schwab
  1 sibling, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

This patch modifies "movem" to manage "word" and "long" register size
instead of only "word". Attach it to M68000 feature.

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c |   52 +++++++++++++++++++++++++++++++++-------------
 1 files changed, 37 insertions(+), 15 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index f2a0c92..c869cf9 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1176,6 +1176,8 @@ DISAS_INSN(movem)
     TCGv reg;
     TCGv tmp;
     int is_load;
+    int opsize;
+    int32_t incr;
 
     mask = lduw_code(s->pc);
     s->pc += 2;
@@ -1187,21 +1189,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);
     }
 }
 
@@ -2975,6 +2996,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(swap,      4840, fff8, CF_ISA_A);
     INSN(swap,      4840, fff8, M68000);
     INSN(movem,     48c0, fbc0, CF_ISA_A);
+    INSN(movem,     48c0, fbc0, M68000);
     INSN(ext,       4880, fff8, CF_ISA_A);
     INSN(ext,       4880, fff8, M68000);
     INSN(ext,       48c0, fff8, CF_ISA_A);
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 09/17] m68k: add 64bit divide.
  2009-05-29 22:41               ` [Qemu-devel] [PATCH 08/17] m68k: modify movem instruction to manage word Laurent Vivier
@ 2009-05-29 22:41                 ` Laurent Vivier
  2009-05-29 22:41                   ` [Qemu-devel] [PATCH 10/17] m68k: add 32bit and 64bit multiply Laurent Vivier
  0 siblings, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

This patch modifies "divl" to support 64bit operands (QUAD_MULDIV
feature).

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.h       |    3 ++
 target-m68k/helpers.h   |    2 +
 target-m68k/op_helper.c |   77 ++++++++++++++++++++++++++++++++++++++++++++--
 target-m68k/qregs.def   |    1 +
 target-m68k/translate.c |   29 +++++++++++++++--
 5 files changed, 104 insertions(+), 8 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 240d75f..fa0b055 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -91,6 +91,9 @@ typedef struct CPUM68KState {
     uint32_t div1;
     uint32_t div2;
 
+    /* Upper 32 bits of a 64bit operand for quad MUL/DIV.  */
+    uint32_t quadh;
+
     /* MMU status.  */
     struct {
         uint32_t ar;
diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h
index cb8a0c7..a158aee 100644
--- a/target-m68k/helpers.h
+++ b/target-m68k/helpers.h
@@ -5,6 +5,8 @@ DEF_HELPER_1(ff1, i32, i32)
 DEF_HELPER_2(sats, i32, i32, i32)
 DEF_HELPER_2(divu, void, env, i32)
 DEF_HELPER_2(divs, void, env, i32)
+DEF_HELPER_1(divu64, void, env)
+DEF_HELPER_1(divs64, void, env)
 DEF_HELPER_3(addx_cc, i32, env, i32, i32)
 DEF_HELPER_3(subx_cc, i32, env, i32, i32)
 DEF_HELPER_3(shl_cc, i32, env, i32, i32)
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index a339a17..2d75b50 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -194,8 +194,11 @@ void HELPER(divu)(CPUState *env, uint32_t word)
         flags |= CCF_Z;
     else if ((int32_t)quot < 0)
         flags |= CCF_N;
-    env->div1 = quot;
-    env->div2 = rem;
+    /* Don't modify destination if overflow occured.  */
+    if ((flags & CCF_V) == 0) {
+        env->div1 = quot;
+        env->div2 = rem;
+    }
     env->cc_dest = flags;
 }
 
@@ -220,7 +223,73 @@ void HELPER(divs)(CPUState *env, uint32_t word)
         flags |= CCF_Z;
     else if (quot < 0)
         flags |= CCF_N;
-    env->div1 = quot;
-    env->div2 = rem;
+    /* Don't modify destination if overflow occured.  */
+    if ((flags & CCF_V) == 0) {
+        env->div1 = quot;
+        env->div2 = rem;
+    }
+    env->cc_dest = flags;
+}
+
+void HELPER(divu64)(CPUState *env)
+{
+    uint32_t num;
+    uint32_t den;
+    uint32_t quot;
+    uint32_t rem;
+    uint32_t flags;
+
+    num = env->div1;
+    den = env->div2;
+    /* ??? This needs to make sure the throwing location is accurate.  */
+    if (den == 0)
+        raise_exception(EXCP_DIV0);
+    quot = (num | ((uint64_t)env->quadh << 32)) / den;
+    rem = (num | ((uint64_t)env->quadh << 32)) % den;
+    flags = 0;
+    /* Avoid using a PARAM1 of zero.  This breaks dyngen because it uses
+       the address of a symbol, and gcc knows symbols can't have address
+       zero.  */
+    if (quot > 0xffffffff)
+        flags |= CCF_V;
+    if (quot == 0)
+        flags |= CCF_Z;
+    else if ((int64_t)quot < 0)
+        flags |= CCF_N;
+    /* Don't modify destination if overflow occured.  */
+    if ((flags & CCF_V) == 0) {
+        env->div1 = quot;
+        env->div2 = rem;
+    }
+    env->cc_dest = flags;
+}
+
+void HELPER(divs64)(CPUState *env)
+{
+    int32_t num;
+    int32_t den;
+    int32_t quot;
+    int32_t rem;
+    int32_t flags;
+
+    num = env->div1;
+    den = env->div2;
+    if (den == 0)
+        raise_exception(EXCP_DIV0);
+    quot = (num | ((int64_t)env->quadh << 32)) / den;
+    rem = (num | ((int64_t)env->quadh << 32)) % den;
+    rem = num % den;
+    flags = 0;
+    if (quot != (int32_t)quot)
+        flags |= CCF_V;
+    if (quot == 0)
+        flags |= CCF_Z;
+    else if (quot < 0)
+        flags |= CCF_N;
+    /* Don't modify destination if overflow occured.  */
+    if ((flags & CCF_V) == 0) {
+        env->div1 = quot;
+        env->div2 = rem;
+    }
     env->cc_dest = flags;
 }
diff --git a/target-m68k/qregs.def b/target-m68k/qregs.def
index 49400c4..76e0236 100644
--- a/target-m68k/qregs.def
+++ b/target-m68k/qregs.def
@@ -7,6 +7,7 @@ DEFO32(CC_SRC, cc_src)
 DEFO32(CC_X, cc_x)
 DEFO32(DIV1, div1)
 DEFO32(DIV2, div2)
+DEFO32(QUADH, quadh)
 DEFO32(EXCEPTION, exception_index)
 DEFO32(HALTED, halted)
 DEFO32(MACSR, macsr)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index c869cf9..d0e223c 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1025,8 +1025,26 @@ DISAS_INSN(divl)
 
     ext = lduw_code(s->pc);
     s->pc += 2;
-    if (ext & 0x87f8) {
-        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+    if (ext & 0x400) {
+        if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
+            gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+            return;
+        }
+        num = DREG(ext, 12);
+        reg = DREG(ext, 0);
+        tcg_gen_mov_i32(QREG_DIV1, num);
+        tcg_gen_mov_i32(QREG_QUADH, reg);
+        SRC_EA(den, OS_LONG, 0, NULL);
+        tcg_gen_mov_i32(QREG_DIV2, den);
+        if (ext & 0x0800) {
+            gen_helper_divs64(cpu_env);
+        } else {
+            gen_helper_divu64(cpu_env);
+        }
+        tcg_gen_mov_i32(num, QREG_DIV1);
+        if (!TCGV_EQUAL(num, reg))
+            tcg_gen_mov_i32(reg, QREG_DIV2);
+        s->cc_op = CC_OP_FLAGS;
         return;
     }
     num = DREG(ext, 12);
@@ -1039,10 +1057,12 @@ DISAS_INSN(divl)
     } else {
         gen_helper_divu(cpu_env, tcg_const_i32(0));
     }
-    if ((ext & 7) == ((ext >> 12) & 7)) {
+    if (((ext & 7) == ((ext >> 12) & 7)) ||
+        m68k_feature(s->env, M68K_FEATURE_LONG_MULDIV)) {
         /* div */
         tcg_gen_mov_i32 (reg, QREG_DIV1);
-    } else {
+    }
+    if ((ext & 7) != ((ext >> 12) & 7)) {
         /* rem */
         tcg_gen_mov_i32 (reg, QREG_DIV2);
     }
@@ -3013,6 +3033,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(illegal,   4afc, ffff, M68000);
     INSN(mull,      4c00, ffc0, CF_ISA_A);
     INSN(divl,      4c40, ffc0, CF_ISA_A);
+    INSN(divl,      4c40, ffc0, LONG_MULDIV);
     INSN(sats,      4c80, fff8, CF_ISA_B);
     INSN(trap,      4e40, fff0, CF_ISA_A);
     INSN(trap,      4e40, fff0, M68000);
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 10/17] m68k: add 32bit and 64bit multiply
  2009-05-29 22:41                 ` [Qemu-devel] [PATCH 09/17] m68k: add 64bit divide Laurent Vivier
@ 2009-05-29 22:41                   ` Laurent Vivier
  2009-05-29 22:41                     ` [Qemu-devel] [PATCH 11/17] m68k: add word data size for suba/adda Laurent Vivier
  0 siblings, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

This patch modify "mull" to support 64bit result, and to update
CC on 32bit operands.

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helpers.h   |    4 +++
 target-m68k/op_helper.c |   66 +++++++++++++++++++++++++++++++++++++++++++++++
 target-m68k/translate.c |   36 +++++++++++++++++++++----
 3 files changed, 100 insertions(+), 6 deletions(-)

diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h
index a158aee..ca2bf82 100644
--- a/target-m68k/helpers.h
+++ b/target-m68k/helpers.h
@@ -7,6 +7,10 @@ DEF_HELPER_2(divu, void, env, i32)
 DEF_HELPER_2(divs, void, env, i32)
 DEF_HELPER_1(divu64, void, env)
 DEF_HELPER_1(divs64, void, env)
+DEF_HELPER_3(mulu32_cc, i32, env, i32, i32)
+DEF_HELPER_3(muls32_cc, i32, env, i32, i32)
+DEF_HELPER_3(mulu64, i32, env, i32, i32)
+DEF_HELPER_3(muls64, i32, env, i32, i32)
 DEF_HELPER_3(addx_cc, i32, env, i32, i32)
 DEF_HELPER_3(subx_cc, i32, env, i32, i32)
 DEF_HELPER_3(shl_cc, i32, env, i32, i32)
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 2d75b50..76176f8 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -293,3 +293,69 @@ void HELPER(divs64)(CPUState *env)
     }
     env->cc_dest = flags;
 }
+
+uint32_t HELPER(mulu32_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+{
+    uint64_t res = (uint32_t)op1 * op2;
+    uint32_t flags;
+
+    flags = 0;
+    if (res >> 32)
+       flags |= CCF_V;
+    if ((uint32_t)res == 0)
+       flags |= CCF_Z;
+    if ((int32_t)res < 0)
+       flags |= CCF_N;
+    env->cc_dest = flags;
+
+    return res;
+}
+
+uint32_t HELPER(muls32_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+{
+    int64_t res = (int32_t)op1 * (int32_t)op2;
+    uint32_t flags;
+
+    flags = 0;
+    if (res != (int64_t)(int32_t)res)
+       flags |= CCF_V;
+    if ((uint32_t)res == 0)
+       flags |= CCF_Z;
+    if ((int32_t)res < 0)
+       flags |= CCF_N;
+    env->cc_dest = flags;
+
+    return res;
+}
+
+uint32_t HELPER(mulu64)(CPUState *env, uint32_t op1, uint32_t op2)
+{
+    uint64_t res = (uint64_t)op1 * op2;
+    uint32_t flags;
+
+    env->quadh = res >> 32;
+    flags = 0;
+    if (res == 0)
+       flags |= CCF_Z;
+    if ((int64_t)res < 0)
+       flags |= CCF_N;
+    env->cc_dest = flags;
+
+    return res;
+}
+
+uint32_t HELPER(muls64)(CPUState *env, uint32_t op1, uint32_t op2)
+{
+    int64_t res = (uint64_t)(int32_t)op1 * (int32_t)op2;
+    uint32_t flags;
+
+    env->quadh = res >> 32;
+    flags = 0;
+    if (res == 0)
+       flags |= CCF_Z;
+    if (res < 0)
+       flags |= CCF_N;
+    env->cc_dest = flags;
+
+    return res;
+}
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index d0e223c..eed804e 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1635,22 +1635,45 @@ DISAS_INSN(mull)
     TCGv reg;
     TCGv src1;
     TCGv dest;
+    TCGv regh;
 
     /* The upper 32 bits of the product are discarded, so
        muls.l and mulu.l are functionally equivalent.  */
     ext = lduw_code(s->pc);
     s->pc += 2;
-    if (ext & 0x87ff) {
-        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
-        return;
+    if (ext & 0x400) {
+       if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
+           gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+           return;
+       }
+       reg = DREG(ext, 12);
+       regh = DREG(ext, 0);
+       SRC_EA(src1, OS_LONG, 0, NULL);
+       dest = tcg_temp_new();
+       if (ext & 0x800)
+           gen_helper_muls64(dest, cpu_env, src1, reg);
+       else
+           gen_helper_mulu64(dest, cpu_env, src1, reg);
+       tcg_gen_mov_i32(reg, dest);
+       tcg_gen_mov_i32(regh, QREG_QUADH);
+       s->cc_op = CC_OP_FLAGS;
+       return;
     }
     reg = DREG(ext, 12);
     SRC_EA(src1, OS_LONG, 0, NULL);
     dest = tcg_temp_new();
-    tcg_gen_mul_i32(dest, src1, reg);
+    if (m68k_feature(s->env, M68K_FEATURE_M68000)) {
+       if (ext & 0x800)
+           gen_helper_muls32_cc(dest, cpu_env, src1, reg);
+       else
+           gen_helper_mulu32_cc(dest, cpu_env, src1, reg);
+       s->cc_op = CC_OP_FLAGS;
+    } else {
+       tcg_gen_mul_i32(dest, src1, reg);
+       /* Unlike m68k, coldfire always clears the overflow bit.  */
+       gen_logic_cc(s, dest);
+    }
     tcg_gen_mov_i32(reg, dest);
-    /* Unlike m68k, coldfire always clears the overflow bit.  */
-    gen_logic_cc(s, dest);
 }
 
 DISAS_INSN(link)
@@ -3032,6 +3055,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(illegal,   4afc, ffff, CF_ISA_A);
     INSN(illegal,   4afc, ffff, M68000);
     INSN(mull,      4c00, ffc0, CF_ISA_A);
+    INSN(mull,      4c00, ffc0, LONG_MULDIV);
     INSN(divl,      4c40, ffc0, CF_ISA_A);
     INSN(divl,      4c40, ffc0, LONG_MULDIV);
     INSN(sats,      4c80, fff8, CF_ISA_B);
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 11/17] m68k: add word data size for suba/adda
  2009-05-29 22:41                   ` [Qemu-devel] [PATCH 10/17] m68k: add 32bit and 64bit multiply Laurent Vivier
@ 2009-05-29 22:41                     ` Laurent Vivier
  2009-05-29 22:41                       ` [Qemu-devel] [PATCH 12/17] m68k: add fpu Laurent Vivier
  0 siblings, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

Allows suba and adda to manage word sized effective address, and attach
them to M68000 feature.

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index eed804e..89e5d5e 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1885,7 +1885,7 @@ DISAS_INSN(suba)
     TCGv src;
     TCGv reg;
 
-    SRC_EA(src, OS_LONG, 0, NULL);
+    SRC_EA(src, (insn & 0x100) ? OS_LONG : OS_WORD, -1, NULL);
     reg = AREG(insn, 9);
     tcg_gen_sub_i32(reg, reg, src);
 }
@@ -1995,7 +1995,7 @@ DISAS_INSN(adda)
     TCGv src;
     TCGv reg;
 
-    SRC_EA(src, OS_LONG, 0, NULL);
+    SRC_EA(src, (insn & 0x100) ? OS_LONG : OS_WORD, -1, NULL);
     reg = AREG(insn, 9);
     tcg_gen_add_i32(reg, reg, src);
 }
@@ -3113,6 +3113,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(subx,      9180, f1f8, CF_ISA_A);
     INSN(subx,      9100, f138, M68000);
     INSN(suba,      91c0, f1c0, CF_ISA_A);
+    INSN(suba,      90c0, f0c0, M68000);
 
     INSN(undef_mac, a000, f000, CF_ISA_A);
     INSN(undef_mac, a000, f000, M68000);
@@ -3148,6 +3149,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(addx,      d180, f1f8, CF_ISA_A);
     INSN(addx,      d100, f138, M68000);
     INSN(adda,      d1c0, f1c0, CF_ISA_A);
+    INSN(adda,      d0c0, f0c0, M68000);
     INSN(shift_im,  e080, f0f0, CF_ISA_A);
     INSN(shift_reg, e0a0, f0f0, CF_ISA_A);
     INSN(shift_im,    e080, f0f0, M68000);
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 12/17] m68k: add fpu
  2009-05-29 22:41                     ` [Qemu-devel] [PATCH 11/17] m68k: add word data size for suba/adda Laurent Vivier
@ 2009-05-29 22:41                       ` Laurent Vivier
  2009-05-29 22:41                         ` [Qemu-devel] [PATCH 13/17] m68k: add "byte", "word" and memory shift Laurent Vivier
  0 siblings, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

Modify "fpu" instruction to be compatible with 680x0 family and attach
it to FPU feature (in addition to CF_FPU).

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c |   49 ++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 89e5d5e..d00bde3 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2346,18 +2346,43 @@ DISAS_INSN(fpu)
     case 7:
         {
             TCGv addr;
+            int incr;
             uint16_t mask;
             int i;
-            if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
+            if ((ext & 0xf00) != 0 || (ext & 0xff) == 0)
                 goto undef;
-            tmp32 = gen_lea(s, insn, OS_LONG);
-            if (IS_NULL_QREG(tmp32)) {
-                gen_addr_fault(s);
-                return;
+            if ((ext & 0x1000) == 0 && !m68k_feature(s->env, M68K_FEATURE_FPU))
+                goto undef;
+            if ((insn & 070) == 040)
+                tmp32 = AREG(insn, 0);
+            else {
+                tmp32 = gen_lea(s, insn, OS_LONG);
+                 if (IS_NULL_QREG(tmp32)) {
+                     gen_addr_fault(s);
+                     return;
+                 }
             }
             addr = tcg_temp_new_i32();
             tcg_gen_mov_i32(addr, tmp32);
             mask = 0x80;
+            if (m68k_feature(s->env, M68K_FEATURE_FPU))
+                incr = 12;
+            else
+                incr = 8;
+            if ((ext & (1 << 13)) && (insn & 070) == 040) {
+                for (i = 0; i < 8; i++) {
+                    if (ext & mask) {
+                        s->is_mem = 1;
+                        dest = FREG(i, 7);
+                        tcg_gen_subi_i32(addr, addr, incr);
+                        tcg_gen_mov_i32(AREG(insn, 0), addr);
+                        tcg_gen_qemu_stf64(dest, addr, IS_USER(s));
+                    }
+                    mask >>= 1;
+                }
+                tcg_temp_free_i32(addr);
+                return;
+            }
             for (i = 0; i < 8; i++) {
                 if (ext & mask) {
                     s->is_mem = 1;
@@ -2369,8 +2394,11 @@ DISAS_INSN(fpu)
                         /* load */
                         tcg_gen_qemu_ldf64(dest, addr, IS_USER(s));
                     }
-                    if (ext & (mask - 1))
-                        tcg_gen_addi_i32(addr, addr, 8);
+                    if (ext & (mask - 1) || (insn & 070) == 030) {
+                        tcg_gen_addi_i32(addr, addr, incr);
+                        if ((insn & 070) == 030)
+                            tcg_gen_mov_i32(AREG(insn, 0), addr);
+                    }
                 }
                 mask >>= 1;
             }
@@ -2478,6 +2506,12 @@ DISAS_INSN(fpu)
     case 0x23: case 0x63: case 0x67: /* fmul */
         gen_helper_mul_f64(res, cpu_env, res, src);
         break;
+    case 0x24:                      /* fsgldiv */
+        gen_helper_div_f64(res, cpu_env, res, src);
+        break;
+    case 0x27:                      /* fsglmul */ 
+        gen_helper_mul_f64(res, cpu_env, res, src);
+        break; 
     case 0x28: case 0x68: case 0x6c: /* fsub */
         gen_helper_sub_f64(res, cpu_env, res, src);
         break;
@@ -3160,6 +3194,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(fbcc,      f280, ffc0, CF_FPU);
     INSN(frestore,  f340, ffc0, CF_FPU);
     INSN(fsave,     f340, ffc0, CF_FPU);
+    INSN(fpu,       f200, ffc0, FPU);
     INSN(fbcc,      f280, ffc0, FPU);
     INSN(frestore,  f340, ffc0, FPU);
     INSN(fsave,     f340, ffc0, FPU);
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 13/17] m68k: add "byte", "word" and memory shift
  2009-05-29 22:41                       ` [Qemu-devel] [PATCH 12/17] m68k: add fpu Laurent Vivier
@ 2009-05-29 22:41                         ` Laurent Vivier
  2009-05-29 22:41                           ` [Qemu-devel] [PATCH 14/17] m68k: add "byte", "word" and memory rotate Laurent Vivier
  0 siblings, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

This patch defines shift8_im, shift16_im, shift8_reg, shift16_reg,
shift_mem and attach them to M68000 feature.

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.h       |    2 +
 target-m68k/helper.c    |  160 +++++++++++++++++++++++++++--------------------
 target-m68k/helpers.h   |   12 +++-
 target-m68k/translate.c |  155 +++++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 249 insertions(+), 80 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index fa0b055..727a0b1 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -146,6 +146,8 @@ enum {
     CC_OP_SUBXB,  /* CC_DEST = result, CC_SRC = source */
     CC_OP_SUBXW,  /* CC_DEST = result, CC_SRC = source */
     CC_OP_SUBX,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SHIFTB, /* CC_DEST = result, CC_SRC = carry */
+    CC_OP_SHIFTW, /* CC_DEST = result, CC_SRC = carry */
     CC_OP_SHIFT, /* CC_DEST = result, CC_SRC = carry */
 };
 
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index bcd73d5..f15902a 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -283,6 +283,12 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
         flags |= CCF_V; \
     } while (0)
 
+#define SET_FLAGS_SHIFT(type) do { \
+    SET_NZ((type)dest); \
+    if (src) \
+        flags |= CCF_C; \
+    } while(0)
+
     flags = 0;
     src = env->cc_src;
     dest = env->cc_dest;
@@ -329,10 +335,14 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
     case CC_OP_SUBX:
         SET_FLAGS_SUBX(int32_t, uint32_t);
         break;
+    case CC_OP_SHIFTB:
+        SET_FLAGS_SHIFT(int8_t);
+	break;
+    case CC_OP_SHIFTW:
+        SET_FLAGS_SHIFT(int16_t);
+	break;
     case CC_OP_SHIFT:
-        SET_NZ(dest);
-        if (src)
-            flags |= CCF_C;
+        SET_FLAGS_SHIFT(int32_t);
         break;
     default:
         cpu_abort(env, "Bad CC_OP %d", cc_op);
@@ -533,77 +543,89 @@ void HELPER(set_sr)(CPUState *env, uint32_t val)
     m68k_switch_sp(env);
 }
 
-uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
-{
-    uint32_t result;
-    uint32_t cf;
-
-    shift &= 63;
-    if (shift == 0) {
-        result = val;
-        cf = env->cc_src & CCF_C;
-    } else if (shift < 32) {
-        result = val << shift;
-        cf = (val >> (32 - shift)) & 1;
-    } else if (shift == 32) {
-        result = 0;
-        cf = val & 1;
-    } else /* shift > 32 */ {
-        result = 0;
-        cf = 0;
-    }
-    env->cc_src = cf;
-    env->cc_x = (cf != 0);
-    env->cc_dest = result;
-    return result;
-}
-
-uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
-{
-    uint32_t result;
-    uint32_t cf;
-
-    shift &= 63;
-    if (shift == 0) {
-        result = val;
-        cf = env->cc_src & CCF_C;
-    } else if (shift < 32) {
-        result = val >> shift;
-        cf = (val >> (shift - 1)) & 1;
-    } else if (shift == 32) {
-        result = 0;
-        cf = val >> 31;
-    } else /* shift > 32 */ {
-        result = 0;
-        cf = 0;
-    }
-    env->cc_src = cf;
-    env->cc_x = (cf != 0);
-    env->cc_dest = result;
-    return result;
-}
-
-uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
-{
-    uint32_t result;
-    uint32_t cf;
-
-    shift &= 63;
-    if (shift == 0) {
-        result = val;
-        cf = (env->cc_src & CCF_C) != 0;
-    } else if (shift < 32) {
-        result = (int32_t)val >> shift;
-        cf = (val >> (shift - 1)) & 1;
-    } else /* shift >= 32 */ {
-        result = (int32_t)val >> 31;
-        cf = val >> 31;
-    }
-    env->cc_src = cf;
-    env->cc_x = cf;
-    env->cc_dest = result;
-    return result;
-}
+#define HELPER_SHL(type, bits) \
+uint32_t HELPER(glue(glue(shl, bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t cf; \
+    shift &= 63; \
+    if (shift == 0) { \
+        result = (type)val; \
+        cf = env->cc_src & CCF_C; \
+    } else if (shift < bits) { \
+        result = (type)val << shift; \
+        cf = ((type)val >> (bits - shift)) & 1; \
+    } else if (shift == bits) { \
+        result = 0; \
+        cf = val & 1; \
+    } else /* shift > bits */ { \
+        result = 0; \
+        cf = 0; \
+    } \
+    env->cc_src = cf; \
+    env->cc_x = (cf != 0); \
+    env->cc_dest = result; \
+    return result; \
+}
+
+HELPER_SHL(uint8_t, 8)
+HELPER_SHL(uint16_t, 16)
+HELPER_SHL(uint32_t, 32)
+
+#define HELPER_SHR(type, bits) \
+uint32_t HELPER(glue(glue(shr, bits), _cc))(CPUState *env, uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t cf; \
+    shift &= 63; \
+    if (shift == 0) { \
+        result = (type)val; \
+        cf = env->cc_src & CCF_C; \
+    } else if (shift < bits) { \
+        result = (type)val >> shift; \
+        cf = ((type)val >> (shift - 1)) & 1; \
+    } else if (shift == bits) { \
+        result = 0; \
+        cf = (type)val >> (bits - 1); \
+    } else /* shift > bits */ { \
+        result = 0; \
+        cf = 0; \
+    } \
+    env->cc_src = cf; \
+    env->cc_x = (cf != 0); \
+    env->cc_dest = result; \
+    return result; \
+}
+
+HELPER_SHR(uint8_t, 8)
+HELPER_SHR(uint16_t, 16)
+HELPER_SHR(uint32_t, 32)
+
+#define HELPER_SAR(type, bits) \
+uint32_t HELPER(glue(glue(sar, bits), _cc))(CPUState *env, uint32_t val, uint32_t shift)					\
+{ \
+    type result; \
+    uint32_t cf; \
+    shift &= 63; \
+    if (shift == 0) { \
+        result = (type)val; \
+        cf = (env->cc_src & CCF_C) != 0; \
+    } else if (shift < bits) { \
+        result = (type)val >> shift; \
+        cf = (val >> (shift - 1)) & 1; \
+    } else /* shift >= bits */ { \
+        result = (type)val >> (bits - 1); \
+        cf = val >> (bits - 1); \
+    } \
+    env->cc_src = cf; \
+    env->cc_x = cf; \
+    env->cc_dest = result; \
+    return result; \
+}
+
+HELPER_SAR(int8_t, 8)
+HELPER_SAR(int16_t, 16)
+HELPER_SAR(int32_t, 32)
 
 /* FPU helpers.  */
 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h
index ca2bf82..d1993ab 100644
--- a/target-m68k/helpers.h
+++ b/target-m68k/helpers.h
@@ -13,9 +13,15 @@ DEF_HELPER_3(mulu64, i32, env, i32, i32)
 DEF_HELPER_3(muls64, i32, env, i32, i32)
 DEF_HELPER_3(addx_cc, i32, env, i32, i32)
 DEF_HELPER_3(subx_cc, i32, env, i32, i32)
-DEF_HELPER_3(shl_cc, i32, env, i32, i32)
-DEF_HELPER_3(shr_cc, i32, env, i32, i32)
-DEF_HELPER_3(sar_cc, i32, env, i32, i32)
+DEF_HELPER_3(shl8_cc, i32, env, i32, i32)
+DEF_HELPER_3(shl16_cc, i32, env, i32, i32)
+DEF_HELPER_3(shl32_cc, i32, env, i32, i32)
+DEF_HELPER_3(shr8_cc, i32, env, i32, i32)
+DEF_HELPER_3(shr16_cc, i32, env, i32, i32)
+DEF_HELPER_3(shr32_cc, i32, env, i32, i32)
+DEF_HELPER_3(sar8_cc, i32, env, i32, i32)
+DEF_HELPER_3(sar16_cc, i32, env, i32, i32)
+DEF_HELPER_3(sar32_cc, i32, env, i32, i32)
 DEF_HELPER_2(xflag_lt, i32, i32, i32)
 DEF_HELPER_2(set_sr, void, env, i32)
 DEF_HELPER_3(movec, void, env, i32, i32)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index d00bde3..10b67e5 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2013,6 +2013,63 @@ DISAS_INSN(addx)
 }
 
 /* TODO: This could be implemented without helper functions.  */
+DISAS_INSN(shift8_im)
+{
+    TCGv reg;
+    int tmp;
+    TCGv shift;
+    TCGv dest;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+        tmp = 8;
+    shift = tcg_const_i32(tmp);
+    dest = tcg_temp_new_i32();
+    /* No need to flush flags becuse we know we will set C flag.  */
+    if (insn & 0x100) {
+        gen_helper_shl8_cc(dest, cpu_env, reg, shift);
+    } else {
+        if (insn & 8) {
+            gen_helper_shr8_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_sar8_cc(dest, cpu_env, reg, shift);
+        }
+    }
+    s->cc_op = CC_OP_SHIFTB;
+    gen_partset_reg(OS_BYTE, reg, dest);
+}
+
+/* TODO: This could be implemented without helper functions.  */
+DISAS_INSN(shift16_im)
+{
+    TCGv reg;
+    int tmp;
+    TCGv shift;
+    TCGv dest;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+        tmp = 8;
+    shift = tcg_const_i32(tmp);
+    dest = tcg_temp_new_i32();
+    /* No need to flush flags becuse we know we will set C flag.  */
+    if (insn & 0x100) {
+        gen_helper_shl16_cc(dest, cpu_env, reg, shift);
+    } else {
+        if (insn & 8) {
+            gen_helper_shr16_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_sar16_cc(dest, cpu_env, reg, shift);
+        }
+    }
+    s->cc_op = CC_OP_SHIFTW;
+    gen_partset_reg(OS_WORD, reg, dest);
+}
+
+
+/* TODO: This could be implemented without helper functions.  */
 DISAS_INSN(shift_im)
 {
     TCGv reg;
@@ -2026,17 +2083,71 @@ DISAS_INSN(shift_im)
     shift = tcg_const_i32(tmp);
     /* No need to flush flags becuse we know we will set C flag.  */
     if (insn & 0x100) {
-        gen_helper_shl_cc(reg, cpu_env, reg, shift);
+        gen_helper_shl32_cc(reg, cpu_env, reg, shift);
     } else {
         if (insn & 8) {
-            gen_helper_shr_cc(reg, cpu_env, reg, shift);
+            gen_helper_shr32_cc(reg, cpu_env, reg, shift);
         } else {
-            gen_helper_sar_cc(reg, cpu_env, reg, shift);
+            gen_helper_sar32_cc(reg, cpu_env, reg, shift);
         }
     }
     s->cc_op = CC_OP_SHIFT;
 }
 
+DISAS_INSN(shift8_reg)
+{
+    TCGv reg;
+    TCGv shift;
+    TCGv dest;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    shift = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, shift, 63);
+    dest = tcg_temp_new_i32();
+    /* Shift by zero leaves C flag unmodified.   */
+    gen_flush_flags(s);
+    if (insn & 0x100) {
+        gen_helper_shl8_cc(dest, cpu_env, reg, tmp);
+    } else {
+        if (insn & 8) {
+            gen_helper_shr8_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_sar8_cc(dest, cpu_env, reg, tmp);
+        }
+    }
+    s->cc_op = CC_OP_SHIFTB;
+    gen_partset_reg(OS_BYTE, reg, dest);
+}
+
+DISAS_INSN(shift16_reg)
+{
+    TCGv reg;
+    TCGv shift;
+    TCGv dest;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    shift = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, shift, 63);
+    dest = tcg_temp_new_i32();
+    /* Shift by zero leaves C flag unmodified.   */
+    gen_flush_flags(s);
+    if (insn & 0x100) {
+        gen_helper_shl16_cc(dest, cpu_env, reg, tmp);
+    } else {
+        if (insn & 8) {
+            gen_helper_shr16_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_sar16_cc(dest, cpu_env, reg, tmp);
+        }
+    }
+    s->cc_op = CC_OP_SHIFTB;
+    gen_partset_reg(OS_WORD, reg, dest);
+}
+
 DISAS_INSN(shift_reg)
 {
     TCGv reg;
@@ -2047,17 +2158,40 @@ DISAS_INSN(shift_reg)
     /* Shift by zero leaves C flag unmodified.   */
     gen_flush_flags(s);
     if (insn & 0x100) {
-        gen_helper_shl_cc(reg, cpu_env, reg, shift);
+        gen_helper_shl32_cc(reg, cpu_env, reg, shift);
     } else {
         if (insn & 8) {
-            gen_helper_shr_cc(reg, cpu_env, reg, shift);
+            gen_helper_shr32_cc(reg, cpu_env, reg, shift);
         } else {
-            gen_helper_sar_cc(reg, cpu_env, reg, shift);
+            gen_helper_sar32_cc(reg, cpu_env, reg, shift);
         }
     }
     s->cc_op = CC_OP_SHIFT;
 }
 
+DISAS_INSN(shift_mem)
+{
+    TCGv src;
+    TCGv dest;
+    TCGv addr;
+    TCGv shift;
+
+    SRC_EA(src, OS_WORD, 0, &addr);
+    dest = tcg_temp_new_i32();
+    shift = tcg_const_i32(1);
+    if (insn & 0x100) {
+        gen_helper_shl16_cc(dest, cpu_env, src, shift);
+    } else {
+        if (insn & 8) {
+            gen_helper_shr16_cc(dest, cpu_env, src, shift);
+        } else {
+            gen_helper_sar16_cc(dest, cpu_env, src, shift);
+        }
+    }
+    s->cc_op = CC_OP_SHIFTW;
+    DEST_EA(insn, OS_WORD, dest, &addr);
+}
+
 DISAS_INSN(ff1)
 {
     TCGv reg;
@@ -3186,8 +3320,13 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(adda,      d0c0, f0c0, M68000);
     INSN(shift_im,  e080, f0f0, CF_ISA_A);
     INSN(shift_reg, e0a0, f0f0, CF_ISA_A);
-    INSN(shift_im,    e080, f0f0, M68000);
-    INSN(shift_reg,   e0a0, f0f0, M68000);
+    INSN(shift8_im, e000, f0f0, M68000);
+    INSN(shift16_im, e040, f0f0, M68000);
+    INSN(shift_im,  e080, f0f0, M68000);
+    INSN(shift8_reg, e020, f0f0, M68000);
+    INSN(shift16_reg, e060, f0f0, M68000);
+    INSN(shift_reg, e0a0, f0f0, M68000);
+    INSN(shift_mem, e0c0, fcc0, M68000);
     INSN(undef_fpu, f000, f000, CF_ISA_A);
     INSN(undef_fpu, f000, f000, M68000);
     INSN(fpu,       f200, ffc0, CF_FPU);
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 14/17] m68k: add "byte", "word" and memory rotate.
  2009-05-29 22:41                         ` [Qemu-devel] [PATCH 13/17] m68k: add "byte", "word" and memory shift Laurent Vivier
@ 2009-05-29 22:41                           ` Laurent Vivier
  2009-05-29 22:41                             ` [Qemu-devel] [PATCH 15/17] m68k: add bitfield_mem, bitfield_reg Laurent Vivier
  0 siblings, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

Add rotate_im, rotate8_im, rotate16_im, rotate_reg, rotate8_reg, rotate16_reg,
 rotate_mem and attach them to M68000 feature.

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/exec.h      |    4 +
 target-m68k/helper.c    |  149 ++++++++++++++++++++++++++++++++++
 target-m68k/helpers.h   |   12 +++
 target-m68k/translate.c |  205 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 370 insertions(+), 0 deletions(-)

diff --git a/target-m68k/exec.h b/target-m68k/exec.h
index 3a86b1f..6f63cd8 100644
--- a/target-m68k/exec.h
+++ b/target-m68k/exec.h
@@ -29,6 +29,10 @@ register uint32_t T0 asm(AREG1);
 #include "cpu.h"
 #include "exec-all.h"
 
+extern const uint8_t rox8_table[64];
+extern const uint8_t rox16_table[64];
+extern const uint8_t rox32_table[64];
+
 static inline void env_to_regs(void)
 {
 }
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index f15902a..92c7621 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -62,6 +62,42 @@ static m68k_def_t m68k_cpu_defs[] = {
     {NULL, 0},
 };
 
+/* modulo 33 table */
+const uint8_t rox32_table[64] = {
+    0, 1, 2, 3, 4, 5, 6, 7,
+    8, 9,10,11,12,13,14,15,
+   16,17,18,19,20,21,22,23,
+   24,25,26,27,28,29,30,31,
+   32, 0, 1, 2, 3, 4, 5, 6,
+    7, 8, 9,10,11,12,13,14,
+   15,16,17,18,19,20,21,22,
+   23,24,25,26,27,28,29,30,
+};
+
+/* modulo 17 table */
+const uint8_t rox16_table[64] = {
+    0, 1, 2, 3, 4, 5, 6, 7,
+    8, 9,10,11,12,13,14,15,
+   16, 0, 1, 2, 3, 4, 5, 6,
+    7, 8, 9,10,11,12,13,14,
+   15,16, 0, 1, 2, 3, 4, 5,
+    6, 7, 8, 9,10,11,12,13,
+   14,15,16, 0, 1, 2, 3, 4,
+    5, 6, 7, 8, 9,10,11,12,
+};
+
+/* modulo 9 table */
+const uint8_t rox8_table[64] = {
+    0, 1, 2, 3, 4, 5, 6, 7,
+    8, 0, 1, 2, 3, 4, 5, 6,
+    7, 8, 0, 1, 2, 3, 4, 5,
+    6, 7, 8, 0, 1, 2, 3, 4,
+    5, 6, 7, 8, 0, 1, 2, 3,
+    4, 5, 6, 7, 8, 0, 1, 2,
+    3, 4, 5, 6, 7, 8, 0, 1,
+    2, 3, 4, 5, 6, 7, 8, 0,
+};
+
 void m68k_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
 {
     unsigned int i;
@@ -627,6 +663,119 @@ HELPER_SAR(int8_t, 8)
 HELPER_SAR(int16_t, 16)
 HELPER_SAR(int32_t, 32)
 
+#define HELPER_ROL(type, bits) \
+uint32_t HELPER(glue(glue(rol,bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t flags; \
+    int count = shift & (bits - 1); \
+    if (count) \
+       result = ((type)val << count) | ((type)val >> (bits - count)); \
+    else \
+       result = (type)val; \
+    flags = 0; \
+    if (result == 0) \
+       flags |= CCF_Z; \
+    if (result & (1 << (bits - 1))) \
+       flags |= CCF_N; \
+    if (shift && result & 1) \
+       flags |= CCF_C; \
+    env->cc_dest = flags; \
+    return result; \
+}
+
+HELPER_ROL(uint8_t, 8)
+HELPER_ROL(uint16_t, 16)
+HELPER_ROL(uint32_t, 32)
+
+#define HELPER_ROR(type, bits) \
+uint32_t HELPER(glue(glue(ror,bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t flags; \
+    int count = shift & (bits - 1); \
+    if (count) \
+       result = ((type)val >> count) | ((type)val << (bits - count)); \
+    else \
+       result = (type)val; \
+    flags = 0; \
+    if (result == 0) \
+       flags |= CCF_Z; \
+    if (result & (1 << (bits - 1))) \
+       flags |= CCF_N; \
+    if (shift && result & (1 << (bits - 1))) \
+       flags |= CCF_C; \
+    env->cc_dest = flags; \
+    return result; \
+}
+
+HELPER_ROR(uint8_t, 8)
+HELPER_ROR(uint16_t, 16)
+HELPER_ROR(uint32_t, 32)
+
+#define HELPER_ROXR(type, bits) \
+uint32_t HELPER(glue(glue(roxr,bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t flags; \
+    int count = shift; \
+    if (bits == 8) count = rox8_table[count]; \
+    if (bits == 16) count = rox16_table[count]; \
+    if (bits == 32) count = rox32_table[count]; \
+    if (count) { \
+       result = ((type)val >> count) | ((type)env->cc_x << (bits - count)); \
+       if (count > 1) \
+           result |= (type)val << (bits + 1 - count); \
+       env->cc_x = ((type)val >> (count - 1)) & 1; \
+    } else \
+       result = (type)val; \
+    flags = 0; \
+    if (result == 0) \
+       flags |= CCF_Z; \
+    if (result & (1 << (bits - 1))) \
+       flags |= CCF_N; \
+    if (env->cc_x) \
+       flags |= CCF_C; \
+    env->cc_dest = flags; \
+    return result; \
+}
+
+HELPER_ROXR(uint8_t, 8)
+HELPER_ROXR(uint16_t, 16)
+HELPER_ROXR(uint32_t, 32)
+
+#define HELPER_ROXL(type, bits) \
+uint32_t HELPER(glue(glue(roxl,bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t flags; \
+    int count; \
+    count = shift; \
+    if (bits == 8) count = rox8_table[count]; \
+    if (bits == 16) count = rox16_table[count]; \
+    if (bits == 32) count = rox32_table[count]; \
+    if (count) { \
+       result = ((type)val << count) | ((type)env->cc_x << (count - 1)); \
+       if (count > 1) \
+           result |= (type)val >> (bits + 1 - count); \
+       env->cc_x = ((type)val >> (bits - count)) & 1; \
+    } else \
+       result = (type)val; \
+    flags = 0; \
+    if (result == 0) \
+       flags |= CCF_Z; \
+    if (result & (1 << (bits - 1))) \
+       flags |= CCF_N; \
+    if (env->cc_x) \
+       flags |= CCF_C; \
+    env->cc_dest = flags; \
+    return result; \
+}
+
+HELPER_ROXL(uint8_t, 8)
+HELPER_ROXL(uint16_t, 16)
+HELPER_ROXL(uint32_t, 32)
+
 /* FPU helpers.  */
 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
 {
diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h
index d1993ab..07d1f82 100644
--- a/target-m68k/helpers.h
+++ b/target-m68k/helpers.h
@@ -22,6 +22,18 @@ DEF_HELPER_3(shr32_cc, i32, env, i32, i32)
 DEF_HELPER_3(sar8_cc, i32, env, i32, i32)
 DEF_HELPER_3(sar16_cc, i32, env, i32, i32)
 DEF_HELPER_3(sar32_cc, i32, env, i32, i32)
+DEF_HELPER_3(rol8_cc, i32, env, i32, i32)
+DEF_HELPER_3(rol16_cc, i32, env, i32, i32)
+DEF_HELPER_3(rol32_cc, i32, env, i32, i32)
+DEF_HELPER_3(ror8_cc, i32, env, i32, i32)
+DEF_HELPER_3(ror16_cc, i32, env, i32, i32)
+DEF_HELPER_3(ror32_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxr8_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxr16_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxr32_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxl8_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxl16_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxl32_cc, i32, env, i32, i32)
 DEF_HELPER_2(xflag_lt, i32, i32, i32)
 DEF_HELPER_2(set_sr, void, env, i32)
 DEF_HELPER_3(movec, void, env, i32, i32)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 10b67e5..17ab88c 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2192,6 +2192,204 @@ DISAS_INSN(shift_mem)
     DEST_EA(insn, OS_WORD, dest, &addr);
 }
 
+DISAS_INSN(rotate_im)
+{
+    TCGv reg;
+    TCGv shift;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+       tmp = 8;
+    shift = tcg_const_i32(tmp);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol32_cc(reg, cpu_env, reg, shift);
+       } else {
+           gen_helper_ror32_cc(reg, cpu_env, reg, shift);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl32_cc(reg, cpu_env, reg, shift);
+        } else {
+            gen_helper_roxr32_cc(reg, cpu_env, reg, shift);
+        }
+    }
+    s->cc_op = CC_OP_FLAGS;
+}
+
+DISAS_INSN(rotate8_im)
+{
+    TCGv reg;
+    TCGv dest;
+    TCGv shift;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+       tmp = 8;
+    dest = tcg_temp_new_i32();
+    shift = tcg_const_i32(tmp);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol8_cc(dest, cpu_env, reg, shift);
+       } else {
+           gen_helper_ror8_cc(dest, cpu_env, reg, shift);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl8_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_roxr8_cc(dest, cpu_env, reg, shift);
+        }
+    }
+    s->cc_op = CC_OP_FLAGS;
+    gen_partset_reg(OS_BYTE, reg, dest);
+}
+
+DISAS_INSN(rotate16_im)
+{
+    TCGv reg;
+    TCGv dest;
+    TCGv shift;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+       tmp = 8;
+    dest = tcg_temp_new_i32();
+    shift = tcg_const_i32(tmp);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol16_cc(dest, cpu_env, reg, shift);
+       } else {
+           gen_helper_ror16_cc(dest, cpu_env, reg, shift);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl16_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_roxr16_cc(dest, cpu_env, reg, shift);
+        }
+    }
+    s->cc_op = CC_OP_FLAGS;
+    gen_partset_reg(OS_WORD, reg, dest);
+}
+
+DISAS_INSN(rotate_reg)
+{
+    TCGv reg;
+    TCGv src;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, src, 63);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol32_cc(reg, cpu_env, reg, tmp);
+       } else {
+           gen_helper_ror32_cc(reg, cpu_env, reg, tmp);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl32_cc(reg, cpu_env, reg, tmp);
+        } else {
+            gen_helper_roxr32_cc(reg, cpu_env, reg, tmp);
+        }
+    }
+    s->cc_op = CC_OP_FLAGS;
+}
+
+DISAS_INSN(rotate8_reg)
+{
+    TCGv reg;
+    TCGv src;
+    TCGv dest;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, src, 63);
+    dest = tcg_temp_new_i32();
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol8_cc(dest, cpu_env, reg, tmp);
+       } else {
+           gen_helper_ror8_cc(dest, cpu_env, reg, tmp);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl8_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_roxr8_cc(dest, cpu_env, reg, tmp);
+        }
+    }
+    s->cc_op = CC_OP_FLAGS;
+    gen_partset_reg(OS_BYTE, reg, dest);
+}
+
+DISAS_INSN(rotate16_reg)
+{
+    TCGv reg;
+    TCGv src;
+    TCGv dest;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, src, 63);
+    dest = tcg_temp_new_i32();
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol16_cc(dest, cpu_env, reg, tmp);
+       } else {
+           gen_helper_ror16_cc(dest, cpu_env, reg, tmp);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl16_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_roxr16_cc(dest, cpu_env, reg, tmp);
+        }
+    }
+    s->cc_op = CC_OP_FLAGS;
+    gen_partset_reg(OS_WORD, reg, dest);
+}
+
+DISAS_INSN(rotate_mem)
+{
+    TCGv src;
+    TCGv dest;
+    TCGv addr;
+    TCGv shift;
+
+    SRC_EA(src, OS_WORD, 0, &addr);
+    dest = tcg_temp_new_i32();
+    shift = tcg_const_i32(1);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol16_cc(dest, cpu_env, src, shift);
+       } else {
+           gen_helper_ror16_cc(dest, cpu_env, src, shift);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl16_cc(dest, cpu_env, src, shift);
+        } else {
+            gen_helper_roxr16_cc(dest, cpu_env, src, shift);
+        }
+    }
+    s->cc_op = CC_OP_FLAGS;
+    DEST_EA(insn, OS_WORD, dest, &addr);
+}
+
 DISAS_INSN(ff1)
 {
     TCGv reg;
@@ -3327,6 +3525,13 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(shift16_reg, e060, f0f0, M68000);
     INSN(shift_reg, e0a0, f0f0, M68000);
     INSN(shift_mem, e0c0, fcc0, M68000);
+    INSN(rotate_im, e090, f0f0, M68000);
+    INSN(rotate8_im, e010, f0f0, M68000);
+    INSN(rotate16_im, e050, f0f0, M68000);
+    INSN(rotate_reg, e0b0, f0f0, M68000);
+    INSN(rotate8_reg, e030, f0f0, M68000);
+    INSN(rotate16_reg,e070, f0f0, M68000);
+    INSN(rotate_mem, e4c0, fcc0, M68000);
     INSN(undef_fpu, f000, f000, CF_ISA_A);
     INSN(undef_fpu, f000, f000, M68000);
     INSN(fpu,       f200, ffc0, CF_FPU);
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 15/17] m68k: add bitfield_mem, bitfield_reg
  2009-05-29 22:41                           ` [Qemu-devel] [PATCH 14/17] m68k: add "byte", "word" and memory rotate Laurent Vivier
@ 2009-05-29 22:41                             ` Laurent Vivier
  2009-05-29 22:42                               ` [Qemu-devel] [PATCH 16/17] m68k: add variable offset/width to bitfield_reg/bitfield_mem Laurent Vivier
  0 siblings, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

This patch implements bitfields instructions: bftst, bfextu, bfexts,
bfffo, bfchg, bfclr, bfset, bfins and attach them to BITFIELD feature.

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    |   27 ++++
 target-m68k/helpers.h   |    3 +
 target-m68k/translate.c |  323 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 353 insertions(+), 0 deletions(-)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 92c7621..32ff8ca 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -514,6 +514,33 @@ uint32_t HELPER(ff1)(uint32_t x)
     return n;
 }
 
+uint32_t HELPER(bfffo)(uint32_t arg, uint32_t width)
+{
+    int n;
+    uint32_t mask;
+    mask = 0x80000000;
+    for (n = 0; n < width; n++) {
+       if (arg & mask)
+           break;
+       mask >>= 1;
+    }
+    return n;
+}
+
+uint32_t HELPER(rol32)(uint32_t val, uint32_t shift)
+{
+    uint32_t result;
+    result = (val << shift) | (val >> (32 - shift));
+    return result;
+}
+
+uint32_t HELPER(ror32)(uint32_t val, uint32_t shift)
+{
+    uint32_t result;
+    result = (val >> shift) | (val << (32 - shift));
+    return result;
+}
+
 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
 {
     /* The result has the opposite sign to the original value.  */
diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h
index 07d1f82..949d5d5 100644
--- a/target-m68k/helpers.h
+++ b/target-m68k/helpers.h
@@ -2,6 +2,9 @@
 
 DEF_HELPER_1(bitrev, i32, i32)
 DEF_HELPER_1(ff1, i32, i32)
+DEF_HELPER_2(bfffo, i32, i32, i32)
+DEF_HELPER_2(rol32, i32, i32, i32)
+DEF_HELPER_2(ror32, i32, i32, i32)
 DEF_HELPER_2(sats, i32, i32, i32)
 DEF_HELPER_2(divu, void, env, i32)
 DEF_HELPER_2(divs, void, env, i32)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 17ab88c..289e3bb 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2390,6 +2390,327 @@ DISAS_INSN(rotate_mem)
     DEST_EA(insn, OS_WORD, dest, &addr);
 }
 
+DISAS_INSN(bitfield_reg)
+{
+    uint16_t ext;
+    TCGv tmp;
+    TCGv tmp1;
+    TCGv reg;
+    int offset;
+    int width;
+    int op;
+    TCGv reg2;
+    uint32_t mask;
+
+    reg = DREG(insn, 0);
+    op = (insn >> 8) & 7;
+    ext = lduw_code(s->pc);
+    s->pc += 2;
+    if ((ext & 0x820) == 0) {
+       /* constant offset and width */
+       offset = (ext >> 6) & 31;
+       width = (ext & 31);
+       if (width == 0)
+           width = 32;
+       reg2 = DREG(ext, 12);
+       mask = 0xffffffff << (32 - width);
+       if (offset > 0)
+           mask = (mask >> offset) | (mask << (32 - offset));
+       tmp = tcg_temp_new_i32();
+       tcg_gen_andi_i32(tmp, reg, mask);
+       if (offset > 0) {
+           tmp1 = tcg_temp_new_i32();
+           gen_helper_rol32(tmp1, tmp, tcg_const_i32(offset));
+       } else
+           tmp1 = tmp;
+       gen_logic_cc(s, tmp1);
+       switch (op) {
+       case 0: /* bftst */
+           break;
+       case 1: /* bfextu */
+           if (offset + width != 32)
+               gen_helper_rol32(reg2, tmp, tcg_const_i32((offset + width) & 31));
+           else
+               tcg_gen_mov_i32(reg2, tmp);
+           break;
+       case 2: /* bfchg */
+           tcg_gen_xor_i32(reg, reg, tcg_const_i32(mask));
+           break;
+       case 3: /* bfexts */
+           if (offset > 0)
+               gen_helper_rol32(reg2, tmp, tcg_const_i32(offset));
+           if (width < 32)
+               tcg_gen_sari_i32(reg2, reg2, 32 - width);
+           break;
+       case 4: /* bfclr */
+	   tcg_gen_and_i32(reg, reg, tcg_const_i32(mask));
+           break;
+       case 5: /* bfffo */
+           if (offset > 0)
+               gen_helper_rol32(reg2, tmp, tcg_const_i32(offset));
+           gen_helper_bfffo(tmp, tmp, tcg_const_i32(width));
+           tcg_gen_addi_i32(reg2, tmp, offset);
+           break;
+       case 6: /* bfset */
+           tcg_gen_ori_i32(reg, reg, mask);
+           break;
+       case 7: /* bfins */
+           if (width == 32) {
+               if (offset > 0)
+                   gen_helper_ror32(reg, reg2, tcg_const_i32(offset));
+               else
+                   tcg_gen_mov_i32(reg, reg2);
+           } else {
+               tcg_gen_andi_i32(tmp, reg2, (1u << width) - 1);
+               if (offset + width != 32)
+                   gen_helper_ror32(tmp, tmp, tcg_const_i32((offset + width) & 31));
+               tcg_gen_andi_i32(reg, reg, ~mask);
+               tcg_gen_or_i32(reg, reg, tmp);
+           }
+           break;
+       }
+       return;
+    }
+    /* Not yet implemented */
+    gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+}
+
+/* Generate a load from a bitfield.  */
+static void gen_bitfield_load(DisasContext *s, TCGv addr, int endpos,
+                             TCGv *val1, TCGv *val2)
+{   
+    TCGv tmp;
+    
+    if (endpos <= 8)
+       *val1 = gen_load(s, OS_BYTE, addr, 0);
+    else if (endpos <= 24) {
+       *val1 = gen_load(s, OS_WORD, addr, 0);
+       if (endpos > 16) {
+           tmp = tcg_temp_new_i32();
+           tcg_gen_addi_i32(tmp, addr, 2);
+           *val2 = gen_load(s, OS_BYTE, tmp, 0);
+       }
+    } else {
+       *val1 = gen_load(s, OS_LONG, addr, 0);
+       if (endpos > 32) {
+           tmp = tcg_temp_new_i32();
+           tcg_gen_addi_i32(tmp, addr, 4);
+           *val2 = gen_load(s, OS_BYTE, tmp, 0);
+       }
+    }
+}
+
+/* Generate a store to a bitfield.  */
+static void gen_bitfield_store(DisasContext *s, TCGv addr, int endpos,
+                              TCGv val1, TCGv val2)
+{
+    TCGv tmp;
+
+    if (endpos <= 8)
+       gen_store(s, OS_BYTE, addr, val1);
+    else if (endpos <= 24) {
+       gen_store(s, OS_WORD, addr, val1);
+       if (endpos > 16) {
+           tmp = tcg_temp_new_i32();
+           tcg_gen_addi_i32(tmp, addr, 2);
+           gen_store(s, OS_BYTE, tmp, val2);
+       }
+    } else {
+       gen_store(s, OS_LONG, addr, val1);
+       if (endpos > 32) {
+           tmp = tcg_temp_new_i32();
+           tcg_gen_addi_i32(tmp, addr, 4);
+           gen_store(s, OS_BYTE, tmp, val2);
+       }
+    }
+}
+
+static TCGv gen_bitfield_cc(DisasContext *s, int offset, int width,
+                          TCGv val1, TCGv val2)
+{
+    TCGv dest;
+    TCGv tmp;
+
+    dest = tcg_temp_new_i32();
+
+    if (offset + width <= 8)
+       tcg_gen_shli_i32(dest, val1, 24 + offset);
+    else if (offset + width <= 24) {
+       tcg_gen_shli_i32(dest, val1, 16 + offset);
+       if (offset + width > 16) {
+           tmp = tcg_temp_new_i32();
+           tcg_gen_shli_i32(tmp, val2, 8 + offset);
+           tcg_gen_or_i32(dest, dest, tmp);
+       }
+    } else {
+       tcg_gen_shli_i32(dest, val1, offset);
+       if (offset + width > 32) {
+           tmp = tcg_temp_new_i32();
+           tcg_gen_shri_i32(tmp, val2, offset);
+           tcg_gen_or_i32(dest, dest, tmp);
+       }
+    }
+    tcg_gen_andi_i32(dest, dest, 0xffffffff << (32 - width));
+    gen_logic_cc(s, dest);
+    return dest;
+}
+
+static void gen_bitfield_op(int offset, int width, int op, TCGv val1, TCGv val2)
+{
+    uint32_t mask1;
+    uint32_t mask2;
+    int endpos = offset + width;
+
+    if (endpos <= 8) {
+       mask1 = (0xff >> offset) & (0xff << (8 - endpos));
+       mask2 = 0;
+    } else if (endpos <= 16) {
+       mask1 = (0xffff >> offset) & (0xffff << (16 - endpos));
+       mask2 = 0;
+    } else if (endpos <= 24) {
+       mask1 = 0xffffff >> offset;
+       mask2 = 0xff & (0xff << (24 - endpos));
+    } else if (endpos <= 32) {
+       mask1 = (0xffffffff >> offset) & (0xffffffff << (32 - endpos));
+       mask2 = 0;
+    } else {
+       mask1 = 0xffffffff >> offset;
+       mask2 = 0xff & (0xff << (40 - endpos));
+    }
+    switch (op) {
+    case 2:                    /* bfchg */
+       tcg_gen_xori_i32(val1, val1, mask1);
+       if (mask2)
+           tcg_gen_xori_i32(val2, val2, mask2);
+       break;
+    case 4:                    /* bfclr */
+       tcg_gen_andi_i32(val1, val1, ~mask1);
+       if (mask2)
+           tcg_gen_andi_i32(val2, val2, ~mask2);
+       break;
+    case 6:                    /* bfset */
+       tcg_gen_ori_i32(val1, val1, mask1);
+       if (mask2)
+           tcg_gen_ori_i32(val2, val2, mask2);
+       break;
+    }
+}
+
+static void gen_bitfield_ins(int offset, int width, TCGv src,
+                            TCGv val1, TCGv val2)
+{
+    TCGv tmp;
+    int endpos = offset + width;
+
+    tmp = tcg_temp_new_i32();
+    if (width < 32) {
+       tcg_gen_andi_i32(tmp, src, (1u << width) - 1);
+    } else
+       tcg_gen_mov_i32(tmp, src);
+    if (endpos <= 8) {
+       if (endpos < 8)
+           tcg_gen_shli_i32(tmp, tmp, 8 - endpos);
+       tcg_gen_or_i32(val1, val1, tmp);
+    } else if (endpos <= 16) {
+       if (endpos < 16)
+           tcg_gen_shli_i32(tmp, tmp, 16 - endpos);
+       tcg_gen_or_i32(val1, val1, tmp);
+    } else if (endpos <= 24) {
+       tcg_gen_shri_i32(tmp, tmp, endpos - 16);
+       tcg_gen_or_i32(val1, val1, tmp);
+       tcg_gen_andi_i32(tmp, src, (1u << (endpos - 16)) - 1);
+       if (endpos < 24)
+           tcg_gen_shli_i32(tmp, tmp, 24 - endpos);
+       tcg_gen_or_i32(val2, val2, tmp);
+    } else if (endpos <= 32) {
+       if (endpos < 32)
+           tcg_gen_shli_i32(tmp, tmp, 32 - endpos);
+       tcg_gen_or_i32(val1, val1, tmp);
+    } else {
+       tcg_gen_shri_i32(tmp, tmp, endpos - 32);
+       tcg_gen_or_i32(val1, val1, tmp);
+       tcg_gen_andi_i32(tmp, src, (1u << (endpos - 32)) - 1);
+       tcg_gen_shri_i32(tmp, tmp, 32 - endpos);
+       tcg_gen_or_i32(val2, val2, tmp);
+    }
+}
+
+DISAS_INSN(bitfield_mem)
+{
+    uint16_t ext;
+    TCGv val;
+    TCGv val1, val2;
+    TCGv src;
+    int offset;
+    int width;
+    int op;
+    TCGv reg;
+    TCGv addr;
+    uint32_t mask;
+
+    op = (insn >> 8) & 7;
+    ext = lduw_code(s->pc);
+    s->pc += 2;
+    src = gen_lea(s, insn, OS_LONG);
+    if (IS_NULL_QREG(src)) {
+       gen_addr_fault(s);
+       return;
+    }
+    if ((ext & 0x820) == 0) {
+       /* constant offset and width */
+       offset = (ext >> 6) & 31;
+       width = (ext & 31);
+       if (width == 0)
+           width = 32;
+       reg = DREG(ext, 12);
+       mask = 0xffffffff << (32 - width);
+       addr = tcg_temp_new_i32();
+       if (offset > 7) {
+           tcg_gen_addi_i32(addr, src, offset >> 3);
+           offset &= 7;
+       } else
+           tcg_gen_mov_i32(addr, src);
+       if (offset > 0)
+           mask <<= 32 - offset;
+       gen_bitfield_load(s, addr, offset + width, &val1, &val2);
+       val = gen_bitfield_cc(s, offset, width, val1, val2);
+       switch (op) {
+       case 0: /* bftst */
+           break;
+       case 1: /* bfextu */
+           if (width < 32)
+               tcg_gen_shri_i32(reg, val, 32 - width);
+           else
+               tcg_gen_mov_i32(reg, val);
+           break;
+       case 3: /* bfexts */
+           if (width < 32)
+               tcg_gen_sari_i32(reg, val, 32 - width);
+           else
+               tcg_gen_mov_i32(reg, val);
+           break;
+       case 5: /* bfffo */
+           gen_helper_bfffo(val, val, tcg_const_i32(width));
+           tcg_gen_addi_i32(reg, val, offset);
+           break;
+       case 2: /* bfchg */
+       case 4: /* bfclr */
+       case 6: /* bfset */
+           gen_bitfield_op(offset, width, op, val1, val2);
+           gen_bitfield_store(s, addr, offset + width, val1, val2);
+           break;
+       case 7: /* bfins */
+           gen_bitfield_op(offset, width, 4, val1, val2);
+           gen_bitfield_ins(offset, width, reg, val1, val2);
+           gen_bitfield_store(s, addr, offset + width, val1, val2);
+           break;
+       }
+       return;
+    }
+    /* Not yet implemented */
+    gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+}
+
 DISAS_INSN(ff1)
 {
     TCGv reg;
@@ -3532,6 +3853,8 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(rotate8_reg, e030, f0f0, M68000);
     INSN(rotate16_reg,e070, f0f0, M68000);
     INSN(rotate_mem, e4c0, fcc0, M68000);
+    INSN(bitfield_mem,e8c0, f8c0, BITFIELD);
+    INSN(bitfield_reg,e8c0, f8f8, BITFIELD);
     INSN(undef_fpu, f000, f000, CF_ISA_A);
     INSN(undef_fpu, f000, f000, M68000);
     INSN(fpu,       f200, ffc0, CF_FPU);
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 16/17] m68k: add variable offset/width to bitfield_reg/bitfield_mem
  2009-05-29 22:41                             ` [Qemu-devel] [PATCH 15/17] m68k: add bitfield_mem, bitfield_reg Laurent Vivier
@ 2009-05-29 22:42                               ` Laurent Vivier
  2009-05-29 22:42                                 ` [Qemu-devel] [PATCH 17/17] m68k: add cas Laurent Vivier
  0 siblings, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

This patch allows bitfield instructions to read bit offset and field
size from a register instead of an immediat value.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    |   42 ++++
 target-m68k/helpers.h   |    2 +
 target-m68k/translate.c |  517 +++++++++++++++++++++++------------------------
 3 files changed, 292 insertions(+), 269 deletions(-)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 32ff8ca..3ae0366 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -530,6 +530,8 @@ uint32_t HELPER(bfffo)(uint32_t arg, uint32_t width)
 uint32_t HELPER(rol32)(uint32_t val, uint32_t shift)
 {
     uint32_t result;
+    if (shift == 0 || shift == 32)
+        return val;
     result = (val << shift) | (val >> (32 - shift));
     return result;
 }
@@ -537,6 +539,8 @@ uint32_t HELPER(rol32)(uint32_t val, uint32_t shift)
 uint32_t HELPER(ror32)(uint32_t val, uint32_t shift)
 {
     uint32_t result;
+    if (shift == 0 || shift == 32)
+        return val;
     result = (val >> shift) | (val << (32 - shift));
     return result;
 }
@@ -1182,3 +1186,41 @@ void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
     res |= (uint64_t)(val & 0xffff0000) << 16;
     env->macc[acc + 1] = res;
 }
+
+/* load from a bitfield */
+
+uint64_t HELPER(bitfield_load)(uint32_t addr, uint32_t offset, uint32_t width)
+{
+    uint8_t data[8];
+    uint64_t bitfield;
+    int size;
+    int i;
+
+    size = (offset + width + 7) >> 3;
+    cpu_physical_memory_rw(addr, data, size, 0);
+
+    bitfield = data[0];
+    for (i = 1; i < 8; i++)
+        bitfield = (bitfield << 8) | data[i];
+
+    return bitfield;
+}
+
+/* store to a bitfield */
+
+void HELPER(bitfield_store)(uint32_t addr, uint32_t offset, uint32_t width,
+                            uint64_t bitfield)
+{
+    uint8_t data[8];
+    int size;
+    int i;
+
+    size = (offset + width + 7) >> 3;
+
+    for (i = 0; i < 8; i++) {
+        data[7 - i] = bitfield;
+        bitfield >>= 8;
+    }
+
+    cpu_physical_memory_rw(addr, data, size, 1);
+}
diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h
index 949d5d5..d71ed26 100644
--- a/target-m68k/helpers.h
+++ b/target-m68k/helpers.h
@@ -78,4 +78,6 @@ DEF_HELPER_3(set_mac_extu, void, env, i32, i32)
 DEF_HELPER_2(flush_flags, void, env, i32)
 DEF_HELPER_1(raise_exception, void, i32)
 
+DEF_HELPER_3(bitfield_load, i64, i32, i32, i32);
+DEF_HELPER_4(bitfield_store, void, i32, i32, i32, i64);
 #include "def-helper.h"
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 289e3bb..4c36b6a 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2390,263 +2390,225 @@ DISAS_INSN(rotate_mem)
     DEST_EA(insn, OS_WORD, dest, &addr);
 }
 
+static void bitfield_param(uint16_t ext, TCGv *offset, TCGv *width, TCGv *mask)
+{
+    TCGv tmp;
+
+    /* offset */
+
+    if (ext & 0x0800) {
+        *offset = DREG(ext, 6);
+    } else {
+        *offset = tcg_temp_new_i32();
+        tcg_gen_movi_i32(*offset, (ext >> 6) & 31);
+    }
+
+    /* width */
+
+    if (ext & 0x0020) {
+        *width = DREG(ext, 0);
+        tcg_gen_subi_i32(*width, *width, 1);
+        tcg_gen_andi_i32(*width, *width, 31);
+        tcg_gen_addi_i32(*width, *width, 1);
+    } else {
+        *width = tcg_temp_new_i32();
+        tcg_gen_movi_i32(*width, ((ext - 1) & 31) + 1);
+    }
+
+    /* mask */
+
+    tmp = tcg_temp_new_i32();
+    tcg_gen_sub_i32(tmp, tcg_const_i32(32), *width);
+    *mask = tcg_temp_new_i32();
+    tcg_gen_shl_i32(*mask, tcg_const_i32(0xffffffff), tmp);
+}
+
 DISAS_INSN(bitfield_reg)
 {
     uint16_t ext;
     TCGv tmp;
     TCGv tmp1;
     TCGv reg;
-    int offset;
-    int width;
+    TCGv offset;
+    TCGv width;
     int op;
     TCGv reg2;
-    uint32_t mask;
+    TCGv mask;
 
     reg = DREG(insn, 0);
     op = (insn >> 8) & 7;
     ext = lduw_code(s->pc);
     s->pc += 2;
-    if ((ext & 0x820) == 0) {
-       /* constant offset and width */
-       offset = (ext >> 6) & 31;
-       width = (ext & 31);
-       if (width == 0)
-           width = 32;
-       reg2 = DREG(ext, 12);
-       mask = 0xffffffff << (32 - width);
-       if (offset > 0)
-           mask = (mask >> offset) | (mask << (32 - offset));
-       tmp = tcg_temp_new_i32();
-       tcg_gen_andi_i32(tmp, reg, mask);
-       if (offset > 0) {
-           tmp1 = tcg_temp_new_i32();
-           gen_helper_rol32(tmp1, tmp, tcg_const_i32(offset));
-       } else
-           tmp1 = tmp;
-       gen_logic_cc(s, tmp1);
-       switch (op) {
-       case 0: /* bftst */
-           break;
-       case 1: /* bfextu */
-           if (offset + width != 32)
-               gen_helper_rol32(reg2, tmp, tcg_const_i32((offset + width) & 31));
-           else
-               tcg_gen_mov_i32(reg2, tmp);
-           break;
-       case 2: /* bfchg */
-           tcg_gen_xor_i32(reg, reg, tcg_const_i32(mask));
-           break;
-       case 3: /* bfexts */
-           if (offset > 0)
-               gen_helper_rol32(reg2, tmp, tcg_const_i32(offset));
-           if (width < 32)
-               tcg_gen_sari_i32(reg2, reg2, 32 - width);
-           break;
-       case 4: /* bfclr */
-	   tcg_gen_and_i32(reg, reg, tcg_const_i32(mask));
-           break;
-       case 5: /* bfffo */
-           if (offset > 0)
-               gen_helper_rol32(reg2, tmp, tcg_const_i32(offset));
-           gen_helper_bfffo(tmp, tmp, tcg_const_i32(width));
-           tcg_gen_addi_i32(reg2, tmp, offset);
-           break;
-       case 6: /* bfset */
-           tcg_gen_ori_i32(reg, reg, mask);
-           break;
-       case 7: /* bfins */
-           if (width == 32) {
-               if (offset > 0)
-                   gen_helper_ror32(reg, reg2, tcg_const_i32(offset));
-               else
-                   tcg_gen_mov_i32(reg, reg2);
-           } else {
-               tcg_gen_andi_i32(tmp, reg2, (1u << width) - 1);
-               if (offset + width != 32)
-                   gen_helper_ror32(tmp, tmp, tcg_const_i32((offset + width) & 31));
-               tcg_gen_andi_i32(reg, reg, ~mask);
-               tcg_gen_or_i32(reg, reg, tmp);
-           }
-           break;
-       }
-       return;
-    }
-    /* Not yet implemented */
-    gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
-}
 
-/* Generate a load from a bitfield.  */
-static void gen_bitfield_load(DisasContext *s, TCGv addr, int endpos,
-                             TCGv *val1, TCGv *val2)
-{   
-    TCGv tmp;
-    
-    if (endpos <= 8)
-       *val1 = gen_load(s, OS_BYTE, addr, 0);
-    else if (endpos <= 24) {
-       *val1 = gen_load(s, OS_WORD, addr, 0);
-       if (endpos > 16) {
-           tmp = tcg_temp_new_i32();
-           tcg_gen_addi_i32(tmp, addr, 2);
-           *val2 = gen_load(s, OS_BYTE, tmp, 0);
-       }
-    } else {
-       *val1 = gen_load(s, OS_LONG, addr, 0);
-       if (endpos > 32) {
-           tmp = tcg_temp_new_i32();
-           tcg_gen_addi_i32(tmp, addr, 4);
-           *val2 = gen_load(s, OS_BYTE, tmp, 0);
-       }
-    }
-}
+    bitfield_param(ext, &offset, &width, &mask);
 
-/* Generate a store to a bitfield.  */
-static void gen_bitfield_store(DisasContext *s, TCGv addr, int endpos,
-                              TCGv val1, TCGv val2)
-{
-    TCGv tmp;
+    if (ext & 0x0800)
+        tcg_gen_andi_i32(offset, offset, 31);
+    gen_helper_ror32(mask, mask, offset);
 
-    if (endpos <= 8)
-       gen_store(s, OS_BYTE, addr, val1);
-    else if (endpos <= 24) {
-       gen_store(s, OS_WORD, addr, val1);
-       if (endpos > 16) {
-           tmp = tcg_temp_new_i32();
-           tcg_gen_addi_i32(tmp, addr, 2);
-           gen_store(s, OS_BYTE, tmp, val2);
-       }
-    } else {
-       gen_store(s, OS_LONG, addr, val1);
-       if (endpos > 32) {
-           tmp = tcg_temp_new_i32();
-           tcg_gen_addi_i32(tmp, addr, 4);
-           gen_store(s, OS_BYTE, tmp, val2);
-       }
+    /* reg & mask */
+
+    tmp = tcg_temp_new_i32();
+    tcg_gen_and_i32(tmp, reg, mask);
+
+    tmp1 = tcg_temp_new_i32();
+    gen_helper_rol32(tmp1, tmp, offset);
+    gen_logic_cc(s, tmp1);
+
+    reg2 = DREG(ext, 12);
+    switch (op) {
+    case 0: /* bftst */
+        break;
+    case 1: /* bfextu */
+        tcg_gen_add_i32(tmp1, offset, width);
+        tcg_gen_andi_i32(tmp1, tmp1, 31);
+        gen_helper_rol32(reg2, tmp, tmp1);
+        break;
+    case 2: /* bfchg */
+        tcg_gen_xor_i32(reg, reg, mask);
+        break;
+    case 3: /* bfexts */
+        gen_helper_rol32(reg2, tmp, offset);
+        tcg_gen_sub_i32(width, tcg_const_i32(32), width);
+        tcg_gen_sar_i32(reg2, reg2, width);
+        break;
+    case 4: /* bfclr */
+        tcg_gen_and_i32(reg, reg, mask);
+        break;
+    case 5: /* bfffo */
+        gen_helper_rol32(reg2, tmp, offset);
+        gen_helper_bfffo(tmp, tmp, width);
+        tcg_gen_add_i32(reg2, tmp, offset);
+        break;
+    case 6: /* bfset */
+        tcg_gen_or_i32(reg, reg, mask);
+        break;
+    case 7: /* bfins */
+        tcg_gen_shl_i32(tmp1, tcg_const_i32(1), width);
+        tcg_gen_subi_i32(tmp1, tmp1, 1);
+        tcg_gen_and_i32(tmp, reg2, tmp1);
+        tcg_gen_add_i32(tmp1, offset, width);
+        tcg_gen_andi_i32(tmp1, tmp1, 31);
+        gen_helper_ror32(tmp, tmp, tmp1);
+        tcg_gen_not_i32(mask, mask);
+        tcg_gen_and_i32(reg, reg, mask);
+        tcg_gen_or_i32(reg, reg, tmp);
+        break;
     }
 }
 
-static TCGv gen_bitfield_cc(DisasContext *s, int offset, int width,
-                          TCGv val1, TCGv val2)
+static TCGv gen_bitfield_cc(DisasContext *s,
+                            TCGv offset, TCGv mask_cc, TCGv_i64 bitfield)
 {
     TCGv dest;
-    TCGv tmp;
+    TCGv_i64 tmp64;
 
+    /* move bitfield to a 32bit */
+
+    tmp64 = tcg_temp_new_i64();
+
+    tcg_gen_extu_i32_i64(tmp64, offset);
+
+    /* tmp64 = bitfield << offset */
+
+    tcg_gen_shl_i64(tmp64, bitfield, tmp64);
+
+    /* tmp = (bitfield << offset) >> 32 */
+
+    tcg_gen_shri_i64(tmp64, bitfield, 32ULL);
     dest = tcg_temp_new_i32();
+    tcg_gen_trunc_i64_i32(dest, tmp64);
 
-    if (offset + width <= 8)
-       tcg_gen_shli_i32(dest, val1, 24 + offset);
-    else if (offset + width <= 24) {
-       tcg_gen_shli_i32(dest, val1, 16 + offset);
-       if (offset + width > 16) {
-           tmp = tcg_temp_new_i32();
-           tcg_gen_shli_i32(tmp, val2, 8 + offset);
-           tcg_gen_or_i32(dest, dest, tmp);
-       }
-    } else {
-       tcg_gen_shli_i32(dest, val1, offset);
-       if (offset + width > 32) {
-           tmp = tcg_temp_new_i32();
-           tcg_gen_shri_i32(tmp, val2, offset);
-           tcg_gen_or_i32(dest, dest, tmp);
-       }
-    }
-    tcg_gen_andi_i32(dest, dest, 0xffffffff << (32 - width));
+    /* compute cc */
+
+    tcg_gen_and_i32(dest, dest, mask_cc);
     gen_logic_cc(s, dest);
+
     return dest;
 }
 
-static void gen_bitfield_op(int offset, int width, int op, TCGv val1, TCGv val2)
-{
-    uint32_t mask1;
-    uint32_t mask2;
-    int endpos = offset + width;
-
-    if (endpos <= 8) {
-       mask1 = (0xff >> offset) & (0xff << (8 - endpos));
-       mask2 = 0;
-    } else if (endpos <= 16) {
-       mask1 = (0xffff >> offset) & (0xffff << (16 - endpos));
-       mask2 = 0;
-    } else if (endpos <= 24) {
-       mask1 = 0xffffff >> offset;
-       mask2 = 0xff & (0xff << (24 - endpos));
-    } else if (endpos <= 32) {
-       mask1 = (0xffffffff >> offset) & (0xffffffff << (32 - endpos));
-       mask2 = 0;
-    } else {
-       mask1 = 0xffffffff >> offset;
-       mask2 = 0xff & (0xff << (40 - endpos));
-    }
-    switch (op) {
-    case 2:                    /* bfchg */
-       tcg_gen_xori_i32(val1, val1, mask1);
-       if (mask2)
-           tcg_gen_xori_i32(val2, val2, mask2);
-       break;
-    case 4:                    /* bfclr */
-       tcg_gen_andi_i32(val1, val1, ~mask1);
-       if (mask2)
-           tcg_gen_andi_i32(val2, val2, ~mask2);
-       break;
-    case 6:                    /* bfset */
-       tcg_gen_ori_i32(val1, val1, mask1);
-       if (mask2)
-           tcg_gen_ori_i32(val2, val2, mask2);
-       break;
-    }
-}
-
-static void gen_bitfield_ins(int offset, int width, TCGv src,
-                            TCGv val1, TCGv val2)
+static TCGv_i64 gen_bitfield_mask(TCGv offset, TCGv width)
 {
     TCGv tmp;
-    int endpos = offset + width;
+    TCGv_i64 mask;
+    TCGv_i64 shift;
+
+    mask = tcg_temp_new_i64();
+
+    /* mask = (1u << width) - 1; */
+
+    tcg_gen_extu_i32_i64(mask, width);
+    tcg_gen_shl_i64(mask, tcg_const_i64(1), mask);
+    tcg_gen_subi_i64(mask, mask, 1);
+
+    /* shift = 64 - (width + offset); */
 
     tmp = tcg_temp_new_i32();
-    if (width < 32) {
-       tcg_gen_andi_i32(tmp, src, (1u << width) - 1);
-    } else
-       tcg_gen_mov_i32(tmp, src);
-    if (endpos <= 8) {
-       if (endpos < 8)
-           tcg_gen_shli_i32(tmp, tmp, 8 - endpos);
-       tcg_gen_or_i32(val1, val1, tmp);
-    } else if (endpos <= 16) {
-       if (endpos < 16)
-           tcg_gen_shli_i32(tmp, tmp, 16 - endpos);
-       tcg_gen_or_i32(val1, val1, tmp);
-    } else if (endpos <= 24) {
-       tcg_gen_shri_i32(tmp, tmp, endpos - 16);
-       tcg_gen_or_i32(val1, val1, tmp);
-       tcg_gen_andi_i32(tmp, src, (1u << (endpos - 16)) - 1);
-       if (endpos < 24)
-           tcg_gen_shli_i32(tmp, tmp, 24 - endpos);
-       tcg_gen_or_i32(val2, val2, tmp);
-    } else if (endpos <= 32) {
-       if (endpos < 32)
-           tcg_gen_shli_i32(tmp, tmp, 32 - endpos);
-       tcg_gen_or_i32(val1, val1, tmp);
-    } else {
-       tcg_gen_shri_i32(tmp, tmp, endpos - 32);
-       tcg_gen_or_i32(val1, val1, tmp);
-       tcg_gen_andi_i32(tmp, src, (1u << (endpos - 32)) - 1);
-       tcg_gen_shri_i32(tmp, tmp, 32 - endpos);
-       tcg_gen_or_i32(val2, val2, tmp);
-    }
+    tcg_gen_add_i32(tmp, offset, width);
+    tcg_gen_sub_i32(tmp, tcg_const_i32(64), tmp);
+    shift = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(shift, tmp);
+
+    /* mask <<= shift */
+
+    tcg_gen_shl_i64(mask, mask, shift);
+
+    return mask;
+}
+
+static void gen_bitfield_ins(TCGv offset, TCGv width, TCGv src,
+                                 TCGv_i64 val)
+{
+    TCGv_i64 insert;
+    TCGv_i64 shift;
+    TCGv tmp;
+
+    tmp = tcg_temp_new_i32();
+
+    /* tmp = (1u << width) - 1; */
+
+    tcg_gen_shl_i32(tmp, tcg_const_i32(1), width);
+    tcg_gen_subi_i32(tmp, tmp, 1);
+
+    /* tmp = tmp & src; */
+
+    tcg_gen_and_i32(tmp, tmp, src);
+
+    /* insert = (i64)tmp; */
+
+    insert = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(insert, tmp);
+
+    /* tmp = 64 - (width + offset); */
+
+    tcg_gen_add_i32(tmp, offset, width);
+    tcg_gen_sub_i32(tmp, tcg_const_i32(64), tmp);
+    shift = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(shift, tmp);
+
+    /* insert <<= shift */
+
+    tcg_gen_shl_i64(insert, insert, shift);
+
+    /* val |=  select */
+
+    tcg_gen_or_i64(val, val, insert);
 }
 
 DISAS_INSN(bitfield_mem)
 {
     uint16_t ext;
+    int op;
+    TCGv_i64 bitfield;
+    TCGv_i64 mask_bitfield;
+    TCGv mask_cc;
+    TCGv shift;
     TCGv val;
-    TCGv val1, val2;
     TCGv src;
-    int offset;
-    int width;
-    int op;
+    TCGv offset;
+    TCGv width;
     TCGv reg;
-    TCGv addr;
-    uint32_t mask;
+    TCGv tmp;
 
     op = (insn >> 8) & 7;
     ext = lduw_code(s->pc);
@@ -2656,59 +2618,76 @@ DISAS_INSN(bitfield_mem)
        gen_addr_fault(s);
        return;
     }
-    if ((ext & 0x820) == 0) {
-       /* constant offset and width */
-       offset = (ext >> 6) & 31;
-       width = (ext & 31);
-       if (width == 0)
-           width = 32;
-       reg = DREG(ext, 12);
-       mask = 0xffffffff << (32 - width);
-       addr = tcg_temp_new_i32();
-       if (offset > 7) {
-           tcg_gen_addi_i32(addr, src, offset >> 3);
-           offset &= 7;
-       } else
-           tcg_gen_mov_i32(addr, src);
-       if (offset > 0)
-           mask <<= 32 - offset;
-       gen_bitfield_load(s, addr, offset + width, &val1, &val2);
-       val = gen_bitfield_cc(s, offset, width, val1, val2);
-       switch (op) {
-       case 0: /* bftst */
-           break;
-       case 1: /* bfextu */
-           if (width < 32)
-               tcg_gen_shri_i32(reg, val, 32 - width);
-           else
-               tcg_gen_mov_i32(reg, val);
-           break;
-       case 3: /* bfexts */
-           if (width < 32)
-               tcg_gen_sari_i32(reg, val, 32 - width);
-           else
-               tcg_gen_mov_i32(reg, val);
-           break;
-       case 5: /* bfffo */
-           gen_helper_bfffo(val, val, tcg_const_i32(width));
-           tcg_gen_addi_i32(reg, val, offset);
-           break;
-       case 2: /* bfchg */
-       case 4: /* bfclr */
-       case 6: /* bfset */
-           gen_bitfield_op(offset, width, op, val1, val2);
-           gen_bitfield_store(s, addr, offset + width, val1, val2);
-           break;
-       case 7: /* bfins */
-           gen_bitfield_op(offset, width, 4, val1, val2);
-           gen_bitfield_ins(offset, width, reg, val1, val2);
-           gen_bitfield_store(s, addr, offset + width, val1, val2);
-           break;
-       }
-       return;
+
+    bitfield_param(ext, &offset, &width, &mask_cc);
+
+    /* adjust src and offset */
+
+    /* src += offset >> 3; */
+
+    tmp = tcg_temp_new_i32();
+    tcg_gen_shri_i32(tmp, offset, 3);
+    tcg_gen_add_i32(src, src, tmp);
+
+    /* offset &= 7; */
+
+    tcg_gen_andi_i32(offset, offset, 7);
+
+    /* load */
+
+    bitfield = tcg_temp_new_i64();
+    gen_helper_bitfield_load(bitfield, src, offset, width);
+
+    /* compute CC and move bitfield into a 32bit */
+
+    val = gen_bitfield_cc(s, offset, mask_cc, bitfield);
+
+    /* execute operation */
+
+    reg = DREG(ext, 12);
+    switch (op) {
+    case 0: /* bftst */
+        break;
+    case 1: /* bfextu */
+        shift = tcg_temp_new_i32();
+        tcg_gen_sub_i32(shift, tcg_const_i32(32), width);
+        tcg_gen_shr_i32(reg, val, shift);
+        break;
+    case 2: /* bfchg */
+        mask_bitfield = gen_bitfield_mask(offset, width);
+        tcg_gen_xor_i64(bitfield, bitfield, mask_bitfield);
+        gen_helper_bitfield_store(src, offset, width, bitfield);
+        break;
+    case 3: /* bfexts */
+        shift = tcg_temp_new_i32();
+        tcg_gen_sub_i32(shift, tcg_const_i32(32), width);
+        tcg_gen_sar_i32(reg, val, shift);
+        break;
+    case 4: /* bfclr */
+        mask_bitfield = gen_bitfield_mask(offset, width);
+        tcg_gen_not_i64(mask_bitfield, mask_bitfield);
+        tcg_gen_and_i64(bitfield, bitfield, mask_bitfield);
+        gen_helper_bitfield_store(src, offset, width, bitfield);
+        break;
+    case 5: /* bfffo */
+        gen_helper_bfffo(val, val, width);
+        tcg_gen_add_i32(reg, val, offset);
+        break;
+    case 6: /* bfset */
+        mask_bitfield = gen_bitfield_mask(offset, width);
+        tcg_gen_or_i64(bitfield, bitfield, mask_bitfield);
+        gen_helper_bitfield_store(src, offset, width, bitfield);
+        break;
+    case 7: /* bfins */
+        /* clear */
+        mask_bitfield = gen_bitfield_mask(offset, width);
+        tcg_gen_not_i64(mask_bitfield, mask_bitfield);
+        tcg_gen_and_i64(bitfield, bitfield, mask_bitfield);
+        /* insert */
+        gen_bitfield_ins(offset, width, reg, bitfield);
+        gen_helper_bitfield_store(src, offset, width, bitfield);
+        break;
     }
-    /* Not yet implemented */
-    gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
 }
 
 DISAS_INSN(ff1)
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 17/17] m68k: add cas
  2009-05-29 22:42                               ` [Qemu-devel] [PATCH 16/17] m68k: add variable offset/width to bitfield_reg/bitfield_mem Laurent Vivier
@ 2009-05-29 22:42                                 ` Laurent Vivier
  2009-05-30 13:53                                   ` [Qemu-devel] " Andreas Schwab
  0 siblings, 1 reply; 26+ messages in thread
From: Laurent Vivier @ 2009-05-29 22:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

This instruction is needed to execute commands like "ls" or "date"
(from a debian lenny m68k).

It define a new feaure, CAS, and attach this new instruction to it.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.h       |    3 +-
 target-m68k/helper.c    |    2 +
 target-m68k/translate.c |   62 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 66 insertions(+), 1 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 727a0b1..93956c3 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -209,7 +209,8 @@ enum m68k_features {
     M68K_FEATURE_QUAD_MULDIV,	/* 64 bit multiply/divide. */
     M68K_FEATURE_BCCL,		/* Long conditional branches.  */
     M68K_FEATURE_BITFIELD,	/* Bit field insns.  */
-    M68K_FEATURE_FPU
+    M68K_FEATURE_FPU,
+    M68K_FEATURE_CAS
 };
 
 static inline int m68k_feature(CPUM68KState *env, int feature)
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 3ae0366..67e823a 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -162,6 +162,7 @@ static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
         m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
         m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV);
         m68k_set_feature(env, M68K_FEATURE_FPU);
+        m68k_set_feature(env, M68K_FEATURE_CAS);
     case M68K_CPUID_M68000:
         m68k_set_feature(env, M68K_FEATURE_M68000);
         m68k_set_feature(env, M68K_FEATURE_USP);
@@ -207,6 +208,7 @@ static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
         m68k_set_feature(env, M68K_FEATURE_BITFIELD);
         m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV);
         m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV);
+        m68k_set_feature(env, M68K_FEATURE_CAS);
         break;
     }
 
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 4c36b6a..4372975 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1375,6 +1375,67 @@ DISAS_INSN(arith_im)
     }
 }
 
+DISAS_INSN(cas)
+{
+    int opsize;
+    TCGv dest;
+    TCGv tmp;
+    TCGv cmp;
+    TCGv update;
+    TCGv addr;
+    TCGv res;
+    uint16_t ext;
+    int l1, l2;
+
+    if ((insn & 0x3f) == 0x3c) {
+        /* CAS2: Not yet implemented */
+        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+    }
+
+    switch((insn >> 9) & 3) {
+    case 1:
+        opsize = OS_BYTE;
+        break;
+    case 2:
+        opsize = OS_WORD;
+        break;
+    case 3:
+        opsize = OS_LONG;
+        break;
+    default:
+        abort();
+    }
+
+    ext = lduw_code(s->pc);
+    s->pc += 2;
+    addr = gen_lea(s, insn, opsize);
+    if (IS_NULL_QREG(addr)) {
+        gen_addr_fault(s);
+        return;
+    }
+
+    cmp = DREG(ext, 0);
+    update = DREG(ext, 6);
+    tmp = gen_load(s, opsize, addr, 0);
+    dest = tcg_temp_local_new();
+    tcg_gen_mov_i32(dest, tmp);
+
+    res = tcg_temp_new();
+    tcg_gen_sub_i32(res, dest, cmp);
+    gen_logic_cc(s, res);
+
+    l1 = gen_new_label();
+    l2 = gen_new_label();
+
+    gen_jmpcc(s, 6 /* !Z */, l1);
+    gen_store(s, opsize, addr, update);
+    tcg_gen_br(l2);
+    gen_set_label(l1);
+    tcg_gen_mov_i32(cmp, dest);
+    gen_set_label(l2);
+    tcg_temp_free(dest);
+}
+
 DISAS_INSN(byterev)
 {
     TCGv reg;
@@ -3664,6 +3725,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(bitop_im,  0840, ffc0, M68000);
     INSN(bitop_im,  0880, ffc0, CF_ISA_A);
     INSN(bitop_im,  0880, ffc0, M68000);
+    INSN(cas,       08c0, f9c0, CAS);
     INSN(bitop_im,  08c0, ffc0, CF_ISA_A);
     INSN(bitop_im,  08c0, ffc0, M68000);
     INSN(arith_im,  0a80, fff8, CF_ISA_A);
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] Re: [PATCH 17/17] m68k: add cas
  2009-05-29 22:42                                 ` [Qemu-devel] [PATCH 17/17] m68k: add cas Laurent Vivier
@ 2009-05-30 13:53                                   ` Andreas Schwab
  2009-05-30 16:53                                     ` Laurent Vivier
  0 siblings, 1 reply; 26+ messages in thread
From: Andreas Schwab @ 2009-05-30 13:53 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: qemu-devel

Laurent Vivier <laurent@vivier.eu> writes:

> +    cmp = DREG(ext, 0);
> +    update = DREG(ext, 6);
> +    tmp = gen_load(s, opsize, addr, 0);
> +    dest = tcg_temp_local_new();
> +    tcg_gen_mov_i32(dest, tmp);
> +
> +    res = tcg_temp_new();
> +    tcg_gen_sub_i32(res, dest, cmp);
> +    gen_logic_cc(s, res);
> +
> +    l1 = gen_new_label();
> +    l2 = gen_new_label();
> +
> +    gen_jmpcc(s, 6 /* !Z */, l1);
> +    gen_store(s, opsize, addr, update);

This has a bug: addr is used around a jump.

Andreas.
---
>From b87bc72daf28f519017c79615b962c47a1e0492d Mon Sep 17 00:00:00 2001
From: Andreas Schwab <schwab@linux-m68k.org>
Date: Sat, 30 May 2009 15:32:20 +0200
Subject: [PATCH] m68k: fix use of temporary around jump

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
---
 target-m68k/translate.c |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 4372975..9d68b02 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1382,6 +1382,7 @@ DISAS_INSN(cas)
     TCGv tmp;
     TCGv cmp;
     TCGv update;
+    TCGv taddr;
     TCGv addr;
     TCGv res;
     uint16_t ext;
@@ -1408,17 +1409,19 @@ DISAS_INSN(cas)
 
     ext = lduw_code(s->pc);
     s->pc += 2;
-    addr = gen_lea(s, insn, opsize);
-    if (IS_NULL_QREG(addr)) {
+    taddr = gen_lea(s, insn, opsize);
+    if (IS_NULL_QREG(taddr)) {
         gen_addr_fault(s);
         return;
     }
 
     cmp = DREG(ext, 0);
     update = DREG(ext, 6);
-    tmp = gen_load(s, opsize, addr, 0);
+    tmp = gen_load(s, opsize, taddr, 0);
     dest = tcg_temp_local_new();
     tcg_gen_mov_i32(dest, tmp);
+    addr = tcg_temp_local_new ();
+    tcg_gen_mov_i32(addr, taddr);
 
     res = tcg_temp_new();
     tcg_gen_sub_i32(res, dest, cmp);
@@ -1434,6 +1437,7 @@ DISAS_INSN(cas)
     tcg_gen_mov_i32(cmp, dest);
     gen_set_label(l2);
     tcg_temp_free(dest);
+    tcg_temp_free(addr);
 }
 
 DISAS_INSN(byterev)
-- 
1.6.3.1


-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 17/17] m68k: add cas
  2009-05-30 13:53                                   ` [Qemu-devel] " Andreas Schwab
@ 2009-05-30 16:53                                     ` Laurent Vivier
  0 siblings, 0 replies; 26+ messages in thread
From: Laurent Vivier @ 2009-05-30 16:53 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: qemu-devel

Le samedi 30 mai 2009 à 15:53 +0200, Andreas Schwab a écrit :
> Laurent Vivier <laurent@vivier.eu> writes:
> 
> > +    cmp = DREG(ext, 0);
> > +    update = DREG(ext, 6);
> > +    tmp = gen_load(s, opsize, addr, 0);
> > +    dest = tcg_temp_local_new();
> > +    tcg_gen_mov_i32(dest, tmp);
> > +
> > +    res = tcg_temp_new();
> > +    tcg_gen_sub_i32(res, dest, cmp);
> > +    gen_logic_cc(s, res);
> > +
> > +    l1 = gen_new_label();
> > +    l2 = gen_new_label();
> > +
> > +    gen_jmpcc(s, 6 /* !Z */, l1);
> > +    gen_store(s, opsize, addr, update);
> 
> This has a bug: addr is used around a jump.
> 

I agree, thank you.
(I didn't read tcg/README correctly...)

Laurent

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support
  2009-05-29 22:41 [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support Laurent Vivier
  2009-05-29 22:41 ` [Qemu-devel] [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32() Laurent Vivier
@ 2009-05-30 17:31 ` François Revol
  2009-09-21  2:56 ` Rob Landley
  2 siblings, 0 replies; 26+ messages in thread
From: François Revol @ 2009-05-30 17:31 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: qemu-devel

> This series of patches is a port to Qemu 0.10 of Andreas Schwab M68K
> patch
> to support Motorola 680x0 CPU family.

Ohh cool, now I just need to add a real system target to test my Haiku
port :)

François.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [Qemu-devel] Re: [PATCH 07/17] m68k: add DBcc instruction.
  2009-05-29 22:41             ` [Qemu-devel] [PATCH 07/17] m68k: add DBcc instruction Laurent Vivier
  2009-05-29 22:41               ` [Qemu-devel] [PATCH 08/17] m68k: modify movem instruction to manage word Laurent Vivier
@ 2009-05-30 22:00               ` Andreas Schwab
  2009-05-30 22:05                 ` Laurent Vivier
  1 sibling, 1 reply; 26+ messages in thread
From: Andreas Schwab @ 2009-05-30 22:00 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: qemu-devel

Laurent Vivier <laurent@vivier.eu> writes:

> +    tmp = tcg_temp_new();
> +    tcg_gen_ext16s_i32(tmp, reg);
> +    tcg_gen_addi_i32(tmp, tmp, -1);
> +    gen_partset_reg(OS_WORD, reg, tmp);
> +    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);

The counter needs to be compared with -1, not 0.

Andreas.
---
>From 07f10a1b4a4aa4a54468e1106a4bbc28c5ada45e Mon Sep 17 00:00:00 2001
From: Andreas Schwab <schwab@linux-m68k.org>
Date: Sat, 30 May 2009 23:52:11 +0200
Subject: [PATCH] m68k: fix decoding of dbcc

The counter needs to be compared with -1, not 0.

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
---
 target-m68k/translate.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 9d68b02..ea6b34b 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -942,7 +942,7 @@ DISAS_INSN(dbcc)
     tcg_gen_ext16s_i32(tmp, reg);
     tcg_gen_addi_i32(tmp, tmp, -1);
     gen_partset_reg(OS_WORD, reg, tmp);
-    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
+    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, -1, l1);
     gen_jmp_tb(s, 1, base + offset);
     gen_set_label(l1);
     gen_jmp_tb(s, 0, s->pc);
-- 
1.6.3.1

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] Re: [PATCH 07/17] m68k: add DBcc instruction.
  2009-05-30 22:00               ` [Qemu-devel] Re: [PATCH 07/17] m68k: add DBcc instruction Andreas Schwab
@ 2009-05-30 22:05                 ` Laurent Vivier
  0 siblings, 0 replies; 26+ messages in thread
From: Laurent Vivier @ 2009-05-30 22:05 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: qemu-devel

Le dimanche 31 mai 2009 à 00:00 +0200, Andreas Schwab a écrit :
> Laurent Vivier <laurent@vivier.eu> writes:
> 
> > +    tmp = tcg_temp_new();
> > +    tcg_gen_ext16s_i32(tmp, reg);
> > +    tcg_gen_addi_i32(tmp, tmp, -1);
> > +    gen_partset_reg(OS_WORD, reg, tmp);
> > +    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
> 
> The counter needs to be compared with -1, not 0.

Yes, "ls -l" works better, now.

Laurent

> Andreas.
> ---
> From 07f10a1b4a4aa4a54468e1106a4bbc28c5ada45e Mon Sep 17 00:00:00 2001
> From: Andreas Schwab <schwab@linux-m68k.org>
> Date: Sat, 30 May 2009 23:52:11 +0200
> Subject: [PATCH] m68k: fix decoding of dbcc
> 
> The counter needs to be compared with -1, not 0.
> 
> Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
> ---
>  target-m68k/translate.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
> index 9d68b02..ea6b34b 100644
> --- a/target-m68k/translate.c
> +++ b/target-m68k/translate.c
> @@ -942,7 +942,7 @@ DISAS_INSN(dbcc)
>      tcg_gen_ext16s_i32(tmp, reg);
>      tcg_gen_addi_i32(tmp, tmp, -1);
>      gen_partset_reg(OS_WORD, reg, tmp);
> -    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
> +    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, -1, l1);
>      gen_jmp_tb(s, 1, base + offset);
>      gen_set_label(l1);
>      gen_jmp_tb(s, 0, s->pc);
> -- 
> 1.6.3.1
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions.
  2009-05-29 22:41       ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Laurent Vivier
  2009-05-29 22:41         ` [Qemu-devel] [PATCH 05/17] m68k: add Motorola 680x0 family common instructions Laurent Vivier
@ 2009-05-31  2:06         ` Stuart Brady
  2009-05-31  9:03           ` Laurent Vivier
  1 sibling, 1 reply; 26+ messages in thread
From: Stuart Brady @ 2009-05-31  2:06 UTC (permalink / raw)
  To: qemu-devel

I just happened to notice these:

On Sat, May 30, 2009 at 12:41:48AM +0200, Laurent Vivier wrote:
> +/* Read a 8-bit immediat constant */

Should be:
   /* Read an 8-bit immediate constant */
            ^               ^

> +/* Read a 16-bit immediat constant */

Should be:
   /* Read a 16-bit immediate constant */
                            ^

If I knew more about the M68K, perhaps I'd be of more help... :/

Cheers,
-- 
Stuart Brady

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions.
  2009-05-31  2:06         ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Stuart Brady
@ 2009-05-31  9:03           ` Laurent Vivier
  0 siblings, 0 replies; 26+ messages in thread
From: Laurent Vivier @ 2009-05-31  9:03 UTC (permalink / raw)
  To: Stuart Brady; +Cc: qemu-devel

Le dimanche 31 mai 2009 à 03:06 +0100, Stuart Brady a écrit :
> I just happened to notice these:
> 
> On Sat, May 30, 2009 at 12:41:48AM +0200, Laurent Vivier wrote:
> > +/* Read a 8-bit immediat constant */
> 
> Should be:
>    /* Read an 8-bit immediate constant */
>             ^               ^
> 
> > +/* Read a 16-bit immediat constant */
> 
> Should be:
>    /* Read a 16-bit immediate constant */
>                             ^
> 
> If I knew more about the M68K, perhaps I'd be of more help... :/

Corrected, thank you.

Regards,
Laurent

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support
  2009-05-29 22:41 [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support Laurent Vivier
  2009-05-29 22:41 ` [Qemu-devel] [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32() Laurent Vivier
  2009-05-30 17:31 ` [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support François Revol
@ 2009-09-21  2:56 ` Rob Landley
  2 siblings, 0 replies; 26+ messages in thread
From: Rob Landley @ 2009-09-21  2:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: Till Straumann, Charles Stevens, schwab, Laurent Vivier

On Friday 29 May 2009 17:41:44 Laurent Vivier wrote:
> This series of patches is a port to Qemu 0.10 of Andreas Schwab M68K patch
> to support Motorola 680x0 CPU family.
>
> It has been tested with some commands from a debian m68k lenny disk.

Has there been any progress on this?  (Or current versions I can test?)

I have a cross compiler, root filesystem, and kernel built for m68k, but no 
test environment.  Charles Stevens got a system image running under aranym, 
but that has several limitations (such as no serial I/O, which makes a serial 
console problematic), and I'm testing all my other targets on qemu.

All the current system images are coldfire, which I haven't played with because 
I haven't done any nommu targets yet.  Presumably I could shoehorn a real m68k 
into a coldfire system emulation, assuming I could beat a relevant .config out 
of the kernel...

Rob
-- 
Latency is more important than throughput. It's that simple. - Linus Torvalds

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2009-09-21  2:56 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-29 22:41 [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support Laurent Vivier
2009-05-29 22:41 ` [Qemu-devel] [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32() Laurent Vivier
2009-05-29 22:41   ` [Qemu-devel] [PATCH 02/17] m68k: add tcg_gen_debug_insn_start() Laurent Vivier
2009-05-29 22:41     ` [Qemu-devel] [PATCH 03/17] m68k: define m680x0 CPUs and features Laurent Vivier
2009-05-29 22:41       ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Laurent Vivier
2009-05-29 22:41         ` [Qemu-devel] [PATCH 05/17] m68k: add Motorola 680x0 family common instructions Laurent Vivier
2009-05-29 22:41           ` [Qemu-devel] [PATCH 06/17] m68k: add Scc instruction with memory operand Laurent Vivier
2009-05-29 22:41             ` [Qemu-devel] [PATCH 07/17] m68k: add DBcc instruction Laurent Vivier
2009-05-29 22:41               ` [Qemu-devel] [PATCH 08/17] m68k: modify movem instruction to manage word Laurent Vivier
2009-05-29 22:41                 ` [Qemu-devel] [PATCH 09/17] m68k: add 64bit divide Laurent Vivier
2009-05-29 22:41                   ` [Qemu-devel] [PATCH 10/17] m68k: add 32bit and 64bit multiply Laurent Vivier
2009-05-29 22:41                     ` [Qemu-devel] [PATCH 11/17] m68k: add word data size for suba/adda Laurent Vivier
2009-05-29 22:41                       ` [Qemu-devel] [PATCH 12/17] m68k: add fpu Laurent Vivier
2009-05-29 22:41                         ` [Qemu-devel] [PATCH 13/17] m68k: add "byte", "word" and memory shift Laurent Vivier
2009-05-29 22:41                           ` [Qemu-devel] [PATCH 14/17] m68k: add "byte", "word" and memory rotate Laurent Vivier
2009-05-29 22:41                             ` [Qemu-devel] [PATCH 15/17] m68k: add bitfield_mem, bitfield_reg Laurent Vivier
2009-05-29 22:42                               ` [Qemu-devel] [PATCH 16/17] m68k: add variable offset/width to bitfield_reg/bitfield_mem Laurent Vivier
2009-05-29 22:42                                 ` [Qemu-devel] [PATCH 17/17] m68k: add cas Laurent Vivier
2009-05-30 13:53                                   ` [Qemu-devel] " Andreas Schwab
2009-05-30 16:53                                     ` Laurent Vivier
2009-05-30 22:00               ` [Qemu-devel] Re: [PATCH 07/17] m68k: add DBcc instruction Andreas Schwab
2009-05-30 22:05                 ` Laurent Vivier
2009-05-31  2:06         ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Stuart Brady
2009-05-31  9:03           ` Laurent Vivier
2009-05-30 17:31 ` [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support François Revol
2009-09-21  2:56 ` Rob Landley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).