All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
@ 2016-05-04 20:11 Laurent Vivier
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 01/52] target-m68k: fix DEBUG_DISPATCH Laurent Vivier
                   ` (35 more replies)
  0 siblings, 36 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

This series is an update of the series I sent last year:

https://lists.nongnu.org/archive/html/qemu-devel/2015-08/msg01049.html

Based on the series sent by Richard Henderson:

https://lists.nongnu.org/archive/html/qemu-devel/2015-08/msg01793.html

It is in fact a major rewrite. Most of the instructions are now inlined.

This series doesn't break Coldfire support. I've checked the following
image can always boot:

http://wiki.qemu.org/download/coldfire-test-0.1.tar.bz2

Only non-privileged instruction are implemented.
680x0 FPU instructions are not implemented.

So this is not enough to run 680x0 binaries. I will send a new series
with FPU emulation once this series is merged.

Andreas Schwab (1):
  target-m68k: terminate cpu dump with newline

John Paul Adrian Glaubitz (1):
  target-m68k: Build the opcode table only once to avoid multithreading
    issues

Laurent Vivier (39):
  target-m68k: fix DEBUG_DISPATCH
  target-m68k: define m680x0 CPUs and features
  target-m68k: manage scaled index
  target-m68k: introduce read_imXX() functions
  target-m68k: set disassembler mode to 680x0 or coldfire
  target-m68k: add bkpt instruction
  target-m68k: define operand sizes
  target-m68k: set PAGE_BITS to 12 for m68k
  target-m68k: REG() macro cleanup
  target-m68k: allow to update flags with operation on words and bytes
  target-m68k: update CPU flags management
  target-m68k: update move to/from ccr/sr
  target-m68k: don't update cc_dest in helpers
  target-m68k: update CPU flags management
  target-m68k: add addx/subx/negx ops
  target-m68k: factorize flags computing
  target-m68k: add scc/dbcc
  target-m68k: some bit ops cleanup
  target-m68k: bitfield ops
  target-m68k: inline divu/divs
  target-m68k: add 64bit mull
  target-m68k: inline rotate ops
  target-m68k: inline shift ops
  target-m68k: add cas/cas2 ops
  target-m68k: add linkl
  target-m68k: movem
  target-m68k: add exg ops
  target-m68k: add addressing modes to not
  target-m68k: eor can manage word and byte operands
  target-m68k: or can manage word and byte operands
  target-m68k: and can manage word and byte operands
  target-m68k: suba/adda can manage word operand
  target-m68k: introduce byte and word cc_ops
  target-m68k: add addressing modes to neg
  target-m68k: add/sub manage word and byte operands
  target-m68k: cmp manages word and bytes operands
  target-m68k: immediate ops manage word and byte operands
  target-m68k: add cmpm
  target-m68k: sr/ccr cleanup

Richard Henderson (11):
  target-m68k: Replace helper_xflag_lt with setcond
  target-m68k: Print flags properly
  target-m68k: Some fixes to SR and flags management
  target-m68k: Remove incorrect clearing of cc_x
  target-m68k: Reorg flags handling
  target-m68k: Introduce DisasCompare
  target-m68k: Use setcond for scc
  target-m68k: Optimize some comparisons
  target-m68k: Optimize gen_flush_flags
  target-m68k: Inline shifts
  target-m68k: Inline addx, subx, negx

 cpu-exec.c              |    6 -
 linux-user/main.c       |  200 +++
 target-m68k/cpu-qom.h   |    4 -
 target-m68k/cpu.c       |   65 +-
 target-m68k/cpu.h       |   83 +-
 target-m68k/helper.c    |  335 ++---
 target-m68k/helper.h    |   16 +-
 target-m68k/op_helper.c |  112 +-
 target-m68k/qregs.def   |   13 +-
 target-m68k/translate.c | 3316 +++++++++++++++++++++++++++++++++++++----------
 10 files changed, 3164 insertions(+), 986 deletions(-)

-- 
2.5.5

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

* [Qemu-devel] [PATCH 01/52] target-m68k: fix DEBUG_DISPATCH
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:34   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 02/52] target-m68k: Build the opcode table only once to avoid multithreading issues Laurent Vivier
                   ` (34 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 7560c3a..301f687 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -168,7 +168,7 @@ typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t insn);
                              uint16_t insn)                             \
     {                                                                   \
         qemu_log("Dispatch " #name "\n");                               \
-        real_disas_##name(s, env, insn);                                \
+        real_disas_##name(env, s, insn);                                \
     }                                                                   \
     static void real_disas_##name(CPUM68KState *env, DisasContext *s,   \
                                   uint16_t insn)
-- 
2.5.5

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

* [Qemu-devel] [PATCH 02/52] target-m68k: Build the opcode table only once to avoid multithreading issues
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 01/52] target-m68k: fix DEBUG_DISPATCH Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:35   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 03/52] target-m68k: define m680x0 CPUs and features Laurent Vivier
                   ` (33 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: gerg, schwab, agraf, rth, John Paul Adrian Glaubitz, Laurent Vivier

From: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>

Signed-off-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 301f687..e14e0fd 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2833,6 +2833,11 @@ register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
    Later insn override earlier ones.  */
 void register_m68k_insns (CPUM68KState *env)
 {
+    /* Build the opcode table only once to avoid
+       multithreading issues. */
+    if (opcode_table[0] != NULL) {
+        return;
+    }
 #define INSN(name, opcode, mask, feature) do { \
     if (m68k_feature(env, M68K_FEATURE_##feature)) \
         register_opcode(disas_##name, 0x##opcode, 0x##mask); \
-- 
2.5.5

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

* [Qemu-devel] [PATCH 03/52] target-m68k: define m680x0 CPUs and features
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 01/52] target-m68k: fix DEBUG_DISPATCH Laurent Vivier
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 02/52] target-m68k: Build the opcode table only once to avoid multithreading issues Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:35   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 04/52] target-m68k: manage scaled index Laurent Vivier
                   ` (32 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

This patch defines seven 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
    - M68K_FEATURE_CAS, cas instruction

Original patch from Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.c       |  54 ++++++++++++++++++++++
 target-m68k/cpu.h       |  10 +++-
 target-m68k/translate.c | 120 ++++++++++++++++++++++++++++++------------------
 3 files changed, 139 insertions(+), 45 deletions(-)

diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 0b5f9a5..6857dc4 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -97,6 +97,55 @@ static void m5206_cpu_initfn(Object *obj)
     m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
 }
 
+static void m68000_cpu_initfn(Object *obj)
+{
+    M68kCPU *cpu = M68K_CPU(obj);
+    CPUM68KState *env = &cpu->env;
+
+    m68k_set_feature(env, M68K_FEATURE_M68000);
+    m68k_set_feature(env, M68K_FEATURE_USP);
+    m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+}
+
+static void m68020_cpu_initfn(Object *obj)
+{
+    M68kCPU *cpu = M68K_CPU(obj);
+    CPUM68KState *env = &cpu->env;
+
+    m68k_set_feature(env, M68K_FEATURE_M68000);
+    m68k_set_feature(env, M68K_FEATURE_USP);
+    m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+    m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV);
+    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);
+    m68k_set_feature(env, M68K_FEATURE_CAS);
+}
+#define m68030_cpu_initfn m68020_cpu_initfn
+#define m68040_cpu_initfn m68020_cpu_initfn
+
+static void m68060_cpu_initfn(Object *obj)
+{
+    M68kCPU *cpu = M68K_CPU(obj);
+    CPUM68KState *env = &cpu->env;
+
+    m68k_set_feature(env, M68K_FEATURE_M68000);
+    m68k_set_feature(env, M68K_FEATURE_USP);
+    m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+    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);
+    m68k_set_feature(env, M68K_FEATURE_CAS);
+}
+
 static void m5208_cpu_initfn(Object *obj)
 {
     M68kCPU *cpu = M68K_CPU(obj);
@@ -147,6 +196,11 @@ typedef struct M68kCPUInfo {
 } M68kCPUInfo;
 
 static const M68kCPUInfo m68k_cpus[] = {
+    { .name = "m68000", .instance_init = m68000_cpu_initfn },
+    { .name = "m68020", .instance_init = m68020_cpu_initfn },
+    { .name = "m68030", .instance_init = m68030_cpu_initfn },
+    { .name = "m68040", .instance_init = m68040_cpu_initfn },
+    { .name = "m68060", .instance_init = m68060_cpu_initfn },
     { .name = "m5206", .instance_init = m5206_cpu_initfn },
     { .name = "m5208", .instance_init = m5208_cpu_initfn },
     { .name = "cfv4e", .instance_init = cfv4e_cpu_initfn },
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 48b4c87..2b79f26 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -176,6 +176,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).  */
@@ -186,7 +187,14 @@ 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,
+    M68K_FEATURE_CAS
 };
 
 static inline int m68k_feature(CPUM68KState *env, int feature)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index e14e0fd..c08f35d 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2838,90 +2838,118 @@ void register_m68k_insns (CPUM68KState *env)
     if (opcode_table[0] != NULL) {
         return;
     }
+
+    /* use BASE() for instruction available
+     * for CF_ISA_A and M68000.
+     */
+#define BASE(name, opcode, mask) \
+    register_opcode(disas_##name, 0x##opcode, 0x##mask)
 #define INSN(name, opcode, mask, feature) do { \
     if (m68k_feature(env, M68K_FEATURE_##feature)) \
-        register_opcode(disas_##name, 0x##opcode, 0x##mask); \
+        BASE(name, opcode, mask); \
     } while(0)
-    INSN(undef,     0000, 0000, CF_ISA_A);
+    BASE(undef,     0000, 0000);
     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, 0140, f1c0, CF_ISA_A);
-    INSN(bitop_reg, 0180, f1c0, CF_ISA_A);
-    INSN(bitop_reg, 01c0, f1c0, CF_ISA_A);
+    BASE(bitop_reg, 0100, f1c0);
+    BASE(bitop_reg, 0140, f1c0);
+    BASE(bitop_reg, 0180, f1c0);
+    BASE(bitop_reg, 01c0, f1c0);
     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,  0840, ffc0, CF_ISA_A);
-    INSN(bitop_im,  0880, ffc0, CF_ISA_A);
-    INSN(bitop_im,  08c0, ffc0, CF_ISA_A);
-    INSN(arith_im,  0a80, fff8, CF_ISA_A);
     INSN(arith_im,  0c00, ff38, CF_ISA_A);
-    INSN(move,      1000, f000, CF_ISA_A);
-    INSN(move,      2000, f000, CF_ISA_A);
-    INSN(move,      3000, f000, CF_ISA_A);
+    INSN(arith_im,  0c00, ff00, M68000);
+    BASE(bitop_im,  0800, ffc0);
+    BASE(bitop_im,  0840, ffc0);
+    BASE(bitop_im,  0880, ffc0);
+    BASE(bitop_im,  08c0, ffc0);
+    INSN(arith_im,  0a80, fff8, CF_ISA_A);
+    INSN(arith_im,  0a00, ff00, M68000);
+    BASE(move,      1000, f000);
+    BASE(move,      2000, f000);
+    BASE(move,      3000, f000);
     INSN(strldsr,   40e7, ffff, CF_ISA_APLUSC);
     INSN(negx,      4080, fff8, CF_ISA_A);
     INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
-    INSN(lea,       41c0, f1c0, CF_ISA_A);
-    INSN(clr,       4200, ff00, CF_ISA_A);
-    INSN(undef,     42c0, ffc0, CF_ISA_A);
+    INSN(move_from_sr, 40c0, ffc0, M68000);
+    BASE(lea,       41c0, f1c0);
+    BASE(clr,       4200, ff00);
+    BASE(undef,     42c0, ffc0);
     INSN(move_from_ccr, 42c0, fff8, CF_ISA_A);
     INSN(neg,       4480, fff8, CF_ISA_A);
-    INSN(move_to_ccr, 44c0, ffc0, CF_ISA_A);
+    INSN(neg,       4400, ff00, M68000);
+    INSN(undef,     44c0, ffc0, M68000);
+    BASE(move_to_ccr, 44c0, ffc0);
     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(swap,      4840, fff8, CF_ISA_A);
-    INSN(movem,     48c0, fbc0, CF_ISA_A);
-    INSN(ext,       4880, fff8, CF_ISA_A);
-    INSN(ext,       48c0, fff8, CF_ISA_A);
-    INSN(ext,       49c0, fff8, CF_ISA_A);
-    INSN(tst,       4a00, ff00, CF_ISA_A);
+    BASE(pea,       4840, ffc0);
+    BASE(swap,      4840, fff8);
+    BASE(movem,     48c0, fbc0);
+    BASE(ext,       4880, fff8);
+    BASE(ext,       48c0, fff8);
+    BASE(ext,       49c0, fff8);
+    BASE(tst,       4a00, ff00);
     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);
+    BASE(illegal,   4afc, ffff);
     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);
-    INSN(trap,      4e40, fff0, CF_ISA_A);
-    INSN(link,      4e50, fff8, CF_ISA_A);
-    INSN(unlk,      4e58, fff8, CF_ISA_A);
+    BASE(trap,      4e40, fff0);
+    BASE(link,      4e50, fff8);
+    BASE(unlk,      4e58, fff8);
     INSN(move_to_usp, 4e60, fff8, USP);
     INSN(move_from_usp, 4e68, fff8, USP);
-    INSN(nop,       4e71, ffff, CF_ISA_A);
-    INSN(stop,      4e72, ffff, CF_ISA_A);
-    INSN(rte,       4e73, ffff, CF_ISA_A);
-    INSN(rts,       4e75, ffff, CF_ISA_A);
+    BASE(nop,       4e71, ffff);
+    BASE(stop,      4e72, ffff);
+    BASE(rte,       4e73, ffff);
+    BASE(rts,       4e75, ffff);
     INSN(movec,     4e7b, ffff, CF_ISA_A);
-    INSN(jump,      4e80, ffc0, CF_ISA_A);
+    BASE(jump,      4e80, ffc0);
     INSN(jump,      4ec0, ffc0, CF_ISA_A);
     INSN(addsubq,   5180, f1c0, CF_ISA_A);
+    INSN(jump,      4ec0, ffc0, M68000);
+    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(tpf,       51f8, fff8, CF_ISA_A);
 
     /* Branch instructions.  */
-    INSN(branch,    6000, f000, CF_ISA_A);
+    BASE(branch,    6000, f000);
     /* Disable long branch instructions, then add back the ones we want.  */
-    INSN(undef,     60ff, f0ff, CF_ISA_A); /* All long branches.  */
+    BASE(undef,     60ff, f0ff); /* 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);
+    BASE(moveq,     7000, f100);
     INSN(mvzs,      7100, f100, CF_ISA_B);
-    INSN(or,        8000, f000, CF_ISA_A);
-    INSN(divw,      80c0, f0c0, CF_ISA_A);
-    INSN(addsub,    9000, f000, CF_ISA_A);
+    BASE(or,        8000, f000);
+    BASE(divw,      80c0, f0c0);
+    BASE(addsub,    9000, f000);
     INSN(subx,      9180, f1f8, CF_ISA_A);
     INSN(suba,      91c0, f1c0, CF_ISA_A);
 
-    INSN(undef_mac, a000, f000, CF_ISA_A);
+    BASE(undef_mac, a000, f000);
     INSN(mac,       a000, f100, CF_EMAC);
     INSN(from_mac,  a180, f9b0, CF_EMAC);
     INSN(move_mac,  a110, f9fc, CF_EMAC);
@@ -2940,12 +2968,16 @@ 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(eor,       b100, f100, M68000);
+    INSN(cmpa,      b0c0, f0c0, M68000);
     INSN(eor,       b180, f1c0, CF_ISA_A);
-    INSN(and,       c000, f000, CF_ISA_A);
-    INSN(mulw,      c0c0, f0c0, CF_ISA_A);
-    INSN(addsub,    d000, f000, CF_ISA_A);
+    BASE(and,       c000, f000);
+    BASE(mulw,      c0c0, f0c0);
+    BASE(addsub,    d000, f000);
     INSN(addx,      d180, f1f8, CF_ISA_A);
     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(undef_fpu, f000, f000, CF_ISA_A);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 04/52] target-m68k: manage scaled index
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (2 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 03/52] target-m68k: define m680x0 CPUs and features Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:36   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 05/52] target-m68k: introduce read_imXX() functions Laurent Vivier
                   ` (31 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Scaled index is not supported by 68000, 68008, and 68010.

    EA = (bd + PC) + Xn.SIZE*SCALE + od

Ignore it:

M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL
2.4 BRIEF EXTENSION WORD FORMAT COMPATIBILITY

"If the MC68000 were to execute an instruction that
 encoded a scaling factor, the scaling factor would be
 ignored and would not access the desired memory address.
 The earlier microprocessors do not recognize the brief
 extension word formats implemented by newer processors.
 Although they can detect illegal instructions, they do not
 decode invalid encodings of the brief extension word formats
 as exceptions."

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index c08f35d..a8830a8 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -313,6 +313,11 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
     if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
         return NULL_QREG;
 
+    if (m68k_feature(s->env, M68K_FEATURE_M68000) &&
+        !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))
-- 
2.5.5

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

* [Qemu-devel] [PATCH 05/52] target-m68k: introduce read_imXX() functions
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (3 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 04/52] target-m68k: manage scaled index Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:36   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 06/52] target-m68k: set disassembler mode to 680x0 or coldfire Laurent Vivier
                   ` (30 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Read a 8, 16 or 32bit immediat constant.

An immediate constant is stored in the instruction opcode and
can be in one or two extension words.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 91 ++++++++++++++++++++++---------------------------
 1 file changed, 41 insertions(+), 50 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index a8830a8..bad07a5 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -266,14 +266,27 @@ static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
     }
 }
 
+/* Read a 16-bit immediate constant */
+static inline uint16_t read_im16(CPUM68KState *env, DisasContext *s)
+{
+    uint16_t im;
+    im = cpu_lduw_code(env, s->pc);
+    s->pc += 2;
+    return im;
+}
+
+/* Read an 8-bit immediate constant */
+static inline uint8_t read_im8(CPUM68KState *env, DisasContext *s)
+{
+    return read_im16(env, s);
+}
+
 /* Read a 32-bit immediate constant.  */
 static inline uint32_t read_im32(CPUM68KState *env, DisasContext *s)
 {
     uint32_t im;
-    im = ((uint32_t)cpu_lduw_code(env, s->pc)) << 16;
-    s->pc += 2;
-    im |= cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    im = read_im16(env, s) << 16;
+    im |= 0xffff & read_im16(env, s);
     return im;
 }
 
@@ -307,8 +320,7 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
     uint32_t bd, od;
 
     offset = s->pc;
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
 
     if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
         return NULL_QREG;
@@ -326,8 +338,7 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
         if ((ext & 0x30) > 0x10) {
             /* base displacement */
             if ((ext & 0x30) == 0x20) {
-                bd = (int16_t)cpu_lduw_code(env, s->pc);
-                s->pc += 2;
+                bd = (int16_t)read_im16(env, s);
             } else {
                 bd = read_im32(env, s);
             }
@@ -375,8 +386,7 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
             if ((ext & 3) > 1) {
                 /* outer displacement */
                 if ((ext & 3) == 2) {
-                    od = (int16_t)cpu_lduw_code(env, s->pc);
-                    s->pc += 2;
+                    od = (int16_t)read_im16(env, s);
                 } else {
                     od = read_im32(env, s);
                 }
@@ -528,8 +538,7 @@ static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
     case 5: /* Indirect displacement.  */
         reg = AREG(insn, 0);
         tmp = tcg_temp_new();
-        ext = cpu_lduw_code(env, s->pc);
-        s->pc += 2;
+        ext = read_im16(env, s);
         tcg_gen_addi_i32(tmp, reg, (int16_t)ext);
         return tmp;
     case 6: /* Indirect index + displacement.  */
@@ -538,16 +547,14 @@ static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
     case 7: /* Other */
         switch (insn & 7) {
         case 0: /* Absolute short.  */
-            offset = cpu_ldsw_code(env, s->pc);
-            s->pc += 2;
+            offset = (int16_t)read_im16(env, s);
             return tcg_const_i32(offset);
         case 1: /* Absolute long.  */
             offset = read_im32(env, s);
             return tcg_const_i32(offset);
         case 2: /* pc displacement  */
             offset = s->pc;
-            offset += cpu_ldsw_code(env, s->pc);
-            s->pc += 2;
+            offset += (int16_t)read_im16(env, s);
             return tcg_const_i32(offset);
         case 3: /* pc index+displacement.  */
             return gen_lea_indexed(env, s, NULL_QREG);
@@ -654,19 +661,17 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
             switch (opsize) {
             case OS_BYTE:
                 if (what == EA_LOADS) {
-                    offset = cpu_ldsb_code(env, s->pc + 1);
+                    offset = (int8_t)read_im8(env, s);
                 } else {
-                    offset = cpu_ldub_code(env, s->pc + 1);
+                    offset = read_im8(env, s);
                 }
-                s->pc += 2;
                 break;
             case OS_WORD:
                 if (what == EA_LOADS) {
-                    offset = cpu_ldsw_code(env, s->pc);
+                    offset = (int16_t)read_im16(env, s);
                 } else {
-                    offset = cpu_lduw_code(env, s->pc);
+                    offset = read_im16(env, s);
                 }
-                s->pc += 2;
                 break;
             case OS_LONG:
                 offset = read_im32(env, s);
@@ -953,8 +958,7 @@ DISAS_INSN(divl)
     TCGv reg;
     uint16_t ext;
 
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
     if (ext & 0x87f8) {
         gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
         return;
@@ -1105,8 +1109,7 @@ DISAS_INSN(movem)
     TCGv tmp;
     int is_load;
 
-    mask = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    mask = read_im16(env, s);
     tmp = gen_lea(env, s, insn, OS_LONG);
     if (IS_NULL_QREG(tmp)) {
         gen_addr_fault(s);
@@ -1149,8 +1152,7 @@ DISAS_INSN(bitop_im)
         opsize = OS_LONG;
     op = (insn >> 6) & 3;
 
-    bitnum = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    bitnum = read_im16(env, s);
     if (bitnum & 0xff00) {
         disas_undef(env, s, insn);
         return;
@@ -1403,8 +1405,7 @@ static void gen_set_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
     else if ((insn & 0x3f) == 0x3c)
       {
         uint16_t val;
-        val = cpu_lduw_code(env, s->pc);
-        s->pc += 2;
+        val = read_im16(env, s);
         gen_set_sr_im(s, val, ccr_only);
       }
     else
@@ -1527,8 +1528,7 @@ DISAS_INSN(mull)
 
     /* The upper 32 bits of the product are discarded, so
        muls.l and mulu.l are functionally equivalent.  */
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
     if (ext & 0x87ff) {
         gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
         return;
@@ -1669,8 +1669,7 @@ DISAS_INSN(branch)
     op = (insn >> 8) & 0xf;
     offset = (int8_t)insn;
     if (offset == 0) {
-        offset = cpu_ldsw_code(env, s->pc);
-        s->pc += 2;
+        offset = (int16_t)read_im16(env, s);
     } else if (offset == -1) {
         offset = read_im32(env, s);
     }
@@ -1954,14 +1953,12 @@ DISAS_INSN(strldsr)
     uint32_t addr;
 
     addr = s->pc - 2;
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
     if (ext != 0x46FC) {
         gen_exception(s, addr, EXCP_UNSUPPORTED);
         return;
     }
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
     if (IS_USER(s) || (ext & SR_S) == 0) {
         gen_exception(s, addr, EXCP_PRIVILEGE);
         return;
@@ -2028,8 +2025,7 @@ DISAS_INSN(stop)
         return;
     }
 
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
 
     gen_set_sr_im(s, ext, 0);
     tcg_gen_movi_i32(cpu_halted, 1);
@@ -2055,8 +2051,7 @@ DISAS_INSN(movec)
         return;
     }
 
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
 
     if (ext & 0x8000) {
         reg = AREG(ext, 12);
@@ -2122,8 +2117,7 @@ DISAS_INSN(fpu)
     int set_dest;
     int opsize;
 
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
     opmode = ext & 0x7f;
     switch ((ext >> 13) & 7) {
     case 0: case 2:
@@ -2405,8 +2399,7 @@ DISAS_INSN(fbcc)
     offset = cpu_ldsw_code(env, s->pc);
     s->pc += 2;
     if (insn & (1 << 6)) {
-        offset = (offset << 16) | cpu_lduw_code(env, s->pc);
-        s->pc += 2;
+        offset = (offset << 16) | read_im16(env, s);
     }
 
     l1 = gen_new_label();
@@ -2531,8 +2524,7 @@ DISAS_INSN(mac)
         s->done_mac = 1;
     }
 
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
 
     acc = ((insn >> 7) & 1) | ((ext >> 3) & 2);
     dual = ((insn & 0x30) != 0 && (ext & 3) != 0);
@@ -3003,8 +2995,7 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
 {
     uint16_t insn;
 
-    insn = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    insn = read_im16(env, s);
 
     opcode_table[insn](env, s, insn);
 }
-- 
2.5.5

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

* [Qemu-devel] [PATCH 06/52] target-m68k: set disassembler mode to 680x0 or coldfire
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (4 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 05/52] target-m68k: introduce read_imXX() functions Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:37   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 07/52] target-m68k: add bkpt instruction Laurent Vivier
                   ` (29 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 6857dc4..baca4f8 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -63,9 +63,14 @@ static void m68k_cpu_reset(CPUState *s)
     tlb_flush(s, 1);
 }
 
-static void m68k_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
+static void m68k_cpu_disas_set_info(CPUState *s, disassemble_info *info)
 {
+    M68kCPU *cpu = M68K_CPU(s);
+    CPUM68KState *env = &cpu->env;
     info->print_insn = print_insn_m68k;
+    if (m68k_feature(env, M68K_FEATURE_M68000)) {
+        info->mach = bfd_mach_m68040;
+    }
 }
 
 /* CPU models */
-- 
2.5.5

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

* [Qemu-devel] [PATCH 07/52] target-m68k: add bkpt instruction
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (5 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 06/52] target-m68k: set disassembler mode to 680x0 or coldfire Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:42   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 08/52] target-m68k: define operand sizes Laurent Vivier
                   ` (28 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index bad07a5..e2555f6 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1441,6 +1441,11 @@ DISAS_INSN(swap)
     gen_logic_cc(s, reg);
 }
 
+DISAS_INSN(bkpt)
+{
+    gen_exception(s, s->pc - 2, EXCP_DEBUG);
+}
+
 DISAS_INSN(pea)
 {
     TCGv tmp;
@@ -2894,6 +2899,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
     BASE(pea,       4840, ffc0);
     BASE(swap,      4840, fff8);
+    INSN(bkpt,      4848, fff8, M68000);
     BASE(movem,     48c0, fbc0);
     BASE(ext,       4880, fff8);
     BASE(ext,       48c0, fff8);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 08/52] target-m68k: define operand sizes
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (6 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 07/52] target-m68k: add bkpt instruction Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:43   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 09/52] target-m68k: set PAGE_BITS to 12 for m68k Laurent Vivier
                   ` (27 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.h       |  8 ++++++++
 target-m68k/translate.c | 46 ++++++++++++++--------------------------------
 2 files changed, 22 insertions(+), 32 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 2b79f26..e788684 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -29,6 +29,14 @@
 
 #include "fpu/softfloat.h"
 
+#define OS_BYTE     0
+#define OS_WORD     1
+#define OS_LONG     2
+#define OS_SINGLE   3
+#define OS_DOUBLE   4
+#define OS_EXTENDED 5
+#define OS_PACKED   6
+
 #define MAX_QREGS 32
 
 #define EXCP_ACCESS         2   /* Access (MMU) error.  */
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index e2555f6..0da0dff 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -152,12 +152,6 @@ typedef struct DisasContext {
 static void *gen_throws_exception;
 #define gen_last_qop NULL
 
-#define OS_BYTE 0
-#define OS_WORD 1
-#define OS_LONG 2
-#define OS_SINGLE 4
-#define OS_DOUBLE 5
-
 typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t insn);
 
 #ifdef DEBUG_DISPATCH
@@ -451,11 +445,23 @@ static inline int opsize_bytes(int opsize)
     case OS_LONG: return 4;
     case OS_SINGLE: return 4;
     case OS_DOUBLE: return 8;
+    case OS_EXTENDED: return 12;
+    case OS_PACKED: return 12;
     default:
         g_assert_not_reached();
     }
 }
 
+static inline int insn_opsize(int insn)
+{
+    switch ((insn >> 6) & 3) {
+    case 0: return OS_BYTE;
+    case 1: return OS_WORD;
+    case 2: return OS_LONG;
+    default: g_assert_not_reached(); 
+    }
+}
+
 /* 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)
@@ -1322,19 +1328,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);
     DEST_EA(env, insn, opsize, tcg_const_i32(0), NULL);
     gen_logic_cc(s, tcg_const_i32(0));
 }
@@ -1483,19 +1477,7 @@ 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();
-    }
+    opsize = insn_opsize(insn);
     SRC_EA(env, tmp, opsize, 1, NULL);
     gen_logic_cc(s, tmp);
 }
-- 
2.5.5

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

* [Qemu-devel] [PATCH 09/52] target-m68k: set PAGE_BITS to 12 for m68k
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (7 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 08/52] target-m68k: define operand sizes Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:44   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 10/52] target-m68k: REG() macro cleanup Laurent Vivier
                   ` (26 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.h | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index e788684..de902fd 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -215,8 +215,11 @@ void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 void register_m68k_insns (CPUM68KState *env);
 
 #ifdef CONFIG_USER_ONLY
-/* Linux uses 8k pages.  */
-#define TARGET_PAGE_BITS 13
+/* Coldfire Linux uses 8k pages
+ * and m68k linux uses 4k pages
+ * use the smaller one
+ */
+#define TARGET_PAGE_BITS 12
 #else
 /* Smallest TLB entry size is 1k.  */
 #define TARGET_PAGE_BITS 10
-- 
2.5.5

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

* [Qemu-devel] [PATCH 10/52] target-m68k: REG() macro cleanup
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (8 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 09/52] target-m68k: set PAGE_BITS to 12 for m68k Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:44   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 11/52] target-m68k: allow to update flags with operation on words and bytes Laurent Vivier
                   ` (25 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 0da0dff..3ad3613 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -58,9 +58,10 @@ static TCGv cpu_aregs[8];
 static TCGv_i64 cpu_fregs[8];
 static TCGv_i64 cpu_macc[4];
 
-#define DREG(insn, pos) cpu_dregs[((insn) >> (pos)) & 7]
-#define AREG(insn, pos) cpu_aregs[((insn) >> (pos)) & 7]
-#define FREG(insn, pos) cpu_fregs[((insn) >> (pos)) & 7]
+#define REG(insn, pos) (((insn) >> (pos)) & 7)
+#define DREG(insn, pos) cpu_dregs[REG(insn, pos)]
+#define AREG(insn, pos) cpu_aregs[REG(insn, pos)]
+#define FREG(insn, pos) cpu_fregs[REG(insn, pos)]
 #define MACREG(acc) cpu_macc[acc]
 #define QREG_SP cpu_aregs[7]
 
-- 
2.5.5

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

* [Qemu-devel] [PATCH 11/52] target-m68k: allow to update flags with operation on words and bytes
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (9 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 10/52] target-m68k: REG() macro cleanup Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:45   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 12/52] target-m68k: Replace helper_xflag_lt with setcond Laurent Vivier
                   ` (24 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.h       |  14 ++++-
 target-m68k/helper.c    | 139 ++++++++++++++++++++++++++++++++++--------------
 target-m68k/translate.c |  82 ++++++++++++++--------------
 3 files changed, 151 insertions(+), 84 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index de902fd..c769711 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -133,13 +133,23 @@ void cpu_m68k_flush_flags(CPUM68KState *, int);
 enum {
     CC_OP_DYNAMIC, /* Use env->cc_op  */
     CC_OP_FLAGS, /* CC_DEST = CVZN, CC_SRC = unused */
+    CC_OP_LOGICB, /* CC_DEST = result, CC_SRC = unused */
+    CC_OP_LOGICW, /* CC_DEST = result, 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_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 a8f6d9d..c97b989 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -139,22 +139,63 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
     uint32_t dest;
     uint32_t tmp;
 
-#define HIGHBIT 0x80000000u
-
-#define SET_NZ(x) do { \
-    if ((x) == 0) \
-        flags |= CCF_Z; \
-    else if ((int32_t)(x) < 0) \
-        flags |= CCF_N; \
+#define HIGHBIT(type) (1u << (sizeof(type) * 8 - 1))
+
+#define SET_NZ(x, type) do { \
+        if ((type)(x) == 0) { \
+            flags |= CCF_Z; \
+        } else if ((type)(x) < 0) { \
+            flags |= CCF_N; \
+        } \
     } while (0)
 
 #define SET_FLAGS_SUB(type, utype) do { \
-    SET_NZ((type)dest); \
-    tmp = dest + src; \
-    if ((utype) tmp < (utype) src) \
-        flags |= CCF_C; \
-    if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
-        flags |= CCF_V; \
+        SET_NZ(dest, type); \
+        tmp = dest + src; \
+        if ((utype) tmp < (utype) src) { \
+            flags |= CCF_C; \
+        } \
+        if (HIGHBIT(type) & (tmp ^ dest) & (tmp ^ src)) { \
+            flags |= CCF_V; \
+        } \
+    } while (0)
+
+#define SET_FLAGS_ADD(type, utype) do { \
+        SET_NZ(dest, type); \
+        if ((utype) dest < (utype) src) { \
+            flags |= CCF_C; \
+        } \
+        tmp = dest - src; \
+        if (HIGHBIT(type) & (src ^ dest) & ~(tmp ^ src)) { \
+            flags |= CCF_V; \
+        } \
+    } while (0)
+
+#define SET_FLAGS_ADDX(type, utype) do { \
+        SET_NZ(dest, type); \
+        if ((utype) dest <= (utype) src) { \
+            flags |= CCF_C; \
+        } \
+        tmp = dest - src - 1; \
+        if (HIGHBIT(type) & (src ^ dest) & ~(tmp ^ src)) { \
+            flags |= CCF_V; \
+        } \
+    } while (0)
+
+#define SET_FLAGS_SUBX(type, utype) do { \
+        SET_NZ(dest, type); \
+        tmp = dest + src + 1; \
+        if ((utype) tmp <= (utype) src) { \
+            flags |= CCF_C; \
+        } \
+        if (HIGHBIT(type) & (tmp ^ dest) & (tmp ^ src)) { \
+            flags |= CCF_V; \
+        } \
+    } while (0)
+
+#define SET_FLAGS_SHIFT(type) do { \
+    SET_NZ(dest, type); \
+    flags |= src; \
     } while (0)
 
     flags = 0;
@@ -164,46 +205,66 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
     case CC_OP_FLAGS:
         flags = dest;
         break;
+    case CC_OP_LOGICB:
+        SET_NZ(dest, int8_t);
+        goto set_x;
+        break;
+    case CC_OP_LOGICW:
+        SET_NZ(dest, int16_t);
+        goto set_x;
+        break;
     case CC_OP_LOGIC:
-        SET_NZ(dest);
+        SET_NZ(dest, int32_t);
+set_x:
+        if (!m68k_feature(env, M68K_FEATURE_M68000)) {
+            /* Unlike m68k, coldfire always clears the overflow bit.  */
+            env->cc_x = 0;
+        }
+        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_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(CPU(cpu), "Bad CC_OP %d", cc_op);
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 3ad3613..a2b67bf 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -426,10 +426,23 @@ static inline void gen_flush_flags(DisasContext *s)
     s->cc_op = CC_OP_FLAGS;
 }
 
-static void gen_logic_cc(DisasContext *s, TCGv val)
+#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)
+
+static void gen_logic_cc(DisasContext *s, TCGv val, int opsize)
 {
     tcg_gen_mov_i32(QREG_CC_DEST, val);
-    s->cc_op = CC_OP_LOGIC;
+    SET_CC_OP(opsize, LOGIC);
 }
 
 static void gen_update_cc_add(TCGv dest, TCGv src)
@@ -924,8 +937,7 @@ DISAS_INSN(mulw)
     SRC_EA(env, src, OS_WORD, sign, NULL);
     tcg_gen_mul_i32(tmp, tmp, src);
     tcg_gen_mov_i32(reg, tmp);
-    /* Unlike m68k, coldfire always clears the overflow bit.  */
-    gen_logic_cc(s, tmp);
+    gen_logic_cc(s, tmp, OS_WORD);
 }
 
 DISAS_INSN(divw)
@@ -1094,7 +1106,7 @@ DISAS_INSN(sats)
     reg = DREG(insn, 0);
     gen_flush_flags(s);
     gen_helper_sats(reg, reg, QREG_CC_DEST);
-    gen_logic_cc(s, reg);
+    gen_logic_cc(s, reg, OS_LONG);
 }
 
 static void gen_push(DisasContext *s, TCGv val)
@@ -1219,11 +1231,11 @@ DISAS_INSN(arith_im)
     switch (op) {
     case 0: /* ori */
         tcg_gen_ori_i32(dest, src1, im);
-        gen_logic_cc(s, dest);
+        gen_logic_cc(s, dest, OS_LONG);
         break;
     case 1: /* andi */
         tcg_gen_andi_i32(dest, src1, im);
-        gen_logic_cc(s, dest);
+        gen_logic_cc(s, dest, OS_LONG);
         break;
     case 2: /* subi */
         tcg_gen_mov_i32(dest, src1);
@@ -1241,7 +1253,7 @@ DISAS_INSN(arith_im)
         break;
     case 5: /* eori */
         tcg_gen_xori_i32(dest, src1, im);
-        gen_logic_cc(s, dest);
+        gen_logic_cc(s, dest, OS_LONG);
         break;
     case 6: /* cmpi */
         tcg_gen_mov_i32(dest, src1);
@@ -1298,7 +1310,7 @@ DISAS_INSN(move)
         dest_ea = ((insn >> 9) & 7) | (op << 3);
         DEST_EA(env, dest_ea, opsize, src, NULL);
         /* This will be correct because loads sign extend.  */
-        gen_logic_cc(s, src);
+        gen_logic_cc(s, src, opsize);
     }
 }
 
@@ -1331,7 +1343,7 @@ DISAS_INSN(clr)
 
     opsize = insn_opsize(insn);
     DEST_EA(env, insn, opsize, tcg_const_i32(0), NULL);
-    gen_logic_cc(s, tcg_const_i32(0));
+    gen_logic_cc(s, tcg_const_i32(0), opsize);
 }
 
 static TCGv gen_get_ccr(DisasContext *s)
@@ -1418,7 +1430,7 @@ DISAS_INSN(not)
 
     reg = DREG(insn, 0);
     tcg_gen_not_i32(reg, reg);
-    gen_logic_cc(s, reg);
+    gen_logic_cc(s, reg, OS_LONG);
 }
 
 DISAS_INSN(swap)
@@ -1433,7 +1445,7 @@ DISAS_INSN(swap)
     tcg_gen_shli_i32(src1, reg, 16);
     tcg_gen_shri_i32(src2, reg, 16);
     tcg_gen_or_i32(reg, src1, src2);
-    gen_logic_cc(s, reg);
+    gen_logic_cc(s, reg, OS_LONG);
 }
 
 DISAS_INSN(bkpt)
@@ -1470,7 +1482,7 @@ DISAS_INSN(ext)
         gen_partset_reg(OS_WORD, reg, tmp);
     else
         tcg_gen_mov_i32(reg, tmp);
-    gen_logic_cc(s, tmp);
+    gen_logic_cc(s, tmp, OS_LONG);
 }
 
 DISAS_INSN(tst)
@@ -1480,7 +1492,7 @@ DISAS_INSN(tst)
 
     opsize = insn_opsize(insn);
     SRC_EA(env, tmp, opsize, 1, NULL);
-    gen_logic_cc(s, tmp);
+    gen_logic_cc(s, tmp, opsize);
 }
 
 DISAS_INSN(pulse)
@@ -1502,7 +1514,7 @@ DISAS_INSN(tas)
 
     dest = tcg_temp_new();
     SRC_EA(env, src1, OS_BYTE, 1, &addr);
-    gen_logic_cc(s, src1);
+    gen_logic_cc(s, src1, OS_BYTE);
     tcg_gen_ori_i32(dest, src1, 0x80);
     DEST_EA(env, insn, OS_BYTE, dest, &addr);
 }
@@ -1527,7 +1539,7 @@ DISAS_INSN(mull)
     tcg_gen_mul_i32(dest, src1, reg);
     tcg_gen_mov_i32(reg, dest);
     /* Unlike m68k, coldfire always clears the overflow bit.  */
-    gen_logic_cc(s, dest);
+    gen_logic_cc(s, dest, OS_LONG);
 }
 
 DISAS_INSN(link)
@@ -1685,7 +1697,7 @@ DISAS_INSN(moveq)
 
     val = (int8_t)insn;
     tcg_gen_movi_i32(DREG(insn, 9), val);
-    gen_logic_cc(s, tcg_const_i32(val));
+    gen_logic_cc(s, tcg_const_i32(val), OS_LONG);
 }
 
 DISAS_INSN(mvzs)
@@ -1701,7 +1713,7 @@ DISAS_INSN(mvzs)
     SRC_EA(env, src, opsize, (insn & 0x80) == 0, NULL);
     reg = DREG(insn, 9);
     tcg_gen_mov_i32(reg, src);
-    gen_logic_cc(s, src);
+    gen_logic_cc(s, src, opsize);
 }
 
 DISAS_INSN(or)
@@ -1722,7 +1734,7 @@ DISAS_INSN(or)
         tcg_gen_or_i32(dest, src, reg);
         tcg_gen_mov_i32(reg, dest);
     }
-    gen_logic_cc(s, dest);
+    gen_logic_cc(s, dest, OS_LONG);
 }
 
 DISAS_INSN(suba)
@@ -1755,40 +1767,24 @@ DISAS_INSN(mov3q)
     if (val == 0)
         val = -1;
     src = tcg_const_i32(val);
-    gen_logic_cc(s, src);
+    gen_logic_cc(s, src, OS_LONG);
     DEST_EA(env, insn, OS_LONG, src, NULL);
 }
 
 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(env, src, opsize, 1, NULL);
+    opsize = insn_opsize(insn);
+    SRC_EA(env, 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)
@@ -1808,7 +1804,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(OS_LONG, SUB);
 }
 
 DISAS_INSN(eor)
@@ -1822,7 +1818,7 @@ DISAS_INSN(eor)
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     tcg_gen_xor_i32(dest, src, reg);
-    gen_logic_cc(s, dest);
+    gen_logic_cc(s, dest, OS_LONG);
     DEST_EA(env, insn, OS_LONG, dest, &addr);
 }
 
@@ -1844,7 +1840,7 @@ DISAS_INSN(and)
         tcg_gen_and_i32(dest, src, reg);
         tcg_gen_mov_i32(reg, dest);
     }
-    gen_logic_cc(s, dest);
+    gen_logic_cc(s, dest, OS_LONG);
 }
 
 DISAS_INSN(adda)
@@ -1919,7 +1915,7 @@ DISAS_INSN(ff1)
 {
     TCGv reg;
     reg = DREG(insn, 0);
-    gen_logic_cc(s, reg);
+    gen_logic_cc(s, reg, OS_LONG);
     gen_helper_ff1(reg, reg);
 }
 
-- 
2.5.5

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

* [Qemu-devel] [PATCH 12/52] target-m68k: Replace helper_xflag_lt with setcond
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (10 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 11/52] target-m68k: allow to update flags with operation on words and bytes Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 13/52] target-m68k: update CPU flags management Laurent Vivier
                   ` (23 subsequent siblings)
  35 siblings, 0 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

From: Richard Henderson <rth@twiddle.net>

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    |  5 -----
 target-m68k/helper.h    |  1 -
 target-m68k/translate.c | 14 +++++++-------
 3 files changed, 7 insertions(+), 13 deletions(-)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index c97b989..d0a346f 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -463,11 +463,6 @@ uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
     return res;
 }
 
-uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
-{
-    return a < b;
-}
-
 void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
 {
     env->sr = val & 0xffff;
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index f4e5fdf..c24ace5 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -8,7 +8,6 @@ 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_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 a2b67bf..67d72cc 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1023,10 +1023,10 @@ DISAS_INSN(addsub)
     }
     if (add) {
         tcg_gen_add_i32(dest, tmp, src);
-        gen_helper_xflag_lt(QREG_CC_X, dest, src);
+        tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src);
         s->cc_op = CC_OP_ADD;
     } else {
-        gen_helper_xflag_lt(QREG_CC_X, tmp, src);
+        tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, tmp, src);
         tcg_gen_sub_i32(dest, tmp, src);
         s->cc_op = CC_OP_SUB;
     }
@@ -1239,7 +1239,7 @@ DISAS_INSN(arith_im)
         break;
     case 2: /* subi */
         tcg_gen_mov_i32(dest, src1);
-        gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im));
+        tcg_gen_setcond_i32(TCG_COND_LTU, 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;
@@ -1248,7 +1248,7 @@ DISAS_INSN(arith_im)
         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));
+        tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, tcg_const_i32(im));
         s->cc_op = CC_OP_ADD;
         break;
     case 5: /* eori */
@@ -1378,7 +1378,7 @@ DISAS_INSN(neg)
     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);
+    tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, tcg_const_i32(0), src1);
     s->cc_op = CC_OP_SUB;
 }
 
@@ -1629,12 +1629,12 @@ DISAS_INSN(addsubq)
     } else {
         src2 = tcg_const_i32(val);
         if (insn & 0x0100) {
-            gen_helper_xflag_lt(QREG_CC_X, dest, src2);
+            tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src2);
             tcg_gen_subi_i32(dest, dest, val);
             s->cc_op = CC_OP_SUB;
         } else {
             tcg_gen_addi_i32(dest, dest, val);
-            gen_helper_xflag_lt(QREG_CC_X, dest, src2);
+            tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src2);
             s->cc_op = CC_OP_ADD;
         }
         gen_update_cc_add(dest, src2);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 13/52] target-m68k: update CPU flags management
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (11 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 12/52] target-m68k: Replace helper_xflag_lt with setcond Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:46   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 14/52] target-m68k: update move to/from ccr/sr Laurent Vivier
                   ` (22 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Copied from target-i386

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 cpu-exec.c              |  6 ------
 target-m68k/cpu-qom.h   |  4 ----
 target-m68k/cpu.c       |  2 --
 target-m68k/cpu.h       |  1 +
 target-m68k/helper.c    | 20 --------------------
 target-m68k/translate.c |  6 +++++-
 6 files changed, 6 insertions(+), 33 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index bbfcbfb..1193cc3 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -147,12 +147,6 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
     if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
 #if defined(TARGET_I386)
         log_cpu_state(cpu, CPU_DUMP_CCOP);
-#elif defined(TARGET_M68K)
-        /* ??? Should not modify env state for dumping.  */
-        cpu_m68k_flush_flags(env, env->cc_op);
-        env->cc_op = CC_OP_FLAGS;
-        env->sr = (env->sr & 0xffe0) | env->cc_dest | (env->cc_x << 4);
-        log_cpu_state(cpu, 0);
 #else
         log_cpu_state(cpu, 0);
 #endif
diff --git a/target-m68k/cpu-qom.h b/target-m68k/cpu-qom.h
index c28e55d..1fadf1d 100644
--- a/target-m68k/cpu-qom.h
+++ b/target-m68k/cpu-qom.h
@@ -77,8 +77,4 @@ void m68k_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
 hwaddr m68k_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 int m68k_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 int m68k_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
-
-void m68k_cpu_exec_enter(CPUState *cs);
-void m68k_cpu_exec_exit(CPUState *cs);
-
 #endif
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index baca4f8..81f1579 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -272,8 +272,6 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
 #else
     cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug;
 #endif
-    cc->cpu_exec_enter = m68k_cpu_exec_enter;
-    cc->cpu_exec_exit = m68k_cpu_exec_exit;
     cc->disas_set_info = m68k_cpu_disas_set_info;
 
     cc->gdb_num_core_regs = 18;
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index c769711..0e4ff08 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -60,6 +60,7 @@
 #define EXCP_HALT_INSN      0x101
 
 #define NB_MMU_MODES 2
+#define TARGET_INSN_START_EXTRA_WORDS 1
 
 typedef struct CPUM68KState {
     uint32_t dregs[8];
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index d0a346f..ec37c9d 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -921,23 +921,3 @@ void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
     res |= (uint64_t)(val & 0xffff0000) << 16;
     env->macc[acc + 1] = res;
 }
-
-void m68k_cpu_exec_enter(CPUState *cs)
-{
-    M68kCPU *cpu = M68K_CPU(cs);
-    CPUM68KState *env = &cpu->env;
-
-    env->cc_op = CC_OP_FLAGS;
-    env->cc_dest = env->sr & 0xf;
-    env->cc_x = (env->sr >> 4) & 1;
-}
-
-void m68k_cpu_exec_exit(CPUState *cs)
-{
-    M68kCPU *cpu = M68K_CPU(cs);
-    CPUM68KState *env = &cpu->env;
-
-    cpu_m68k_flush_flags(env, env->cc_op);
-    env->cc_op = CC_OP_FLAGS;
-    env->sr = (env->sr & 0xffe0) | env->cc_dest | (env->cc_x << 4);
-}
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 67d72cc..c7331dc 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3022,7 +3022,7 @@ void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
     do {
         pc_offset = dc->pc - pc_start;
         gen_throws_exception = NULL;
-        tcg_gen_insn_start(dc->pc);
+        tcg_gen_insn_start(dc->pc, dc->cc_op);
         num_insns++;
 
         if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
@@ -3115,5 +3115,9 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
 void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb,
                           target_ulong *data)
 {
+    int cc_op = data[1];
     env->pc = data[0];
+    if (cc_op != CC_OP_DYNAMIC) {
+        env->cc_op = cc_op;
+    }
 }
-- 
2.5.5

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

* [Qemu-devel] [PATCH 14/52] target-m68k: update move to/from ccr/sr
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (12 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 13/52] target-m68k: update CPU flags management Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:47   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 15/52] target-m68k: don't update cc_dest in helpers Laurent Vivier
                   ` (21 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 53 ++++++++++++++++++++-----------------------------
 1 file changed, 22 insertions(+), 31 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index c7331dc..cddc2b5 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1359,12 +1359,10 @@ static TCGv gen_get_ccr(DisasContext *s)
 
 DISAS_INSN(move_from_ccr)
 {
-    TCGv reg;
     TCGv ccr;
 
     ccr = gen_get_ccr(s);
-    reg = DREG(insn, 0);
-    gen_partset_reg(OS_WORD, reg, ccr);
+    DEST_EA(env, insn, OS_WORD, ccr, NULL);
 }
 
 DISAS_INSN(neg)
@@ -1391,37 +1389,31 @@ static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
     }
 }
 
-static void gen_set_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
-                       int ccr_only)
+static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only)
 {
     TCGv tmp;
-    TCGv reg;
+    tmp = tcg_temp_new();
+    tcg_gen_andi_i32(QREG_CC_DEST, val, 0xf);
+    tcg_gen_shri_i32(tmp, val, 4);
+    tcg_gen_andi_i32(QREG_CC_X, tmp, 1);
+    if (!ccr_only) {
+        gen_helper_set_sr(cpu_env, val);
+    }
+}
 
+static void gen_move_to_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
+                           int ccr_only)
+{
+    TCGv src;
     s->cc_op = CC_OP_FLAGS;
-    if ((insn & 0x38) == 0)
-      {
-        tmp = tcg_temp_new();
-        reg = DREG(insn, 0);
-        tcg_gen_andi_i32(QREG_CC_DEST, reg, 0xf);
-        tcg_gen_shri_i32(tmp, reg, 4);
-        tcg_gen_andi_i32(QREG_CC_X, tmp, 1);
-        if (!ccr_only) {
-            gen_helper_set_sr(cpu_env, reg);
-        }
-      }
-    else if ((insn & 0x3f) == 0x3c)
-      {
-        uint16_t val;
-        val = read_im16(env, s);
-        gen_set_sr_im(s, val, ccr_only);
-      }
-    else
-        disas_undef(env, s, insn);
+    SRC_EA(env, src, OS_WORD, 0, NULL);
+    gen_set_sr(s, src, ccr_only);
 }
 
+
 DISAS_INSN(move_to_ccr)
 {
-    gen_set_sr(env, s, insn, 1);
+    gen_move_to_sr(env, s, insn, 1);
 }
 
 DISAS_INSN(not)
@@ -1953,16 +1945,14 @@ DISAS_INSN(strldsr)
 
 DISAS_INSN(move_from_sr)
 {
-    TCGv reg;
     TCGv sr;
 
-    if (IS_USER(s)) {
+    if (IS_USER(s) && !m68k_feature(env, M68K_FEATURE_M68000)) {
         gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
         return;
     }
     sr = gen_get_sr(s);
-    reg = DREG(insn, 0);
-    gen_partset_reg(OS_WORD, reg, sr);
+    DEST_EA(env, insn, OS_WORD, sr, NULL);
 }
 
 DISAS_INSN(move_to_sr)
@@ -1971,7 +1961,7 @@ DISAS_INSN(move_to_sr)
         gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
         return;
     }
-    gen_set_sr(env, s, insn, 0);
+    gen_move_to_sr(env, s, insn, 0);
     gen_lookup_tb(s);
 }
 
@@ -2868,6 +2858,7 @@ void register_m68k_insns (CPUM68KState *env)
     BASE(clr,       4200, ff00);
     BASE(undef,     42c0, ffc0);
     INSN(move_from_ccr, 42c0, fff8, CF_ISA_A);
+    INSN(move_from_ccr, 42c0, ffc0, M68000);
     INSN(neg,       4480, fff8, CF_ISA_A);
     INSN(neg,       4400, ff00, M68000);
     INSN(undef,     44c0, ffc0, M68000);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 15/52] target-m68k: don't update cc_dest in helpers
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (13 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 14/52] target-m68k: update move to/from ccr/sr Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:47   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 16/52] target-m68k: update CPU flags management Laurent Vivier
                   ` (20 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

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

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 0e4ff08..d3acd33 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -129,7 +129,6 @@ int cpu_m68k_exec(CPUState *cpu);
    is returned if the signal was handled by the virtual CPU.  */
 int cpu_m68k_signal_handler(int host_signum, void *pinfo,
                            void *puc);
-void cpu_m68k_flush_flags(CPUM68KState *, int);
 
 enum {
     CC_OP_DYNAMIC, /* Use env->cc_op  */
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index ec37c9d..c3e4380 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -131,9 +131,8 @@ void m68k_cpu_init_gdb(M68kCPU *cpu)
     /* TODO: Add [E]MAC registers.  */
 }
 
-void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
+static uint32_t cpu_m68k_flush_flags(CPUM68KState *env, int op)
 {
-    M68kCPU *cpu = m68k_env_get_cpu(env);
     int flags;
     uint32_t src;
     uint32_t dest;
@@ -201,7 +200,7 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
     flags = 0;
     src = env->cc_src;
     dest = env->cc_dest;
-    switch (cc_op) {
+    switch (op) {
     case CC_OP_FLAGS:
         flags = dest;
         break;
@@ -267,10 +266,9 @@ set_x:
         SET_FLAGS_SHIFT(int32_t);
         break;
     default:
-        cpu_abort(CPU(cpu), "Bad CC_OP %d", cc_op);
+        g_assert_not_reached();
     }
-    env->cc_op = CC_OP_FLAGS;
-    env->cc_dest = flags;
+    return flags;
 }
 
 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
@@ -421,20 +419,21 @@ uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 {
     uint32_t res;
     uint32_t old_flags;
+    int op;
 
     old_flags = env->cc_dest;
     if (env->cc_x) {
         env->cc_x = (op1 <= op2);
-        env->cc_op = CC_OP_SUBX;
+        op = CC_OP_SUBX;
         res = op1 - (op2 + 1);
     } else {
         env->cc_x = (op1 < op2);
-        env->cc_op = CC_OP_SUB;
+        op = CC_OP_SUB;
         res = op1 - op2;
     }
     env->cc_dest = res;
     env->cc_src = op2;
-    cpu_m68k_flush_flags(env, env->cc_op);
+    env->cc_dest = cpu_m68k_flush_flags(env, op);
     /* !Z is sticky.  */
     env->cc_dest &= (old_flags | ~CCF_Z);
     return res;
@@ -444,20 +443,21 @@ uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 {
     uint32_t res;
     uint32_t old_flags;
+    int op;
 
     old_flags = env->cc_dest;
     if (env->cc_x) {
         res = op1 + op2 + 1;
         env->cc_x = (res <= op2);
-        env->cc_op = CC_OP_ADDX;
+        op = CC_OP_ADDX;
     } else {
         res = op1 + op2;
         env->cc_x = (res < op2);
-        env->cc_op = CC_OP_ADD;
+        op = CC_OP_ADD;
     }
     env->cc_dest = res;
     env->cc_src = op2;
-    cpu_m68k_flush_flags(env, env->cc_op);
+    env->cc_dest = cpu_m68k_flush_flags(env, op);
     /* !Z is sticky.  */
     env->cc_dest &= (old_flags | ~CCF_Z);
     return res;
@@ -789,9 +789,9 @@ void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
     }
 }
 
-void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
+uint32_t HELPER(flush_flags)(CPUM68KState *env, uint32_t op)
 {
-    cpu_m68k_flush_flags(env, cc_op);
+    return cpu_m68k_flush_flags(env, op);
 }
 
 uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index c24ace5..0f5a7cf 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -45,5 +45,5 @@ DEF_HELPER_3(set_mac_extf, void, env, i32, i32)
 DEF_HELPER_3(set_mac_exts, void, env, i32, i32)
 DEF_HELPER_3(set_mac_extu, void, env, i32, i32)
 
-DEF_HELPER_2(flush_flags, void, env, i32)
+DEF_HELPER_2(flush_flags, i32, env, i32)
 DEF_HELPER_2(raise_exception, void, env, i32)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index cddc2b5..16f09ca 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -422,7 +422,7 @@ static inline void gen_flush_flags(DisasContext *s)
     if (s->cc_op == CC_OP_FLAGS)
         return;
     gen_flush_cc_op(s);
-    gen_helper_flush_flags(cpu_env, QREG_CC_OP);
+    gen_helper_flush_flags(QREG_CC_DEST, cpu_env, QREG_CC_OP);
     s->cc_op = CC_OP_FLAGS;
 }
 
@@ -716,6 +716,7 @@ static void gen_jmpcc(DisasContext *s, int cond, TCGLabel *l1)
     /* TODO: Optimize compare/branch pairs rather than always flushing
        flag state to CC_OP_FLAGS.  */
     gen_flush_flags(s);
+    gen_flush_cc_op(s);
     switch (cond) {
     case 0: /* T */
         tcg_gen_br(l1);
@@ -1669,7 +1670,6 @@ DISAS_INSN(branch)
         /* bsr */
         gen_push(s, tcg_const_i32(s->pc));
     }
-    gen_flush_cc_op(s);
     if (op > 1) {
         /* Bcc */
         l1 = gen_new_label();
-- 
2.5.5

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

* [Qemu-devel] [PATCH 16/52] target-m68k: update CPU flags management
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (14 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 15/52] target-m68k: don't update cc_dest in helpers Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:47   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 17/52] target-m68k: Print flags properly Laurent Vivier
                   ` (19 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Copied from target-i386

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.h       |   5 +-
 target-m68k/translate.c | 121 +++++++++++++++++++++++++++++++++---------------
 2 files changed, 86 insertions(+), 40 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index d3acd33..8dafaab 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -130,7 +130,7 @@ int cpu_m68k_exec(CPUState *cpu);
 int cpu_m68k_signal_handler(int host_signum, void *pinfo,
                            void *puc);
 
-enum {
+typedef enum {
     CC_OP_DYNAMIC, /* Use env->cc_op  */
     CC_OP_FLAGS, /* CC_DEST = CVZN, CC_SRC = unused */
     CC_OP_LOGICB, /* CC_DEST = result, CC_SRC = unused */
@@ -151,7 +151,8 @@ enum {
     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 */
-};
+    CC_OP_NB,
+} CCOp;
 
 #define CCF_C 0x01
 #define CCF_V 0x02
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 16f09ca..82c22b2 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -131,7 +131,7 @@ typedef struct DisasContext {
     target_ulong insn_pc; /* Start of the current instruction.  */
     target_ulong pc;
     int is_jmp;
-    int cc_op;
+    CCOp cc_op; /* Current CC operation */
     int user;
     uint32_t fpcr;
     struct TranslationBlock *tb;
@@ -173,6 +173,53 @@ typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t insn);
                              uint16_t insn)
 #endif
 
+enum {
+    USES_CC_DST  = 1,
+    USES_CC_SRC  = 2,
+};
+
+static const uint8_t cc_op_live[CC_OP_NB] = {
+    [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC,
+    [CC_OP_FLAGS] = USES_CC_DST,
+    [CC_OP_LOGICB ... CC_OP_LOGIC] = USES_CC_DST,
+    [CC_OP_ADDB ... CC_OP_ADD] = USES_CC_DST | USES_CC_SRC,
+    [CC_OP_SUBB ... CC_OP_SUB] = USES_CC_DST | USES_CC_SRC,
+    [CC_OP_ADDXB ... CC_OP_ADDX] = USES_CC_DST | USES_CC_SRC,
+    [CC_OP_SUBXB ... CC_OP_SUBX] = USES_CC_DST | USES_CC_SRC,
+    [CC_OP_SHIFTB ... CC_OP_SHIFT] = USES_CC_DST | USES_CC_SRC,
+};
+
+static void set_cc_op(DisasContext *s, CCOp op)
+{
+    int dead;
+
+    if (s->cc_op == op) {
+        return;
+    }
+
+    /* Discard CC computation that will no longer be used.  */
+
+    dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
+    if (dead & USES_CC_DST) {
+        tcg_gen_discard_i32(QREG_CC_DEST);
+    }
+    if (dead & USES_CC_SRC) {
+        tcg_gen_discard_i32(QREG_CC_SRC);
+    }
+    if (s->cc_op == CC_OP_DYNAMIC) {
+        tcg_gen_discard_i32(QREG_CC_OP);
+    }
+    s->cc_op = op;
+}
+
+/* Update the CPU env CC_OP state.  */
+static inline void update_cc_op(DisasContext *s)
+{
+    if (s->cc_op != CC_OP_DYNAMIC) {
+        tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
+    }
+}
+
 /* 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)
@@ -409,31 +456,28 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
     return add;
 }
 
-/* Update the CPU env CC_OP state.  */
-static inline void gen_flush_cc_op(DisasContext *s)
-{
-    if (s->cc_op != CC_OP_DYNAMIC)
-        tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
-}
-
 /* Evaluate all the CC flags.  */
+
 static inline void gen_flush_flags(DisasContext *s)
 {
     if (s->cc_op == CC_OP_FLAGS)
         return;
-    gen_flush_cc_op(s);
-    gen_helper_flush_flags(QREG_CC_DEST, cpu_env, QREG_CC_OP);
-    s->cc_op = CC_OP_FLAGS;
+    if (s->cc_op == CC_OP_DYNAMIC) {
+        gen_helper_flush_flags(QREG_CC_DEST, cpu_env, QREG_CC_OP);
+    } else {
+        gen_helper_flush_flags(QREG_CC_DEST, cpu_env, tcg_const_i32(s->cc_op));
+    }
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 #define SET_CC_OP(opsize, op) do { \
     switch (opsize) { \
     case OS_BYTE: \
-        s->cc_op = CC_OP_##op##B; break; \
+        set_cc_op(s, CC_OP_##op##B); break; \
     case OS_WORD: \
-        s->cc_op = CC_OP_##op##W; break; \
+        set_cc_op(s, CC_OP_##op##W); break; \
     case OS_LONG: \
-        s->cc_op = CC_OP_##op; break; \
+        set_cc_op(s, CC_OP_##op); break; \
     default: \
         abort(); \
     } \
@@ -716,7 +760,7 @@ static void gen_jmpcc(DisasContext *s, int cond, TCGLabel *l1)
     /* TODO: Optimize compare/branch pairs rather than always flushing
        flag state to CC_OP_FLAGS.  */
     gen_flush_flags(s);
-    gen_flush_cc_op(s);
+    update_cc_op(s);
     switch (cond) {
     case 0: /* T */
         tcg_gen_br(l1);
@@ -833,7 +877,7 @@ DISAS_INSN(scc)
 /* Force a TB lookup after an instruction that changes the CPU state.  */
 static void gen_lookup_tb(DisasContext *s)
 {
-    gen_flush_cc_op(s);
+    update_cc_op(s);
     tcg_gen_movi_i32(QREG_PC, s->pc);
     s->is_jmp = DISAS_UPDATE;
 }
@@ -841,7 +885,7 @@ static void gen_lookup_tb(DisasContext *s)
 /* Generate a jump to an immediate address.  */
 static void gen_jmp_im(DisasContext *s, uint32_t dest)
 {
-    gen_flush_cc_op(s);
+    update_cc_op(s);
     tcg_gen_movi_i32(QREG_PC, dest);
     s->is_jmp = DISAS_JUMP;
 }
@@ -849,14 +893,14 @@ static void gen_jmp_im(DisasContext *s, uint32_t dest)
 /* Generate a jump to the address in qreg DEST.  */
 static void gen_jmp(DisasContext *s, TCGv dest)
 {
-    gen_flush_cc_op(s);
+    update_cc_op(s);
     tcg_gen_mov_i32(QREG_PC, dest);
     s->is_jmp = DISAS_JUMP;
 }
 
 static void gen_exception(DisasContext *s, uint32_t where, int nr)
 {
-    gen_flush_cc_op(s);
+    update_cc_op(s);
     gen_jmp_im(s, where);
     gen_helper_raise_exception(cpu_env, tcg_const_i32(nr));
 }
@@ -968,7 +1012,7 @@ DISAS_INSN(divw)
     tcg_gen_ext16u_i32(tmp, QREG_DIV1);
     tcg_gen_shli_i32(src, QREG_DIV2, 16);
     tcg_gen_or_i32(reg, tmp, src);
-    s->cc_op = CC_OP_FLAGS;
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 DISAS_INSN(divl)
@@ -1000,7 +1044,7 @@ DISAS_INSN(divl)
         /* rem */
         tcg_gen_mov_i32 (reg, QREG_DIV2);
     }
-    s->cc_op = CC_OP_FLAGS;
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 DISAS_INSN(addsub)
@@ -1025,11 +1069,11 @@ DISAS_INSN(addsub)
     if (add) {
         tcg_gen_add_i32(dest, tmp, src);
         tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src);
-        s->cc_op = CC_OP_ADD;
+        set_cc_op(s, CC_OP_ADD);
     } else {
         tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, tmp, src);
         tcg_gen_sub_i32(dest, tmp, src);
-        s->cc_op = CC_OP_SUB;
+        set_cc_op(s, CC_OP_SUB);
     }
     gen_update_cc_add(dest, src);
     if (insn & 0x100) {
@@ -1216,7 +1260,6 @@ DISAS_INSN(bitop_im)
         DEST_EA(env, insn, opsize, tmp, &addr);
     }
 }
-
 DISAS_INSN(arith_im)
 {
     int op;
@@ -1243,14 +1286,14 @@ DISAS_INSN(arith_im)
         tcg_gen_setcond_i32(TCG_COND_LTU, 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(s, 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, tcg_const_i32(im));
         tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, tcg_const_i32(im));
-        s->cc_op = CC_OP_ADD;
+        set_cc_op(s, CC_OP_ADD);
         break;
     case 5: /* eori */
         tcg_gen_xori_i32(dest, src1, im);
@@ -1260,7 +1303,7 @@ 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(s, CC_OP_SUB);
         break;
     default:
         abort();
@@ -1375,10 +1418,9 @@ DISAS_INSN(neg)
     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);
     tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, tcg_const_i32(0), src1);
-    s->cc_op = CC_OP_SUB;
+    set_cc_op(s, CC_OP_SUB);
 }
 
 static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
@@ -1388,6 +1430,7 @@ static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
     if (!ccr_only) {
         gen_helper_set_sr(cpu_env, tcg_const_i32(val & 0xff00));
     }
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only)
@@ -1624,11 +1667,11 @@ DISAS_INSN(addsubq)
         if (insn & 0x0100) {
             tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src2);
             tcg_gen_subi_i32(dest, dest, val);
-            s->cc_op = CC_OP_SUB;
+            set_cc_op(s, CC_OP_SUB);
         } else {
             tcg_gen_addi_i32(dest, dest, val);
             tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src2);
-            s->cc_op = CC_OP_ADD;
+            set_cc_op(s, CC_OP_ADD);
         }
         gen_update_cc_add(dest, src2);
     }
@@ -1674,11 +1717,14 @@ DISAS_INSN(branch)
         /* Bcc */
         l1 = gen_new_label();
         gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
+        update_cc_op(s);
         gen_jmp_tb(s, 1, base + offset);
         gen_set_label(l1);
+        update_cc_op(s);
         gen_jmp_tb(s, 0, s->pc);
     } else {
         /* Unconditional branch.  */
+        update_cc_op(s);
         gen_jmp_tb(s, 0, base + offset);
     }
 }
@@ -1854,7 +1900,6 @@ DISAS_INSN(addx)
     reg = DREG(insn, 9);
     src = DREG(insn, 0);
     gen_helper_addx_cc(reg, cpu_env, reg, src);
-    s->cc_op = CC_OP_FLAGS;
 }
 
 /* TODO: This could be implemented without helper functions.  */
@@ -1879,7 +1924,7 @@ DISAS_INSN(shift_im)
             gen_helper_sar_cc(reg, cpu_env, reg, shift);
         }
     }
-    s->cc_op = CC_OP_SHIFT;
+    set_cc_op(s, CC_OP_SHIFT);
 }
 
 DISAS_INSN(shift_reg)
@@ -1900,7 +1945,7 @@ DISAS_INSN(shift_reg)
             gen_helper_sar_cc(reg, cpu_env, reg, shift);
         }
     }
-    s->cc_op = CC_OP_SHIFT;
+    set_cc_op(s, CC_OP_SHIFT);
 }
 
 DISAS_INSN(ff1)
@@ -2712,7 +2757,7 @@ DISAS_INSN(macsr_to_ccr)
 {
     tcg_gen_movi_i32(QREG_CC_X, 0);
     tcg_gen_andi_i32(QREG_CC_DEST, QREG_MACSR, 0xf);
-    s->cc_op = CC_OP_FLAGS;
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 DISAS_INSN(to_mac)
@@ -3044,20 +3089,20 @@ void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
     if (unlikely(cs->singlestep_enabled)) {
         /* Make sure the pc is updated, and raise a debug exception.  */
         if (!dc->is_jmp) {
-            gen_flush_cc_op(dc);
+            update_cc_op(dc);
             tcg_gen_movi_i32(QREG_PC, dc->pc);
         }
         gen_helper_raise_exception(cpu_env, tcg_const_i32(EXCP_DEBUG));
     } else {
         switch(dc->is_jmp) {
         case DISAS_NEXT:
-            gen_flush_cc_op(dc);
+            update_cc_op(dc);
             gen_jmp_tb(dc, 0, dc->pc);
             break;
         default:
         case DISAS_JUMP:
         case DISAS_UPDATE:
-            gen_flush_cc_op(dc);
+            update_cc_op(dc);
             /* indicate that the hash table must be used to find the next TB */
             tcg_gen_exit_tb(0);
             break;
-- 
2.5.5

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

* [Qemu-devel] [PATCH 17/52] target-m68k: Print flags properly
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (15 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 16/52] target-m68k: update CPU flags management Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 18/52] target-m68k: Some fixes to SR and flags management Laurent Vivier
                   ` (18 subsequent siblings)
  35 siblings, 0 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

From: Richard Henderson <rth@twiddle.net>

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

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 8dafaab..b2d9f3a 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -129,6 +129,7 @@ int cpu_m68k_exec(CPUState *cpu);
    is returned if the signal was handled by the virtual CPU.  */
 int cpu_m68k_signal_handler(int host_signum, void *pinfo,
                            void *puc);
+uint32_t cpu_m68k_flush_flags(CPUM68KState *env, int op);
 
 typedef enum {
     CC_OP_DYNAMIC, /* Use env->cc_op  */
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index c3e4380..e9ec8bc 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -131,7 +131,7 @@ void m68k_cpu_init_gdb(M68kCPU *cpu)
     /* TODO: Add [E]MAC registers.  */
 }
 
-static uint32_t cpu_m68k_flush_flags(CPUM68KState *env, int op)
+uint32_t cpu_m68k_flush_flags(CPUM68KState *env, int op)
 {
     int flags;
     uint32_t src;
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 82c22b2..a116c17 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3141,8 +3141,8 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                      i, u.l.upper, u.l.lower, *(double *)&u.d);
       }
     cpu_fprintf (f, "PC = %08x   ", env->pc);
-    sr = env->sr;
-    cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & 0x10) ? 'X' : '-',
+    sr = env->sr | cpu_m68k_flush_flags(env, env->cc_op) | env->cc_x * CCF_X;
+    cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & CCF_X) ? 'X' : '-',
                  (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
                  (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
     cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 18/52] target-m68k: Some fixes to SR and flags management
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (16 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 17/52] target-m68k: Print flags properly Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:49   ` Richard Henderson
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 19/52] target-m68k: terminate cpu dump with newline Laurent Vivier
                   ` (17 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

From: Richard Henderson <rth@twiddle.net>

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.h       |  3 ++-
 target-m68k/helper.c    | 17 +++++++++++++++--
 target-m68k/op_helper.c |  5 +++--
 target-m68k/translate.c |  2 +-
 4 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index b2d9f3a..8347d04 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -129,7 +129,8 @@ int cpu_m68k_exec(CPUState *cpu);
    is returned if the signal was handled by the virtual CPU.  */
 int cpu_m68k_signal_handler(int host_signum, void *pinfo,
                            void *puc);
-uint32_t cpu_m68k_flush_flags(CPUM68KState *env, int op);
+uint32_t cpu_m68k_get_ccr(CPUM68KState *env);
+void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t);
 
 typedef enum {
     CC_OP_DYNAMIC, /* Use env->cc_op  */
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index e9ec8bc..ffed180 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -131,7 +131,7 @@ void m68k_cpu_init_gdb(M68kCPU *cpu)
     /* TODO: Add [E]MAC registers.  */
 }
 
-uint32_t cpu_m68k_flush_flags(CPUM68KState *env, int op)
+static uint32_t cpu_m68k_flush_flags(CPUM68KState *env, int op)
 {
     int flags;
     uint32_t src;
@@ -271,6 +271,18 @@ set_x:
     return flags;
 }
 
+uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
+{
+    return cpu_m68k_flush_flags(env, env->cc_op) | env->cc_x * CCF_X;
+}
+
+void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t val)
+{
+    env->cc_op = CC_OP_FLAGS;
+    env->cc_dest = val & 0xf;
+    env->cc_x = (val & CCF_X ? 1 : 0);
+}
+
 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
 {
     M68kCPU *cpu = m68k_env_get_cpu(env);
@@ -465,7 +477,8 @@ uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 
 void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
 {
-    env->sr = val & 0xffff;
+    env->sr = val & 0xffe0;
+    cpu_m68k_set_ccr(env, val);
     m68k_switch_sp(env);
 }
 
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 17d0a11..9262946 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -62,9 +62,9 @@ static void do_rte(CPUM68KState *env)
     fmt = cpu_ldl_kernel(env, sp);
     env->pc = cpu_ldl_kernel(env, sp + 4);
     sp |= (fmt >> 28) & 3;
-    env->sr = fmt & 0xffff;
     env->aregs[7] = sp + 8;
-    m68k_switch_sp(env);
+
+    helper_set_sr(env, fmt);
 }
 
 static void do_interrupt_all(CPUM68KState *env, int is_hw)
@@ -111,6 +111,7 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
     fmt |= 0x40000000;
     fmt |= vector << 16;
     fmt |= env->sr;
+    fmt |= cpu_m68k_get_ccr(env);
 
     env->sr |= SR_S;
     if (is_hw) {
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index a116c17..ddc3100 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3141,7 +3141,7 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                      i, u.l.upper, u.l.lower, *(double *)&u.d);
       }
     cpu_fprintf (f, "PC = %08x   ", env->pc);
-    sr = env->sr | cpu_m68k_flush_flags(env, env->cc_op) | env->cc_x * CCF_X;
+    sr = env->sr | cpu_m68k_get_ccr(env);
     cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & CCF_X) ? 'X' : '-',
                  (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
                  (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
-- 
2.5.5

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

* [Qemu-devel] [PATCH 19/52] target-m68k: terminate cpu dump with newline
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (17 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 18/52] target-m68k: Some fixes to SR and flags management Laurent Vivier
@ 2016-05-04 20:11 ` Laurent Vivier
  2016-05-06 16:49   ` Richard Henderson
  2016-05-06 17:41   ` Andreas Schwab
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 20/52] target-m68k: Remove incorrect clearing of cc_x Laurent Vivier
                   ` (16 subsequent siblings)
  35 siblings, 2 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

From: Andreas Schwab <schwab@linux-m68k.org>

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index ddc3100..37c1b95 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3142,7 +3142,7 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
       }
     cpu_fprintf (f, "PC = %08x   ", env->pc);
     sr = env->sr | cpu_m68k_get_ccr(env);
-    cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & CCF_X) ? 'X' : '-',
+    cpu_fprintf (f, "SR = %04x %c%c%c%c%c\n", sr, (sr & CCF_X) ? 'X' : '-',
                  (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
                  (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
     cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 20/52] target-m68k: Remove incorrect clearing of cc_x
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (18 preceding siblings ...)
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 19/52] target-m68k: terminate cpu dump with newline Laurent Vivier
@ 2016-05-04 20:12 ` Laurent Vivier
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 21/52] target-m68k: Reorg flags handling Laurent Vivier
                   ` (15 subsequent siblings)
  35 siblings, 0 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

From: Richard Henderson <rth@twiddle.net>

The CF docs certainly doesnt suggest this is true.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index ffed180..9c14d6f 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -206,19 +206,12 @@ static uint32_t cpu_m68k_flush_flags(CPUM68KState *env, int op)
         break;
     case CC_OP_LOGICB:
         SET_NZ(dest, int8_t);
-        goto set_x;
         break;
     case CC_OP_LOGICW:
         SET_NZ(dest, int16_t);
-        goto set_x;
         break;
     case CC_OP_LOGIC:
         SET_NZ(dest, int32_t);
-set_x:
-        if (!m68k_feature(env, M68K_FEATURE_M68000)) {
-            /* Unlike m68k, coldfire always clears the overflow bit.  */
-            env->cc_x = 0;
-        }
         break;
     case CC_OP_ADDB:
         SET_FLAGS_ADD(int8_t, uint8_t);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 21/52] target-m68k: Reorg flags handling
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (19 preceding siblings ...)
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 20/52] target-m68k: Remove incorrect clearing of cc_x Laurent Vivier
@ 2016-05-04 20:12 ` Laurent Vivier
  2016-05-06 16:51   ` Richard Henderson
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 22/52] target-m68k: Introduce DisasCompare Laurent Vivier
                   ` (14 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

From: Richard Henderson <rth@twiddle.net>

Separate all ccr bits.  Continue to batch updates via cc_op.

Signed-off-by: Richard Henderson <rth@twiddle.net>

Fix gen_logic_cc() to really extend the size of the result.
Fix gen_get_ccr(): update cc_op as it is used by the helper.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.c       |   2 +-
 target-m68k/cpu.h       |  46 +++---
 target-m68k/helper.c    | 402 +++++++++++++++++++++---------------------------
 target-m68k/helper.h    |   6 +-
 target-m68k/op_helper.c |  30 ++--
 target-m68k/qregs.def   |   6 +-
 target-m68k/translate.c | 384 ++++++++++++++++++++-------------------------
 7 files changed, 389 insertions(+), 487 deletions(-)

diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 81f1579..5ea154f 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -57,7 +57,7 @@ static void m68k_cpu_reset(CPUState *s)
 #endif
     m68k_switch_sp(env);
     /* ??? FP regs should be initialized to NaN.  */
-    env->cc_op = CC_OP_FLAGS;
+    cpu_m68k_set_ccr(env, 0);
     /* TODO: We should set PC from the interrupt vector.  */
     env->pc = 0;
     tlb_flush(s, 1);
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 8347d04..9415d2b 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -74,9 +74,11 @@ typedef struct CPUM68KState {
 
     /* Condition flags.  */
     uint32_t cc_op;
-    uint32_t cc_dest;
-    uint32_t cc_src;
-    uint32_t cc_x;
+    uint32_t cc_x; /* always 0/1 */
+    uint32_t cc_n; /* in bit 31 (i.e. negative) */
+    uint32_t cc_v; /* in bit 31, unused, or computed from cc_n and cc_v */
+    uint32_t cc_c; /* either 0/1, unused, or computed from cc_n and cc_v */
+    uint32_t cc_z; /* == 0 or unused */
 
     float64 fregs[8];
     float64 fp_result;
@@ -133,27 +135,23 @@ uint32_t cpu_m68k_get_ccr(CPUM68KState *env);
 void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t);
 
 typedef enum {
-    CC_OP_DYNAMIC, /* Use env->cc_op  */
-    CC_OP_FLAGS, /* CC_DEST = CVZN, CC_SRC = unused */
-    CC_OP_LOGICB, /* CC_DEST = result, CC_SRC = unused */
-    CC_OP_LOGICW, /* CC_DEST = result, 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_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_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 */
-    CC_OP_NB,
+    /* Translator only -- use env->cc_op.  */
+    CC_OP_DYNAMIC = -1,
+
+    /* Each flag bit computed into cc_[xcnvz].  */
+    CC_OP_FLAGS,
+
+    /* X in cc_x, C = X, N in cc_n, Z in cc_n, V via cc_n/cc_v.  */
+    CC_OP_ADD,
+    CC_OP_SUB,
+
+    /* X in cc_x, {N,Z,C,V} via cc_n/cc_v.  */
+    CC_OP_CMP,
+
+    /* X in cc_x, C = 0, V = 0, N in cc_n, Z in cc_n.  */
+    CC_OP_LOGIC,
+
+    CC_OP_NB
 } CCOp;
 
 #define CCF_C 0x01
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 9c14d6f..8758016 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -131,151 +131,6 @@ void m68k_cpu_init_gdb(M68kCPU *cpu)
     /* TODO: Add [E]MAC registers.  */
 }
 
-static uint32_t cpu_m68k_flush_flags(CPUM68KState *env, int op)
-{
-    int flags;
-    uint32_t src;
-    uint32_t dest;
-    uint32_t tmp;
-
-#define HIGHBIT(type) (1u << (sizeof(type) * 8 - 1))
-
-#define SET_NZ(x, type) do { \
-        if ((type)(x) == 0) { \
-            flags |= CCF_Z; \
-        } else if ((type)(x) < 0) { \
-            flags |= CCF_N; \
-        } \
-    } while (0)
-
-#define SET_FLAGS_SUB(type, utype) do { \
-        SET_NZ(dest, type); \
-        tmp = dest + src; \
-        if ((utype) tmp < (utype) src) { \
-            flags |= CCF_C; \
-        } \
-        if (HIGHBIT(type) & (tmp ^ dest) & (tmp ^ src)) { \
-            flags |= CCF_V; \
-        } \
-    } while (0)
-
-#define SET_FLAGS_ADD(type, utype) do { \
-        SET_NZ(dest, type); \
-        if ((utype) dest < (utype) src) { \
-            flags |= CCF_C; \
-        } \
-        tmp = dest - src; \
-        if (HIGHBIT(type) & (src ^ dest) & ~(tmp ^ src)) { \
-            flags |= CCF_V; \
-        } \
-    } while (0)
-
-#define SET_FLAGS_ADDX(type, utype) do { \
-        SET_NZ(dest, type); \
-        if ((utype) dest <= (utype) src) { \
-            flags |= CCF_C; \
-        } \
-        tmp = dest - src - 1; \
-        if (HIGHBIT(type) & (src ^ dest) & ~(tmp ^ src)) { \
-            flags |= CCF_V; \
-        } \
-    } while (0)
-
-#define SET_FLAGS_SUBX(type, utype) do { \
-        SET_NZ(dest, type); \
-        tmp = dest + src + 1; \
-        if ((utype) tmp <= (utype) src) { \
-            flags |= CCF_C; \
-        } \
-        if (HIGHBIT(type) & (tmp ^ dest) & (tmp ^ src)) { \
-            flags |= CCF_V; \
-        } \
-    } while (0)
-
-#define SET_FLAGS_SHIFT(type) do { \
-    SET_NZ(dest, type); \
-    flags |= src; \
-    } while (0)
-
-    flags = 0;
-    src = env->cc_src;
-    dest = env->cc_dest;
-    switch (op) {
-    case CC_OP_FLAGS:
-        flags = dest;
-        break;
-    case CC_OP_LOGICB:
-        SET_NZ(dest, int8_t);
-        break;
-    case CC_OP_LOGICW:
-        SET_NZ(dest, int16_t);
-        break;
-    case CC_OP_LOGIC:
-        SET_NZ(dest, int32_t);
-        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_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_ADDXB:
-        SET_FLAGS_ADDX(int8_t, uint8_t);
-        break;
-    case CC_OP_ADDXW:
-        SET_FLAGS_ADDX(int16_t, uint16_t);
-        break;
-    case CC_OP_ADDX:
-        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_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_FLAGS_SHIFT(int32_t);
-        break;
-    default:
-        g_assert_not_reached();
-    }
-    return flags;
-}
-
-uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
-{
-    return cpu_m68k_flush_flags(env, env->cc_op) | env->cc_x * CCF_X;
-}
-
-void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t val)
-{
-    env->cc_op = CC_OP_FLAGS;
-    env->cc_dest = val & 0xf;
-    env->cc_x = (val & CCF_X ? 1 : 0);
-}
-
 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
 {
     M68kCPU *cpu = m68k_env_get_cpu(env);
@@ -412,59 +267,52 @@ uint32_t HELPER(ff1)(uint32_t x)
     return n;
 }
 
-uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
+uint32_t HELPER(sats)(uint32_t val, uint32_t v)
 {
     /* The result has the opposite sign to the original value.  */
-    if (ccr & CCF_V)
+    if ((int32_t)v < 0) {
         val = (((int32_t)val) >> 31) ^ SIGNBIT;
+    }
     return val;
 }
 
 uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 {
-    uint32_t res;
-    uint32_t old_flags;
-    int op;
+    uint32_t res, new_x;
 
-    old_flags = env->cc_dest;
     if (env->cc_x) {
-        env->cc_x = (op1 <= op2);
-        op = CC_OP_SUBX;
+        new_x = (op1 <= op2);
         res = op1 - (op2 + 1);
     } else {
-        env->cc_x = (op1 < op2);
-        op = CC_OP_SUB;
+        new_x = (op1 < op2);
         res = op1 - op2;
     }
-    env->cc_dest = res;
-    env->cc_src = op2;
-    env->cc_dest = cpu_m68k_flush_flags(env, op);
-    /* !Z is sticky.  */
-    env->cc_dest &= (old_flags | ~CCF_Z);
+    env->cc_x = new_x;
+    env->cc_c = new_x;
+    env->cc_n = res;
+    env->cc_z |= res; /* !Z is sticky */
+    env->cc_v = (res ^ op1) & (op1 ^ op2);
+
     return res;
 }
 
 uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 {
-    uint32_t res;
-    uint32_t old_flags;
-    int op;
+    uint32_t res, new_x;
 
-    old_flags = env->cc_dest;
     if (env->cc_x) {
         res = op1 + op2 + 1;
-        env->cc_x = (res <= op2);
-        op = CC_OP_ADDX;
+        new_x = (res <= op2);
     } else {
         res = op1 + op2;
-        env->cc_x = (res < op2);
-        op = CC_OP_ADD;
-    }
-    env->cc_dest = res;
-    env->cc_src = op2;
-    env->cc_dest = cpu_m68k_flush_flags(env, op);
-    /* !Z is sticky.  */
-    env->cc_dest &= (old_flags | ~CCF_Z);
+        new_x = (res < op2);
+    }
+    env->cc_x = new_x;
+    env->cc_c = new_x;
+    env->cc_n = res;
+    env->cc_z |= res; /* !Z is sticky.  */
+    env->cc_v = (res ^ op1) & ~(op1 ^ op2);
+
     return res;
 }
 
@@ -477,73 +325,53 @@ void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
 
 uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
 {
-    uint32_t result;
-    uint32_t cf;
+    uint64_t result;
 
     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;
+    result = (uint64_t)val << shift;
+
+    env->cc_c = (result >> 32) & 1;
+    env->cc_n = result;
+    env->cc_z = result;
+    env->cc_v = 0;
+    env->cc_x = shift ? env->cc_c : env->cc_x;
+
     return result;
 }
 
 uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
 {
+    uint64_t temp;
     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;
+    temp = (uint64_t)val << 32 >> shift;
+    result = temp >> 32;
+
+    env->cc_c = (temp >> 31) & 1;
+    env->cc_n = result;
+    env->cc_z = result;
+    env->cc_v = 0;
+    env->cc_x = shift ? env->cc_c : env->cc_x;
+
     return result;
 }
 
 uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
 {
+    uint64_t temp;
     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;
+    temp = (int64_t)val << 32 >> shift;
+    result = temp >> 32;
+
+    env->cc_c = (temp >> 31) & 1;
+    env->cc_n = result;
+    env->cc_z = result;
+    env->cc_v = result ^ val;
+    env->cc_x = shift ? env->cc_c : env->cc_x;
+
     return result;
 }
 
@@ -795,9 +623,133 @@ void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
     }
 }
 
-uint32_t HELPER(flush_flags)(CPUM68KState *env, uint32_t op)
+uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
 {
-    return cpu_m68k_flush_flags(env, op);
+    uint32_t x, c, n, z, v;
+    uint32_t res, src1, src2;
+
+    x = env->cc_x;
+    c = env->cc_c;
+    n = env->cc_n;
+    z = env->cc_z;
+    v = env->cc_v;
+
+    switch (env->cc_op) {
+    case CC_OP_FLAGS:
+        /* Everything in place.  */
+        break;
+
+    case CC_OP_ADD:
+        res = n;
+        src2 = v;
+        src1 = res - src2;
+        c = x;
+        z = n;
+        v = (res ^ src1) & ~(src1 ^ src2);
+        break;
+
+    case CC_OP_SUB:
+        res = n;
+        src2 = v;
+        src1 = res + src2;
+        c = x;
+        z = n;
+        v = (res ^ src1) & (src1 ^ src2);
+        break;
+
+    case CC_OP_CMP:
+        src1 = n;
+        src2 = v;
+        res = src1 - src2;
+        n = res;
+        z = res;
+        c = src1 < src2;
+        v = (res ^ src1) & (src1 ^ src2);
+        break;
+
+    case CC_OP_LOGIC:
+        c = v = 0;
+        z = n;
+        break;
+
+    default:
+        cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", env->cc_op);
+    }
+
+    n = n >> 31;
+    v = v >> 31;
+    z = (z == 0);
+
+    return x*CCF_X + n*CCF_N + z*CCF_Z + v*CCF_V + c*CCF_C;
+}
+
+uint32_t HELPER(get_ccr)(CPUM68KState *env)
+{
+    return cpu_m68k_get_ccr(env);
+}
+
+void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr)
+{
+    env->cc_x = (ccr & CCF_X ? 1 : 0);
+    env->cc_n = (ccr & CCF_N ? -1 : 0);
+    env->cc_z = (ccr & CCF_Z ? 0 : 1);
+    env->cc_v = (ccr & CCF_V ? -1 : 0);
+    env->cc_c = (ccr & CCF_C ? 1 : 0);
+    env->cc_op = CC_OP_FLAGS;
+}
+
+void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr)
+{
+    cpu_m68k_set_ccr(env, ccr);
+}
+
+void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
+{
+    uint32_t res, src1, src2;
+
+    switch (cc_op) {
+    case CC_OP_FLAGS:
+        /* Everything up to date.  */
+        return;
+
+    case CC_OP_ADD:
+        res = env->cc_n;
+        src2 = env->cc_v;
+        src1 = res - src2;
+        env->cc_z = res;
+        env->cc_c = env->cc_x;
+        env->cc_v = (res ^ src1) & ~(src1 ^ src2);
+        break;
+
+    case CC_OP_SUB:
+        res = env->cc_n;
+        src2 = env->cc_v;
+        src1 = res + src2;
+        env->cc_z = res;
+        env->cc_c = env->cc_x;
+        env->cc_v = (res ^ src1) & (src1 ^ src2);
+        break;
+
+    case CC_OP_CMP:
+        src1 = env->cc_n;
+        src2 = env->cc_v;
+        res = src1 - src2;
+        env->cc_n = res;
+        env->cc_z = res;
+        env->cc_c = src1 < src2;
+        env->cc_v = (res ^ src1) & (src1 ^ src2);
+        break;
+
+    case CC_OP_LOGIC:
+        env->cc_c = 0;
+        env->cc_v = 0;
+        env->cc_z = env->cc_n;
+        break;
+
+    default:
+        cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", cc_op);
+    }
+    env->cc_op = CC_OP_FLAGS;
 }
 
 uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index 0f5a7cf..c868148 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -1,6 +1,6 @@
 DEF_HELPER_1(bitrev, i32, i32)
 DEF_HELPER_1(ff1, i32, i32)
-DEF_HELPER_2(sats, i32, i32, i32)
+DEF_HELPER_FLAGS_2(sats, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_2(divu, void, env, i32)
 DEF_HELPER_2(divs, void, env, i32)
 DEF_HELPER_3(addx_cc, i32, env, i32, i32)
@@ -45,5 +45,7 @@ DEF_HELPER_3(set_mac_extf, void, env, i32, i32)
 DEF_HELPER_3(set_mac_exts, void, env, i32, i32)
 DEF_HELPER_3(set_mac_extu, void, env, i32, i32)
 
-DEF_HELPER_2(flush_flags, i32, env, i32)
+DEF_HELPER_2(flush_flags, void, env, i32)
+DEF_HELPER_2(set_ccr, void, env, i32)
+DEF_HELPER_FLAGS_1(get_ccr, TCG_CALL_NO_WG_SE, i32, env)
 DEF_HELPER_2(raise_exception, void, env, i32)
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 9262946..1c95ea0 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -184,7 +184,6 @@ void HELPER(divu)(CPUM68KState *env, uint32_t word)
     uint32_t den;
     uint32_t quot;
     uint32_t rem;
-    uint32_t flags;
 
     num = env->div1;
     den = env->div2;
@@ -194,16 +193,14 @@ void HELPER(divu)(CPUM68KState *env, uint32_t word)
     }
     quot = num / den;
     rem = num % den;
-    flags = 0;
-    if (word && quot > 0xffff)
-        flags |= CCF_V;
-    if (quot == 0)
-        flags |= CCF_Z;
-    else if ((int32_t)quot < 0)
-        flags |= CCF_N;
+
+    env->cc_v = (word && quot > 0xffff ? -1 : 0);
+    env->cc_z = quot;
+    env->cc_n = quot;
+    env->cc_c = 0;
+
     env->div1 = quot;
     env->div2 = rem;
-    env->cc_dest = flags;
 }
 
 void HELPER(divs)(CPUM68KState *env, uint32_t word)
@@ -212,7 +209,6 @@ void HELPER(divs)(CPUM68KState *env, uint32_t word)
     int32_t den;
     int32_t quot;
     int32_t rem;
-    int32_t flags;
 
     num = env->div1;
     den = env->div2;
@@ -221,14 +217,12 @@ void HELPER(divs)(CPUM68KState *env, uint32_t word)
     }
     quot = num / den;
     rem = num % den;
-    flags = 0;
-    if (word && quot != (int16_t)quot)
-        flags |= CCF_V;
-    if (quot == 0)
-        flags |= CCF_Z;
-    else if (quot < 0)
-        flags |= CCF_N;
+
+    env->cc_v = (word && quot != (int16_t)quot ? -1 : 0);
+    env->cc_z = quot;
+    env->cc_n = quot;
+    env->cc_c = 0;
+
     env->div1 = quot;
     env->div2 = rem;
-    env->cc_dest = flags;
 }
diff --git a/target-m68k/qregs.def b/target-m68k/qregs.def
index 204663e..156c0f5 100644
--- a/target-m68k/qregs.def
+++ b/target-m68k/qregs.def
@@ -2,9 +2,11 @@ DEFF64(FP_RESULT, fp_result)
 DEFO32(PC, pc)
 DEFO32(SR, sr)
 DEFO32(CC_OP, cc_op)
-DEFO32(CC_DEST, cc_dest)
-DEFO32(CC_SRC, cc_src)
 DEFO32(CC_X, cc_x)
+DEFO32(CC_C, cc_c)
+DEFO32(CC_N, cc_n)
+DEFO32(CC_V, cc_v)
+DEFO32(CC_Z, cc_z)
 DEFO32(DIV1, div1)
 DEFO32(DIV2, div2)
 DEFO32(MACSR, macsr)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 37c1b95..c3d7318 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -132,6 +132,7 @@ typedef struct DisasContext {
     target_ulong pc;
     int is_jmp;
     CCOp cc_op; /* Current CC operation */
+    int cc_op_synced;
     int user;
     uint32_t fpcr;
     struct TranslationBlock *tb;
@@ -173,49 +174,44 @@ typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t insn);
                              uint16_t insn)
 #endif
 
-enum {
-    USES_CC_DST  = 1,
-    USES_CC_SRC  = 2,
-};
-
 static const uint8_t cc_op_live[CC_OP_NB] = {
-    [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC,
-    [CC_OP_FLAGS] = USES_CC_DST,
-    [CC_OP_LOGICB ... CC_OP_LOGIC] = USES_CC_DST,
-    [CC_OP_ADDB ... CC_OP_ADD] = USES_CC_DST | USES_CC_SRC,
-    [CC_OP_SUBB ... CC_OP_SUB] = USES_CC_DST | USES_CC_SRC,
-    [CC_OP_ADDXB ... CC_OP_ADDX] = USES_CC_DST | USES_CC_SRC,
-    [CC_OP_SUBXB ... CC_OP_SUBX] = USES_CC_DST | USES_CC_SRC,
-    [CC_OP_SHIFTB ... CC_OP_SHIFT] = USES_CC_DST | USES_CC_SRC,
+    [CC_OP_FLAGS] = CCF_C | CCF_V | CCF_Z | CCF_N | CCF_X,
+    [CC_OP_ADD] = CCF_X | CCF_N | CCF_V,
+    [CC_OP_SUB] = CCF_X | CCF_N | CCF_V,
+    [CC_OP_CMP] = CCF_X | CCF_N | CCF_V,
+    [CC_OP_LOGIC] = CCF_X | CCF_N
 };
 
 static void set_cc_op(DisasContext *s, CCOp op)
 {
+    CCOp old_op = s->cc_op;
     int dead;
 
-    if (s->cc_op == op) {
+    if (old_op == op) {
         return;
     }
+    s->cc_op = op;
+    s->cc_op_synced = 0;
 
-    /* Discard CC computation that will no longer be used.  */
-
-    dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
-    if (dead & USES_CC_DST) {
-        tcg_gen_discard_i32(QREG_CC_DEST);
+    /* Discard CC computation that will no longer be used.
+       Note that X and N are never dead.  */
+    dead = cc_op_live[old_op] & ~cc_op_live[op];
+    if (dead & CCF_C) {
+        tcg_gen_discard_i32(QREG_CC_C);
     }
-    if (dead & USES_CC_SRC) {
-        tcg_gen_discard_i32(QREG_CC_SRC);
+    if (dead & CCF_Z) {
+        tcg_gen_discard_i32(QREG_CC_Z);
     }
-    if (s->cc_op == CC_OP_DYNAMIC) {
-        tcg_gen_discard_i32(QREG_CC_OP);
+    if (dead & CCF_V) {
+        tcg_gen_discard_i32(QREG_CC_V);
     }
-    s->cc_op = op;
 }
 
 /* Update the CPU env CC_OP state.  */
-static inline void update_cc_op(DisasContext *s)
+static void update_cc_op(DisasContext *s)
 {
-    if (s->cc_op != CC_OP_DYNAMIC) {
+    if (!s->cc_op_synced) {
+        s->cc_op_synced = 1;
         tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
     }
 }
@@ -458,41 +454,79 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
 
 /* Evaluate all the CC flags.  */
 
-static inline void gen_flush_flags(DisasContext *s)
+static void gen_flush_flags(DisasContext *s)
 {
-    if (s->cc_op == CC_OP_FLAGS)
+    TCGv tmp;
+
+    switch (s->cc_op) {
+    case CC_OP_FLAGS:
         return;
-    if (s->cc_op == CC_OP_DYNAMIC) {
-        gen_helper_flush_flags(QREG_CC_DEST, cpu_env, QREG_CC_OP);
-    } else {
-        gen_helper_flush_flags(QREG_CC_DEST, cpu_env, tcg_const_i32(s->cc_op));
+    case CC_OP_DYNAMIC:
+        gen_helper_flush_flags(cpu_env, QREG_CC_OP);
+        break;
+    default:
+        tmp = tcg_const_i32(s->cc_op);
+        gen_helper_flush_flags(cpu_env, tmp);
+        tcg_temp_free(tmp);
+        break;
     }
-    set_cc_op(s, CC_OP_FLAGS);
+
+    /* Note that flush_flags also assigned to env->cc_op.  */
+    s->cc_op = CC_OP_FLAGS;
+    s->cc_op_synced = 1;
 }
 
-#define SET_CC_OP(opsize, op) do { \
-    switch (opsize) { \
-    case OS_BYTE: \
-        set_cc_op(s, CC_OP_##op##B); break; \
-    case OS_WORD: \
-        set_cc_op(s, CC_OP_##op##W); break; \
-    case OS_LONG: \
-        set_cc_op(s, CC_OP_##op); break; \
-    default: \
-        abort(); \
-    } \
-} while (0)
+/* Sign or zero extend a value.  */
+
+static inline void gen_ext(TCGv res, TCGv val, int opsize, int sign)
+{
+    switch (opsize) {
+    case OS_BYTE:
+        if (sign) {
+            tcg_gen_ext8s_i32(res, val);
+        } else {
+            tcg_gen_ext8u_i32(res, val);
+        }
+        break;
+    case OS_WORD:
+        if (sign) {
+            tcg_gen_ext16s_i32(res, val);
+        } else {
+            tcg_gen_ext16u_i32(res, val);
+        }
+        break;
+    case OS_LONG:
+        tcg_gen_mov_i32(res, val);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+static TCGv gen_extend(TCGv val, int opsize, int sign)
+{
+    TCGv tmp;
+
+    if (opsize == OS_LONG) {
+        tmp = val;
+    } else {
+        tmp = tcg_temp_new();
+        gen_ext(tmp, val, opsize, sign);
+    }
+
+    return tmp;
+}
 
 static void gen_logic_cc(DisasContext *s, TCGv val, int opsize)
 {
-    tcg_gen_mov_i32(QREG_CC_DEST, val);
-    SET_CC_OP(opsize, LOGIC);
+    gen_ext(QREG_CC_N, val, opsize, 1);
+    set_cc_op(s, CC_OP_LOGIC);
 }
 
 static void gen_update_cc_add(TCGv dest, TCGv src)
 {
-    tcg_gen_mov_i32(QREG_CC_DEST, dest);
-    tcg_gen_mov_i32(QREG_CC_SRC, src);
+    tcg_gen_mov_i32(QREG_CC_N, dest);
+    tcg_gen_mov_i32(QREG_CC_V, src);
 }
 
 static inline int opsize_bytes(int opsize)
@@ -547,36 +581,6 @@ static void gen_partset_reg(int opsize, TCGv reg, TCGv val)
     }
 }
 
-/* Sign or zero extend a value.  */
-static inline TCGv gen_extend(TCGv val, int opsize, int sign)
-{
-    TCGv tmp;
-
-    switch (opsize) {
-    case OS_BYTE:
-        tmp = tcg_temp_new();
-        if (sign)
-            tcg_gen_ext8s_i32(tmp, val);
-        else
-            tcg_gen_ext8u_i32(tmp, val);
-        break;
-    case OS_WORD:
-        tmp = tcg_temp_new();
-        if (sign)
-            tcg_gen_ext16s_i32(tmp, val);
-        else
-            tcg_gen_ext16u_i32(tmp, val);
-        break;
-    case OS_LONG:
-    case OS_SINGLE:
-        tmp = val;
-        break;
-    default:
-        g_assert_not_reached();
-    }
-    return tmp;
-}
-
 /* Generate code for an "effective address".  Does not adjust the base
    register for autoincrement addressing modes.  */
 static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
@@ -755,7 +759,8 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
 /* This generates a conditional branch, clobbering all temporaries.  */
 static void gen_jmpcc(DisasContext *s, int cond, TCGLabel *l1)
 {
-    TCGv tmp;
+    TCGv tmp, tmp2;
+    TCGCond tcond;
 
     /* TODO: Optimize compare/branch pairs rather than always flushing
        flag state to CC_OP_FLAGS.  */
@@ -764,97 +769,57 @@ static void gen_jmpcc(DisasContext *s, int cond, TCGLabel *l1)
     switch (cond) {
     case 0: /* T */
         tcg_gen_br(l1);
-        break;
+        return;
     case 1: /* F */
-        break;
-    case 2: /* HI (!C && !Z) */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C | CCF_Z);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
-        break;
+        return;
+    case 2: /* HI (!C && !Z) -> !(C || Z)*/
     case 3: /* LS (C || Z) */
         tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C | CCF_Z);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, QREG_CC_Z, 0);
+        tcg_gen_or_i32(tmp, tmp, QREG_CC_C);
+        tcond = (cond & 1 ? TCG_COND_NE: TCG_COND_EQ);
         break;
     case 4: /* CC (!C) */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
-        break;
     case 5: /* CS (C) */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        tmp = QREG_CC_C;
+        tcond = (cond & 1 ? TCG_COND_NE : TCG_COND_EQ);
         break;
     case 6: /* NE (!Z) */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_Z);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
-        break;
     case 7: /* EQ (Z) */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_Z);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        tmp = QREG_CC_Z;
+        tcond = (cond & 1 ? TCG_COND_EQ : TCG_COND_NE);
         break;
     case 8: /* VC (!V) */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_V);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
-        break;
     case 9: /* VS (V) */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_V);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        tmp = QREG_CC_V;
+        tcond = (cond & 1 ? TCG_COND_LT : TCG_COND_GE);
         break;
     case 10: /* PL (!N) */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
-        break;
     case 11: /* MI (N) */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        tmp = QREG_CC_N;
+        tcond = (cond & 1 ? TCG_COND_LT : TCG_COND_GE);
         break;
     case 12: /* GE (!(N ^ V)) */
-        tmp = tcg_temp_new();
-        assert(CCF_V == (CCF_N >> 2));
-        tcg_gen_shri_i32(tmp, QREG_CC_DEST, 2);
-        tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
-        tcg_gen_andi_i32(tmp, tmp, CCF_V);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
-        break;
     case 13: /* LT (N ^ V) */
         tmp = tcg_temp_new();
-        assert(CCF_V == (CCF_N >> 2));
-        tcg_gen_shri_i32(tmp, QREG_CC_DEST, 2);
-        tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
-        tcg_gen_andi_i32(tmp, tmp, CCF_V);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        tcg_gen_xor_i32(tmp, QREG_CC_N, QREG_CC_V);
+        tcond = (cond & 1 ? TCG_COND_LT : TCG_COND_GE);
         break;
     case 14: /* GT (!(Z || (N ^ V))) */
-        tmp = tcg_temp_new();
-        assert(CCF_V == (CCF_N >> 2));
-        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
-        tcg_gen_shri_i32(tmp, tmp, 2);
-        tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
-        tcg_gen_andi_i32(tmp, tmp, CCF_V | CCF_Z);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
-        break;
     case 15: /* LE (Z || (N ^ V)) */
         tmp = tcg_temp_new();
-        assert(CCF_V == (CCF_N >> 2));
-        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
-        tcg_gen_shri_i32(tmp, tmp, 2);
-        tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
-        tcg_gen_andi_i32(tmp, tmp, CCF_V | CCF_Z);
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
+        tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, QREG_CC_Z, 0);
+        tcg_gen_neg_i32(tmp, tmp);
+        tmp2 = tcg_temp_new();
+        tcg_gen_xor_i32(tmp2, QREG_CC_N, QREG_CC_V);
+        tcg_gen_or_i32(tmp, tmp, tmp2);
+        tcond = (cond & 1 ? TCG_COND_LT : TCG_COND_GE);
         break;
     default:
         /* Should ever happen.  */
         abort();
     }
+  tcg_gen_brcondi_i32(tcond, tmp, 0, l1);
 }
 
 DISAS_INSN(scc)
@@ -1012,6 +977,7 @@ DISAS_INSN(divw)
     tcg_gen_ext16u_i32(tmp, QREG_DIV1);
     tcg_gen_shli_i32(src, QREG_DIV2, 16);
     tcg_gen_or_i32(reg, tmp, src);
+
     set_cc_op(s, CC_OP_FLAGS);
 }
 
@@ -1107,42 +1073,43 @@ DISAS_INSN(bitop_reg)
     else
         opsize = OS_LONG;
     op = (insn >> 6) & 3;
+
+    gen_flush_flags(s);
+
     SRC_EA(env, src1, opsize, 0, op ? &addr: NULL);
     src2 = DREG(insn, 9);
     dest = tcg_temp_new();
 
-    gen_flush_flags(s);
     tmp = tcg_temp_new();
     if (opsize == OS_BYTE)
         tcg_gen_andi_i32(tmp, src2, 7);
     else
         tcg_gen_andi_i32(tmp, src2, 31);
-    src2 = tmp;
-    tmp = tcg_temp_new();
-    tcg_gen_shr_i32(tmp, src1, src2);
-    tcg_gen_andi_i32(tmp, tmp, 1);
-    tcg_gen_shli_i32(tmp, tmp, 2);
-    /* Clear CCF_Z if bit set.  */
-    tcg_gen_ori_i32(QREG_CC_DEST, QREG_CC_DEST, CCF_Z);
-    tcg_gen_xor_i32(QREG_CC_DEST, QREG_CC_DEST, tmp);
-
-    tcg_gen_shl_i32(tmp, tcg_const_i32(1), src2);
+
+    src2 = tcg_const_i32(1);
+    tcg_gen_shl_i32(src2, src2, tmp);
+    tcg_temp_free(tmp);
+
+    tcg_gen_and_i32(QREG_CC_Z, src1, src2);
+
     switch (op) {
     case 1: /* bchg */
-        tcg_gen_xor_i32(dest, src1, tmp);
+        tcg_gen_xor_i32(dest, src1, src2);
         break;
     case 2: /* bclr */
-        tcg_gen_not_i32(tmp, tmp);
-        tcg_gen_and_i32(dest, src1, tmp);
+        tcg_gen_andc_i32(dest, src1, src2);
         break;
     case 3: /* bset */
-        tcg_gen_or_i32(dest, src1, tmp);
+        tcg_gen_or_i32(dest, src1, src2);
         break;
     default: /* btst */
         break;
     }
-    if (op)
+    tcg_temp_free(src2);
+    if (op) {
         DEST_EA(env, insn, opsize, dest, &addr);
+    }
+    tcg_temp_free(dest);
 }
 
 DISAS_INSN(sats)
@@ -1150,7 +1117,7 @@ DISAS_INSN(sats)
     TCGv reg;
     reg = DREG(insn, 0);
     gen_flush_flags(s);
-    gen_helper_sats(reg, reg, QREG_CC_DEST);
+    gen_helper_sats(reg, reg, QREG_CC_V);
     gen_logic_cc(s, reg, OS_LONG);
 }
 
@@ -1222,28 +1189,20 @@ DISAS_INSN(bitop_im)
         return;
     }
 
+    gen_flush_flags(s);
+
     SRC_EA(env, src1, opsize, 0, op ? &addr: NULL);
 
-    gen_flush_flags(s);
     if (opsize == OS_BYTE)
         bitnum &= 7;
     else
         bitnum &= 31;
     mask = 1 << bitnum;
 
-    tmp = tcg_temp_new();
-    assert (CCF_Z == (1 << 2));
-    if (bitnum > 2)
-        tcg_gen_shri_i32(tmp, src1, bitnum - 2);
-    else if (bitnum < 2)
-        tcg_gen_shli_i32(tmp, src1, 2 - bitnum);
-    else
-        tcg_gen_mov_i32(tmp, src1);
-    tcg_gen_andi_i32(tmp, tmp, CCF_Z);
-    /* Clear CCF_Z if bit set.  */
-    tcg_gen_ori_i32(QREG_CC_DEST, QREG_CC_DEST, CCF_Z);
-    tcg_gen_xor_i32(QREG_CC_DEST, QREG_CC_DEST, tmp);
+    tcg_gen_andi_i32(QREG_CC_Z, src1, mask);
+
     if (op) {
+        tmp = tcg_temp_new();
         switch (op) {
         case 1: /* bchg */
             tcg_gen_xori_i32(tmp, src1, mask);
@@ -1258,8 +1217,10 @@ DISAS_INSN(bitop_im)
             break;
         }
         DEST_EA(env, insn, opsize, tmp, &addr);
+        tcg_temp_free(tmp);
     }
 }
+
 DISAS_INSN(arith_im)
 {
     int op;
@@ -1283,7 +1244,7 @@ DISAS_INSN(arith_im)
         break;
     case 2: /* subi */
         tcg_gen_mov_i32(dest, src1);
-        tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, tcg_const_i32(im));
+        tcg_gen_setcondi_i32(TCG_COND_LTU, QREG_CC_X, dest, im);
         tcg_gen_subi_i32(dest, dest, im);
         gen_update_cc_add(dest, tcg_const_i32(im));
         set_cc_op(s, CC_OP_SUB);
@@ -1292,7 +1253,7 @@ DISAS_INSN(arith_im)
         tcg_gen_mov_i32(dest, src1);
         tcg_gen_addi_i32(dest, dest, im);
         gen_update_cc_add(dest, tcg_const_i32(im));
-        tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, tcg_const_i32(im));
+        tcg_gen_setcondi_i32(TCG_COND_LTU, QREG_CC_X, dest, im);
         set_cc_op(s, CC_OP_ADD);
         break;
     case 5: /* eori */
@@ -1300,10 +1261,8 @@ DISAS_INSN(arith_im)
         gen_logic_cc(s, dest, OS_LONG);
         break;
     case 6: /* cmpi */
-        tcg_gen_mov_i32(dest, src1);
-        tcg_gen_subi_i32(dest, dest, im);
-        gen_update_cc_add(dest, tcg_const_i32(im));
-        set_cc_op(s, CC_OP_SUB);
+        gen_update_cc_add(src1, tcg_const_i32(im));
+        set_cc_op(s, CC_OP_CMP);
         break;
     default:
         abort();
@@ -1395,9 +1354,9 @@ static TCGv gen_get_ccr(DisasContext *s)
     TCGv dest;
 
     gen_flush_flags(s);
+    update_cc_op(s);
     dest = tcg_temp_new();
-    tcg_gen_shli_i32(dest, QREG_CC_X, 4);
-    tcg_gen_or_i32(dest, dest, QREG_CC_DEST);
+    gen_helper_get_ccr(dest, cpu_env);
     return dest;
 }
 
@@ -1419,37 +1378,39 @@ DISAS_INSN(neg)
     tcg_gen_mov_i32(src1, reg);
     tcg_gen_neg_i32(reg, src1);
     gen_update_cc_add(reg, src1);
-    tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, tcg_const_i32(0), src1);
+    tcg_gen_setcondi_i32(TCG_COND_NE, QREG_CC_X, src1, 0);
     set_cc_op(s, CC_OP_SUB);
 }
 
 static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
 {
-    tcg_gen_movi_i32(QREG_CC_DEST, val & 0xf);
-    tcg_gen_movi_i32(QREG_CC_X, (val & 0x10) >> 4);
-    if (!ccr_only) {
-        gen_helper_set_sr(cpu_env, tcg_const_i32(val & 0xff00));
+    if (ccr_only) {
+        tcg_gen_movi_i32(QREG_CC_C, val & CCF_C ? 1 : 0);
+        tcg_gen_movi_i32(QREG_CC_V, val & CCF_V ? -1 : 0);
+        tcg_gen_movi_i32(QREG_CC_Z, val & CCF_Z ? 0 : 1);
+        tcg_gen_movi_i32(QREG_CC_N, val & CCF_N ? -1 : 0);
+        tcg_gen_movi_i32(QREG_CC_X, val & CCF_X ? 1 : 0);
+    } else {
+        gen_helper_set_sr(cpu_env, tcg_const_i32(val));
     }
     set_cc_op(s, CC_OP_FLAGS);
 }
 
 static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only)
 {
-    TCGv tmp;
-    tmp = tcg_temp_new();
-    tcg_gen_andi_i32(QREG_CC_DEST, val, 0xf);
-    tcg_gen_shri_i32(tmp, val, 4);
-    tcg_gen_andi_i32(QREG_CC_X, tmp, 1);
-    if (!ccr_only) {
+    if (ccr_only) {
+        gen_helper_set_ccr(cpu_env, val);
+    } else {
         gen_helper_set_sr(cpu_env, val);
     }
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 static void gen_move_to_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
                            int ccr_only)
 {
     TCGv src;
-    s->cc_op = CC_OP_FLAGS;
+
     SRC_EA(env, src, OS_WORD, 0, NULL);
     gen_set_sr(s, src, ccr_only);
 }
@@ -1666,10 +1627,10 @@ DISAS_INSN(addsubq)
         src2 = tcg_const_i32(val);
         if (insn & 0x0100) {
             tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src2);
-            tcg_gen_subi_i32(dest, dest, val);
+            tcg_gen_sub_i32(dest, dest, src2);
             set_cc_op(s, CC_OP_SUB);
         } else {
-            tcg_gen_addi_i32(dest, dest, val);
+            tcg_gen_add_i32(dest, dest, src2);
             tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src2);
             set_cc_op(s, CC_OP_ADD);
         }
@@ -1713,18 +1674,16 @@ DISAS_INSN(branch)
         /* bsr */
         gen_push(s, tcg_const_i32(s->pc));
     }
+    update_cc_op(s);
     if (op > 1) {
         /* Bcc */
         l1 = gen_new_label();
         gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
-        update_cc_op(s);
         gen_jmp_tb(s, 1, base + offset);
         gen_set_label(l1);
-        update_cc_op(s);
         gen_jmp_tb(s, 0, s->pc);
     } else {
         /* Unconditional branch.  */
-        update_cc_op(s);
         gen_jmp_tb(s, 0, base + offset);
     }
 }
@@ -1813,16 +1772,13 @@ DISAS_INSN(cmp)
 {
     TCGv src;
     TCGv reg;
-    TCGv dest;
     int opsize;
 
     opsize = insn_opsize(insn);
     SRC_EA(env, 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);
+    gen_update_cc_add(reg, src);
+    set_cc_op(s, CC_OP_CMP);
 }
 
 DISAS_INSN(cmpa)
@@ -1830,7 +1786,6 @@ DISAS_INSN(cmpa)
     int opsize;
     TCGv src;
     TCGv reg;
-    TCGv dest;
 
     if (insn & 0x100) {
         opsize = OS_LONG;
@@ -1839,10 +1794,8 @@ DISAS_INSN(cmpa)
     }
     SRC_EA(env, src, opsize, 1, NULL);
     reg = AREG(insn, 9);
-    dest = tcg_temp_new();
-    tcg_gen_sub_i32(dest, reg, src);
-    gen_update_cc_add(dest, src);
-    SET_CC_OP(OS_LONG, SUB);
+    gen_update_cc_add(reg, src);
+    set_cc_op(s, CC_OP_CMP);
 }
 
 DISAS_INSN(eor)
@@ -1909,6 +1862,8 @@ DISAS_INSN(shift_im)
     int tmp;
     TCGv shift;
 
+    set_cc_op(s, CC_OP_FLAGS);
+
     reg = DREG(insn, 0);
     tmp = (insn >> 9) & 7;
     if (tmp == 0)
@@ -1924,7 +1879,6 @@ DISAS_INSN(shift_im)
             gen_helper_sar_cc(reg, cpu_env, reg, shift);
         }
     }
-    set_cc_op(s, CC_OP_SHIFT);
 }
 
 DISAS_INSN(shift_reg)
@@ -1934,8 +1888,6 @@ DISAS_INSN(shift_reg)
 
     reg = DREG(insn, 0);
     shift = DREG(insn, 9);
-    /* Shift by zero leaves C flag unmodified.   */
-    gen_flush_flags(s);
     if (insn & 0x100) {
         gen_helper_shl_cc(reg, cpu_env, reg, shift);
     } else {
@@ -1945,7 +1897,7 @@ DISAS_INSN(shift_reg)
             gen_helper_sar_cc(reg, cpu_env, reg, shift);
         }
     }
-    set_cc_op(s, CC_OP_SHIFT);
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 DISAS_INSN(ff1)
@@ -2755,9 +2707,10 @@ DISAS_INSN(from_mext)
 
 DISAS_INSN(macsr_to_ccr)
 {
-    tcg_gen_movi_i32(QREG_CC_X, 0);
-    tcg_gen_andi_i32(QREG_CC_DEST, QREG_MACSR, 0xf);
-    set_cc_op(s, CC_OP_FLAGS);
+    TCGv tmp = tcg_temp_new();
+    tcg_gen_andi_i32(tmp, QREG_MACSR, 0xf);
+    gen_set_sr(s, tmp, 1);
+    tcg_temp_free(tmp);
 }
 
 DISAS_INSN(to_mac)
@@ -3041,6 +2994,7 @@ void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
     dc->cc_op = CC_OP_DYNAMIC;
+    dc->cc_op_synced = 1;
     dc->singlestep_enabled = cs->singlestep_enabled;
     dc->fpcr = env->fpcr;
     dc->user = (env->sr & SR_S) == 0;
-- 
2.5.5

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

* [Qemu-devel] [PATCH 22/52] target-m68k: Introduce DisasCompare
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (20 preceding siblings ...)
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 21/52] target-m68k: Reorg flags handling Laurent Vivier
@ 2016-05-04 20:12 ` Laurent Vivier
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 23/52] target-m68k: Use setcond for scc Laurent Vivier
                   ` (13 subsequent siblings)
  35 siblings, 0 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

From: Richard Henderson <rth@twiddle.net>

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 85 +++++++++++++++++++++++++++++++++++--------------
 1 file changed, 61 insertions(+), 24 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index c3d7318..efd4d9c 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -756,8 +756,15 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
     return NULL_QREG;
 }
 
-/* This generates a conditional branch, clobbering all temporaries.  */
-static void gen_jmpcc(DisasContext *s, int cond, TCGLabel *l1)
+typedef struct {
+    TCGCond tcond;
+    bool g1;
+    bool g2;
+    TCGv v1;
+    TCGv v2;
+} DisasCompare;
+
+static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
 {
     TCGv tmp, tmp2;
     TCGCond tcond;
@@ -765,61 +772,92 @@ static void gen_jmpcc(DisasContext *s, int cond, TCGLabel *l1)
     /* TODO: Optimize compare/branch pairs rather than always flushing
        flag state to CC_OP_FLAGS.  */
     gen_flush_flags(s);
-    update_cc_op(s);
+
+    c->g1 = 1;
+    c->g2 = 0;
+    c->v2 = tcg_const_i32(0);
+
     switch (cond) {
     case 0: /* T */
-        tcg_gen_br(l1);
-        return;
     case 1: /* F */
-        return;
+        c->v1 = c->v2;
+        tcond = TCG_COND_NEVER;
+        break;
     case 2: /* HI (!C && !Z) -> !(C || Z)*/
     case 3: /* LS (C || Z) */
-        tmp = tcg_temp_new();
-        tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, QREG_CC_Z, 0);
+        c->v1 = tmp = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_setcond_i32(TCG_COND_EQ, tmp, QREG_CC_Z, c->v2);
         tcg_gen_or_i32(tmp, tmp, QREG_CC_C);
-        tcond = (cond & 1 ? TCG_COND_NE: TCG_COND_EQ);
+        tcond = TCG_COND_NE;
         break;
     case 4: /* CC (!C) */
     case 5: /* CS (C) */
-        tmp = QREG_CC_C;
-        tcond = (cond & 1 ? TCG_COND_NE : TCG_COND_EQ);
+        c->v1 = QREG_CC_C;
+        tcond = TCG_COND_NE;
         break;
     case 6: /* NE (!Z) */
     case 7: /* EQ (Z) */
-        tmp = QREG_CC_Z;
-        tcond = (cond & 1 ? TCG_COND_EQ : TCG_COND_NE);
+        c->v1 = QREG_CC_Z;
+        tcond = TCG_COND_EQ;
         break;
     case 8: /* VC (!V) */
     case 9: /* VS (V) */
-        tmp = QREG_CC_V;
-        tcond = (cond & 1 ? TCG_COND_LT : TCG_COND_GE);
+        c->v1 = QREG_CC_V;
+        tcond = TCG_COND_LT;
         break;
     case 10: /* PL (!N) */
     case 11: /* MI (N) */
-        tmp = QREG_CC_N;
-        tcond = (cond & 1 ? TCG_COND_LT : TCG_COND_GE);
+        c->v1 = QREG_CC_N;
+        tcond = TCG_COND_LT;
         break;
     case 12: /* GE (!(N ^ V)) */
     case 13: /* LT (N ^ V) */
-        tmp = tcg_temp_new();
+        c->v1 = tmp = tcg_temp_new();
+        c->g1 = 0;
         tcg_gen_xor_i32(tmp, QREG_CC_N, QREG_CC_V);
-        tcond = (cond & 1 ? TCG_COND_LT : TCG_COND_GE);
+        tcond = TCG_COND_LT;
         break;
     case 14: /* GT (!(Z || (N ^ V))) */
     case 15: /* LE (Z || (N ^ V)) */
-        tmp = tcg_temp_new();
-        tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, QREG_CC_Z, 0);
+        c->v1 = tmp = tcg_temp_new();
+        c->g1 = 0;
+        tcg_gen_setcond_i32(TCG_COND_EQ, tmp, QREG_CC_Z, c->v2);
         tcg_gen_neg_i32(tmp, tmp);
         tmp2 = tcg_temp_new();
         tcg_gen_xor_i32(tmp2, QREG_CC_N, QREG_CC_V);
         tcg_gen_or_i32(tmp, tmp, tmp2);
-        tcond = (cond & 1 ? TCG_COND_LT : TCG_COND_GE);
+        tcg_temp_free(tmp2);
+        tcond = TCG_COND_LT;
         break;
     default:
         /* Should ever happen.  */
         abort();
     }
-  tcg_gen_brcondi_i32(tcond, tmp, 0, l1);
+    if ((cond & 1) == 0) {
+        tcond = tcg_invert_cond(tcond);
+    }
+    c->tcond = tcond;
+}
+
+static void free_cond(DisasCompare *c)
+{
+    if (!c->g1) {
+        tcg_temp_free(c->v1);
+    }
+    if (!c->g2) {
+        tcg_temp_free(c->v2);
+    }
+}
+
+static void gen_jmpcc(DisasContext *s, int cond, TCGLabel *l1)
+{
+  DisasCompare c;
+
+  gen_cc_cond(&c, s, cond);
+  update_cc_op(s);
+  tcg_gen_brcond_i32(c.tcond, c.v1, c.v2, l1);
+  free_cond(&c);
 }
 
 DISAS_INSN(scc)
@@ -1674,7 +1712,6 @@ DISAS_INSN(branch)
         /* bsr */
         gen_push(s, tcg_const_i32(s->pc));
     }
-    update_cc_op(s);
     if (op > 1) {
         /* Bcc */
         l1 = gen_new_label();
-- 
2.5.5

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

* [Qemu-devel] [PATCH 23/52] target-m68k: Use setcond for scc
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (21 preceding siblings ...)
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 22/52] target-m68k: Introduce DisasCompare Laurent Vivier
@ 2016-05-04 20:12 ` Laurent Vivier
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 24/52] target-m68k: Optimize some comparisons Laurent Vivier
                   ` (12 subsequent siblings)
  35 siblings, 0 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

From: Richard Henderson <rth@twiddle.net>

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index efd4d9c..332c34f 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -862,19 +862,21 @@ static void gen_jmpcc(DisasContext *s, int cond, TCGLabel *l1)
 
 DISAS_INSN(scc)
 {
-    TCGLabel *l1;
+    DisasCompare c;
     int cond;
-    TCGv reg;
+    TCGv reg, tmp;
 
-    l1 = gen_new_label();
     cond = (insn >> 8) & 0xf;
+    gen_cc_cond(&c, s, cond);
+
+    tmp = tcg_temp_new();
+    tcg_gen_setcond_i32(c.tcond, tmp, c.v1, c.v2);
+    free_cond(&c);
+
     reg = DREG(insn, 0);
-    tcg_gen_andi_i32(reg, reg, 0xffffff00);
-    /* This is safe because we modify the reg directly, with no other values
-       live.  */
-    gen_jmpcc(s, cond ^ 1, l1);
-    tcg_gen_ori_i32(reg, reg, 0xff);
-    gen_set_label(l1);
+    tcg_gen_neg_i32(tmp, tmp);
+    tcg_gen_deposit_i32(reg, reg, tmp, 0, 8);
+    tcg_temp_free(tmp);
 }
 
 /* Force a TB lookup after an instruction that changes the CPU state.  */
-- 
2.5.5

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

* [Qemu-devel] [PATCH 24/52] target-m68k: Optimize some comparisons
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (22 preceding siblings ...)
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 23/52] target-m68k: Use setcond for scc Laurent Vivier
@ 2016-05-04 20:12 ` Laurent Vivier
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 25/52] target-m68k: Optimize gen_flush_flags Laurent Vivier
                   ` (11 subsequent siblings)
  35 siblings, 0 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

From: Richard Henderson <rth@twiddle.net>

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 108 +++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 102 insertions(+), 6 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 332c34f..cc8a000 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -768,10 +768,43 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
 {
     TCGv tmp, tmp2;
     TCGCond tcond;
+    CCOp op = s->cc_op;
 
-    /* TODO: Optimize compare/branch pairs rather than always flushing
-       flag state to CC_OP_FLAGS.  */
-    gen_flush_flags(s);
+    /* The CC_OP_CMP form can handle most normal comparisons directly.  */
+    if (op == CC_OP_CMP) {
+        c->g1 = c->g2 = 1;
+        c->v1 = QREG_CC_N;
+        c->v2 = QREG_CC_V;
+        switch (cond) {
+        case 2: /* HI */
+        case 3: /* LS */
+            tcond = TCG_COND_LEU;
+            goto done;
+        case 4: /* CC */
+        case 5: /* CS */
+            tcond = TCG_COND_LTU;
+            goto done;
+        case 6: /* NE */
+        case 7: /* EQ */
+            tcond = TCG_COND_EQ;
+            goto done;
+        case 10: /* PL */
+        case 11: /* MI */
+            c->g1 = c->g2 = 0;
+            c->v2 = tcg_const_i32(0);
+            c->v1 = tmp = tcg_temp_new();
+            tcg_gen_sub_i32(tmp, QREG_CC_N, QREG_CC_V);
+            /* fallthru */
+        case 12: /* GE */
+        case 13: /* LT */
+            tcond = TCG_COND_LT;
+            goto done;
+        case 14: /* GT */
+        case 15: /* LE */
+            tcond = TCG_COND_LE;
+            goto done;
+        }
+    }
 
     c->g1 = 1;
     c->g2 = 0;
@@ -782,7 +815,71 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
     case 1: /* F */
         c->v1 = c->v2;
         tcond = TCG_COND_NEVER;
+        goto done;
+    case 14: /* GT (!(Z || (N ^ V))) */
+    case 15: /* LE (Z || (N ^ V)) */
+        /* Logic operations clear V, which simplifies LE to (Z || N),
+           and since Z and N are co-located, this becomes a normal
+           comparison vs N.  */
+        if (op == CC_OP_LOGIC) {
+            c->v1 = QREG_CC_N;
+            tcond = TCG_COND_LE;
+            goto done;
+        }
+        break;
+    case 12: /* GE (!(N ^ V)) */
+    case 13: /* LT (N ^ V) */
+        /* Logic operations clear V, which simplifies this to N.  */
+        if (op != CC_OP_LOGIC) {
+            break;
+        }
+        /* fallthru */
+    case 10: /* PL (!N) */
+    case 11: /* MI (N) */
+        /* Several cases represent N normally.  */
+        if (op == CC_OP_ADD || op == CC_OP_SUB || op == CC_OP_LOGIC) {
+            c->v1 = QREG_CC_N;
+            tcond = TCG_COND_LT;
+            goto done;
+        }
+        break;
+    case 6: /* NE (!Z) */
+    case 7: /* EQ (Z) */
+        /* Some cases fold Z into N.  */
+        if (op == CC_OP_ADD || op == CC_OP_SUB || op == CC_OP_LOGIC) {
+            tcond = TCG_COND_EQ;
+            c->v1 = QREG_CC_N;
+            goto done;
+        }
         break;
+    case 4: /* CC (!C) */
+    case 5: /* CS (C) */
+        /* Some cases fold C into X.  */
+        if (op == CC_OP_ADD || op == CC_OP_SUB) {
+            tcond = TCG_COND_NE;
+            c->v1 = QREG_CC_X;
+            goto done;
+        }
+        /* fallthru */
+    case 8: /* VC (!V) */
+    case 9: /* VS (V) */
+        /* Logic operations clear V and C.  */
+        if (op == CC_OP_LOGIC) {
+            tcond = TCG_COND_NEVER;
+            c->v2 = c->v1;
+        }
+        break;
+    }
+
+    /* Otherwise, flush flag state to CC_OP_FLAGS.  */
+    gen_flush_flags(s);
+
+    switch (cond) {
+    case 0: /* T */
+    case 1: /* F */
+    default:
+        /* Invalid, or handled above.  */
+        abort();
     case 2: /* HI (!C && !Z) -> !(C || Z)*/
     case 3: /* LS (C || Z) */
         c->v1 = tmp = tcg_temp_new();
@@ -830,10 +927,9 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
         tcg_temp_free(tmp2);
         tcond = TCG_COND_LT;
         break;
-    default:
-        /* Should ever happen.  */
-        abort();
     }
+
+ done:
     if ((cond & 1) == 0) {
         tcond = tcg_invert_cond(tcond);
     }
-- 
2.5.5

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

* [Qemu-devel] [PATCH 25/52] target-m68k: Optimize gen_flush_flags
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (23 preceding siblings ...)
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 24/52] target-m68k: Optimize some comparisons Laurent Vivier
@ 2016-05-04 20:12 ` Laurent Vivier
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 26/52] target-m68k: Inline shifts Laurent Vivier
                   ` (10 subsequent siblings)
  35 siblings, 0 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

From: Richard Henderson <rth@twiddle.net>

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 56 +++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 52 insertions(+), 4 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index cc8a000..58cc9d9 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -456,18 +456,66 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
 
 static void gen_flush_flags(DisasContext *s)
 {
-    TCGv tmp;
+    TCGv t0, t1;
 
     switch (s->cc_op) {
     case CC_OP_FLAGS:
         return;
+
+    case CC_OP_ADD:
+        tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
+        tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+        /* Compute signed overflow for addition.  */
+        t0 = tcg_temp_new();
+        t1 = tcg_temp_new();
+        tcg_gen_sub_i32(t0, QREG_CC_N, QREG_CC_V);
+        tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V);
+        tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0);
+        tcg_temp_free(t0);
+        tcg_gen_andc_i32(QREG_CC_V, t1, QREG_CC_V);
+        tcg_temp_free(t1);
+        break;
+
+    case CC_OP_SUB:
+        tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
+        tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+        /* Compute signed overflow for subtraction.  */
+        t0 = tcg_temp_new();
+        t1 = tcg_temp_new();
+        tcg_gen_add_i32(t0, QREG_CC_N, QREG_CC_V);
+        tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V);
+        tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0);
+        tcg_temp_free(t0);
+        tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t1);
+        tcg_temp_free(t1);
+        break;
+
+    case CC_OP_CMP:
+        tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_C, QREG_CC_N, QREG_CC_V);
+        tcg_gen_sub_i32(QREG_CC_Z, QREG_CC_N, QREG_CC_V);
+        /* Compute signed overflow for subtraction.  */
+        t0 = tcg_temp_new();
+        tcg_gen_xor_i32(t0, QREG_CC_Z, QREG_CC_N);
+        tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, QREG_CC_N);
+        tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t0);
+        tcg_temp_free(t0);
+        tcg_gen_mov_i32(QREG_CC_N, QREG_CC_Z);
+        break;
+
+    case CC_OP_LOGIC:
+        tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+        tcg_gen_movi_i32(QREG_CC_C, 0);
+        tcg_gen_movi_i32(QREG_CC_V, 0);
+        break;
+
     case CC_OP_DYNAMIC:
         gen_helper_flush_flags(cpu_env, QREG_CC_OP);
         break;
+
     default:
-        tmp = tcg_const_i32(s->cc_op);
-        gen_helper_flush_flags(cpu_env, tmp);
-        tcg_temp_free(tmp);
+        t0 = tcg_const_i32(s->cc_op);
+        gen_helper_flush_flags(cpu_env, t0);
+        tcg_temp_free(t0);
         break;
     }
 
-- 
2.5.5

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

* [Qemu-devel] [PATCH 26/52] target-m68k: Inline shifts
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (24 preceding siblings ...)
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 25/52] target-m68k: Optimize gen_flush_flags Laurent Vivier
@ 2016-05-04 20:12 ` Laurent Vivier
  2016-05-06 16:53   ` Richard Henderson
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 27/52] target-m68k: Inline addx, subx, negx Laurent Vivier
                   ` (9 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

From: Richard Henderson <rth@twiddle.net>

Signed-off-by: Richard Henderson <rth@twiddle.net>

fix arithmetical/logical switch

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    | 52 ---------------------------
 target-m68k/helper.h    |  3 --
 target-m68k/translate.c | 94 +++++++++++++++++++++++++++++++++++++------------
 3 files changed, 72 insertions(+), 77 deletions(-)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 8758016..0ca8d3f 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -323,58 +323,6 @@ void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
     m68k_switch_sp(env);
 }
 
-uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
-{
-    uint64_t result;
-
-    shift &= 63;
-    result = (uint64_t)val << shift;
-
-    env->cc_c = (result >> 32) & 1;
-    env->cc_n = result;
-    env->cc_z = result;
-    env->cc_v = 0;
-    env->cc_x = shift ? env->cc_c : env->cc_x;
-
-    return result;
-}
-
-uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
-{
-    uint64_t temp;
-    uint32_t result;
-
-    shift &= 63;
-    temp = (uint64_t)val << 32 >> shift;
-    result = temp >> 32;
-
-    env->cc_c = (temp >> 31) & 1;
-    env->cc_n = result;
-    env->cc_z = result;
-    env->cc_v = 0;
-    env->cc_x = shift ? env->cc_c : env->cc_x;
-
-    return result;
-}
-
-uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
-{
-    uint64_t temp;
-    uint32_t result;
-
-    shift &= 63;
-    temp = (int64_t)val << 32 >> shift;
-    result = temp >> 32;
-
-    env->cc_c = (temp >> 31) & 1;
-    env->cc_n = result;
-    env->cc_z = result;
-    env->cc_v = result ^ val;
-    env->cc_x = shift ? env->cc_c : env->cc_x;
-
-    return result;
-}
-
 /* FPU helpers.  */
 uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
 {
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index c868148..9985f9b 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -5,9 +5,6 @@ DEF_HELPER_2(divu, void, env, i32)
 DEF_HELPER_2(divs, void, env, 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_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 58cc9d9..1e8cb37 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2038,48 +2038,98 @@ DISAS_INSN(addx)
     gen_helper_addx_cc(reg, cpu_env, reg, src);
 }
 
-/* TODO: This could be implemented without helper functions.  */
 DISAS_INSN(shift_im)
 {
-    TCGv reg;
-    int tmp;
-    TCGv shift;
+    TCGv reg = DREG(insn, 0);
+    int count = (insn >> 9) & 7;
+    int logical = insn & 8;
 
-    set_cc_op(s, CC_OP_FLAGS);
+    if (count == 0) {
+        count = 8;
+    }
 
-    reg = DREG(insn, 0);
-    tmp = (insn >> 9) & 7;
-    if (tmp == 0)
-        tmp = 8;
-    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);
+        tcg_gen_shri_i32(QREG_CC_C, reg, 31 - count);
+        tcg_gen_shli_i32(QREG_CC_N, reg, count);
     } else {
-        if (insn & 8) {
-            gen_helper_shr_cc(reg, cpu_env, reg, shift);
+        tcg_gen_shri_i32(QREG_CC_C, reg, count - 1);
+        if (logical) {
+            tcg_gen_shri_i32(QREG_CC_N, reg, count);
         } else {
-            gen_helper_sar_cc(reg, cpu_env, reg, shift);
+            tcg_gen_sari_i32(QREG_CC_N, reg, count);
         }
     }
+    tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
+    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+    tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
+
+    /* Note that ColdFire always clears V, while M68000 sets it for
+       a change in the sign bit.  */
+    if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
+        tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, reg);
+    } else {
+        tcg_gen_movi_i32(QREG_CC_V, 0);
+    }
+
+    tcg_gen_mov_i32(reg, QREG_CC_N);
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 DISAS_INSN(shift_reg)
 {
-    TCGv reg;
-    TCGv shift;
+    TCGv reg, s32;
+    TCGv_i64 t64, s64;
+    int logical = insn & 8;
 
     reg = DREG(insn, 0);
-    shift = DREG(insn, 9);
+    t64 = tcg_temp_new_i64();
+    s64 = tcg_temp_new_i64();
+    s32 = tcg_temp_new();
+
+    /* Note that m68k truncates the shift count modulo 64, not 32.
+       In addition, a 64-bit shift makes it easy to find "the last
+       bit shifted out", for the carry flag.  */
+    tcg_gen_andi_i32(s32, DREG(insn, 9), 63);
+    tcg_gen_extu_i32_i64(s64, s32);
+
+    /* Non-arithmetic shift clears V.  Use it as a source zero here.  */
+    tcg_gen_movi_i32(QREG_CC_V, 0);
+
     if (insn & 0x100) {
-        gen_helper_shl_cc(reg, cpu_env, reg, shift);
+        tcg_gen_extu_i32_i64(t64, reg);
+        tcg_gen_shl_i64(t64, t64, s64);
+        tcg_temp_free_i64(s64);
+        tcg_gen_extr_i64_i32(QREG_CC_N, QREG_CC_C, t64);
+        tcg_temp_free_i64(t64);
+        tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
     } else {
-        if (insn & 8) {
-            gen_helper_shr_cc(reg, cpu_env, reg, shift);
+        tcg_gen_extu_i32_i64(t64, reg);
+        tcg_gen_shli_i64(t64, t64, 32);
+        if (logical) {
+            tcg_gen_shr_i64(t64, t64, s64);
         } else {
-            gen_helper_sar_cc(reg, cpu_env, reg, shift);
+            tcg_gen_sar_i64(t64, t64, s64);
         }
+        tcg_temp_free_i64(s64);
+        tcg_gen_extr_i64_i32(QREG_CC_C, QREG_CC_N, t64);
+        tcg_temp_free_i64(t64);
+        tcg_gen_shri_i32(QREG_CC_C, QREG_CC_C, 31);
     }
+    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+
+    /* Note that X = C, but only if the shift count was non-zero.  */
+    tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V,
+                        QREG_CC_C, QREG_CC_X);
+    tcg_temp_free(s32);
+
+    /* Note that ColdFire always clears V (which we have done above),
+       while M68000 sets it for a change in the sign bit.  */
+    if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
+        tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, reg);
+    }
+
+    /* Write back the result.  */
+    tcg_gen_mov_i32(reg, QREG_CC_N);
     set_cc_op(s, CC_OP_FLAGS);
 }
 
-- 
2.5.5

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

* [Qemu-devel] [PATCH 27/52] target-m68k: Inline addx, subx, negx
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (25 preceding siblings ...)
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 26/52] target-m68k: Inline shifts Laurent Vivier
@ 2016-05-04 20:12 ` Laurent Vivier
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 28/52] target-m68k: add addx/subx/negx ops Laurent Vivier
                   ` (8 subsequent siblings)
  35 siblings, 0 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

From: Richard Henderson <rth@twiddle.net>

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    | 40 -----------------------------
 target-m68k/helper.h    |  2 --
 target-m68k/translate.c | 67 +++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 56 insertions(+), 53 deletions(-)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 0ca8d3f..42a2f1c 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -276,46 +276,6 @@ uint32_t HELPER(sats)(uint32_t val, uint32_t v)
     return val;
 }
 
-uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
-{
-    uint32_t res, new_x;
-
-    if (env->cc_x) {
-        new_x = (op1 <= op2);
-        res = op1 - (op2 + 1);
-    } else {
-        new_x = (op1 < op2);
-        res = op1 - op2;
-    }
-    env->cc_x = new_x;
-    env->cc_c = new_x;
-    env->cc_n = res;
-    env->cc_z |= res; /* !Z is sticky */
-    env->cc_v = (res ^ op1) & (op1 ^ op2);
-
-    return res;
-}
-
-uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
-{
-    uint32_t res, new_x;
-
-    if (env->cc_x) {
-        res = op1 + op2 + 1;
-        new_x = (res <= op2);
-    } else {
-        res = op1 + op2;
-        new_x = (res < op2);
-    }
-    env->cc_x = new_x;
-    env->cc_c = new_x;
-    env->cc_n = res;
-    env->cc_z |= res; /* !Z is sticky.  */
-    env->cc_v = (res ^ op1) & ~(op1 ^ op2);
-
-    return res;
-}
-
 void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
 {
     env->sr = val & 0xffe0;
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index 9985f9b..aae01f9 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -3,8 +3,6 @@ DEF_HELPER_1(ff1, i32, i32)
 DEF_HELPER_FLAGS_2(sats, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_2(divu, void, env, i32)
 DEF_HELPER_2(divs, void, env, i32)
-DEF_HELPER_3(addx_cc, i32, env, i32, i32)
-DEF_HELPER_3(subx_cc, i32, env, 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 1e8cb37..13ae953 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1503,11 +1503,27 @@ DISAS_INSN(move)
 
 DISAS_INSN(negx)
 {
-    TCGv reg;
+    TCGv reg, z;
 
-    gen_flush_flags(s);
     reg = DREG(insn, 0);
-    gen_helper_subx_cc(reg, cpu_env, tcg_const_i32(0), reg);
+
+    /* Perform subtraction with borrow.  */
+    z = tcg_const_i32(0);
+    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, reg, z, QREG_CC_X, z);
+    tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, z, z, QREG_CC_N, QREG_CC_X);
+    tcg_temp_free(z);
+    tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1);
+
+    /* Compute signed-overflow for negation.  The normal formula for
+       subtraction is (res ^ src1) & (src1 ^ src2), but with src1==0
+       this simplies to res & src2.  */
+    tcg_gen_and_i32(QREG_CC_V, QREG_CC_N, reg);
+
+    /* Copy the rest of the results into place.  */
+    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+    tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
+    tcg_gen_mov_i32(reg, QREG_CC_N);
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 DISAS_INSN(lea)
@@ -1929,13 +1945,28 @@ DISAS_INSN(suba)
 
 DISAS_INSN(subx)
 {
-    TCGv reg;
-    TCGv src;
+    TCGv reg, src, z;
 
-    gen_flush_flags(s);
     reg = DREG(insn, 9);
     src = DREG(insn, 0);
-    gen_helper_subx_cc(reg, cpu_env, reg, src);
+
+    /* Perform subtract with borrow.  */
+    z = tcg_const_i32(0);
+    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, z, QREG_CC_X, z);
+    tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, reg, z, QREG_CC_N, QREG_CC_X);
+    tcg_temp_free(z);
+    tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1);
+
+    /* Compute signed-overflow for subtraction.  */
+    tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, reg);
+    tcg_gen_xor_i32(QREG_CC_Z, reg, src);
+    tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, QREG_CC_Z);
+
+    /* Copy the rest of the results into place.  */
+    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+    tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
+    tcg_gen_mov_i32(reg, QREG_CC_N);
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 DISAS_INSN(mov3q)
@@ -2029,13 +2060,27 @@ DISAS_INSN(adda)
 
 DISAS_INSN(addx)
 {
-    TCGv reg;
-    TCGv src;
+    TCGv reg, src, z;
 
-    gen_flush_flags(s);
     reg = DREG(insn, 9);
     src = DREG(insn, 0);
-    gen_helper_addx_cc(reg, cpu_env, reg, src);
+
+    /* Perform addition with carry.  */
+    z = tcg_const_i32(0);
+    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_X, z, reg, z);
+    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_N, QREG_CC_X, src, z);
+    tcg_temp_free(z);
+
+    /* Compute signed-overflow for addition.  */
+    tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, reg);
+    tcg_gen_xor_i32(QREG_CC_Z, reg, src);
+    tcg_gen_andc_i32(QREG_CC_V, QREG_CC_V, QREG_CC_Z);
+
+    /* Copy the rest of the results into place.  */
+    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+    tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
+    tcg_gen_mov_i32(reg, QREG_CC_N);
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 DISAS_INSN(shift_im)
-- 
2.5.5

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

* [Qemu-devel] [PATCH 28/52] target-m68k: add addx/subx/negx ops
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (26 preceding siblings ...)
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 27/52] target-m68k: Inline addx, subx, negx Laurent Vivier
@ 2016-05-04 20:12 ` Laurent Vivier
  2016-05-06 17:11   ` Richard Henderson
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 29/52] target-m68k: factorize flags computing Laurent Vivier
                   ` (7 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 200 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 160 insertions(+), 40 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 13ae953..5914185 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1503,27 +1503,46 @@ DISAS_INSN(move)
 
 DISAS_INSN(negx)
 {
-    TCGv reg, z;
+    TCGv z;
+    TCGv src;
+    TCGv addr;
+    int opsize;
 
-    reg = DREG(insn, 0);
+    opsize = insn_opsize(insn);
+    SRC_EA(env, src, opsize, 1, &addr);
+
+    gen_flush_flags(s); /* compute old Z */
+
+    /* Perform substract with borrow.
+     * (X, N) =  -(src + X);
+     */
 
-    /* Perform subtraction with borrow.  */
     z = tcg_const_i32(0);
-    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, reg, z, QREG_CC_X, z);
+    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, z, QREG_CC_X, z);
     tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, z, z, QREG_CC_N, QREG_CC_X);
     tcg_temp_free(z);
+    gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
+
     tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1);
 
     /* Compute signed-overflow for negation.  The normal formula for
-       subtraction is (res ^ src1) & (src1 ^ src2), but with src1==0
-       this simplies to res & src2.  */
-    tcg_gen_and_i32(QREG_CC_V, QREG_CC_N, reg);
+     * subtraction is (res ^ src) & (src ^ dest), but with dest==0
+     * this simplies to res & src.
+     */
+
+    tcg_gen_and_i32(QREG_CC_V, QREG_CC_N, src);
 
     /* Copy the rest of the results into place.  */
-    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+    tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
+    gen_ext(QREG_CC_Z, QREG_CC_Z, opsize, 0);
+
     tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
-    tcg_gen_mov_i32(reg, QREG_CC_N);
+
     set_cc_op(s, CC_OP_FLAGS);
+
+    /* result is in QREG_CC_N */
+
+    DEST_EA(env, insn, opsize, QREG_CC_N, &addr);
 }
 
 DISAS_INSN(lea)
@@ -1943,32 +1962,78 @@ DISAS_INSN(suba)
     tcg_gen_sub_i32(reg, reg, src);
 }
 
-DISAS_INSN(subx)
+static inline void gen_subx(DisasContext *s, TCGv src, TCGv dest, int opsize)
 {
-    TCGv reg, src, z;
+    TCGv tmp;
 
-    reg = DREG(insn, 9);
-    src = DREG(insn, 0);
+    gen_flush_flags(s); /* compute old Z */
 
-    /* Perform subtract with borrow.  */
-    z = tcg_const_i32(0);
-    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, z, QREG_CC_X, z);
-    tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, reg, z, QREG_CC_N, QREG_CC_X);
-    tcg_temp_free(z);
+    /* Perform substract with borrow.
+     * (X, N) = dest - (src + X);
+     */
+
+    tmp = tcg_const_i32(0);
+    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, tmp, QREG_CC_X, tmp);
+    tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, dest, tmp, QREG_CC_N, QREG_CC_X);
+    gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
     tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1);
 
-    /* Compute signed-overflow for subtraction.  */
-    tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, reg);
-    tcg_gen_xor_i32(QREG_CC_Z, reg, src);
-    tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, QREG_CC_Z);
+    /* Compute signed-overflow for substract.  */
+
+    tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, dest);
+    tcg_gen_xor_i32(tmp, dest, src);
+    tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, tmp);
+    tcg_temp_free(tmp);
 
     /* Copy the rest of the results into place.  */
-    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+    tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
+    gen_ext(QREG_CC_Z, QREG_CC_Z, opsize, 0);
+
     tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
-    tcg_gen_mov_i32(reg, QREG_CC_N);
+
     set_cc_op(s, CC_OP_FLAGS);
+
+    /* result is in QREG_CC_N */
+}
+
+DISAS_INSN(subx_reg)
+{
+    TCGv dest;
+    TCGv src;
+    int opsize;
+
+    opsize = insn_opsize(insn);
+
+    src = gen_extend(DREG(insn, 0), opsize, 1);
+    dest = gen_extend(DREG(insn, 9), opsize, 1);
+
+    gen_subx(s, src, dest, opsize);
+
+    gen_partset_reg(opsize, DREG(insn, 9), QREG_CC_N);
 }
 
+DISAS_INSN(subx_mem)
+{
+    TCGv src;
+    TCGv addr_src;
+    TCGv dest;
+    TCGv addr_dest;
+    int opsize;
+
+    opsize = insn_opsize(insn);
+
+    addr_src = AREG(insn, 0);
+    tcg_gen_subi_i32(addr_src, addr_src, opsize);
+    src = gen_load(s, opsize, addr_src, 1);
+
+    addr_dest = AREG(insn, 9);
+    tcg_gen_subi_i32(addr_dest, addr_dest, opsize);
+    dest = gen_load(s, opsize, addr_dest, 1);
+
+    gen_subx(s, src, dest, opsize);
+
+    gen_store(s, opsize, addr_dest, QREG_CC_N);
+}
 DISAS_INSN(mov3q)
 {
     TCGv src;
@@ -2058,29 +2123,76 @@ DISAS_INSN(adda)
     tcg_gen_add_i32(reg, reg, src);
 }
 
-DISAS_INSN(addx)
+static inline void gen_addx(DisasContext *s, TCGv src, TCGv dest, int opsize)
 {
-    TCGv reg, src, z;
+    TCGv tmp;
 
-    reg = DREG(insn, 9);
-    src = DREG(insn, 0);
+    gen_flush_flags(s); /* compute old Z */
 
-    /* Perform addition with carry.  */
-    z = tcg_const_i32(0);
-    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_X, z, reg, z);
-    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_N, QREG_CC_X, src, z);
-    tcg_temp_free(z);
+    /* Perform addition with carry.
+     * (X, N) = src + dest + X;
+     */
+
+    tmp = tcg_const_i32(0);
+    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_X, tmp, dest, tmp);
+    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_N, QREG_CC_X, src, tmp);
+    gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
 
     /* Compute signed-overflow for addition.  */
-    tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, reg);
-    tcg_gen_xor_i32(QREG_CC_Z, reg, src);
-    tcg_gen_andc_i32(QREG_CC_V, QREG_CC_V, QREG_CC_Z);
+
+    tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, src);
+    tcg_gen_xor_i32(tmp, dest, src);
+    tcg_gen_andc_i32(QREG_CC_V, QREG_CC_V, tmp);
+    tcg_temp_free(tmp);
 
     /* Copy the rest of the results into place.  */
-    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+    tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
+    gen_ext(QREG_CC_Z, QREG_CC_Z, opsize, 0);
+
     tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
-    tcg_gen_mov_i32(reg, QREG_CC_N);
+
     set_cc_op(s, CC_OP_FLAGS);
+
+    /* result is in QREG_CC_N */
+}
+
+DISAS_INSN(addx_reg)
+{
+    TCGv dest;
+    TCGv src;
+    int opsize;
+
+    opsize = insn_opsize(insn);
+
+    dest = gen_extend(DREG(insn, 9), opsize, 1);
+    src = gen_extend(DREG(insn, 0), opsize, 1);
+
+    gen_addx(s, src, dest, opsize);
+
+    gen_partset_reg(opsize, DREG(insn, 9), QREG_CC_N);
+}
+
+DISAS_INSN(addx_mem)
+{
+    TCGv src;
+    TCGv addr_src;
+    TCGv dest;
+    TCGv addr_dest;
+    int opsize;
+
+    opsize = insn_opsize(insn);
+
+    addr_src = AREG(insn, 0);
+    tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(opsize));
+    src = gen_load(s, opsize, addr_src, 1);
+
+    addr_dest = AREG(insn, 9);
+    tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(opsize));
+    dest = gen_load(s, opsize, addr_dest, 1);
+
+    gen_addx(s, src, dest, opsize);
+
+    gen_store(s, opsize, addr_dest, QREG_CC_N);
 }
 
 DISAS_INSN(shift_im)
@@ -3128,6 +3240,8 @@ void register_m68k_insns (CPUM68KState *env)
     BASE(move,      3000, f000);
     INSN(strldsr,   40e7, ffff, CF_ISA_APLUSC);
     INSN(negx,      4080, fff8, CF_ISA_A);
+    INSN(negx,      4000, ff00, M68000);
+    INSN(undef,     40c0, ffc0, M68000);
     INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
     INSN(move_from_sr, 40c0, ffc0, M68000);
     BASE(lea,       41c0, f1c0);
@@ -3195,7 +3309,10 @@ void register_m68k_insns (CPUM68KState *env)
     BASE(or,        8000, f000);
     BASE(divw,      80c0, f0c0);
     BASE(addsub,    9000, f000);
-    INSN(subx,      9180, f1f8, CF_ISA_A);
+    INSN(undef,     90c0, f0c0, CF_ISA_A);
+    INSN(subx_reg,  9180, f1f8, CF_ISA_A);
+    INSN(subx_reg,  9100, f138, M68000);
+    INSN(subx_mem,  9108, f138, M68000);
     INSN(suba,      91c0, f1c0, CF_ISA_A);
 
     BASE(undef_mac, a000, f000);
@@ -3224,7 +3341,10 @@ void register_m68k_insns (CPUM68KState *env)
     BASE(and,       c000, f000);
     BASE(mulw,      c0c0, f0c0);
     BASE(addsub,    d000, f000);
-    INSN(addx,      d180, f1f8, CF_ISA_A);
+    INSN(undef,     d0c0, f0c0, CF_ISA_A);
+    INSN(addx_reg,      d180, f1f8, CF_ISA_A);
+    INSN(addx_reg,  d100, f138, M68000);
+    INSN(addx_mem,  d108, f138, M68000);
     INSN(adda,      d1c0, f1c0, CF_ISA_A);
     INSN(adda,      d0c0, f0c0, M68000);
     INSN(shift_im,  e080, f0f0, CF_ISA_A);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 29/52] target-m68k: factorize flags computing
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (27 preceding siblings ...)
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 28/52] target-m68k: add addx/subx/negx ops Laurent Vivier
@ 2016-05-04 20:12 ` Laurent Vivier
  2016-05-06 17:11   ` Richard Henderson
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 30/52] target-m68k: add scc/dbcc Laurent Vivier
                   ` (6 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c | 125 +++++++++++++++++----------------------------------
 1 file changed, 42 insertions(+), 83 deletions(-)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 42a2f1c..e9e7cee 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -531,6 +531,46 @@ void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
     }
 }
 
+
+#define COMPUTE_CCR(op, x, n, z, v, c) {                                   \
+    switch (op) {                                                          \
+    case CC_OP_FLAGS:                                                      \
+        /* Everything in place.  */                                        \
+        break;                                                             \
+    case CC_OP_ADD:                                                        \
+        res = n;                                                           \
+        src2 = v;                                                          \
+        src1 = res - src2;                                                 \
+        c = x;                                                             \
+        z = n;                                                             \
+        v = (res ^ src1) & ~(src1 ^ src2);                                 \
+        break;                                                             \
+    case CC_OP_SUB:                                                        \
+        res = n;                                                           \
+        src2 = v;                                                          \
+        src1 = res + src2;                                                 \
+        c = x;                                                             \
+        z = n;                                                             \
+        v = (res ^ src1) & (src1 ^ src2);                                  \
+        break;                                                             \
+    case CC_OP_CMP:                                                        \
+        src1 = n;                                                          \
+        src2 = v;                                                          \
+        res = src1 - src2;                                                 \
+        n = res;                                                           \
+        z = res;                                                           \
+        c = src1 < src2;                                                   \
+        v = (res ^ src1) & (src1 ^ src2);                                  \
+        break;                                                             \
+    case CC_OP_LOGIC:                                                      \
+        c = v = 0;                                                         \
+        z = n;                                                             \
+        break;                                                             \
+    default:                                                               \
+        cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", op);         \
+    }                                                                      \
+} while (0)
+
 uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
 {
     uint32_t x, c, n, z, v;
@@ -542,47 +582,7 @@ uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
     z = env->cc_z;
     v = env->cc_v;
 
-    switch (env->cc_op) {
-    case CC_OP_FLAGS:
-        /* Everything in place.  */
-        break;
-
-    case CC_OP_ADD:
-        res = n;
-        src2 = v;
-        src1 = res - src2;
-        c = x;
-        z = n;
-        v = (res ^ src1) & ~(src1 ^ src2);
-        break;
-
-    case CC_OP_SUB:
-        res = n;
-        src2 = v;
-        src1 = res + src2;
-        c = x;
-        z = n;
-        v = (res ^ src1) & (src1 ^ src2);
-        break;
-
-    case CC_OP_CMP:
-        src1 = n;
-        src2 = v;
-        res = src1 - src2;
-        n = res;
-        z = res;
-        c = src1 < src2;
-        v = (res ^ src1) & (src1 ^ src2);
-        break;
-
-    case CC_OP_LOGIC:
-        c = v = 0;
-        z = n;
-        break;
-
-    default:
-        cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", env->cc_op);
-    }
+    COMPUTE_CCR(env->cc_op, x, n, z, v, c);
 
     n = n >> 31;
     v = v >> 31;
@@ -615,48 +615,7 @@ void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
 {
     uint32_t res, src1, src2;
 
-    switch (cc_op) {
-    case CC_OP_FLAGS:
-        /* Everything up to date.  */
-        return;
-
-    case CC_OP_ADD:
-        res = env->cc_n;
-        src2 = env->cc_v;
-        src1 = res - src2;
-        env->cc_z = res;
-        env->cc_c = env->cc_x;
-        env->cc_v = (res ^ src1) & ~(src1 ^ src2);
-        break;
-
-    case CC_OP_SUB:
-        res = env->cc_n;
-        src2 = env->cc_v;
-        src1 = res + src2;
-        env->cc_z = res;
-        env->cc_c = env->cc_x;
-        env->cc_v = (res ^ src1) & (src1 ^ src2);
-        break;
-
-    case CC_OP_CMP:
-        src1 = env->cc_n;
-        src2 = env->cc_v;
-        res = src1 - src2;
-        env->cc_n = res;
-        env->cc_z = res;
-        env->cc_c = src1 < src2;
-        env->cc_v = (res ^ src1) & (src1 ^ src2);
-        break;
-
-    case CC_OP_LOGIC:
-        env->cc_c = 0;
-        env->cc_v = 0;
-        env->cc_z = env->cc_n;
-        break;
-
-    default:
-        cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", cc_op);
-    }
+    COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c);
     env->cc_op = CC_OP_FLAGS;
 }
 
-- 
2.5.5

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

* [Qemu-devel] [PATCH 30/52] target-m68k: add scc/dbcc
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (28 preceding siblings ...)
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 29/52] target-m68k: factorize flags computing Laurent Vivier
@ 2016-05-04 20:12 ` Laurent Vivier
  2016-05-06 17:18   ` Richard Henderson
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 31/52] target-m68k: some bit ops cleanup Laurent Vivier
                   ` (5 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 5914185..cd656fe 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1096,6 +1096,49 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
     s->is_jmp = DISAS_TB_JUMP;
 }
 
+DISAS_INSN(scc_mem)
+{
+    TCGLabel *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(env, insn, OS_BYTE, dest, NULL);
+    tcg_temp_free(dest);
+}
+
+DISAS_INSN(dbcc)
+{
+    TCGLabel *l1;
+    TCGv reg;
+    TCGv tmp;
+    int16_t offset;
+    uint32_t base;
+
+    reg = DREG(insn, 0);
+    base = s->pc;
+    offset = (int16_t)read_im16(env, s);
+    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, -1, l1);
+    update_cc_op(s);
+    gen_jmp_tb(s, 1, base + offset);
+    gen_set_label(l1);
+    update_cc_op(s);
+    gen_jmp_tb(s, 0, s->pc);
+}
+
 DISAS_INSN(undef_mac)
 {
     gen_exception(s, s->pc - 2, EXCP_LINEA);
@@ -3292,6 +3335,9 @@ 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(dbcc,      50c8, f0f8, M68000);
     INSN(addsubq,   5080, f1c0, CF_ISA_A);
     INSN(tpf,       51f8, fff8, CF_ISA_A);
 
-- 
2.5.5

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

* [Qemu-devel] [PATCH 31/52] target-m68k: some bit ops cleanup
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (29 preceding siblings ...)
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 30/52] target-m68k: add scc/dbcc Laurent Vivier
@ 2016-05-04 20:12 ` Laurent Vivier
  2016-05-06 17:20   ` Richard Henderson
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 32/52] target-m68k: bitfield ops Laurent Vivier
                   ` (4 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 34 +++++++++++++++-------------------
 1 file changed, 15 insertions(+), 19 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index cd656fe..817f0b3 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1300,39 +1300,36 @@ DISAS_INSN(bitop_reg)
     else
         opsize = OS_LONG;
     op = (insn >> 6) & 3;
-
-    gen_flush_flags(s);
-
     SRC_EA(env, src1, opsize, 0, op ? &addr: NULL);
-    src2 = DREG(insn, 9);
-    dest = tcg_temp_new();
 
-    tmp = tcg_temp_new();
+    gen_flush_flags(s);
+    src2 = tcg_temp_new();
     if (opsize == OS_BYTE)
-        tcg_gen_andi_i32(tmp, src2, 7);
+        tcg_gen_andi_i32(src2, DREG(insn, 9), 7);
     else
-        tcg_gen_andi_i32(tmp, src2, 31);
+        tcg_gen_andi_i32(src2, DREG(insn, 9), 31);
 
-    src2 = tcg_const_i32(1);
-    tcg_gen_shl_i32(src2, src2, tmp);
-    tcg_temp_free(tmp);
+    tmp = tcg_const_i32(1);
+    tcg_gen_shl_i32(tmp, tmp, src2);
+    tcg_temp_free(src2);
 
-    tcg_gen_and_i32(QREG_CC_Z, src1, src2);
+    tcg_gen_and_i32(QREG_CC_Z, src1, tmp);
 
+    dest = tcg_temp_new();
     switch (op) {
     case 1: /* bchg */
-        tcg_gen_xor_i32(dest, src1, src2);
+        tcg_gen_xor_i32(dest, src1, tmp);
         break;
     case 2: /* bclr */
-        tcg_gen_andc_i32(dest, src1, src2);
+        tcg_gen_andc_i32(dest, src1, tmp);
         break;
     case 3: /* bset */
-        tcg_gen_or_i32(dest, src1, src2);
+        tcg_gen_or_i32(dest, src1, tmp);
         break;
     default: /* btst */
         break;
     }
-    tcg_temp_free(src2);
+    tcg_temp_free(tmp);
     if (op) {
         DEST_EA(env, insn, opsize, dest, &addr);
     }
@@ -1416,17 +1413,16 @@ DISAS_INSN(bitop_im)
         return;
     }
 
-    gen_flush_flags(s);
-
     SRC_EA(env, src1, opsize, 0, op ? &addr: NULL);
 
+    gen_flush_flags(s);
     if (opsize == OS_BYTE)
         bitnum &= 7;
     else
         bitnum &= 31;
     mask = 1 << bitnum;
 
-    tcg_gen_andi_i32(QREG_CC_Z, src1, mask);
+   tcg_gen_andi_i32(QREG_CC_Z, src1, mask);
 
     if (op) {
         tmp = tcg_temp_new();
-- 
2.5.5

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

* [Qemu-devel] [PATCH 32/52] target-m68k: bitfield ops
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (30 preceding siblings ...)
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 31/52] target-m68k: some bit ops cleanup Laurent Vivier
@ 2016-05-04 20:12 ` Laurent Vivier
  2016-05-06 19:11   ` Richard Henderson
  2016-05-04 21:08 ` [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs Laurent Vivier
                   ` (3 subsequent siblings)
  35 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: gerg, schwab, agraf, rth, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    |  13 ++
 target-m68k/helper.h    |   4 +
 target-m68k/op_helper.c |  68 ++++++
 target-m68k/translate.c | 560 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 645 insertions(+)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index e9e7cee..76dda44 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -267,6 +267,19 @@ 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(sats)(uint32_t val, uint32_t v)
 {
     /* The result has the opposite sign to the original value.  */
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index aae01f9..0b819cb 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -1,5 +1,6 @@
 DEF_HELPER_1(bitrev, i32, i32)
 DEF_HELPER_1(ff1, i32, i32)
+DEF_HELPER_2(bfffo, i32, i32, i32)
 DEF_HELPER_FLAGS_2(sats, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_2(divu, void, env, i32)
 DEF_HELPER_2(divs, void, env, i32)
@@ -44,3 +45,6 @@ DEF_HELPER_2(flush_flags, void, env, i32)
 DEF_HELPER_2(set_ccr, void, env, i32)
 DEF_HELPER_FLAGS_1(get_ccr, TCG_CALL_NO_WG_SE, i32, env)
 DEF_HELPER_2(raise_exception, void, env, i32)
+
+DEF_HELPER_4(bitfield_load, i64, env, i32, i32, i32)
+DEF_HELPER_5(bitfield_store, void, env, i32, i32, i32, i64)
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 1c95ea0..71caba9 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -178,6 +178,74 @@ void HELPER(raise_exception)(CPUM68KState *env, uint32_t tt)
     raise_exception(env, tt);
 }
 
+/* load from a bitfield */
+
+uint64_t HELPER(bitfield_load)(CPUM68KState *env, uint32_t addr,
+                               uint32_t offset, uint32_t width)
+{
+    uint64_t bitfield = 0;
+    int size;
+
+    size = (offset + width + 7) >> 3;
+    switch (size) {
+    case 1:
+        bitfield = cpu_ldub_data(env, addr);
+        bitfield <<= 56;
+        break;
+    case 2:
+        bitfield = cpu_lduw_data(env, addr);
+        bitfield <<= 48;
+        break;
+    case 3:
+        bitfield = cpu_lduw_data(env, addr);
+        bitfield <<= 8;
+        bitfield |= cpu_ldub_data(env, addr + 2);
+        bitfield <<= 40;
+        break;
+    case 4:
+        bitfield = cpu_ldl_data(env, addr);
+        bitfield <<= 32;
+        break;
+    case 5:
+        bitfield = cpu_ldl_data(env, addr);
+        bitfield <<= 8;
+        bitfield |= cpu_ldub_data(env, addr + 4);
+        bitfield <<= 24;
+        break;
+    }
+
+    return bitfield;
+}
+
+/* store to a bitfield */
+
+void HELPER(bitfield_store)(CPUM68KState *env, uint32_t addr, uint32_t offset,
+                            uint32_t width, uint64_t bitfield)
+{
+    int size;
+
+    size = (offset + width + 7) >> 3;
+    switch (size) {
+    case 1:
+        cpu_stb_data(env, addr, bitfield >> 56);
+        break;
+    case 2:
+        cpu_stw_data(env, addr, bitfield >> 48);
+        break;
+    case 3:
+        cpu_stw_data(env, addr, bitfield >> 48);
+        cpu_stb_data(env, addr + 2, bitfield >> 40);
+        break;
+    case 4:
+        cpu_stl_data(env, addr, bitfield >> 32);
+        break;
+    case 5:
+        cpu_stl_data(env, addr, bitfield >> 32);
+        cpu_stb_data(env, addr + 4, bitfield >> 24);
+        break;
+    }
+}
+
 void HELPER(divu)(CPUM68KState *env, uint32_t word)
 {
     uint32_t num;
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 817f0b3..00fd2f1 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1240,6 +1240,231 @@ DISAS_INSN(divl)
     set_cc_op(s, CC_OP_FLAGS);
 }
 
+static inline void bcd_add(TCGv src, TCGv dest)
+{
+    TCGv t0, t1;
+
+    /* t1 = (src + 0x0066) + dest
+     *    = result with some possible exceding 0x6
+     */
+
+    t0 = tcg_const_i32(0x0066);
+    tcg_gen_add_i32(t0, t0, src);
+
+    t1 = tcg_temp_new();
+    tcg_gen_add_i32(t1, t0, dest);
+
+    /* we will remove exceding 0x6 where there is no carry */
+
+    /* t0 = (src + 0x0066) ^ dest
+     *    = t1 without carries
+     */
+
+    tcg_gen_xor_i32(t0, t0, dest);
+
+    /* extract the carries
+     * t0 = t0 ^ t1
+     *    = only the carries
+     */
+
+    tcg_gen_xor_i32(t0, t0, t1);
+
+    /* generate 0x1 where there is no carry */
+
+    tcg_gen_not_i32(t0, t0);
+    tcg_gen_andi_i32(t0, t0, 0x110);
+
+    /* for each 0x10, generate a 0x6 */
+
+    tcg_gen_shri_i32(dest, t0, 2);
+    tcg_gen_shri_i32(t0, t0, 3);
+    tcg_gen_or_i32(dest, dest, t0);
+    tcg_temp_free(t0);
+
+    /* remove the exceding 0x6
+     * for digits that have not generated a carry
+     */
+
+    tcg_gen_sub_i32(dest, t1, dest);
+    tcg_temp_free(t1);
+}
+
+static inline void bcd_neg(TCGv dest, TCGv src)
+{
+    TCGv t0, t1;
+
+    /* compute the 10's complement
+     *
+     *    bcd_add(0xff99 - (src + X), 0x0001)
+     *
+     *        t1 = 0xF9999999 - src - X)
+     *        t2 = t1 + 0x06666666
+     *        t3 = t2 + 0x00000001
+     *        t4 = t2 ^ 0x00000001
+     *        t5 = t3 ^ t4
+     *        t6 = ~t5 & 0x11111110
+     *        t7 = (t6 >> 2) | (t6 >> 3)
+     *        return t3 - t7
+     *
+     * reduced in:
+     *
+     *        t2 = 0xFFFFFFFF + (-src)
+     *        t3 = (-src)
+     *        t4 = t2  ^ (X ^ 1)
+     *        t5 = (t3 - X) ^ t4
+     *        t6 = ~t5 & 0x11111110
+     *        t7 = (t6 >> 2) | (t6 >> 3)
+     *        return (t3 - X) - t7
+     *
+     */
+
+    tcg_gen_neg_i32(src, src);
+
+    t0 = tcg_temp_new();
+    tcg_gen_addi_i32(t0, src, 0xffff);
+    tcg_gen_xori_i32(t0, t0, 1);
+    tcg_gen_xor_i32(t0, t0, QREG_CC_X);
+    tcg_gen_sub_i32(src, src, QREG_CC_X);
+    tcg_gen_xor_i32(t0, t0, src);
+    tcg_gen_not_i32(t0, t0);
+    tcg_gen_andi_i32(t0, t0, 0x110);
+
+    t1 = tcg_temp_new();
+    tcg_gen_shri_i32(t1, t0, 2);
+    tcg_gen_shri_i32(t0, t0, 3);
+    tcg_gen_or_i32(t0, t0, t1);
+    tcg_temp_free(t1);
+
+    tcg_gen_sub_i32(dest, src, t0);
+    tcg_temp_free(t0);
+}
+
+static inline void bcd_flags(TCGv val)
+{
+    tcg_gen_andi_i32(QREG_CC_C, val, 0x00ff);
+    tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_C);
+
+    tcg_gen_movi_i32(QREG_CC_X, 0);
+    tcg_gen_andi_i32(val, val, 0xff00);
+    tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_C, val, QREG_CC_X);
+
+    tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
+}
+
+DISAS_INSN(abcd_reg)
+{
+    TCGv src;
+    TCGv dest;
+
+    gen_flush_flags(s); /* !Z is sticky */
+
+    src = gen_extend(DREG(insn, 0), OS_BYTE, 0);
+    dest = gen_extend(DREG(insn, 9), OS_BYTE, 0);
+    bcd_add(src, dest);
+    gen_partset_reg(OS_BYTE, DREG(insn, 9), dest);
+
+    bcd_flags(dest);
+
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(abcd_mem)
+{
+    TCGv src;
+    TCGv addr_src;
+    TCGv dest;
+    TCGv addr_dest;
+
+    gen_flush_flags(s); /* !Z is sticky */
+
+    addr_src = AREG(insn, 0);
+    tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(OS_BYTE));
+    src = gen_load(s, OS_BYTE, addr_src, 0);
+
+    addr_dest = AREG(insn, 9);
+    tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(OS_BYTE));
+    dest = gen_load(s, OS_BYTE, addr_dest, 0);
+
+    bcd_add(src, dest);
+
+    gen_store(s, OS_BYTE, addr_dest, dest);
+
+    bcd_flags(dest);
+
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(sbcd_reg)
+{
+    TCGv src;
+    TCGv dest;
+    TCGv tmp;
+
+    gen_flush_flags(s); /* !Z is sticky */
+
+    src = gen_extend(DREG(insn, 0), OS_BYTE, 0);
+    dest = gen_extend(DREG(insn, 9), OS_BYTE, 0);
+
+    tmp = tcg_temp_new();
+    bcd_neg(tmp, src);
+    bcd_add(tmp, dest);
+    tcg_temp_free(tmp);
+
+    gen_partset_reg(OS_BYTE, DREG(insn, 9), dest);
+
+    bcd_flags(dest);
+
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(sbcd_mem)
+{
+    TCGv src;
+    TCGv addr_src;
+    TCGv dest;
+    TCGv addr_dest;
+    TCGv tmp;
+
+    gen_flush_flags(s); /* !Z is sticky */
+
+    addr_src = AREG(insn, 0);
+    tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(OS_BYTE));
+    src = gen_load(s, OS_BYTE, addr_src, 0);
+
+    addr_dest = AREG(insn, 9);
+    tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(OS_BYTE));
+    dest = gen_load(s, OS_BYTE, addr_dest, 0);
+
+    tmp = tcg_temp_new();
+    bcd_neg(tmp, src);
+    bcd_add(tmp, dest);
+    tcg_temp_free(tmp);
+
+    gen_store(s, OS_BYTE, addr_dest, dest);
+
+    bcd_flags(dest);
+
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(nbcd)
+{
+    TCGv dest;
+    TCGv addr;
+
+    gen_flush_flags(s); /* !Z is sticky */
+
+    SRC_EA(env, dest, OS_BYTE, 0, &addr);
+
+    bcd_neg(dest, dest);
+
+    DEST_EA(env, insn, OS_BYTE, dest, &addr);
+
+    bcd_flags(dest);
+
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
 DISAS_INSN(addsub)
 {
     TCGv reg;
@@ -2329,6 +2554,334 @@ DISAS_INSN(shift_reg)
     set_cc_op(s, CC_OP_FLAGS);
 }
 
+static void bitfield_param(uint16_t ext, TCGv *offset, TCGv *width, TCGv *mask)
+{
+    TCGv tmp;
+
+    /* offset */
+
+    if (ext & 0x0800) {
+        *offset = tcg_temp_new_i32();
+        tcg_gen_mov_i32(*offset, DREG(ext, 6));
+    } else {
+        *offset = tcg_temp_new_i32();
+        tcg_gen_movi_i32(*offset, (ext >> 6) & 31);
+    }
+
+    /* width */
+
+    if (ext & 0x0020) {
+        *width = tcg_temp_new_i32();
+        tcg_gen_subi_i32(*width, DREG(ext, 0), 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;
+    TCGv offset;
+    TCGv width;
+    int op;
+    TCGv reg2;
+    TCGv mask;
+
+    reg = DREG(insn, 0);
+    op = (insn >> 8) & 7;
+    ext = read_im16(env, s);
+
+    bitfield_param(ext, &offset, &width, &mask);
+
+    if (ext & 0x0800)
+        tcg_gen_andi_i32(offset, offset, 31);
+    tcg_gen_rotr_i32(mask, mask, offset);
+
+    /* reg & mask */
+
+    tmp = tcg_temp_new_i32();
+    tcg_gen_and_i32(tmp, reg, mask);
+
+    tmp1 = tcg_temp_new_i32();
+    tcg_gen_rotl_i32(tmp1, tmp, offset);
+
+    reg2 = DREG(ext, 12);
+    if (op == 7) {
+        TCGv tmp2;
+
+        tmp2 = tcg_temp_new_i32();
+        tcg_gen_sub_i32(tmp2, tcg_const_i32(32), width);
+        tcg_gen_shl_i32(tmp2, reg2, tmp2);
+        tcg_gen_and_i32(tmp2, tmp2, mask);
+        gen_logic_cc(s, tmp2, OS_LONG);
+
+        tcg_temp_free_i32(tmp1);
+    } else {
+        gen_logic_cc(s, tmp1, OS_LONG);
+    }
+
+    switch (op) {
+    case 0: /* bftst */
+        break;
+    case 1: /* bfextu */
+        tcg_gen_add_i32(tmp1, offset, width);
+        tcg_gen_andi_i32(tmp1, tmp1, 31);
+        tcg_gen_rotl_i32(reg2, tmp, tmp1);
+        break;
+    case 2: /* bfchg */
+        tcg_gen_xor_i32(reg, reg, mask);
+        break;
+    case 3: /* bfexts */
+        tcg_gen_rotl_i32(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_not_i32(mask, mask);
+        tcg_gen_and_i32(reg, reg, mask);
+        break;
+    case 5: /* bfffo */
+        tcg_gen_rotl_i32(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);
+        tcg_gen_rotr_i32(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,
+                            TCGv offset, TCGv mask_cc, TCGv_i64 bitfield)
+{
+    TCGv dest;
+    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, tmp64, 32ULL);
+    dest = tcg_temp_new_i32();
+    tcg_gen_extrl_i64_i32(dest, tmp64);
+    tcg_gen_and_i32(dest, dest, mask_cc);
+
+    return dest;
+}
+
+static TCGv_i64 gen_bitfield_mask(TCGv offset, TCGv width)
+{
+    TCGv tmp;
+    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();
+    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; */
+
+    /* width is between 1 and 32
+     * tcg_gen_shl_i32() cannot manage value 32
+     */
+    tcg_gen_subi_i32(tmp, width, 1);
+    tcg_gen_shl_i32(tmp, tcg_const_i32(2), tmp);
+    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 src;
+    TCGv offset;
+    TCGv width;
+    TCGv reg;
+    TCGv tmp;
+
+    op = (insn >> 8) & 7;
+    ext = read_im16(env, s);
+    src = gen_lea(env, s, insn, OS_LONG);
+    if (IS_NULL_QREG(src)) {
+       gen_addr_fault(s);
+       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, cpu_env, 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);
+
+    if (op == 7) {
+        TCGv tmp1;
+
+        tmp1 = tcg_temp_new_i32();
+        tcg_gen_sub_i32(tmp1, tcg_const_i32(32), width);
+        tcg_gen_shl_i32(tmp1, reg, tmp1);
+        tcg_gen_and_i32(tmp1, tmp1, mask_cc);
+        gen_logic_cc(s, tmp1, OS_LONG);
+
+        tcg_temp_free_i32(tmp1);
+    } else {
+        gen_logic_cc(s, val, OS_LONG);
+    }
+
+    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(cpu_env, 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(cpu_env, 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(cpu_env, 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(cpu_env, src, offset, width, bitfield);
+        break;
+    }
+}
+
 DISAS_INSN(ff1)
 {
     TCGv reg;
@@ -3296,6 +3849,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(not,       4600, ff00, M68000);
     INSN(undef,     46c0, ffc0, M68000);
     INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
+    INSN(nbcd,      4800, ffc0, M68000);
     BASE(pea,       4840, ffc0);
     BASE(swap,      4840, fff8);
     INSN(bkpt,      4848, fff8, M68000);
@@ -3350,6 +3904,8 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(mvzs,      7100, f100, CF_ISA_B);
     BASE(or,        8000, f000);
     BASE(divw,      80c0, f0c0);
+    INSN(sbcd_reg,  8100, f1f8, M68000);
+    INSN(sbcd_mem,  8108, f1f8, M68000);
     BASE(addsub,    9000, f000);
     INSN(undef,     90c0, f0c0, CF_ISA_A);
     INSN(subx_reg,  9180, f1f8, CF_ISA_A);
@@ -3382,6 +3938,8 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(eor,       b180, f1c0, CF_ISA_A);
     BASE(and,       c000, f000);
     BASE(mulw,      c0c0, f0c0);
+    INSN(abcd_reg,  c100, f1f8, M68000);
+    INSN(abcd_mem,  c108, f1f8, M68000);
     BASE(addsub,    d000, f000);
     INSN(undef,     d0c0, f0c0, CF_ISA_A);
     INSN(addx_reg,      d180, f1f8, CF_ISA_A);
@@ -3391,6 +3949,8 @@ 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(bitfield_mem,e8c0, f8c0, BITFIELD);
+    INSN(bitfield_reg,e8c0, f8f8, BITFIELD);
     INSN(undef_fpu, f000, f000, CF_ISA_A);
     INSN(fpu,       f200, ffc0, CF_FPU);
     INSN(fbcc,      f280, ffc0, CF_FPU);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (31 preceding siblings ...)
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 32/52] target-m68k: bitfield ops Laurent Vivier
@ 2016-05-04 21:08 ` Laurent Vivier
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 34/52] target-m68k: add 64bit mull Laurent Vivier
                     ` (6 more replies)
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
                   ` (2 subsequent siblings)
  35 siblings, 7 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/main.c       |   7 ++
 target-m68k/cpu.h       |   4 -
 target-m68k/helper.h    |   2 -
 target-m68k/op_helper.c |  49 ------------
 target-m68k/qregs.def   |   2 -
 target-m68k/translate.c | 198 +++++++++++++++++++++++++++++++++++++++---------
 6 files changed, 169 insertions(+), 93 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 5f3ec97..74b02c7 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3034,6 +3034,13 @@ void cpu_loop(CPUM68KState *env)
             info._sifields._sigfault._addr = env->pc;
             queue_signal(env, info.si_signo, &info);
             break;
+        case EXCP_DIV0:
+            info.si_signo = TARGET_SIGFPE;
+            info.si_errno = 0;
+            info.si_code = TARGET_FPE_INTDIV;
+            info._sifields._sigfault._addr = env->pc;
+            queue_signal(env, info.si_signo, &info);
+            break;
         case EXCP_TRAP0:
             {
                 ts->sim_syscalls = 0;
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 9415d2b..b300a92 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -94,10 +94,6 @@ typedef struct CPUM68KState {
     uint32_t macsr;
     uint32_t mac_mask;
 
-    /* Temporary storage for DIV helpers.  */
-    uint32_t div1;
-    uint32_t div2;
-
     /* MMU status.  */
     struct {
         uint32_t ar;
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index 0b819cb..80ee4f8 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -2,8 +2,6 @@ DEF_HELPER_1(bitrev, i32, i32)
 DEF_HELPER_1(ff1, i32, i32)
 DEF_HELPER_2(bfffo, i32, i32, i32)
 DEF_HELPER_FLAGS_2(sats, TCG_CALL_NO_RWG_SE, i32, i32, i32)
-DEF_HELPER_2(divu, void, env, i32)
-DEF_HELPER_2(divs, void, env, i32)
 DEF_HELPER_2(set_sr, void, env, i32)
 DEF_HELPER_3(movec, void, env, i32, i32)
 
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 71caba9..bf3c813 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -245,52 +245,3 @@ void HELPER(bitfield_store)(CPUM68KState *env, uint32_t addr, uint32_t offset,
         break;
     }
 }
-
-void HELPER(divu)(CPUM68KState *env, uint32_t word)
-{
-    uint32_t num;
-    uint32_t den;
-    uint32_t quot;
-    uint32_t rem;
-
-    num = env->div1;
-    den = env->div2;
-    /* ??? This needs to make sure the throwing location is accurate.  */
-    if (den == 0) {
-        raise_exception(env, EXCP_DIV0);
-    }
-    quot = num / den;
-    rem = num % den;
-
-    env->cc_v = (word && quot > 0xffff ? -1 : 0);
-    env->cc_z = quot;
-    env->cc_n = quot;
-    env->cc_c = 0;
-
-    env->div1 = quot;
-    env->div2 = rem;
-}
-
-void HELPER(divs)(CPUM68KState *env, uint32_t word)
-{
-    int32_t num;
-    int32_t den;
-    int32_t quot;
-    int32_t rem;
-
-    num = env->div1;
-    den = env->div2;
-    if (den == 0) {
-        raise_exception(env, EXCP_DIV0);
-    }
-    quot = num / den;
-    rem = num % den;
-
-    env->cc_v = (word && quot != (int16_t)quot ? -1 : 0);
-    env->cc_z = quot;
-    env->cc_n = quot;
-    env->cc_c = 0;
-
-    env->div1 = quot;
-    env->div2 = rem;
-}
diff --git a/target-m68k/qregs.def b/target-m68k/qregs.def
index 156c0f5..51ff43b 100644
--- a/target-m68k/qregs.def
+++ b/target-m68k/qregs.def
@@ -7,7 +7,5 @@ DEFO32(CC_C, cc_c)
 DEFO32(CC_N, cc_n)
 DEFO32(CC_V, cc_v)
 DEFO32(CC_Z, cc_z)
-DEFO32(DIV1, div1)
-DEFO32(DIV2, div2)
 DEFO32(MACSR, macsr)
 DEFO32(MAC_MASK, mac_mask)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 00fd2f1..b47f9c1 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1047,11 +1047,19 @@ static void gen_jmp(DisasContext *s, TCGv dest)
     s->is_jmp = DISAS_JUMP;
 }
 
+static inline void gen_raise_exception(int nr)
+{
+    TCGv_i32 tmp = tcg_const_i32(nr);
+
+    gen_helper_raise_exception(cpu_env, tmp);
+    tcg_temp_free_i32(tmp);
+}
+
 static void gen_exception(DisasContext *s, uint32_t where, int nr)
 {
     update_cc_op(s);
     gen_jmp_im(s, where);
-    gen_helper_raise_exception(cpu_env, tcg_const_i32(nr));
+    gen_raise_exception(nr);
 }
 
 static inline void gen_addr_fault(DisasContext *s)
@@ -1179,64 +1187,182 @@ DISAS_INSN(mulw)
 
 DISAS_INSN(divw)
 {
-    TCGv reg;
-    TCGv tmp;
-    TCGv src;
+    TCGLabel *l1;
+    TCGv t0, src;
+    TCGv quot, rem;
     int sign;
 
     sign = (insn & 0x100) != 0;
-    reg = DREG(insn, 9);
-    if (sign) {
-        tcg_gen_ext16s_i32(QREG_DIV1, reg);
-    } else {
-        tcg_gen_ext16u_i32(QREG_DIV1, reg);
-    }
-    SRC_EA(env, src, OS_WORD, sign, NULL);
-    tcg_gen_mov_i32(QREG_DIV2, src);
+
+    tcg_gen_movi_i32(QREG_CC_C, 0); /* C is always cleared, use as 0 */
+
+    /* dest.l / src.w */
+
+    SRC_EA(env, t0, OS_WORD, sign, NULL);
+
+    src = tcg_temp_local_new_i32();
+    tcg_gen_mov_i32(src, t0);
+    l1 = gen_new_label();
+    tcg_gen_brcondi_i32(TCG_COND_NE, src, 0, l1);
+    tcg_gen_movi_i32(QREG_PC, s->insn_pc);
+    gen_raise_exception(EXCP_DIV0);
+    gen_set_label(l1);
+
+    tcg_gen_movi_i32(QREG_CC_C, 0); /* C is always cleared, use as 0 */
+
+    quot = tcg_temp_new();
+    rem = tcg_temp_new();
     if (sign) {
-        gen_helper_divs(cpu_env, tcg_const_i32(1));
+        tcg_gen_div_i32(quot, DREG(insn, 9), src);
+        tcg_gen_rem_i32(rem, DREG(insn, 9), src);
+        tcg_gen_ext16s_i32(QREG_CC_V, quot);
+        tcg_gen_movi_i32(src, -1);
+        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_V,
+                            QREG_CC_V, quot,
+                            QREG_CC_C /* 0 */, src /* -1 */);
     } else {
-        gen_helper_divu(cpu_env, tcg_const_i32(1));
+        tcg_gen_divu_i32(quot, DREG(insn, 9), src);
+        tcg_gen_remu_i32(rem, DREG(insn, 9), src);
+        tcg_gen_shri_i32(QREG_CC_V, quot, 16);
+        tcg_gen_movi_i32(src, -1);
+        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_V,
+                            QREG_CC_V, QREG_CC_C /* 0 */,
+                            QREG_CC_V /* 0 */, src /* -1 */);
     }
+    tcg_temp_free(src);
 
-    tmp = tcg_temp_new();
-    src = tcg_temp_new();
-    tcg_gen_ext16u_i32(tmp, QREG_DIV1);
-    tcg_gen_shli_i32(src, QREG_DIV2, 16);
-    tcg_gen_or_i32(reg, tmp, src);
+    /* result rem:quot */
+
+    tcg_gen_ext16u_i32(quot, quot);
+    tcg_gen_deposit_i32(quot, quot, rem, 16, 16);
+    tcg_temp_free(rem);
+
+    /* on overflow, operands and flags are unaffected */
+
+    tcg_gen_movcond_i32(TCG_COND_EQ, DREG(insn, 9),
+                        QREG_CC_V, QREG_CC_C /* zero */,
+                        quot, DREG(insn, 9));
+    tcg_gen_ext16s_i32(quot, quot);
+    tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_Z,
+                        QREG_CC_V, QREG_CC_C /* zero */,
+                        quot, QREG_CC_Z);
+    tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_N,
+                        QREG_CC_V, QREG_CC_C /* zero */,
+                        quot, QREG_CC_N);
+    tcg_temp_free(quot);
 
     set_cc_op(s, CC_OP_FLAGS);
 }
 
 DISAS_INSN(divl)
 {
-    TCGv num;
-    TCGv den;
-    TCGv reg;
+    TCGLabel *l1;
+    TCGv t0, den, minusone, quot, rem;
+    TCGv_i64 num64, den64, quot64, rem64;
     uint16_t ext;
+    int sign;
 
     ext = read_im16(env, s);
-    if (ext & 0x87f8) {
+
+    if ((ext & 0x400) && !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);
-    SRC_EA(env, den, OS_LONG, 0, NULL);
-    tcg_gen_mov_i32(QREG_DIV2, den);
-    if (ext & 0x0800) {
-        gen_helper_divs(cpu_env, tcg_const_i32(0));
+
+    sign = ext & 0x0800;
+
+    tcg_gen_movi_i32(QREG_CC_C, 0); /* used as 0 later */
+
+    SRC_EA(env, t0, OS_LONG, 0, NULL);
+
+    den = tcg_temp_local_new_i32();
+    tcg_gen_mov_i32(den, t0);
+    l1 = gen_new_label();
+    tcg_gen_brcondi_i32(TCG_COND_NE, den, 0, l1);
+    tcg_gen_movi_i32(QREG_PC, s->insn_pc);
+    gen_raise_exception(EXCP_DIV0);
+    gen_set_label(l1);
+
+    num64 = tcg_temp_new_i64();
+    den64 = tcg_temp_new_i64();
+    quot64 = tcg_temp_new_i64();
+    rem64 = tcg_temp_new_i64();
+    if (ext & 0x400) {
+        tcg_gen_concat_i32_i64(num64, DREG(ext, 12), DREG(ext, 0));
+    } else {
+        if (sign) {
+            tcg_gen_ext_i32_i64(num64, DREG(ext, 12));
+        } else {
+            tcg_gen_extu_i32_i64(num64, DREG(ext, 12));
+        }
+    }
+
+    if (sign) {
+        tcg_gen_ext_i32_i64(den64, den);
+        tcg_gen_div_i64(quot64, num64, den64);
+        tcg_gen_rem_i64(rem64, num64, den64);
+    } else {
+        tcg_gen_extu_i32_i64(den64, den);
+        tcg_gen_divu_i64(quot64, num64, den64);
+        tcg_gen_remu_i64(rem64, num64, den64);
+    }
+    tcg_temp_free_i64(den64);
+    tcg_temp_free_i64(num64);
+
+    /* compute result and overflow flag */
+
+    quot = tcg_temp_new();
+    tcg_gen_extr_i64_i32(quot, QREG_CC_V, quot64);
+
+    rem = tcg_temp_new();
+    minusone = tcg_const_i32(-1);
+    if (sign) {
+        tcg_gen_ext32s_i64(quot64, quot64);
+        tcg_gen_extrh_i64_i32(rem, quot64);
+        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_V,
+                            QREG_CC_V, rem,
+                            QREG_CC_C /* 0 */, minusone /* -1 */);
     } else {
-        gen_helper_divu(cpu_env, tcg_const_i32(0));
+        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_V,
+                            QREG_CC_V, QREG_CC_C /* 0 */ ,
+                            QREG_CC_V /* 0 */, minusone /* -1 */);
     }
-    if ((ext & 7) == ((ext >> 12) & 7)) {
-        /* div */
-        tcg_gen_mov_i32 (reg, QREG_DIV1);
+    tcg_temp_free(minusone);
+    tcg_temp_free_i64(quot64);
+
+    tcg_gen_extrl_i64_i32(rem, rem64);
+    tcg_temp_free_i64(rem64);
+
+    /* on overflow, operands and flags are unaffected */
+
+    if (m68k_feature(s->env, M68K_FEATURE_CF_ISA_A)) {
+        if (REG(ext, 0) == REG(ext, 12)) {
+            /* div */
+            tcg_gen_movcond_i32(TCG_COND_EQ, DREG(ext, 12),
+                                QREG_CC_V, QREG_CC_C /* zero */ ,
+                                quot, DREG(ext, 12));
+        } else {
+            /* rem */
+            tcg_gen_movcond_i32(TCG_COND_EQ, DREG(ext, 0),
+                                QREG_CC_V, QREG_CC_C /* zero */ ,
+                                rem, DREG(ext, 0));
+        }
     } else {
-        /* rem */
-        tcg_gen_mov_i32 (reg, QREG_DIV2);
+        tcg_gen_movcond_i32(TCG_COND_EQ, DREG(ext, 0),
+                            QREG_CC_V, QREG_CC_C /* zero */ ,
+                            rem, DREG(ext, 0));
+        tcg_gen_movcond_i32(TCG_COND_EQ, DREG(ext, 12),
+                            QREG_CC_V, QREG_CC_C /* zero */ ,
+                            quot, DREG(ext, 12));
     }
+    tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_Z,
+                        QREG_CC_V, QREG_CC_C /* zero */ ,
+                        quot, QREG_CC_Z);
+    tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_N,
+                        QREG_CC_V, QREG_CC_C /* zero */ ,
+                        quot, QREG_CC_N);
+    tcg_temp_free(quot);
+
     set_cc_op(s, CC_OP_FLAGS);
 }
 
-- 
2.5.5

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

* [Qemu-devel] [PATCH 34/52] target-m68k: add 64bit mull
  2016-05-04 21:08 ` [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs Laurent Vivier
@ 2016-05-04 21:08   ` Laurent Vivier
  2016-05-06 19:48     ` Richard Henderson
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 35/52] target-m68k: inline rotate ops Laurent Vivier
                     ` (5 subsequent siblings)
  6 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 54 ++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 42 insertions(+), 12 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index b47f9c1..1d05c6a 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2128,24 +2128,54 @@ DISAS_INSN(tas)
 DISAS_INSN(mull)
 {
     uint16_t ext;
-    TCGv reg;
     TCGv src1;
-    TCGv dest;
+    int sign;
 
-    /* The upper 32 bits of the product are discarded, so
-       muls.l and mulu.l are functionally equivalent.  */
     ext = read_im16(env, s);
-    if (ext & 0x87ff) {
-        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+
+    sign = ext & 0x800;
+
+    if (ext & 0x400) {
+        if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
+            gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+            return;
+        }
+
+        SRC_EA(env, src1, OS_LONG, 0, NULL);
+
+        if (sign) {
+            tcg_gen_muls2_i32(DREG(ext, 12), DREG(ext, 0), src1, DREG(ext, 12));
+        } else {
+            tcg_gen_mulu2_i32(DREG(ext, 12), DREG(ext, 0), src1, DREG(ext, 12));
+        }
+
+        tcg_gen_movi_i32(QREG_CC_V, 0);
+        tcg_gen_mov_i32(QREG_CC_C, QREG_CC_V);
+        tcg_gen_mov_i32(QREG_CC_N, DREG(ext, 0));
+        tcg_gen_or_i32(QREG_CC_Z, DREG(ext, 12), DREG(ext, 0));
+
+        set_cc_op(s, CC_OP_FLAGS);
         return;
     }
-    reg = DREG(ext, 12);
     SRC_EA(env, src1, OS_LONG, 0, NULL);
-    dest = tcg_temp_new();
-    tcg_gen_mul_i32(dest, src1, reg);
-    tcg_gen_mov_i32(reg, dest);
-    /* Unlike m68k, coldfire always clears the overflow bit.  */
-    gen_logic_cc(s, dest, OS_LONG);
+    if (m68k_feature(s->env, M68K_FEATURE_M68000)) {
+        if (sign) {
+            tcg_gen_muls2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12));
+        } else {
+            tcg_gen_mulu2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12));
+        }
+        tcg_gen_mov_i32(DREG(ext, 12), QREG_CC_N);
+
+        tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+        tcg_gen_movi_i32(QREG_CC_C, 0);
+
+        set_cc_op(s, CC_OP_FLAGS);
+    } else {
+        /* The upper 32 bits of the product are discarded, so
+           muls.l and mulu.l are functionally equivalent.  */
+        tcg_gen_mul_i32(DREG(ext, 12), src1, DREG(ext, 12));
+        gen_logic_cc(s, DREG(ext, 12), OS_LONG);
+    }
 }
 
 DISAS_INSN(link)
-- 
2.5.5

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

* [Qemu-devel] [PATCH 35/52] target-m68k: inline rotate ops
  2016-05-04 21:08 ` [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs Laurent Vivier
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 34/52] target-m68k: add 64bit mull Laurent Vivier
@ 2016-05-04 21:08   ` Laurent Vivier
  2016-05-06 20:28     ` Richard Henderson
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 36/52] target-m68k: inline shift ops Laurent Vivier
                     ` (4 subsequent siblings)
  6 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 353 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 353 insertions(+)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 1d05c6a..d183a3c 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2710,6 +2710,352 @@ DISAS_INSN(shift_reg)
     set_cc_op(s, CC_OP_FLAGS);
 }
 
+static inline void rotate(TCGv reg, TCGv shift, int left, int size)
+{
+    if (size == 32) {
+        if (left) {
+            tcg_gen_rotl_i32(reg, reg, shift);
+        } else {
+            tcg_gen_rotr_i32(reg, reg, shift);
+        }
+    } else {
+        TCGv t0;
+
+        if (left) {
+            tcg_gen_shl_i32(reg, reg, shift);
+        } else {
+            tcg_gen_shli_i32(reg, reg, size);
+            tcg_gen_shr_i32(reg, reg, shift);
+        }
+
+        t0 = tcg_temp_new();
+        tcg_gen_shri_i32(t0, reg, size);
+        tcg_gen_or_i32(reg, reg, t0);
+        tcg_temp_free(t0);
+        if (size == 8) {
+            tcg_gen_ext8s_i32(reg, reg);
+        } else if (size == 16) {
+            tcg_gen_ext16s_i32(reg, reg);
+        }
+    }
+
+    if (left) {
+        tcg_gen_andi_i32(QREG_CC_C, reg, 1);
+    } else {
+        tcg_gen_shri_i32(QREG_CC_C, reg, 31);
+    }
+
+    tcg_gen_movi_i32(QREG_CC_V, 0);
+    tcg_gen_mov_i32(QREG_CC_N, reg);
+    tcg_gen_mov_i32(QREG_CC_Z, reg);
+}
+
+static inline void rotate_x_flags(TCGv reg, int size)
+{
+    switch (size) {
+    case 8:
+        tcg_gen_ext8s_i32(reg, reg);
+        break;
+    case 16:
+        tcg_gen_ext16s_i32(reg, reg);
+        break;
+    default:
+        break;
+    }
+    tcg_gen_mov_i32(QREG_CC_N, reg);
+    tcg_gen_mov_i32(QREG_CC_Z, reg);
+    tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
+}
+
+static inline void rotate_x(TCGv dest, TCGv X, TCGv reg, TCGv shift,
+                            int left, int size)
+{
+    TCGv_i64 t0, shift64;
+    TCGv lo, hi;
+
+    shift64 = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(shift64, shift);
+
+    t0 = tcg_temp_new_i64();
+
+    lo = tcg_temp_new();
+    hi = tcg_temp_new();
+
+    if (left) {
+        /* create [reg:X:..] */
+
+        if (size == 32) {
+            tcg_gen_shli_i32(X, QREG_CC_X, 31);
+            tcg_gen_concat_i32_i64(t0, X, reg);
+        } else {
+            tcg_gen_shli_i32(X, reg, 1);
+            tcg_gen_or_i32(X, X, QREG_CC_X);
+            tcg_gen_extu_i32_i64(t0, X);
+            tcg_gen_shli_i64(t0, t0, 64 - size - 1);
+        }
+
+        /* rotate */
+
+        tcg_gen_rotl_i64(t0, t0, shift64);
+        tcg_temp_free_i64(shift64);
+
+        /* result is [reg:..:reg:X] */
+
+        tcg_gen_extr_i64_i32(lo, hi, t0);
+        tcg_gen_andi_i32(X, lo, 1);
+
+        tcg_gen_shri_i32(lo, lo, 1);
+        tcg_gen_shri_i32(hi, hi, 32 - size);
+        tcg_gen_or_i32(dest, lo, hi);
+    } else {
+        if (size == 32) {
+            tcg_gen_concat_i32_i64(t0, reg, QREG_CC_X);
+        } else {
+            tcg_gen_shli_i32(X, QREG_CC_X, size);
+            tcg_gen_or_i32(X, reg, X);
+            tcg_gen_extu_i32_i64(t0, X);
+        }
+
+        tcg_gen_rotr_i64(t0, t0, shift64);
+        tcg_temp_free_i64(shift64);
+
+        /* result is value: [X:reg:..:reg] */
+
+        tcg_gen_extr_i64_i32(lo, hi, t0);
+
+        /* extract X */
+
+        tcg_gen_shri_i32(X, hi, 31);
+
+        /* extract result */
+
+        tcg_gen_shli_i32(hi, hi, 1);
+        tcg_gen_shri_i32(hi, hi, 32 - size);
+        tcg_gen_or_i32(dest, lo, hi);
+    }
+    tcg_temp_free(hi);
+    tcg_temp_free(lo);
+    tcg_temp_free_i64(t0);
+
+    tcg_gen_movi_i32(QREG_CC_V, 0); /* always cleared */
+}
+
+DISAS_INSN(rotate_im)
+{
+    TCGv reg;
+    TCGv shift;
+    int tmp;
+    int left = (insn & 0x100);
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    tmp = ((tmp - 1) & 7) + 1; /* 1..8 */
+
+    shift = tcg_const_i32(tmp);
+    if (insn & 8) {
+        rotate(reg, shift, left, 32);
+    } else {
+        rotate_x(reg, QREG_CC_X, reg, shift, left, 32);
+        rotate_x_flags(reg, 32);
+    }
+    tcg_temp_free(shift);
+
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(rotate8_im)
+{
+    int left = (insn & 0x100);
+    TCGv reg;
+    TCGv shift;
+    int tmp;
+
+    reg = gen_extend(DREG(insn, 0), OS_BYTE, 0);
+
+    tmp = (insn >> 9) & 7;
+    tmp = ((tmp - 1) & 7) + 1; /* 1..8 */
+
+    shift = tcg_const_i32(tmp);
+    if (insn & 8) {
+        rotate(reg, shift, left, 8);
+    } else {
+        rotate_x(reg, QREG_CC_X, reg, shift, left, 8);
+        rotate_x_flags(reg, 8);
+    }
+    gen_partset_reg(OS_BYTE, DREG(insn, 0), reg);
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(rotate16_im)
+{
+    int left = (insn & 0x100);
+    TCGv reg;
+    TCGv shift;
+    int tmp;
+
+    reg = gen_extend(DREG(insn, 0), OS_WORD, 0);
+    tmp = (insn >> 9) & 7;
+    tmp = ((tmp - 1) & 7) + 1; /* 1..8 */
+
+    shift = tcg_const_i32(tmp);
+    if (insn & 8) {
+        rotate(reg, shift, left, 16);
+    } else {
+        rotate_x(reg, QREG_CC_X, reg, shift, left, 16);
+        rotate_x_flags(reg, 8);
+    }
+    gen_partset_reg(OS_WORD, DREG(insn, 0), reg);
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(rotate_reg)
+{
+    TCGv reg;
+    TCGv src;
+    TCGv tmp, t0;
+    int left = (insn & 0x100);
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    if (insn & 8) {
+        tcg_gen_andi_i32(tmp, src, 31);
+        rotate(reg, tmp, left, 32);
+        /* if shift == 0, clear C */
+        tcg_gen_andi_i32(tmp, src, 63);
+        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
+                            tmp, QREG_CC_V /* 0 */,
+                            QREG_CC_V /* 0 */, QREG_CC_C);
+    } else {
+        TCGv dest, X;
+        dest = tcg_temp_new();
+        X = tcg_temp_new();
+        /* shift in [0..63] */
+        tcg_gen_andi_i32(tmp, src, 63);
+        /* modulo 33 */
+        t0 = tcg_const_i32(33);
+        tcg_gen_remu_i32(tmp, tmp, t0);
+        tcg_temp_free(t0);
+        rotate_x(dest, X, reg, tmp, left, 32);
+        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_X,
+                            tmp, QREG_CC_V /* 0 */,
+                            QREG_CC_X /* 0 */, X);
+        tcg_gen_movcond_i32(TCG_COND_EQ, reg,
+                            tmp, QREG_CC_V /* 0 */,
+                            reg /* 0 */, dest);
+        tcg_temp_free(X);
+        tcg_temp_free(dest);
+        rotate_x_flags(reg, 32);
+    }
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(rotate8_reg)
+{
+    TCGv reg;
+    TCGv src;
+    TCGv tmp, t0;
+    int left = (insn & 0x100);
+
+    reg = gen_extend(DREG(insn, 0), OS_BYTE, 0);
+    src = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    if (insn & 8) {
+        tcg_gen_andi_i32(tmp, src, 7);
+        rotate(reg, tmp, left, 8);
+        /* if shift == 0, clear C */
+        tcg_gen_andi_i32(tmp, src, 63);
+        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
+                            tmp, QREG_CC_V /* 0 */,
+                            QREG_CC_V /* 0 */, QREG_CC_C);
+    } else {
+        TCGv dest, X;
+        dest = tcg_temp_new();
+        X = tcg_temp_new();
+        /* shift in [0..63] */
+        tcg_gen_andi_i32(tmp, src, 63);
+        /* modulo 9 */
+        t0 = tcg_const_i32(9);
+        tcg_gen_remu_i32(tmp, tmp, t0);
+        tcg_temp_free(t0);
+        rotate_x(dest, X, reg, tmp, left, 8);
+        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_X,
+                            tmp, QREG_CC_V /* 0 */,
+                            QREG_CC_X /* 0 */, X);
+        tcg_gen_movcond_i32(TCG_COND_EQ, reg,
+                            tmp, QREG_CC_V /* 0 */,
+                            reg /* 0 */, dest);
+        tcg_temp_free(X);
+        tcg_temp_free(dest);
+        rotate_x_flags(reg, 8);
+    }
+    gen_partset_reg(OS_BYTE, DREG(insn, 0), reg);
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(rotate16_reg)
+{
+    TCGv reg;
+    TCGv src;
+    TCGv tmp, t0;
+    int left = (insn & 0x100);
+
+    reg = gen_extend(DREG(insn, 0), OS_WORD, 0);
+    src = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    if (insn & 8) {
+        tcg_gen_andi_i32(tmp, src, 15);
+        rotate(reg, tmp, left, 16);
+        /* if shift == 0, clear C */
+        tcg_gen_andi_i32(tmp, src, 63);
+        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
+                            tmp, QREG_CC_V /* 0 */,
+                            QREG_CC_V /* 0 */, QREG_CC_C);
+    } else {
+        TCGv dest, X;
+        dest = tcg_temp_new();
+        X = tcg_temp_new();
+        /* shift in [0..63] */
+        tcg_gen_andi_i32(tmp, src, 63);
+        /* modulo 17 */
+        t0 = tcg_const_i32(17);
+        tcg_gen_remu_i32(tmp, tmp, t0);
+        tcg_temp_free(t0);
+        rotate_x(dest, X, reg, tmp, left, 16);
+        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_X,
+                            tmp, QREG_CC_V /* 0 */,
+                            QREG_CC_X /* 0 */, X);
+        tcg_gen_movcond_i32(TCG_COND_EQ, reg,
+                            tmp, QREG_CC_V /* 0 */,
+                            reg /* 0 */, dest);
+        tcg_temp_free(X);
+        tcg_temp_free(dest);
+        rotate_x_flags(reg, 16);
+    }
+    gen_partset_reg(OS_WORD, DREG(insn, 0), reg);
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(rotate_mem)
+{
+    TCGv src;
+    TCGv addr;
+    TCGv shift;
+    int left = (insn & 0x100);
+
+    SRC_EA(env, src, OS_WORD, 0, &addr);
+
+    shift = tcg_const_i32(1);
+    if (insn & 8) {
+        rotate(src, shift, left, 16);
+    } else {
+        rotate_x(src, QREG_CC_X, src, shift, left, 16);
+        rotate_x_flags(src, 16);
+    }
+    DEST_EA(env, insn, OS_WORD, src, &addr);
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
 static void bitfield_param(uint16_t ext, TCGv *offset, TCGv *width, TCGv *mask)
 {
     TCGv tmp;
@@ -4105,6 +4451,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(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(bitfield_mem,e8c0, f8c0, BITFIELD);
     INSN(bitfield_reg,e8c0, f8f8, BITFIELD);
     INSN(undef_fpu, f000, f000, CF_ISA_A);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 36/52] target-m68k: inline shift ops
  2016-05-04 21:08 ` [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs Laurent Vivier
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 34/52] target-m68k: add 64bit mull Laurent Vivier
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 35/52] target-m68k: inline rotate ops Laurent Vivier
@ 2016-05-04 21:08   ` Laurent Vivier
  2016-05-06 20:53     ` Richard Henderson
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 37/52] target-m68k: add cas/cas2 ops Laurent Vivier
                     ` (3 subsequent siblings)
  6 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 211 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 176 insertions(+), 35 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index d183a3c..d48ab66 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -551,7 +551,7 @@ static inline void gen_ext(TCGv res, TCGv val, int opsize, int sign)
     }
 }
 
-static TCGv gen_extend(TCGv val, int opsize, int sign)
+static inline TCGv gen_extend(TCGv val, int opsize, int sign)
 {
     TCGv tmp;
 
@@ -2615,19 +2615,51 @@ DISAS_INSN(addx_mem)
     gen_store(s, opsize, addr_dest, QREG_CC_N);
 }
 
-DISAS_INSN(shift_im)
+static inline void shift_im(DisasContext *s, uint16_t insn, int opsize)
 {
-    TCGv reg = DREG(insn, 0);
     int count = (insn >> 9) & 7;
     int logical = insn & 8;
+    int left = insn & 0x100;
+    int bits = opsize_bytes(opsize) * 8;
+    TCGv reg = gen_extend(DREG(insn, 0), opsize, !logical);
+    TCGv zero;
 
-    if (count == 0) {
-        count = 8;
-    }
+    count = ((count - 1) & 0x7) + 1; /* 1..8 */
 
-    if (insn & 0x100) {
-        tcg_gen_shri_i32(QREG_CC_C, reg, 31 - count);
+    zero = tcg_const_i32(0);
+    if (left) {
+        tcg_gen_shri_i32(QREG_CC_C, reg, bits - count);
         tcg_gen_shli_i32(QREG_CC_N, reg, count);
+
+        /* Note that ColdFire always clears V,
+           while M68000 sets if the most significant bit is changed at
+           any time during the shift operation */
+        tcg_gen_mov_i32(QREG_CC_V, zero);
+        if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
+            /* if shift count >= bits, V is (reg != 0) */
+            if (count >= bits) {
+                tcg_gen_setcond_i32(TCG_COND_EQ, QREG_CC_V, reg, zero);
+                /* adjust V: (1,0) -> (0,-1) */
+                tcg_gen_subi_i32(QREG_CC_V, QREG_CC_V, 1);
+            } else {
+                TCGv t0 = tcg_temp_new();
+                TCGv t1 = tcg_const_i32(bits - 1 - count);
+
+                tcg_gen_shr_i32(QREG_CC_V, reg, t1);
+                tcg_gen_sar_i32(t0, reg, t1);
+                tcg_temp_free(t1);
+                tcg_gen_not_i32(t0, t0);
+
+                tcg_gen_setcond_i32(TCG_COND_EQ, QREG_CC_V, QREG_CC_V, zero);
+                tcg_gen_setcond_i32(TCG_COND_EQ, t0, t0, zero);
+                tcg_gen_or_i32(QREG_CC_V, QREG_CC_V, t0); /* V is !V here */
+
+                tcg_temp_free(t0);
+
+                /* adjust V: (1,0) -> (0,-1) */
+                tcg_gen_subi_i32(QREG_CC_V, QREG_CC_V, 1);
+            }
+        }
     } else {
         tcg_gen_shri_i32(QREG_CC_C, reg, count - 1);
         if (logical) {
@@ -2635,30 +2667,28 @@ DISAS_INSN(shift_im)
         } else {
             tcg_gen_sari_i32(QREG_CC_N, reg, count);
         }
+        tcg_gen_mov_i32(QREG_CC_V, zero);
     }
+
+    gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
     tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
     tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
     tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
 
-    /* Note that ColdFire always clears V, while M68000 sets it for
-       a change in the sign bit.  */
-    if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
-        tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, reg);
-    } else {
-        tcg_gen_movi_i32(QREG_CC_V, 0);
-    }
-
-    tcg_gen_mov_i32(reg, QREG_CC_N);
+    gen_partset_reg(opsize, DREG(insn, 0), QREG_CC_N);
     set_cc_op(s, CC_OP_FLAGS);
 }
 
-DISAS_INSN(shift_reg)
+static inline void shift_reg(DisasContext *s, uint16_t insn, int opsize)
 {
-    TCGv reg, s32;
-    TCGv_i64 t64, s64;
     int logical = insn & 8;
+    int left = insn & 0x100;
+    int bits = opsize_bytes(opsize) * 8;
+    TCGv reg = gen_extend(DREG(insn, 0), opsize, !logical);
+    TCGv s32;
+    TCGv_i64 t64, s64;
+    TCGv zero;
 
-    reg = DREG(insn, 0);
     t64 = tcg_temp_new_i64();
     s64 = tcg_temp_new_i64();
     s32 = tcg_temp_new();
@@ -2669,44 +2699,148 @@ DISAS_INSN(shift_reg)
     tcg_gen_andi_i32(s32, DREG(insn, 9), 63);
     tcg_gen_extu_i32_i64(s64, s32);
 
-    /* Non-arithmetic shift clears V.  Use it as a source zero here.  */
-    tcg_gen_movi_i32(QREG_CC_V, 0);
+    zero = tcg_const_i32(0);
 
-    if (insn & 0x100) {
-        tcg_gen_extu_i32_i64(t64, reg);
+    tcg_gen_extu_i32_i64(t64, reg);
+    if (left) {
+        tcg_gen_shli_i64(t64, t64, 32 - bits);
         tcg_gen_shl_i64(t64, t64, s64);
         tcg_temp_free_i64(s64);
         tcg_gen_extr_i64_i32(QREG_CC_N, QREG_CC_C, t64);
         tcg_temp_free_i64(t64);
+        tcg_gen_sari_i32(QREG_CC_N, QREG_CC_N, 32 - bits);
         tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
+
+        /* Note that ColdFire always clears V,
+           while M68000 sets if the most significant bit is changed at
+           any time during the shift operation */
+        tcg_gen_mov_i32(QREG_CC_V, zero);
+        if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
+
+            TCGv t1 = tcg_const_i32(bits - 1);
+            TCGv t0 = tcg_temp_new();
+
+            tcg_gen_sub_i32(t0, t1, s32);
+            tcg_gen_shr_i32(QREG_CC_V, reg, t0);
+            tcg_gen_sar_i32(t0, reg, t0);
+            tcg_gen_not_i32(t0, t0);
+
+            tcg_gen_setcond_i32(TCG_COND_EQ, QREG_CC_V, QREG_CC_V, zero);
+            tcg_gen_setcond_i32(TCG_COND_EQ, t0, t0, zero);
+            tcg_gen_or_i32(QREG_CC_V, QREG_CC_V, t0); /* V is !V here */
+
+            /* if shift count >= bits, V is (reg != 0) */
+            tcg_gen_setcond_i32(TCG_COND_EQ, t0, reg, zero);
+            tcg_gen_movcond_i32(TCG_COND_GT, QREG_CC_V, s32, t1, t0, QREG_CC_V);
+
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+
+            /* adjust V: (1,0) -> (0,-1) */
+            tcg_gen_subi_i32(QREG_CC_V, QREG_CC_V, 1);
+
+            /* if shift count is zero, V is 0 */
+            tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_V, s32, zero,
+                                QREG_CC_V, zero);
+        }
     } else {
-        tcg_gen_extu_i32_i64(t64, reg);
-        tcg_gen_shli_i64(t64, t64, 32);
+        tcg_gen_shli_i64(t64, t64, 64 - bits);
         if (logical) {
+            tcg_gen_shri_i64(t64, t64, 32 - bits);
             tcg_gen_shr_i64(t64, t64, s64);
         } else {
+            tcg_gen_sari_i64(t64, t64, 32 - bits);
             tcg_gen_sar_i64(t64, t64, s64);
         }
         tcg_temp_free_i64(s64);
         tcg_gen_extr_i64_i32(QREG_CC_C, QREG_CC_N, t64);
         tcg_temp_free_i64(t64);
+        gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
         tcg_gen_shri_i32(QREG_CC_C, QREG_CC_C, 31);
+        tcg_gen_mov_i32(QREG_CC_V, zero);
     }
     tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
 
-    /* Note that X = C, but only if the shift count was non-zero.  */
-    tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V,
+    /* C is cleared if shift count was zero */
+    tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_C, s32, zero,
+                        QREG_CC_C, zero);
+
+    /* X = C, but only if the shift count was non-zero.  */
+    tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, zero,
                         QREG_CC_C, QREG_CC_X);
+    tcg_temp_free(zero);
     tcg_temp_free(s32);
 
-    /* Note that ColdFire always clears V (which we have done above),
-       while M68000 sets it for a change in the sign bit.  */
-    if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
-        tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, reg);
+    /* Write back the result.  */
+    gen_partset_reg(opsize, DREG(insn, 0), QREG_CC_N);
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(shift8_im)
+{
+    shift_im(s, insn, OS_BYTE);
+}
+
+DISAS_INSN(shift16_im)
+{
+    shift_im(s, insn, OS_WORD);
+}
+
+DISAS_INSN(shift_im)
+{
+    shift_im(s, insn, OS_LONG);
+}
+
+DISAS_INSN(shift8_reg)
+{
+    shift_reg(s, insn, OS_BYTE);
+}
+
+DISAS_INSN(shift16_reg)
+{
+    shift_reg(s, insn, OS_WORD);
+}
+
+DISAS_INSN(shift_reg)
+{
+    shift_reg(s, insn, OS_LONG);
+}
+
+DISAS_INSN(shift_mem)
+{
+    int logical = insn & 8;
+    int left = insn & 0x100;
+    TCGv src;
+    TCGv addr;
+
+    SRC_EA(env, src, OS_WORD, !logical, &addr);
+    tcg_gen_movi_i32(QREG_CC_V, 0);
+    if (left) {
+        tcg_gen_shri_i32(QREG_CC_C, src, 15);
+        tcg_gen_shli_i32(QREG_CC_N, src, 1);
+
+        /* Note that ColdFire always clears V,
+           while M68000 sets if the most significant bit is changed at
+           any time during the shift operation */
+        if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
+            src = gen_extend(src, OS_WORD, 1);
+            tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, src);
+        }
+    } else {
+        tcg_gen_mov_i32(QREG_CC_C, src);
+        if (logical) {
+            tcg_gen_shri_i32(QREG_CC_N, src, 1);
+        } else {
+            tcg_gen_sari_i32(QREG_CC_N, src, 1);
+        }
     }
 
-    /* Write back the result.  */
-    tcg_gen_mov_i32(reg, QREG_CC_N);
+    gen_ext(QREG_CC_N, QREG_CC_N, OS_WORD, 1);
+    tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
+    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+    tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
+
+    DEST_EA(env, insn, OS_WORD, QREG_CC_N, &addr);
     set_cc_op(s, CC_OP_FLAGS);
 }
 
@@ -4451,6 +4585,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(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(rotate_im, e090, f0f0, M68000);
     INSN(rotate8_im, e010, f0f0, M68000);
     INSN(rotate16_im, e050, f0f0, M68000);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 37/52] target-m68k: add cas/cas2 ops
  2016-05-04 21:08 ` [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs Laurent Vivier
                     ` (2 preceding siblings ...)
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 36/52] target-m68k: inline shift ops Laurent Vivier
@ 2016-05-04 21:08   ` Laurent Vivier
  2016-05-06 21:29     ` Richard Henderson
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 38/52] target-m68k: add linkl Laurent Vivier
                     ` (2 subsequent siblings)
  6 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/main.c       | 193 ++++++++++++++++++++++++++++++++++++++++++++++++
 target-m68k/cpu.h       |   9 +++
 target-m68k/qregs.def   |   5 ++
 target-m68k/translate.c | 175 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 382 insertions(+)

diff --git a/linux-user/main.c b/linux-user/main.c
index 74b02c7..3c51afe 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2994,6 +2994,194 @@ void cpu_loop(CPUMBState *env)
 
 #ifdef TARGET_M68K
 
+static int do_cas(CPUM68KState *env)
+{
+    int size, is_cas;
+    int cmp1_reg, upd1_reg;
+    int cmp2_reg, upd2_reg;
+    uint32_t dest1, cmp1, addr1;
+    uint32_t dest2, cmp2, addr2;
+    int segv = 0;
+    int z;
+
+    start_exclusive();
+
+    /* cas_param bits
+     * 31    -> CAS(0) / CAS2(1)
+     * 11:13 -> update reg 2
+     * 8:10  -> cmp reg 2
+     * 5:7   -> update reg 1
+     * 2:4   -> cmp reg 1
+     * 0:1   -> opsize
+     */
+
+    is_cas = (env->cas_param & 0x80000000) == 0;
+
+    size = env->cas_param & 0x3;
+
+    cmp1_reg = (env->cas_param >> 2) & 7;
+    upd1_reg = (env->cas_param >> 5) & 7;
+    cmp2_reg = (env->cas_param >> 8) & 7;
+    upd2_reg = (env->cas_param >> 11) & 7;
+
+    addr1 = env->cas_addr1;
+    addr2 = env->cas_addr2;
+
+    switch (size) {
+    case OS_BYTE:
+        segv = get_user_u8(dest1, addr1);
+        cmp1 = (uint8_t)env->dregs[cmp1_reg];
+        break;
+    case OS_WORD:
+        segv = get_user_u16(dest1, addr1);
+        cmp1 = (uint16_t)env->dregs[cmp1_reg];
+        break;
+    case OS_LONG:
+    default:
+        segv = get_user_u32(dest1, addr1);
+        cmp1 = env->dregs[cmp1_reg];
+        break;
+    }
+    if (segv) {
+        env->mmu.ar = addr1;
+        goto done;
+    }
+    env->cc_n = dest1;
+    env->cc_v = cmp1;
+    z = dest1 - cmp1;
+    env->cc_op = CC_OP_CMPB + size;
+
+    if (is_cas) {
+        /* CAS */
+
+        /* if (addr1) == cmp1 then (addr1) = upd1 */
+
+        if (z == 0) {
+            switch (size) {
+            case OS_BYTE:
+                segv = put_user_u8(env->dregs[upd1_reg], addr1);
+                break;
+            case OS_WORD:
+                segv = put_user_u16(env->dregs[upd1_reg], addr1);
+                break;
+            case OS_LONG:
+                segv = put_user_u32(env->dregs[upd1_reg], addr1);
+                break;
+            default:
+                break;
+            }
+            if (segv) {
+                env->mmu.ar = addr1;
+            }
+            goto done;
+        }
+        /* else cmp1 = (addr1) */
+        switch (size) {
+        case OS_BYTE:
+            env->dregs[cmp1_reg] = deposit32(env->dregs[cmp1_reg],
+                                            0, 8, dest1);
+            break;
+        case OS_WORD:
+            env->dregs[cmp1_reg] = deposit32(env->dregs[cmp1_reg],
+                                            0, 16, dest1);
+            break;
+        case OS_LONG:
+            env->dregs[cmp1_reg] = dest1;
+            break;
+        default:
+            break;
+        }
+    } else {
+        /* CAS2 */
+        switch (size) {
+        case OS_BYTE:
+            segv = get_user_u8(dest2, addr2);
+            cmp2 = (uint8_t)env->dregs[cmp2_reg];
+            break;
+        case OS_WORD:
+            segv = get_user_u16(dest2, addr2);
+            cmp2 = (uint16_t)env->dregs[cmp2_reg];
+            break;
+        case OS_LONG:
+        default:
+            segv = get_user_u32(dest2, addr2);
+            cmp2 = env->dregs[cmp2_reg];
+            break;
+        }
+        if (segv) {
+            env->mmu.ar = addr2;
+            goto done;
+        }
+        /* if (addr1) == cmp1 && (addr2) == cmp2 then
+         *    (addr1) = upd1, (addr2) = udp2
+         */
+        if (z == 0) {
+            z = dest2 - cmp2;
+        }
+        if (z == 0) {
+            switch (size) {
+            case OS_BYTE:
+                segv = put_user_u8(env->dregs[upd1_reg], addr1);
+                break;
+            case OS_WORD:
+                segv = put_user_u16(env->dregs[upd1_reg], addr1);
+                break;
+            case OS_LONG:
+                segv = put_user_u32(env->dregs[upd1_reg], addr1);
+                break;
+            default:
+                break;
+            }
+            if (segv) {
+                env->mmu.ar = addr1;
+            }
+            switch (size) {
+            case OS_BYTE:
+                segv = put_user_u8(env->dregs[upd2_reg], addr2);
+                break;
+            case OS_WORD:
+                segv = put_user_u16(env->dregs[upd2_reg], addr2);
+                break;
+            case OS_LONG:
+                segv = put_user_u32(env->dregs[upd2_reg], addr2);
+                break;
+            default:
+                break;
+            }
+            if (segv) {
+                env->mmu.ar = addr2;
+            }
+            goto done;
+        }
+        /* else cmp1 = (addr1), cmp2 = (addr2) */
+        switch (size) {
+        case OS_BYTE:
+            env->dregs[cmp1_reg] = deposit32(env->dregs[cmp1_reg],
+                                            0, 8, dest1);
+            env->dregs[cmp2_reg] = deposit32(env->dregs[cmp2_reg],
+                                            0, 8, dest2);
+            break;
+        case OS_WORD:
+            env->dregs[cmp1_reg] = deposit32(env->dregs[cmp1_reg],
+                                            0, 16, dest1);
+            env->dregs[cmp2_reg] = deposit32(env->dregs[cmp2_reg],
+                                            0, 16, dest2);
+            break;
+        case OS_LONG:
+            env->dregs[cmp1_reg] = dest1;
+            env->dregs[cmp2_reg] = dest2;
+            break;
+        default:
+            break;
+        }
+    }
+
+done:
+    end_exclusive();
+
+    return segv;
+}
+
 void cpu_loop(CPUM68KState *env)
 {
     CPUState *cs = CPU(m68k_env_get_cpu(env));
@@ -3060,6 +3248,11 @@ void cpu_loop(CPUM68KState *env)
         case EXCP_INTERRUPT:
             /* just indicate that signals should be handled asap */
             break;
+        case EXCP_CAS:
+            if (!do_cas(env)) {
+                break;
+            }
+            /* fall through for segv */
         case EXCP_ACCESS:
             {
                 info.si_signo = TARGET_SIGSEGV;
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index b300a92..5ce77e4 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -58,6 +58,7 @@
 
 #define EXCP_RTE            0x100
 #define EXCP_HALT_INSN      0x101
+#define EXCP_CAS            0x102
 
 #define NB_MMU_MODES 2
 #define TARGET_INSN_START_EXTRA_WORDS 1
@@ -110,6 +111,14 @@ typedef struct CPUM68KState {
 
     uint32_t qregs[MAX_QREGS];
 
+#ifdef CONFIG_USER_ONLY
+    /* CAS/CAS2 parameters */
+
+    uint32_t cas_param;
+    uint32_t cas_addr1;
+    uint32_t cas_addr2;
+#endif
+
     CPU_COMMON
 
     /* Fields from here on are preserved across CPU reset. */
diff --git a/target-m68k/qregs.def b/target-m68k/qregs.def
index 51ff43b..c4581b1 100644
--- a/target-m68k/qregs.def
+++ b/target-m68k/qregs.def
@@ -9,3 +9,8 @@ DEFO32(CC_V, cc_v)
 DEFO32(CC_Z, cc_z)
 DEFO32(MACSR, macsr)
 DEFO32(MAC_MASK, mac_mask)
+#ifdef CONFIG_USER_ONLY
+DEFO32(CAS_PARAM, cas_param)
+DEFO32(CAS_ADDR1, cas_addr1)
+DEFO32(CAS_ADDR2, cas_addr2)
+#endif
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index d48ab66..80033fc 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1846,6 +1846,179 @@ DISAS_INSN(arith_im)
     }
 }
 
+DISAS_INSN(cas)
+{
+    int opsize;
+    TCGv addr;
+    uint16_t ext;
+
+    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 = read_im16(env, s);
+
+    addr = gen_lea(env, s, insn, opsize);
+    if (IS_NULL_QREG(addr)) {
+        gen_addr_fault(s);
+        return;
+    }
+
+#ifdef CONFIG_USER_ONLY
+    tcg_gen_mov_i32(QREG_CAS_ADDR1, addr);
+    tcg_gen_movi_i32(QREG_CAS_PARAM,
+                     (REG(ext, 6) << 5) | (REG(ext, 0) << 2) |
+                     opsize);
+    gen_exception(s, s->pc, EXCP_CAS);
+    s->is_jmp = DISAS_JUMP;
+#else
+    TCGv dest;
+    TCGv res;
+    TCGv cmp;
+    TCGv zero;
+
+    dest = gen_load(s, opsize, addr, 0);
+
+    zero = tcg_const_i32(0);
+    cmp = gen_extend(DREG(ext, 0), opsize, 0);
+
+    /* if  dest - cmp == 0 */
+
+    res = tcg_temp_new();
+    tcg_gen_sub_i32(res, dest, cmp);
+
+    /* then dest = update1 */
+
+    tcg_gen_movcond_i32(TCG_COND_EQ, dest,
+                        res, zero,
+                        DREG(ext, 6), dest);
+
+    /* else cmp = dest */
+
+    tcg_gen_movcond_i32(TCG_COND_NE, cmp,
+                        res, zero,
+                        dest, cmp);
+
+    gen_partset_reg(opsize, DREG(ext, 0), cmp);
+    gen_store(s, opsize, addr, dest);
+    gen_logic_cc(s, res, opsize);
+
+    tcg_temp_free_i32(res);
+    tcg_temp_free_i32(zero);
+#endif
+}
+
+DISAS_INSN(cas2)
+{
+    int opsize;
+    uint16_t ext1, ext2;
+    TCGv addr1, addr2;
+
+    switch ((insn >> 9) & 3) {
+    case 1:
+        opsize = OS_BYTE;
+        break;
+    case 2:
+        opsize = OS_WORD;
+        break;
+    case 3:
+        opsize = OS_LONG;
+        break;
+    default:
+        abort();
+    }
+
+    ext1 = read_im16(env, s);
+
+    if (ext1 & 0x8000) {
+        /* Address Register */
+        addr1 = AREG(ext1, 12);
+    } else {
+        /* Data Register */
+        addr1 = DREG(ext1, 12);
+    }
+
+    ext2 = read_im16(env, s);
+    if (ext2 & 0x8000) {
+        /* Address Register */
+        addr2 = AREG(ext2, 12);
+    } else {
+        /* Data Register */
+        addr2 = DREG(ext2, 12);
+    }
+#ifdef CONFIG_USER_ONLY
+    tcg_gen_mov_i32(QREG_CAS_ADDR1, addr1);
+    tcg_gen_mov_i32(QREG_CAS_ADDR2, addr2);
+    tcg_gen_movi_i32(QREG_CAS_PARAM,
+                     (REG(ext2, 6) << 11) | (REG(ext2, 0) << 8) |
+                     (REG(ext1, 6) << 5) | (REG(ext1, 0) << 2) |
+                     0x80000000 | opsize);
+    gen_exception(s, s->pc, EXCP_CAS);
+    s->is_jmp = DISAS_JUMP;
+#else
+    TCGv cmp1, cmp2;
+    TCGv dest1, dest2;
+    TCGv res1, res2;
+    TCGv zero;
+    zero = tcg_const_i32(0);
+    dest1 = gen_load(s, opsize, addr1, 0);
+    cmp1 = gen_extend(DREG(ext1, 0), opsize, 0);
+
+    res1 = tcg_temp_new();
+    tcg_gen_sub_i32(res1, dest1, cmp1);
+    dest2 = gen_load(s, opsize, addr2, 0);
+    cmp2 = gen_extend(DREG(ext2, 0), opsize, 0);
+
+    res2 = tcg_temp_new();
+    tcg_gen_sub_i32(res2, dest2, cmp2);
+
+    /* if dest1 - cmp1 == 0 and dest2 - cmp2 == 0 */
+
+    tcg_gen_movcond_i32(TCG_COND_EQ, res1,
+                        res1, zero,
+                        res2, res1);
+
+    /* then dest1 = update1, dest2 = update2 */
+
+    tcg_gen_movcond_i32(TCG_COND_EQ, dest1,
+                        res1, zero,
+                        DREG(ext1, 6), dest1);
+    tcg_gen_movcond_i32(TCG_COND_EQ, dest2,
+                        res1, zero,
+                        DREG(ext2, 6), dest2);
+
+    /* else cmp1 = dest1, cmp2 = dest2 */
+
+    tcg_gen_movcond_i32(TCG_COND_NE, cmp1,
+                        res1, zero,
+                        dest1, cmp1);
+    tcg_gen_movcond_i32(TCG_COND_NE, cmp2,
+                        res1, zero,
+                        dest2, cmp2);
+
+    gen_partset_reg(opsize, DREG(ext1, 0), cmp1);
+    gen_partset_reg(opsize, DREG(ext2, 0), cmp2);
+    gen_store(s, opsize, addr1, dest1);
+    gen_store(s, opsize, addr2, dest2);
+
+    gen_logic_cc(s, res1, opsize);
+
+    tcg_temp_free_i32(res2);
+    tcg_temp_free_i32(res1);
+    tcg_temp_free_i32(zero);
+#endif
+}
+
 DISAS_INSN(byterev)
 {
     TCGv reg;
@@ -4457,6 +4630,8 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(arith_im,  0680, fff8, CF_ISA_A);
     INSN(arith_im,  0c00, ff38, CF_ISA_A);
     INSN(arith_im,  0c00, ff00, M68000);
+    INSN(cas,       08c0, f9c0, CAS);
+    INSN(cas2,      08fc, f9ff, CAS);
     BASE(bitop_im,  0800, ffc0);
     BASE(bitop_im,  0840, ffc0);
     BASE(bitop_im,  0880, ffc0);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 38/52] target-m68k: add linkl
  2016-05-04 21:08 ` [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs Laurent Vivier
                     ` (3 preceding siblings ...)
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 37/52] target-m68k: add cas/cas2 ops Laurent Vivier
@ 2016-05-04 21:08   ` Laurent Vivier
  2016-05-06 21:30     ` Richard Henderson
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 39/52] target-m68k: movem Laurent Vivier
  2016-05-06 19:44   ` [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs Richard Henderson
  6 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 80033fc..9a38235 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2351,21 +2351,36 @@ DISAS_INSN(mull)
     }
 }
 
-DISAS_INSN(link)
+static void gen_link(DisasContext *s, uint16_t insn, int32_t offset)
 {
-    int16_t offset;
     TCGv reg;
     TCGv tmp;
 
-    offset = cpu_ldsw_code(env, s->pc);
-    s->pc += 2;
     reg = AREG(insn, 0);
     tmp = tcg_temp_new();
     tcg_gen_subi_i32(tmp, QREG_SP, 4);
     gen_store(s, OS_LONG, tmp, reg);
-    if ((insn & 7) != 7)
+    if ((insn & 7) != 7) {
         tcg_gen_mov_i32(reg, tmp);
+    }
     tcg_gen_addi_i32(QREG_SP, tmp, offset);
+    tcg_temp_free(tmp);
+}
+
+DISAS_INSN(link)
+{
+    int16_t offset;
+
+    offset = read_im16(env, s);
+    gen_link(s, insn, offset);
+}
+
+DISAS_INSN(linkl)
+{
+    int32_t offset;
+
+    offset = read_im32(env, s);
+    gen_link(s, insn, offset);
 }
 
 DISAS_INSN(unlk)
@@ -4661,6 +4676,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(undef,     46c0, ffc0, M68000);
     INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
     INSN(nbcd,      4800, ffc0, M68000);
+    INSN(linkl,     4808, fff8, M68000);
     BASE(pea,       4840, ffc0);
     BASE(swap,      4840, fff8);
     INSN(bkpt,      4848, fff8, M68000);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 39/52] target-m68k: movem
  2016-05-04 21:08 ` [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs Laurent Vivier
                     ` (4 preceding siblings ...)
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 38/52] target-m68k: add linkl Laurent Vivier
@ 2016-05-04 21:08   ` Laurent Vivier
  2016-05-06 21:45     ` Richard Henderson
  2016-05-06 19:44   ` [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs Richard Henderson
  6 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 51 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 36 insertions(+), 15 deletions(-)

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

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

* [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (32 preceding siblings ...)
  2016-05-04 21:08 ` [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs Laurent Vivier
@ 2016-05-04 21:20 ` Laurent Vivier
  2016-05-04 21:20   ` [Qemu-devel] [PATCH 41/52] target-m68k: add addressing modes to not Laurent Vivier
                     ` (12 more replies)
  2016-05-06  9:35 ` [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Andreas Schwab
  2016-05-06 10:06 ` Alexander Graf
  35 siblings, 13 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 53c3c41..df5ce94 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2721,6 +2721,45 @@ DISAS_INSN(eor)
     DEST_EA(env, insn, OS_LONG, dest, &addr);
 }
 
+DISAS_INSN(exg)
+{
+    TCGv src;
+    TCGv reg;
+    TCGv dest;
+    int exg_mode;
+
+    exg_mode = insn & 0x1f8;
+
+    dest = tcg_temp_new();
+    switch (exg_mode) {
+    case 0x140:
+        /* exchange Dx and Dy */
+        src = DREG(insn, 9);
+        reg = DREG(insn, 0);
+        tcg_gen_mov_i32(dest, src);
+        tcg_gen_mov_i32(src, reg);
+        tcg_gen_mov_i32(reg, dest);
+        break;
+    case 0x148:
+        /* exchange Ax and Ay */
+        src = AREG(insn, 9);
+        reg = AREG(insn, 0);
+        tcg_gen_mov_i32(dest, src);
+        tcg_gen_mov_i32(src, reg);
+        tcg_gen_mov_i32(reg, dest);
+        break;
+    case 0x188:
+        /* exchange Dx and Ay */
+        src = DREG(insn, 9);
+        reg = AREG(insn, 0);
+        tcg_gen_mov_i32(dest, src);
+        tcg_gen_mov_i32(src, reg);
+        tcg_gen_mov_i32(reg, dest);
+        break;
+    }
+    tcg_temp_free(dest);
+}
+
 DISAS_INSN(and)
 {
     TCGv src;
@@ -4785,6 +4824,12 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(cmpa,      b0c0, f0c0, M68000);
     INSN(eor,       b180, f1c0, CF_ISA_A);
     BASE(and,       c000, f000);
+    INSN(undef,     c140, f1f8, CF_ISA_A);
+    INSN(exg,       c140, f1f8, M68000);
+    INSN(undef,     c148, f1f8, CF_ISA_A);
+    INSN(exg,       c148, f1f8, M68000);
+    INSN(undef,     c188, f1f8, CF_ISA_A);
+    INSN(exg,       c188, f1f8, M68000);
     BASE(mulw,      c0c0, f0c0);
     INSN(abcd_reg,  c100, f1f8, M68000);
     INSN(abcd_mem,  c108, f1f8, M68000);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 41/52] target-m68k: add addressing modes to not
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
@ 2016-05-04 21:20   ` Laurent Vivier
  2016-05-06 21:47     ` Richard Henderson
  2016-05-04 21:20   ` [Qemu-devel] [PATCH 42/52] target-m68k: eor can manage word and byte operands Laurent Vivier
                     ` (11 subsequent siblings)
  12 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index df5ce94..1c3c9a2 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2226,11 +2226,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, OS_LONG);
+    opsize = insn_opsize(insn);
+    SRC_EA(env, src1, opsize, 1, &addr);
+    dest = tcg_temp_new();
+    tcg_gen_not_i32(dest, src1);
+    DEST_EA(env, insn, opsize, dest, &addr);
+    gen_logic_cc(s, dest, opsize);
 }
 
 DISAS_INSN(swap)
-- 
2.5.5

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

* [Qemu-devel] [PATCH 42/52] target-m68k: eor can manage word and byte operands
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
  2016-05-04 21:20   ` [Qemu-devel] [PATCH 41/52] target-m68k: add addressing modes to not Laurent Vivier
@ 2016-05-04 21:20   ` Laurent Vivier
  2016-05-06 21:48     ` Richard Henderson
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 43/52] target-m68k: or " Laurent Vivier
                     ` (10 subsequent siblings)
  12 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 1c3c9a2..cfe878a 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2715,16 +2715,17 @@ DISAS_INSN(cmpa)
 DISAS_INSN(eor)
 {
     TCGv src;
-    TCGv reg;
     TCGv dest;
     TCGv addr;
+    int opsize;
 
-    SRC_EA(env, src, OS_LONG, 0, &addr);
-    reg = DREG(insn, 9);
+    opsize = insn_opsize(insn);
+
+    SRC_EA(env, src, opsize, 0, &addr);
     dest = tcg_temp_new();
-    tcg_gen_xor_i32(dest, src, reg);
-    gen_logic_cc(s, dest, OS_LONG);
-    DEST_EA(env, insn, OS_LONG, dest, &addr);
+    tcg_gen_xor_i32(dest, src, DREG(insn, 9));
+    gen_logic_cc(s, dest, opsize);
+    DEST_EA(env, insn, opsize, dest, &addr);
 }
 
 DISAS_INSN(exg)
-- 
2.5.5

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

* [Qemu-devel] [PATCH 43/52] target-m68k: or can manage word and byte operands
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
  2016-05-04 21:20   ` [Qemu-devel] [PATCH 41/52] target-m68k: add addressing modes to not Laurent Vivier
  2016-05-04 21:20   ` [Qemu-devel] [PATCH 42/52] target-m68k: eor can manage word and byte operands Laurent Vivier
@ 2016-05-04 21:21   ` Laurent Vivier
  2016-05-06 21:49     ` Richard Henderson
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 44/52] target-m68k: and " Laurent Vivier
                     ` (9 subsequent siblings)
  12 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index cfe878a..15109ed 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2572,19 +2572,21 @@ DISAS_INSN(or)
     TCGv dest;
     TCGv src;
     TCGv addr;
+    int opsize;
 
-    reg = DREG(insn, 9);
+    opsize = insn_opsize(insn);
+    reg = gen_extend(DREG(insn, 9), opsize, 0);
     dest = tcg_temp_new();
     if (insn & 0x100) {
-        SRC_EA(env, src, OS_LONG, 0, &addr);
+        SRC_EA(env, src, opsize, 0, &addr);
         tcg_gen_or_i32(dest, src, reg);
-        DEST_EA(env, insn, OS_LONG, dest, &addr);
+        DEST_EA(env, insn, opsize, dest, &addr);
     } else {
-        SRC_EA(env, src, OS_LONG, 0, NULL);
+        SRC_EA(env, src, opsize, 0, NULL);
         tcg_gen_or_i32(dest, src, reg);
-        tcg_gen_mov_i32(reg, dest);
+        gen_partset_reg(opsize, DREG(insn, 9), dest);
     }
-    gen_logic_cc(s, dest, OS_LONG);
+    gen_logic_cc(s, dest, opsize);
 }
 
 DISAS_INSN(suba)
-- 
2.5.5

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

* [Qemu-devel] [PATCH 44/52] target-m68k: and can manage word and byte operands
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
                     ` (2 preceding siblings ...)
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 43/52] target-m68k: or " Laurent Vivier
@ 2016-05-04 21:21   ` Laurent Vivier
  2016-05-06 21:49     ` Richard Henderson
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 45/52] target-m68k: suba/adda can manage word operand Laurent Vivier
                     ` (8 subsequent siblings)
  12 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 15109ed..9fed334 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2775,19 +2775,23 @@ DISAS_INSN(and)
     TCGv reg;
     TCGv dest;
     TCGv addr;
+    int opsize;
 
-    reg = DREG(insn, 9);
     dest = tcg_temp_new();
+
+    opsize = insn_opsize(insn);
+    reg = DREG(insn, 9);
     if (insn & 0x100) {
-        SRC_EA(env, src, OS_LONG, 0, &addr);
+        SRC_EA(env, src, opsize, 0, &addr);
         tcg_gen_and_i32(dest, src, reg);
-        DEST_EA(env, insn, OS_LONG, dest, &addr);
+        DEST_EA(env, insn, opsize, dest, &addr);
     } else {
-        SRC_EA(env, src, OS_LONG, 0, NULL);
+        SRC_EA(env, src, opsize, 0, 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, OS_LONG);
+    tcg_temp_free(dest);
+    gen_logic_cc(s, dest, opsize);
 }
 
 DISAS_INSN(adda)
-- 
2.5.5

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

* [Qemu-devel] [PATCH 45/52] target-m68k: suba/adda can manage word operand
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
                     ` (3 preceding siblings ...)
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 44/52] target-m68k: and " Laurent Vivier
@ 2016-05-04 21:21   ` Laurent Vivier
  2016-05-06 21:50     ` Richard Henderson
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 46/52] target-m68k: introduce byte and word cc_ops Laurent Vivier
                     ` (7 subsequent siblings)
  12 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 9fed334..a8e9b64 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2594,7 +2594,7 @@ DISAS_INSN(suba)
     TCGv src;
     TCGv reg;
 
-    SRC_EA(env, src, OS_LONG, 0, NULL);
+    SRC_EA(env, src, (insn & 0x100) ? OS_LONG : OS_WORD, 1, NULL);
     reg = AREG(insn, 9);
     tcg_gen_sub_i32(reg, reg, src);
 }
@@ -2799,7 +2799,7 @@ DISAS_INSN(adda)
     TCGv src;
     TCGv reg;
 
-    SRC_EA(env, src, OS_LONG, 0, NULL);
+    SRC_EA(env, src, (insn & 0x100) ? OS_LONG : OS_WORD, 1, NULL);
     reg = AREG(insn, 9);
     tcg_gen_add_i32(reg, reg, src);
 }
@@ -4812,6 +4812,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(subx_reg,  9100, f138, M68000);
     INSN(subx_mem,  9108, f138, M68000);
     INSN(suba,      91c0, f1c0, CF_ISA_A);
+    INSN(suba,      90c0, f0c0, M68000);
 
     BASE(undef_mac, a000, f000);
     INSN(mac,       a000, f100, CF_EMAC);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 46/52] target-m68k: introduce byte and word cc_ops
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
                     ` (4 preceding siblings ...)
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 45/52] target-m68k: suba/adda can manage word operand Laurent Vivier
@ 2016-05-04 21:21   ` Laurent Vivier
  2016-05-06 21:53     ` Richard Henderson
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 47/52] target-m68k: add addressing modes to neg Laurent Vivier
                     ` (6 subsequent siblings)
  12 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.h       |  6 +--
 target-m68k/helper.c    | 25 +++++++++----
 target-m68k/translate.c | 99 ++++++++++++++++++++++++++++++-------------------
 3 files changed, 80 insertions(+), 50 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 5ce77e4..1112502 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -147,11 +147,11 @@ typedef enum {
     CC_OP_FLAGS,
 
     /* X in cc_x, C = X, N in cc_n, Z in cc_n, V via cc_n/cc_v.  */
-    CC_OP_ADD,
-    CC_OP_SUB,
+    CC_OP_ADDB, CC_OP_ADDW, CC_OP_ADDL,
+    CC_OP_SUBB, CC_OP_SUBW, CC_OP_SUBL,
 
     /* X in cc_x, {N,Z,C,V} via cc_n/cc_v.  */
-    CC_OP_CMP,
+    CC_OP_CMPB, CC_OP_CMPW, CC_OP_CMPL,
 
     /* X in cc_x, C = 0, V = 0, N in cc_n, Z in cc_n.  */
     CC_OP_LOGIC,
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 76dda44..4d346a7 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -544,32 +544,41 @@ void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
     }
 }
 
+#define EXTSIGN(val, index) (     \
+    (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \
+)
 
 #define COMPUTE_CCR(op, x, n, z, v, c) {                                   \
     switch (op) {                                                          \
     case CC_OP_FLAGS:                                                      \
         /* Everything in place.  */                                        \
         break;                                                             \
-    case CC_OP_ADD:                                                        \
+    case CC_OP_ADDB:                                                       \
+    case CC_OP_ADDW:                                                       \
+    case CC_OP_ADDL:                                                       \
         res = n;                                                           \
         src2 = v;                                                          \
-        src1 = res - src2;                                                 \
+        src1 = EXTSIGN(res - src2, op - CC_OP_ADDB);                       \
         c = x;                                                             \
         z = n;                                                             \
         v = (res ^ src1) & ~(src1 ^ src2);                                 \
         break;                                                             \
-    case CC_OP_SUB:                                                        \
+    case CC_OP_SUBB:                                                       \
+    case CC_OP_SUBW:                                                       \
+    case CC_OP_SUBL:                                                       \
         res = n;                                                           \
         src2 = v;                                                          \
-        src1 = res + src2;                                                 \
+        src1 = EXTSIGN(res + src2, op - CC_OP_SUBB);                       \
         c = x;                                                             \
         z = n;                                                             \
         v = (res ^ src1) & (src1 ^ src2);                                  \
         break;                                                             \
-    case CC_OP_CMP:                                                        \
+    case CC_OP_CMPB:                                                       \
+    case CC_OP_CMPW:                                                       \
+    case CC_OP_CMPL:                                                       \
         src1 = n;                                                          \
         src2 = v;                                                          \
-        res = src1 - src2;                                                 \
+        res = EXTSIGN(src1 - src2, op - CC_OP_CMPB);                       \
         n = res;                                                           \
         z = res;                                                           \
         c = src1 < src2;                                                   \
@@ -590,16 +599,16 @@ uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
     uint32_t res, src1, src2;
 
     x = env->cc_x;
-    c = env->cc_c;
     n = env->cc_n;
     z = env->cc_z;
     v = env->cc_v;
+    c = env->cc_c;
 
     COMPUTE_CCR(env->cc_op, x, n, z, v, c);
 
     n = n >> 31;
-    v = v >> 31;
     z = (z == 0);
+    v = v >> 31;
 
     return x*CCF_X + n*CCF_N + z*CCF_Z + v*CCF_V + c*CCF_C;
 }
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index a8e9b64..2b6ba15 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -176,9 +176,9 @@ typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t insn);
 
 static const uint8_t cc_op_live[CC_OP_NB] = {
     [CC_OP_FLAGS] = CCF_C | CCF_V | CCF_Z | CCF_N | CCF_X,
-    [CC_OP_ADD] = CCF_X | CCF_N | CCF_V,
-    [CC_OP_SUB] = CCF_X | CCF_N | CCF_V,
-    [CC_OP_CMP] = CCF_X | CCF_N | CCF_V,
+    [CC_OP_ADDB ... CC_OP_ADDL] = CCF_X | CCF_N | CCF_V,
+    [CC_OP_SUBB ... CC_OP_SUBL] = CCF_X | CCF_N | CCF_V,
+    [CC_OP_CMPB ... CC_OP_CMPL] = CCF_X | CCF_N | CCF_V,
     [CC_OP_LOGIC] = CCF_X | CCF_N
 };
 
@@ -452,6 +452,33 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
     return add;
 }
 
+/* Sign or zero extend a value.  */
+
+static inline void gen_ext(TCGv res, TCGv val, int opsize, int sign)
+{
+    switch (opsize) {
+    case OS_BYTE:
+        if (sign) {
+            tcg_gen_ext8s_i32(res, val);
+        } else {
+            tcg_gen_ext8u_i32(res, val);
+        }
+        break;
+    case OS_WORD:
+        if (sign) {
+            tcg_gen_ext16s_i32(res, val);
+        } else {
+            tcg_gen_ext16u_i32(res, val);
+        }
+        break;
+    case OS_LONG:
+        tcg_gen_mov_i32(res, val);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
 /* Evaluate all the CC flags.  */
 
 static void gen_flush_flags(DisasContext *s)
@@ -462,13 +489,16 @@ static void gen_flush_flags(DisasContext *s)
     case CC_OP_FLAGS:
         return;
 
-    case CC_OP_ADD:
+    case CC_OP_ADDB:
+    case CC_OP_ADDW:
+    case CC_OP_ADDL:
         tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
         tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
         /* Compute signed overflow for addition.  */
         t0 = tcg_temp_new();
         t1 = tcg_temp_new();
         tcg_gen_sub_i32(t0, QREG_CC_N, QREG_CC_V);
+        gen_ext(t0, t0, s->cc_op - CC_OP_ADDB, 1);
         tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V);
         tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0);
         tcg_temp_free(t0);
@@ -476,13 +506,16 @@ static void gen_flush_flags(DisasContext *s)
         tcg_temp_free(t1);
         break;
 
-    case CC_OP_SUB:
+    case CC_OP_SUBB:
+    case CC_OP_SUBW:
+    case CC_OP_SUBL:
         tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
         tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
         /* Compute signed overflow for subtraction.  */
         t0 = tcg_temp_new();
         t1 = tcg_temp_new();
         tcg_gen_add_i32(t0, QREG_CC_N, QREG_CC_V);
+        gen_ext(t0, t0, s->cc_op - CC_OP_SUBB, 1);
         tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V);
         tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0);
         tcg_temp_free(t0);
@@ -490,9 +523,12 @@ static void gen_flush_flags(DisasContext *s)
         tcg_temp_free(t1);
         break;
 
-    case CC_OP_CMP:
+    case CC_OP_CMPB:
+    case CC_OP_CMPW:
+    case CC_OP_CMPL:
         tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_C, QREG_CC_N, QREG_CC_V);
         tcg_gen_sub_i32(QREG_CC_Z, QREG_CC_N, QREG_CC_V);
+        gen_ext(QREG_CC_Z, QREG_CC_Z, s->cc_op - CC_OP_CMPB, 1);
         /* Compute signed overflow for subtraction.  */
         t0 = tcg_temp_new();
         tcg_gen_xor_i32(t0, QREG_CC_Z, QREG_CC_N);
@@ -524,33 +560,6 @@ static void gen_flush_flags(DisasContext *s)
     s->cc_op_synced = 1;
 }
 
-/* Sign or zero extend a value.  */
-
-static inline void gen_ext(TCGv res, TCGv val, int opsize, int sign)
-{
-    switch (opsize) {
-    case OS_BYTE:
-        if (sign) {
-            tcg_gen_ext8s_i32(res, val);
-        } else {
-            tcg_gen_ext8u_i32(res, val);
-        }
-        break;
-    case OS_WORD:
-        if (sign) {
-            tcg_gen_ext16s_i32(res, val);
-        } else {
-            tcg_gen_ext16u_i32(res, val);
-        }
-        break;
-    case OS_LONG:
-        tcg_gen_mov_i32(res, val);
-        break;
-    default:
-        g_assert_not_reached();
-    }
-}
-
 static inline TCGv gen_extend(TCGv val, int opsize, int sign)
 {
     TCGv tmp;
@@ -571,10 +580,17 @@ static void gen_logic_cc(DisasContext *s, TCGv val, int opsize)
     set_cc_op(s, CC_OP_LOGIC);
 }
 
-static void gen_update_cc_add(TCGv dest, TCGv src)
+static void gen_update_cc_cmp(DisasContext *s, TCGv dest, TCGv src, int opsize)
 {
     tcg_gen_mov_i32(QREG_CC_N, dest);
     tcg_gen_mov_i32(QREG_CC_V, src);
+    set_cc_op(s, CC_OP_CMPB + opsize);
+}
+
+static void gen_update_cc_add(TCGv dest, TCGv src, int opsize)
+{
+    gen_ext(QREG_CC_N, dest, opsize, 1);
+    tcg_gen_mov_i32(QREG_CC_V, src);
 }
 
 static inline int opsize_bytes(int opsize)
@@ -819,7 +835,7 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
     CCOp op = s->cc_op;
 
     /* The CC_OP_CMP form can handle most normal comparisons directly.  */
-    if (op == CC_OP_CMP) {
+    if (op == CC_OP_CMPB || op == CC_OP_CMPW || op == CC_OP_CMPL) {
         c->g1 = c->g2 = 1;
         c->v1 = QREG_CC_N;
         c->v2 = QREG_CC_V;
@@ -842,6 +858,7 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
             c->v2 = tcg_const_i32(0);
             c->v1 = tmp = tcg_temp_new();
             tcg_gen_sub_i32(tmp, QREG_CC_N, QREG_CC_V);
+            gen_ext(tmp, tmp, op - CC_OP_CMPB, 1);
             /* fallthru */
         case 12: /* GE */
         case 13: /* LT */
@@ -864,7 +881,6 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
         c->v1 = c->v2;
         tcond = TCG_COND_NEVER;
         goto done;
-    case 14: /* GT (!(Z || (N ^ V))) */
     case 15: /* LE (Z || (N ^ V)) */
         /* Logic operations clear V, which simplifies LE to (Z || N),
            and since Z and N are co-located, this becomes a normal
@@ -885,7 +901,9 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
     case 10: /* PL (!N) */
     case 11: /* MI (N) */
         /* Several cases represent N normally.  */
-        if (op == CC_OP_ADD || op == CC_OP_SUB || op == CC_OP_LOGIC) {
+        if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL ||
+            op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL ||
+            op == CC_OP_LOGIC) {
             c->v1 = QREG_CC_N;
             tcond = TCG_COND_LT;
             goto done;
@@ -894,7 +912,9 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
     case 6: /* NE (!Z) */
     case 7: /* EQ (Z) */
         /* Some cases fold Z into N.  */
-        if (op == CC_OP_ADD || op == CC_OP_SUB || op == CC_OP_LOGIC) {
+        if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL ||
+            op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL ||
+            op == CC_OP_LOGIC) {
             tcond = TCG_COND_EQ;
             c->v1 = QREG_CC_N;
             goto done;
@@ -903,7 +923,8 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
     case 4: /* CC (!C) */
     case 5: /* CS (C) */
         /* Some cases fold C into X.  */
-        if (op == CC_OP_ADD || op == CC_OP_SUB) {
+        if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL ||
+            op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL) {
             tcond = TCG_COND_NE;
             c->v1 = QREG_CC_X;
             goto done;
-- 
2.5.5

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

* [Qemu-devel] [PATCH 47/52] target-m68k: add addressing modes to neg
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
                     ` (5 preceding siblings ...)
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 46/52] target-m68k: introduce byte and word cc_ops Laurent Vivier
@ 2016-05-04 21:21   ` Laurent Vivier
  2016-05-06 21:54     ` Richard Henderson
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 48/52] target-m68k: add/sub manage word and byte operands Laurent Vivier
                     ` (5 subsequent siblings)
  12 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 2b6ba15..bd7394f 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2194,16 +2194,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);
-    gen_update_cc_add(reg, src1);
-    tcg_gen_setcondi_i32(TCG_COND_NE, QREG_CC_X, src1, 0);
-    set_cc_op(s, CC_OP_SUB);
+    opsize = insn_opsize(insn);
+    SRC_EA(env, src1, opsize, 1, &addr);
+    dest = tcg_temp_new();
+    tcg_gen_neg_i32(dest, src1);
+    set_cc_op(s, CC_OP_SUBB + opsize);
+    gen_update_cc_add(dest, src1, opsize);
+    tcg_gen_setcondi_i32(TCG_COND_NE, QREG_CC_X, dest, 0);
+    DEST_EA(env, insn, opsize, dest, &addr);
+    tcg_temp_free(dest);
 }
 
 static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
-- 
2.5.5

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

* [Qemu-devel] [PATCH 48/52] target-m68k: add/sub manage word and byte operands
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
                     ` (6 preceding siblings ...)
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 47/52] target-m68k: add addressing modes to neg Laurent Vivier
@ 2016-05-04 21:21   ` Laurent Vivier
  2016-05-06 21:57     ` Richard Henderson
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 49/52] target-m68k: cmp manages word and bytes operands Laurent Vivier
                     ` (4 subsequent siblings)
  12 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 71 ++++++++++++++++++++++++++-----------------------
 1 file changed, 38 insertions(+), 33 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index bd7394f..f880a2a 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1620,35 +1620,37 @@ DISAS_INSN(addsub)
     TCGv tmp;
     TCGv addr;
     int add;
+    int opsize;
 
     add = (insn & 0x4000) != 0;
-    reg = DREG(insn, 9);
+    opsize = insn_opsize(insn);
+    reg = gen_extend(DREG(insn, 9), opsize, 1);
     dest = tcg_temp_new();
     if (insn & 0x100) {
-        SRC_EA(env, tmp, OS_LONG, 0, &addr);
+        SRC_EA(env, tmp, opsize, 1, &addr);
         src = reg;
     } else {
         tmp = reg;
-        SRC_EA(env, src, OS_LONG, 0, NULL);
+        SRC_EA(env, src, opsize, 1, NULL);
     }
     if (add) {
         tcg_gen_add_i32(dest, tmp, src);
         tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src);
-        set_cc_op(s, CC_OP_ADD);
+        set_cc_op(s, CC_OP_ADDB + opsize);
     } else {
         tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, tmp, src);
         tcg_gen_sub_i32(dest, tmp, src);
-        set_cc_op(s, CC_OP_SUB);
+        set_cc_op(s, CC_OP_SUBB + opsize);
     }
-    gen_update_cc_add(dest, src);
+    gen_update_cc_add(dest, src, opsize);
     if (insn & 0x100) {
-        DEST_EA(env, insn, OS_LONG, dest, &addr);
+        DEST_EA(env, insn, opsize, dest, &addr);
     } else {
-        tcg_gen_mov_i32(reg, dest);
+        gen_partset_reg(opsize, DREG(insn, 9), dest);
     }
+    tcg_temp_free(dest);
 }
 
-
 /* Reverse the order of the bits in REG.  */
 DISAS_INSN(bitrev)
 {
@@ -2482,40 +2484,46 @@ DISAS_INSN(jump)
 
 DISAS_INSN(addsubq)
 {
-    TCGv src1;
-    TCGv src2;
+    TCGv src;
     TCGv dest;
-    int val;
+    TCGv val;
+    int imm;
     TCGv addr;
+    int opsize;
 
-    SRC_EA(env, src1, OS_LONG, 0, &addr);
-    val = (insn >> 9) & 7;
-    if (val == 0)
-        val = 8;
+    if ((insn & 070) == 010) {
+        /* Operation on address register is always long.  */
+        opsize = OS_LONG;
+    } else
+        opsize = insn_opsize(insn);
+    SRC_EA(env, src, opsize, 1, &addr);
+    imm = (insn >> 9) & 7;
+    if (imm == 0)
+        imm = 8;
+    val = tcg_const_i32(imm);
     dest = tcg_temp_new();
-    tcg_gen_mov_i32(dest, src1);
+    tcg_gen_mov_i32(dest, src);
     if ((insn & 0x38) == 0x08) {
         /* Don't update condition codes if the destination is an
            address register.  */
         if (insn & 0x0100) {
-            tcg_gen_subi_i32(dest, dest, val);
+            tcg_gen_sub_i32(dest, dest, val);
         } else {
-            tcg_gen_addi_i32(dest, dest, val);
+            tcg_gen_add_i32(dest, dest, val);
         }
     } else {
-        src2 = tcg_const_i32(val);
         if (insn & 0x0100) {
-            tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src2);
-            tcg_gen_sub_i32(dest, dest, src2);
-            set_cc_op(s, CC_OP_SUB);
+            tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, val);
+            tcg_gen_sub_i32(dest, dest, val);
+            set_cc_op(s, CC_OP_SUBB + opsize);
         } else {
-            tcg_gen_add_i32(dest, dest, src2);
-            tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src2);
-            set_cc_op(s, CC_OP_ADD);
+            tcg_gen_add_i32(dest, dest, val);
+            tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, val);
+            set_cc_op(s, CC_OP_ADDB + opsize);
         }
-        gen_update_cc_add(dest, src2);
+        gen_update_cc_add(dest, val, opsize);
     }
-    DEST_EA(env, insn, OS_LONG, dest, &addr);
+    DEST_EA(env, insn, opsize, dest, &addr);
 }
 
 DISAS_INSN(tpf)
@@ -4804,16 +4812,13 @@ void register_m68k_insns (CPUM68KState *env)
     BASE(rts,       4e75, ffff);
     INSN(movec,     4e7b, ffff, CF_ISA_A);
     BASE(jump,      4e80, ffc0);
-    INSN(jump,      4ec0, ffc0, CF_ISA_A);
-    INSN(addsubq,   5180, f1c0, CF_ISA_A);
-    INSN(jump,      4ec0, ffc0, M68000);
+    BASE(jump,      4ec0, ffc0);
     INSN(addsubq,   5000, f080, M68000);
-    INSN(addsubq,   5080, f0c0, M68000);
+    BASE(addsubq,   5080, f0c0);
     INSN(scc,       50c0, f0f8, CF_ISA_A);
     INSN(scc_mem,   50c0, f0c0, M68000);
     INSN(scc,       50c0, f0f8, M68000);
     INSN(dbcc,      50c8, f0f8, M68000);
-    INSN(addsubq,   5080, f1c0, CF_ISA_A);
     INSN(tpf,       51f8, fff8, CF_ISA_A);
 
     /* Branch instructions.  */
-- 
2.5.5

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

* [Qemu-devel] [PATCH 49/52] target-m68k: cmp manages word and bytes operands
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
                     ` (7 preceding siblings ...)
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 48/52] target-m68k: add/sub manage word and byte operands Laurent Vivier
@ 2016-05-04 21:21   ` Laurent Vivier
  2016-05-06 21:57     ` Richard Henderson
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 50/52] target-m68k: immediate ops manage word and byte operands Laurent Vivier
                     ` (3 subsequent siblings)
  12 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index f880a2a..a22ee67 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2724,10 +2724,9 @@ DISAS_INSN(cmp)
     int opsize;
 
     opsize = insn_opsize(insn);
-    SRC_EA(env, src, opsize, -1, NULL);
-    reg = DREG(insn, 9);
-    gen_update_cc_add(reg, src);
-    set_cc_op(s, CC_OP_CMP);
+    SRC_EA(env, src, opsize, 1, NULL);
+    reg = gen_extend(DREG(insn, 9), opsize, 1);
+    gen_update_cc_cmp(s, reg, src, opsize);
 }
 
 DISAS_INSN(cmpa)
@@ -2743,8 +2742,7 @@ DISAS_INSN(cmpa)
     }
     SRC_EA(env, src, opsize, 1, NULL);
     reg = AREG(insn, 9);
-    gen_update_cc_add(reg, src);
-    set_cc_op(s, CC_OP_CMP);
+    gen_update_cc_cmp(s, reg, src, opsize);
 }
 
 DISAS_INSN(eor)
-- 
2.5.5

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

* [Qemu-devel] [PATCH 50/52] target-m68k: immediate ops manage word and byte operands
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
                     ` (8 preceding siblings ...)
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 49/52] target-m68k: cmp manages word and bytes operands Laurent Vivier
@ 2016-05-04 21:21   ` Laurent Vivier
  2016-05-06 21:59     ` Richard Henderson
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 51/52] target-m68k: add cmpm Laurent Vivier
                     ` (2 subsequent siblings)
  12 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 57 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 35 insertions(+), 22 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index a22ee67..029c166 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1842,52 +1842,65 @@ DISAS_INSN(bitop_im)
 DISAS_INSN(arith_im)
 {
     int op;
-    uint32_t im;
+    TCGv im;
     TCGv src1;
     TCGv dest;
     TCGv addr;
+    int opsize;
 
     op = (insn >> 9) & 7;
-    SRC_EA(env, src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
-    im = read_im32(env, s);
+    opsize = insn_opsize(insn);
+    switch (opsize) {
+    case OS_BYTE:
+        im = tcg_const_i32((int8_t)read_im8(env, s));
+        break;
+    case OS_WORD:
+        im = tcg_const_i32((int16_t)read_im16(env, s));
+        break;
+    case OS_LONG:
+        im = tcg_const_i32(read_im32(env, s));
+        break;
+    default:
+       abort();
+    }
+    SRC_EA(env, src1, opsize, 1, (op == 6) ? NULL : &addr);
     dest = tcg_temp_new();
     switch (op) {
     case 0: /* ori */
-        tcg_gen_ori_i32(dest, src1, im);
-        gen_logic_cc(s, dest, OS_LONG);
+        tcg_gen_or_i32(dest, src1, im);
+        gen_logic_cc(s, dest, opsize);
         break;
     case 1: /* andi */
-        tcg_gen_andi_i32(dest, src1, im);
-        gen_logic_cc(s, dest, OS_LONG);
+        tcg_gen_and_i32(dest, src1, im);
+        gen_logic_cc(s, dest, opsize);
         break;
     case 2: /* subi */
-        tcg_gen_mov_i32(dest, src1);
-        tcg_gen_setcondi_i32(TCG_COND_LTU, QREG_CC_X, dest, im);
-        tcg_gen_subi_i32(dest, dest, im);
-        gen_update_cc_add(dest, tcg_const_i32(im));
-        set_cc_op(s, CC_OP_SUB);
+        tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, src1, im);
+        tcg_gen_sub_i32(dest, src1, im);
+        gen_update_cc_add(dest, im, opsize);
+        set_cc_op(s, CC_OP_SUBB + opsize);
         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));
-        tcg_gen_setcondi_i32(TCG_COND_LTU, QREG_CC_X, dest, im);
-        set_cc_op(s, CC_OP_ADD);
+        tcg_gen_add_i32(dest, src1, im);
+        gen_update_cc_add(dest, im, opsize);
+        tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, im);
+        set_cc_op(s, CC_OP_ADDB + opsize);
         break;
     case 5: /* eori */
-        tcg_gen_xori_i32(dest, src1, im);
-        gen_logic_cc(s, dest, OS_LONG);
+        tcg_gen_xor_i32(dest, src1, im);
+        gen_logic_cc(s, dest, opsize);
         break;
     case 6: /* cmpi */
-        gen_update_cc_add(src1, tcg_const_i32(im));
-        set_cc_op(s, CC_OP_CMP);
+        gen_update_cc_cmp(s, src1, im, opsize);
         break;
     default:
         abort();
     }
+    tcg_temp_free(im);
     if (op != 6) {
-        DEST_EA(env, insn, OS_LONG, dest, &addr);
+        DEST_EA(env, insn, opsize, dest, &addr);
     }
+    tcg_temp_free(dest);
 }
 
 DISAS_INSN(cas)
-- 
2.5.5

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

* [Qemu-devel] [PATCH 51/52] target-m68k: add cmpm
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
                     ` (9 preceding siblings ...)
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 50/52] target-m68k: immediate ops manage word and byte operands Laurent Vivier
@ 2016-05-04 21:21   ` Laurent Vivier
  2016-05-06 22:00     ` Richard Henderson
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 52/52] target-m68k: sr/ccr cleanup Laurent Vivier
  2016-05-06 21:47   ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Richard Henderson
  12 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 029c166..2d92bdd 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2758,6 +2758,26 @@ DISAS_INSN(cmpa)
     gen_update_cc_cmp(s, reg, src, opsize);
 }
 
+DISAS_INSN(cmpm)
+{
+    TCGv src;
+    TCGv dest;
+    TCGv reg;
+    int opsize;
+
+    opsize = insn_opsize(insn);
+
+    reg = AREG(insn, 0);
+    src = gen_load(s, opsize, reg, 1);
+    tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
+
+    reg = AREG(insn, 9);
+    dest = gen_load(s, opsize, reg, 1);
+    tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
+
+    gen_update_cc_cmp(s, dest, src, opsize);
+}
+
 DISAS_INSN(eor)
 {
     TCGv src;
@@ -4876,6 +4896,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(cmpa,      b1c0, f1c0, CF_ISA_A);
     INSN(cmp,       b000, f100, M68000);
     INSN(eor,       b100, f100, M68000);
+    INSN(cmpm,      b108, f138, M68000);
     INSN(cmpa,      b0c0, f0c0, M68000);
     INSN(eor,       b180, f1c0, CF_ISA_A);
     BASE(and,       c000, f000);
-- 
2.5.5

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

* [Qemu-devel] [PATCH 52/52] target-m68k: sr/ccr cleanup
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
                     ` (10 preceding siblings ...)
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 51/52] target-m68k: add cmpm Laurent Vivier
@ 2016-05-04 21:21   ` Laurent Vivier
  2016-05-06 22:02     ` Richard Henderson
  2016-05-06 21:47   ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Richard Henderson
  12 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-04 21:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: rth, schwab, gerg, agraf, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 35 ++++++++++++++++++-----------------
 1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 2d92bdd..4f3e8ca 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2239,29 +2239,29 @@ static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
     set_cc_op(s, CC_OP_FLAGS);
 }
 
-static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only)
+static void gen_set_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
+                       int ccr_only)
 {
-    if (ccr_only) {
-        gen_helper_set_ccr(cpu_env, val);
+    if ((insn & 0x38) == 0) {
+        if (ccr_only) {
+            gen_helper_set_ccr(cpu_env, DREG(insn, 0));
+        } else {
+            gen_helper_set_sr(cpu_env, DREG(insn, 0));
+        }
+        set_cc_op(s, CC_OP_FLAGS);
+    } else if ((insn & 0x3f) == 0x3c) {
+        uint16_t val;
+        val = read_im16(env, s);
+        gen_set_sr_im(s, val, ccr_only);
     } else {
-        gen_helper_set_sr(cpu_env, val);
+        disas_undef(env, s, insn);
     }
-    set_cc_op(s, CC_OP_FLAGS);
-}
-
-static void gen_move_to_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
-                           int ccr_only)
-{
-    TCGv src;
-
-    SRC_EA(env, src, OS_WORD, 0, NULL);
-    gen_set_sr(s, src, ccr_only);
 }
 
 
 DISAS_INSN(move_to_ccr)
 {
-    gen_move_to_sr(env, s, insn, 1);
+    gen_set_sr(env, s, insn, 1);
 }
 
 DISAS_INSN(not)
@@ -3901,7 +3901,7 @@ DISAS_INSN(move_to_sr)
         gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
         return;
     }
-    gen_move_to_sr(env, s, insn, 0);
+    gen_set_sr(env, s, insn, 0);
     gen_lookup_tb(s);
 }
 
@@ -4652,8 +4652,9 @@ DISAS_INSN(macsr_to_ccr)
 {
     TCGv tmp = tcg_temp_new();
     tcg_gen_andi_i32(tmp, QREG_MACSR, 0xf);
-    gen_set_sr(s, tmp, 1);
+    gen_helper_set_sr(cpu_env, tmp);
     tcg_temp_free(tmp);
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 DISAS_INSN(to_mac)
-- 
2.5.5

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (33 preceding siblings ...)
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
@ 2016-05-06  9:35 ` Andreas Schwab
  2016-05-06  9:54   ` Laurent Vivier
  2016-05-06 10:06 ` Alexander Graf
  35 siblings, 1 reply; 131+ messages in thread
From: Andreas Schwab @ 2016-05-06  9:35 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: qemu-devel, gerg, agraf, rth

When I bootstrap gcc with the qemu built from your 680x0-master-dev
branch I get a bootstrap comparison failure for a lot of files.
Rerunning the stage1 compiler in aranym then produces object files that
are identical to what the stage2 compiler produced, thus some insn (or
combination thereof) only used in the stage1 compiler (which is built
unoptimized) isn't handled correctly yet.

Andreas.

-- 
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	[flat|nested] 131+ messages in thread

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06  9:35 ` [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Andreas Schwab
@ 2016-05-06  9:54   ` Laurent Vivier
  2016-05-06 10:15     ` Andreas Schwab
                       ` (2 more replies)
  0 siblings, 3 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-06  9:54 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: qemu-devel, gerg, agraf, rth, John Paul Adrian Glaubitz



Le 06/05/2016 à 11:35, Andreas Schwab a écrit :
> When I bootstrap gcc with the qemu built from your 680x0-master-dev
> branch I get a bootstrap comparison failure for a lot of files.
> Rerunning the stage1 compiler in aranym then produces object files that
> are identical to what the stage2 compiler produced, thus some insn (or
> combination thereof) only used in the stage1 compiler (which is built
> unoptimized) isn't handled correctly yet.

Yes, I know this is not perfect, but keeping all these patches in my own
tree doesn't help.

It's why I try to have them merged.

BTW, Adrian is using this branch (680x0-master-dev) for months to build
Debian packages.

Thanks,
Laurent

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
                   ` (34 preceding siblings ...)
  2016-05-06  9:35 ` [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Andreas Schwab
@ 2016-05-06 10:06 ` Alexander Graf
  2016-05-06 10:30   ` [Qemu-devel] [PATCH] MAINTAINERS: update M68K entry Laurent Vivier
  35 siblings, 1 reply; 131+ messages in thread
From: Alexander Graf @ 2016-05-06 10:06 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, rth



On 04.05.16 22:11, Laurent Vivier wrote:
> This series is an update of the series I sent last year:
> 
> https://lists.nongnu.org/archive/html/qemu-devel/2015-08/msg01049.html
> 
> Based on the series sent by Richard Henderson:
> 
> https://lists.nongnu.org/archive/html/qemu-devel/2015-08/msg01793.html
> 
> It is in fact a major rewrite. Most of the instructions are now inlined.
> 
> This series doesn't break Coldfire support. I've checked the following
> image can always boot:
> 
> http://wiki.qemu.org/download/coldfire-test-0.1.tar.bz2
> 
> Only non-privileged instruction are implemented.
> 680x0 FPU instructions are not implemented.
> 
> So this is not enough to run 680x0 binaries. I will send a new series
> with FPU emulation once this series is merged.
> 
> Andreas Schwab (1):
>   target-m68k: terminate cpu dump with newline
> 
> John Paul Adrian Glaubitz (1):
>   target-m68k: Build the opcode table only once to avoid multithreading
>     issues
> 
> Laurent Vivier (39):
>   target-m68k: fix DEBUG_DISPATCH
>   target-m68k: define m680x0 CPUs and features
>   target-m68k: manage scaled index
>   target-m68k: introduce read_imXX() functions
>   target-m68k: set disassembler mode to 680x0 or coldfire
>   target-m68k: add bkpt instruction
>   target-m68k: define operand sizes
>   target-m68k: set PAGE_BITS to 12 for m68k
>   target-m68k: REG() macro cleanup
>   target-m68k: allow to update flags with operation on words and bytes
>   target-m68k: update CPU flags management
>   target-m68k: update move to/from ccr/sr
>   target-m68k: don't update cc_dest in helpers
>   target-m68k: update CPU flags management
>   target-m68k: add addx/subx/negx ops
>   target-m68k: factorize flags computing
>   target-m68k: add scc/dbcc
>   target-m68k: some bit ops cleanup
>   target-m68k: bitfield ops
>   target-m68k: inline divu/divs
>   target-m68k: add 64bit mull
>   target-m68k: inline rotate ops
>   target-m68k: inline shift ops
>   target-m68k: add cas/cas2 ops
>   target-m68k: add linkl
>   target-m68k: movem
>   target-m68k: add exg ops
>   target-m68k: add addressing modes to not
>   target-m68k: eor can manage word and byte operands
>   target-m68k: or can manage word and byte operands
>   target-m68k: and can manage word and byte operands
>   target-m68k: suba/adda can manage word operand
>   target-m68k: introduce byte and word cc_ops
>   target-m68k: add addressing modes to neg
>   target-m68k: add/sub manage word and byte operands
>   target-m68k: cmp manages word and bytes operands
>   target-m68k: immediate ops manage word and byte operands
>   target-m68k: add cmpm
>   target-m68k: sr/ccr cleanup
> 
> Richard Henderson (11):
>   target-m68k: Replace helper_xflag_lt with setcond
>   target-m68k: Print flags properly
>   target-m68k: Some fixes to SR and flags management
>   target-m68k: Remove incorrect clearing of cc_x
>   target-m68k: Reorg flags handling
>   target-m68k: Introduce DisasCompare
>   target-m68k: Use setcond for scc
>   target-m68k: Optimize some comparisons
>   target-m68k: Optimize gen_flush_flags
>   target-m68k: Inline shifts
>   target-m68k: Inline addx, subx, negx
> 
>  cpu-exec.c              |    6 -
>  linux-user/main.c       |  200 +++
>  target-m68k/cpu-qom.h   |    4 -
>  target-m68k/cpu.c       |   65 +-
>  target-m68k/cpu.h       |   83 +-
>  target-m68k/helper.c    |  335 ++---
>  target-m68k/helper.h    |   16 +-
>  target-m68k/op_helper.c |  112 +-
>  target-m68k/qregs.def   |   13 +-
>  target-m68k/translate.c | 3316 +++++++++++++++++++++++++++++++++++++----------

IMHO the most important change would be a patch to the MAINTAINERS file :)


Alex

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06  9:54   ` Laurent Vivier
@ 2016-05-06 10:15     ` Andreas Schwab
  2016-05-06 11:40       ` John Paul Adrian Glaubitz
  2016-05-06 13:53       ` Laurent Vivier
  2016-05-06 11:40     ` John Paul Adrian Glaubitz
  2016-05-12 21:17     ` John Paul Adrian Glaubitz
  2 siblings, 2 replies; 131+ messages in thread
From: Andreas Schwab @ 2016-05-06 10:15 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: qemu-devel, gerg, agraf, rth, John Paul Adrian Glaubitz

Laurent Vivier <laurent@vivier.eu> writes:

> BTW, Adrian is using this branch (680x0-master-dev) for months to build
> Debian packages.

I don't trust it yet until it can bootstrap gcc.

Andreas.

-- 
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	[flat|nested] 131+ messages in thread

* [Qemu-devel] [PATCH] MAINTAINERS: update M68K entry
  2016-05-06 10:06 ` Alexander Graf
@ 2016-05-06 10:30   ` Laurent Vivier
  2016-05-12  7:55     ` Thomas Huth
  0 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-06 10:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, agraf, Laurent Vivier

Add myself to be the M68K maintainer.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 MAINTAINERS | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 81e7fac..c79404c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -131,7 +131,8 @@ F: include/hw/lm32/
 F: tests/tcg/lm32/
 
 M68K
-S: Orphan
+M: Laurent Vivier <laurent@vivier.eu>
+S: Maintained
 F: target-m68k/
 F: hw/m68k/
 
-- 
2.5.5

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06  9:54   ` Laurent Vivier
  2016-05-06 10:15     ` Andreas Schwab
@ 2016-05-06 11:40     ` John Paul Adrian Glaubitz
  2016-05-06 11:45       ` Alexander Graf
  2016-05-12 21:17     ` John Paul Adrian Glaubitz
  2 siblings, 1 reply; 131+ messages in thread
From: John Paul Adrian Glaubitz @ 2016-05-06 11:40 UTC (permalink / raw)
  To: Laurent Vivier, Andreas Schwab; +Cc: qemu-devel, gerg, agraf, rth

On 05/06/2016 11:54 AM, Laurent Vivier wrote:
>> When I bootstrap gcc with the qemu built from your 680x0-master-dev
>> branch I get a bootstrap comparison failure for a lot of files.

That is odd. Both gcc-5 [1] and gcc-6 [2] build fine for me.

> Yes, I know this is not perfect, but keeping all these patches in my own
> tree doesn't help.
> 
> It's why I try to have them merged.

Exactly. Laurent is doing a great job on the m68k code and I'm trying
to help him where I can and so are other Debian people whose packages
are failing to build on qemu-m68k.

There are still several issues, but we are working on ironing these
out.

> BTW, Adrian is using this branch (680x0-master-dev) for months to build
> Debian packages.

And it's getting better and better with every snapshot I use!

Adrian

> [1]
https://buildd.debian.org/status/fetch.php?pkg=gcc-5&arch=m68k&ver=5.3.1-17&stamp=1462233110
> [2]
https://buildd.debian.org/status/fetch.php?pkg=gcc-6&arch=m68k&ver=6.1.1-1&stamp=1462224003

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 10:15     ` Andreas Schwab
@ 2016-05-06 11:40       ` John Paul Adrian Glaubitz
  2016-05-06 12:44         ` Andreas Schwab
  2016-05-06 13:53       ` Laurent Vivier
  1 sibling, 1 reply; 131+ messages in thread
From: John Paul Adrian Glaubitz @ 2016-05-06 11:40 UTC (permalink / raw)
  To: Andreas Schwab, Laurent Vivier; +Cc: qemu-devel, gerg, agraf, rth

On 05/06/2016 12:15 PM, Andreas Schwab wrote:
> Laurent Vivier <laurent@vivier.eu> writes:
> 
>> BTW, Adrian is using this branch (680x0-master-dev) for months to build
>> Debian packages.
> 
> I don't trust it yet until it can bootstrap gcc.

How are you bootstrapping gcc? I'm surprised it doesn't work
for you.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 11:40     ` John Paul Adrian Glaubitz
@ 2016-05-06 11:45       ` Alexander Graf
  2016-05-06 11:57         ` Laurent Vivier
  0 siblings, 1 reply; 131+ messages in thread
From: Alexander Graf @ 2016-05-06 11:45 UTC (permalink / raw)
  To: John Paul Adrian Glaubitz, Laurent Vivier, Andreas Schwab
  Cc: qemu-devel, gerg, rth



On 06.05.16 13:40, John Paul Adrian Glaubitz wrote:
> On 05/06/2016 11:54 AM, Laurent Vivier wrote:
>>> When I bootstrap gcc with the qemu built from your 680x0-master-dev
>>> branch I get a bootstrap comparison failure for a lot of files.
> 
> That is odd. Both gcc-5 [1] and gcc-6 [2] build fine for me.
> 
>> Yes, I know this is not perfect, but keeping all these patches in my own
>> tree doesn't help.
>>
>> It's why I try to have them merged.
> 
> Exactly. Laurent is doing a great job on the m68k code and I'm trying
> to help him where I can and so are other Debian people whose packages
> are failing to build on qemu-m68k.
> 
> There are still several issues, but we are working on ironing these
> out.

Awesome, do you think you could port risu to 68k?

  https://git.linaro.org/people/peter.maydell/risu.git/

I was amazed by the quality the aarch64 emulation received once it was
properly testable.


Alex

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 11:45       ` Alexander Graf
@ 2016-05-06 11:57         ` Laurent Vivier
  2016-05-06 12:03           ` Peter Maydell
  0 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-06 11:57 UTC (permalink / raw)
  To: Alexander Graf, John Paul Adrian Glaubitz, Andreas Schwab
  Cc: qemu-devel, gerg, rth



Le 06/05/2016 à 13:45, Alexander Graf a écrit :
> 
> 
> On 06.05.16 13:40, John Paul Adrian Glaubitz wrote:
>> On 05/06/2016 11:54 AM, Laurent Vivier wrote:
>>>> When I bootstrap gcc with the qemu built from your 680x0-master-dev
>>>> branch I get a bootstrap comparison failure for a lot of files.
>>
>> That is odd. Both gcc-5 [1] and gcc-6 [2] build fine for me.
>>
>>> Yes, I know this is not perfect, but keeping all these patches in my own
>>> tree doesn't help.
>>>
>>> It's why I try to have them merged.
>>
>> Exactly. Laurent is doing a great job on the m68k code and I'm trying
>> to help him where I can and so are other Debian people whose packages
>> are failing to build on qemu-m68k.
>>
>> There are still several issues, but we are working on ironing these
>> out.
> 
> Awesome, do you think you could port risu to 68k?
> 
>   https://git.linaro.org/people/peter.maydell/risu.git/
> 
> I was amazed by the quality the aarch64 emulation received once it was
> properly testable.

I've already had a look at risu for that.

But risu uses a perl scripts to generate the instruction from the .risu
file, and it is very ARM specific (and I don't like perl :) )

I will try again.

BTW, M68k emulation has been tested and compared to real hardware execution.

It's not as good as risu, but it helps
(it works only with register access).

https://github.com/vivier/m68k-testgen
From
   http://lisa.sunder.net/cputest.html
   (extended by Gwenole Beauchesne for BasiliskII)

For the FPU part, I've compared the result in QEMU and on a real host with:

https://github.com/vivier/m68k-testfloat
https://github.com/vivier/m68k-softfloat

Laurent

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 11:57         ` Laurent Vivier
@ 2016-05-06 12:03           ` Peter Maydell
  0 siblings, 0 replies; 131+ messages in thread
From: Peter Maydell @ 2016-05-06 12:03 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: Alexander Graf, John Paul Adrian Glaubitz, Andreas Schwab,
	Richard Henderson, QEMU Developers, Greg Ungerer

On 6 May 2016 at 12:57, Laurent Vivier <laurent@vivier.eu> wrote:
> Le 06/05/2016 à 13:45, Alexander Graf a écrit :
>> Awesome, do you think you could port risu to 68k?
>>
>>   https://git.linaro.org/people/peter.maydell/risu.git/
>>
>> I was amazed by the quality the aarch64 emulation received once it was
>> properly testable.
>
> I've already had a look at risu for that.
>
> But risu uses a perl scripts to generate the instruction from the .risu
> file, and it is very ARM specific (and I don't like perl :) )

Yeah, the risugen script is the most awkward part for porting to
a new architecture. It needs restructuring to make it properly
architecture-independent (with a subclass per architecture, and
some kind of architecture specification directive in the input file.)

This is one of those awkward step-points where the first person to
need to add a different architecture has the pain of doing the
restructuring but then everybody else gets a much easier job later.

The rest of risu (the C code) is much better factored out to
allow new architectures to be slotted in.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 11:40       ` John Paul Adrian Glaubitz
@ 2016-05-06 12:44         ` Andreas Schwab
  2016-05-06 13:02           ` John Paul Adrian Glaubitz
  0 siblings, 1 reply; 131+ messages in thread
From: Andreas Schwab @ 2016-05-06 12:44 UTC (permalink / raw)
  To: John Paul Adrian Glaubitz; +Cc: Laurent Vivier, qemu-devel, gerg, agraf, rth

John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> writes:

> On 05/06/2016 12:15 PM, Andreas Schwab wrote:
>> Laurent Vivier <laurent@vivier.eu> writes:
>> 
>>> BTW, Adrian is using this branch (680x0-master-dev) for months to build
>>> Debian packages.
>> 
>> I don't trust it yet until it can bootstrap gcc.
>
> How are you bootstrapping gcc? I'm surprised it doesn't work
> for you.

You are cheating, you override BOOT_CFLAGS.

Andreas.

-- 
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	[flat|nested] 131+ messages in thread

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 12:44         ` Andreas Schwab
@ 2016-05-06 13:02           ` John Paul Adrian Glaubitz
  2016-05-06 13:24             ` Andreas Schwab
  0 siblings, 1 reply; 131+ messages in thread
From: John Paul Adrian Glaubitz @ 2016-05-06 13:02 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Laurent Vivier, qemu-devel, gerg, agraf, rth

On 05/06/2016 02:44 PM, Andreas Schwab wrote:
> You are cheating, you override BOOT_CFLAGS.

I'm not doing anything. I'm building the package as Matthias has
provided it and it builds fine.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 13:02           ` John Paul Adrian Glaubitz
@ 2016-05-06 13:24             ` Andreas Schwab
  2016-05-06 13:45               ` John Paul Adrian Glaubitz
  0 siblings, 1 reply; 131+ messages in thread
From: Andreas Schwab @ 2016-05-06 13:24 UTC (permalink / raw)
  To: John Paul Adrian Glaubitz; +Cc: Laurent Vivier, qemu-devel, gerg, agraf, rth

John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> writes:

> On 05/06/2016 02:44 PM, Andreas Schwab wrote:
>> You are cheating, you override BOOT_CFLAGS.
>
> I'm not doing anything.

Yes, you do.  See the build log.

Andreas.

-- 
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	[flat|nested] 131+ messages in thread

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 13:24             ` Andreas Schwab
@ 2016-05-06 13:45               ` John Paul Adrian Glaubitz
  2016-05-06 13:48                 ` Andreas Schwab
  0 siblings, 1 reply; 131+ messages in thread
From: John Paul Adrian Glaubitz @ 2016-05-06 13:45 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Laurent Vivier, qemu-devel, gerg, agraf, rth

On 05/06/2016 03:24 PM, Andreas Schwab wrote:
> John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> writes:
> 
>> On 05/06/2016 02:44 PM, Andreas Schwab wrote:
>>> You are cheating, you override BOOT_CFLAGS.
>>
>> I'm not doing anything.
> 
> Yes, you do.  See the build log.

As I have said before, the gcc package is being built on the buildd
as it comes from Matthias Klose. I'm not sure how I am supposed
to have changed anything when the package is being built automatically.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 13:45               ` John Paul Adrian Glaubitz
@ 2016-05-06 13:48                 ` Andreas Schwab
  2016-05-06 13:53                   ` John Paul Adrian Glaubitz
  0 siblings, 1 reply; 131+ messages in thread
From: Andreas Schwab @ 2016-05-06 13:48 UTC (permalink / raw)
  To: John Paul Adrian Glaubitz; +Cc: Laurent Vivier, qemu-devel, gerg, agraf, rth

John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> writes:

> On 05/06/2016 03:24 PM, Andreas Schwab wrote:
>> John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> writes:
>> 
>>> On 05/06/2016 02:44 PM, Andreas Schwab wrote:
>>>> You are cheating, you override BOOT_CFLAGS.
>>>
>>> I'm not doing anything.
>> 
>> Yes, you do.  See the build log.
>
> As I have said before, the gcc package is being built on the buildd
> as it comes from Matthias Klose. I'm not sure how I am supposed
> to have changed anything when the package is being built automatically.

It doesn't matter what you changed, fact is that you are not building an
unoptimized stage1 compiler, so you are comparing apples with oranges.

Andreas.

-- 
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	[flat|nested] 131+ messages in thread

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 13:48                 ` Andreas Schwab
@ 2016-05-06 13:53                   ` John Paul Adrian Glaubitz
  0 siblings, 0 replies; 131+ messages in thread
From: John Paul Adrian Glaubitz @ 2016-05-06 13:53 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Laurent Vivier, qemu-devel, gerg, agraf, rth

On 05/06/2016 03:48 PM, Andreas Schwab wrote:
> It doesn't matter what you changed, fact is that you are not building an
> unoptimized stage1 compiler, so you are comparing apples with oranges.

Well, I know Matthias Klose well enough in that regard that I think
I can trust him to produce a usable gcc package. I'm aware that this
isn't the vanilla upstream gcc, but at least it gives me something
that I can use and that builds all three stages on qemu-m68k without
any issues.

I'm not claiming that the emulation is on par with Aranym yet, it
isn't. But at least we are able to set up m68k buildds that can
keep up with the rest of the crowd speedwise.

As good as Aranym is, it's just too slow for the purpose of setting
up a buildd and I'm very glad that qemu-m68k exists in that regard.

My only goal is to make qemu-m68k better and it's getting there,
we even had ghc developers fix issues in the code, so we are
making some actual progress.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 10:15     ` Andreas Schwab
  2016-05-06 11:40       ` John Paul Adrian Glaubitz
@ 2016-05-06 13:53       ` Laurent Vivier
  2016-05-06 13:58         ` Andreas Schwab
  2016-05-06 14:25         ` Andreas Schwab
  1 sibling, 2 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-06 13:53 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: qemu-devel, gerg, agraf, rth, John Paul Adrian Glaubitz



Le 06/05/2016 à 12:15, Andreas Schwab a écrit :
> Laurent Vivier <laurent@vivier.eu> writes:
> 
>> BTW, Adrian is using this branch (680x0-master-dev) for months to build
>> Debian packages.
> 
> I don't trust it yet until it can bootstrap gcc.

I will try to debug that.

What is the version of gcc?
what are your configure parameters?

Thanks,
Laurent

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 13:53       ` Laurent Vivier
@ 2016-05-06 13:58         ` Andreas Schwab
  2016-05-06 14:25         ` Andreas Schwab
  1 sibling, 0 replies; 131+ messages in thread
From: Andreas Schwab @ 2016-05-06 13:58 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: qemu-devel, gerg, agraf, rth, John Paul Adrian Glaubitz

Laurent Vivier <laurent@vivier.eu> writes:

> What is the version of gcc?

It doesn't matter, any version.

> what are your configure parameters?

Nothing special.

Andreas.

-- 
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	[flat|nested] 131+ messages in thread

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 13:53       ` Laurent Vivier
  2016-05-06 13:58         ` Andreas Schwab
@ 2016-05-06 14:25         ` Andreas Schwab
  2016-05-06 14:47           ` Andreas Schwab
  1 sibling, 1 reply; 131+ messages in thread
From: Andreas Schwab @ 2016-05-06 14:25 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: qemu-devel, gerg, agraf, rth, John Paul Adrian Glaubitz

Here is a testcase:

when compiling tlink.c from the gcc sources with gcc-6 r234449 (which
was bootstrapped in aranym):

$ g++ -fno-PIE -c   -fomit-frame-pointer -O2 -DIN_GCC     -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Werror   -DHAVE_CONFIG_H -I. -I. -I../../gcc -I../../gcc/. -I../../gcc/../include -I../../gcc/../libcpp/include  -I../../gcc/../libdecnumber -I../../gcc/../libdecnumber/dpd -I../libdecnumber -I../../gcc/../libbacktrace   -o tlink.o ../../gcc/tlink.c

I get this difference for the generated assembler:

--- aranym/tlink.s	2016-05-06 16:19:02.377982900 +0200
+++ qemu/tlink.s	2016-05-06 16:18:26.385935256 +0200
@@ -2202,12 +2202,12 @@ _Z8do_tlinkPPcS0_:
 	move.l ldout,-(%sp)
 	move.l %d6,-(%sp)
 	pea .LC23
-	jsr _Z15collect_executePKcPPcS0_S0_ib
+	move.l #_Z15collect_executePKcPPcS0_S0_ib,%d4
+	move.l %d4,%a1
+	jsr (%a1)
 	move.l %a0,-(%sp)
 	pea .LC23
-	move.l #_Z12collect_waitPKcP7pex_obj,%d4
-	move.l %d4,%a0
-	jsr (%a0)
+	jsr _Z12collect_waitPKcP7pex_obj
 	move.l %d0,%d3
 	lea (28,%sp),%sp
 	clr.l (%sp)
@@ -2416,7 +2416,8 @@ _Z8do_tlinkPPcS0_:
 	move.l 4(%a5),%d0
 	cmp.l %d2,%d0
 	jne .L327
-	btst #0,3(%a5)
+	move.b 3(%a5),%d0
+	btst #0,%d0
 	jeq .L382
 	clr.l 4(%a0)
 	move.l %d2,%d0
@@ -2489,11 +2490,11 @@ _Z8do_tlinkPPcS0_:
 	move.l ldout,-(%sp)
 	move.l %d6,-(%sp)
 	pea .LC23
-	jsr _Z15collect_executePKcPPcS0_S0_ib
+	move.l %d4,%a1
+	jsr (%a1)
 	move.l %a0,-(%sp)
 	pea .LC23
-	move.l %d4,%a0
-	jsr (%a0)
+	jsr _Z12collect_waitPKcP7pex_obj
 	move.l %d0,%d3
 	lea (32,%sp),%sp
 	jne .L387
@@ -2562,11 +2563,11 @@ _Z8do_tlinkPPcS0_:
 	move.l ldout,-(%sp)
 	move.l %d6,-(%sp)
 	pea .LC23
-	jsr _Z15collect_executePKcPPcS0_S0_ib
+	move.l %d4,%a1
+	jsr (%a1)
 	move.l %a0,-(%sp)
 	pea .LC23
-	move.l %d4,%a0
-	jsr (%a0)
+	jsr _Z12collect_waitPKcP7pex_obj
 	move.l %d0,%d3
 	lea (32,%sp),%sp
 	jeq .L368

Andreas.

-- 
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	[flat|nested] 131+ messages in thread

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06 14:25         ` Andreas Schwab
@ 2016-05-06 14:47           ` Andreas Schwab
  0 siblings, 0 replies; 131+ messages in thread
From: Andreas Schwab @ 2016-05-06 14:47 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: agraf, John Paul Adrian Glaubitz, rth, qemu-devel, gerg

Andreas Schwab <schwab@linux-m68k.org> writes:

> Here is a testcase:
>
> when compiling tlink.c from the gcc sources with gcc-6 r234449 (which
> was bootstrapped in aranym):
>
> $ g++ -fno-PIE -c   -fomit-frame-pointer -O2 -DIN_GCC     -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Werror   -DHAVE_CONFIG_H -I. -I. -I../../gcc -I../../gcc/. -I../../gcc/../include -I../../gcc/../libcpp/include  -I../../gcc/../libdecnumber -I../../gcc/../libdecnumber/dpd -I../libdecnumber -I../../gcc/../libbacktrace   -o tlink.o ../../gcc/tlink.c
>
> I get this difference for the generated assembler:

I have accidentially used gcc-5 for the test.  With gcc-6 as above this
is the only difference:

--- aranym/tlink.s	2016-05-06 16:45:31.924100718 +0200
+++ qemu/tlink.s	2016-05-06 16:44:54.568052423 +0200
@@ -2471,7 +2471,8 @@ _Z8do_tlinkPPcS0_:
 	move.l 4(%a5),%d7
 	cmp.l %d2,%d7
 	jne .L329
-	btst #0,3(%a5)
+	move.b 3(%a5),%d0
+	btst #0,%d0
 	jeq .L384
 	move.l -14(%fp),%a1
 	clr.l 4(%a1)

Andreas.

-- 
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	[flat|nested] 131+ messages in thread

* Re: [Qemu-devel] [PATCH 01/52] target-m68k: fix DEBUG_DISPATCH
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 01/52] target-m68k: fix DEBUG_DISPATCH Laurent Vivier
@ 2016-05-06 16:34   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:34 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 02/52] target-m68k: Build the opcode table only once to avoid multithreading issues
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 02/52] target-m68k: Build the opcode table only once to avoid multithreading issues Laurent Vivier
@ 2016-05-06 16:35   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:35 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf, John Paul Adrian Glaubitz

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> From: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
>
> Signed-off-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 5 +++++
>  1 file changed, 5 insertions(+)


Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 03/52] target-m68k: define m680x0 CPUs and features
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 03/52] target-m68k: define m680x0 CPUs and features Laurent Vivier
@ 2016-05-06 16:35   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:35 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> This patch defines seven 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
>     - M68K_FEATURE_CAS, cas instruction
>
> Original patch from Andreas Schwab <schwab@linux-m68k.org>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/cpu.c       |  54 ++++++++++++++++++++++
>  target-m68k/cpu.h       |  10 +++-
>  target-m68k/translate.c | 120 ++++++++++++++++++++++++++++++------------------
>  3 files changed, 139 insertions(+), 45 deletions(-)


Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 04/52] target-m68k: manage scaled index
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 04/52] target-m68k: manage scaled index Laurent Vivier
@ 2016-05-06 16:36   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:36 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> Scaled index is not supported by 68000, 68008, and 68010.
>
>     EA = (bd + PC) + Xn.SIZE*SCALE + od
>
> Ignore it:
>
> M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL
> 2.4 BRIEF EXTENSION WORD FORMAT COMPATIBILITY
>
> "If the MC68000 were to execute an instruction that
>  encoded a scaling factor, the scaling factor would be
>  ignored and would not access the desired memory address.
>  The earlier microprocessors do not recognize the brief
>  extension word formats implemented by newer processors.
>  Although they can detect illegal instructions, they do not
>  decode invalid encodings of the brief extension word formats
>  as exceptions."
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 5 +++++
>  1 file changed, 5 insertions(+)


Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 05/52] target-m68k: introduce read_imXX() functions
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 05/52] target-m68k: introduce read_imXX() functions Laurent Vivier
@ 2016-05-06 16:36   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:36 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> Read a 8, 16 or 32bit immediat constant.
>
> An immediate constant is stored in the instruction opcode and
> can be in one or two extension words.
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 91 ++++++++++++++++++++++---------------------------
>  1 file changed, 41 insertions(+), 50 deletions(-)


Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 06/52] target-m68k: set disassembler mode to 680x0 or coldfire
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 06/52] target-m68k: set disassembler mode to 680x0 or coldfire Laurent Vivier
@ 2016-05-06 16:37   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:37 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/cpu.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)


Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 07/52] target-m68k: add bkpt instruction
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 07/52] target-m68k: add bkpt instruction Laurent Vivier
@ 2016-05-06 16:42   ` Richard Henderson
  2016-05-07  7:08     ` Laurent Vivier
  0 siblings, 1 reply; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:42 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> +    INSN(bkpt,      4848, fff8, M68000);

Do we care that this comes in with 68010 not 68000?

Otherwise,

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 08/52] target-m68k: define operand sizes
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 08/52] target-m68k: define operand sizes Laurent Vivier
@ 2016-05-06 16:43   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:43 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/cpu.h       |  8 ++++++++
>  target-m68k/translate.c | 46 ++++++++++++++--------------------------------
>  2 files changed, 22 insertions(+), 32 deletions(-)


Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 09/52] target-m68k: set PAGE_BITS to 12 for m68k
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 09/52] target-m68k: set PAGE_BITS to 12 for m68k Laurent Vivier
@ 2016-05-06 16:44   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:44 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/cpu.h | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)


Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 10/52] target-m68k: REG() macro cleanup
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 10/52] target-m68k: REG() macro cleanup Laurent Vivier
@ 2016-05-06 16:44   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:44 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)


Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 11/52] target-m68k: allow to update flags with operation on words and bytes
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 11/52] target-m68k: allow to update flags with operation on words and bytes Laurent Vivier
@ 2016-05-06 16:45   ` Richard Henderson
  2016-05-07  7:19     ` Laurent Vivier
  0 siblings, 1 reply; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:45 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/cpu.h       |  14 ++++-
>  target-m68k/helper.c    | 139 ++++++++++++++++++++++++++++++++++--------------
>  target-m68k/translate.c |  82 ++++++++++++++--------------
>  3 files changed, 151 insertions(+), 84 deletions(-)

I wonder if this shouldn't just be dropped, or squished into some of the other 
flags-related patches?  That said,

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 13/52] target-m68k: update CPU flags management
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 13/52] target-m68k: update CPU flags management Laurent Vivier
@ 2016-05-06 16:46   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:46 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> Copied from target-i386
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  cpu-exec.c              |  6 ------
>  target-m68k/cpu-qom.h   |  4 ----
>  target-m68k/cpu.c       |  2 --
>  target-m68k/cpu.h       |  1 +
>  target-m68k/helper.c    | 20 --------------------
>  target-m68k/translate.c |  6 +++++-
>  6 files changed, 6 insertions(+), 33 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 14/52] target-m68k: update move to/from ccr/sr
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 14/52] target-m68k: update move to/from ccr/sr Laurent Vivier
@ 2016-05-06 16:47   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:47 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 53 ++++++++++++++++++++-----------------------------
>  1 file changed, 22 insertions(+), 31 deletions(-)


Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 15/52] target-m68k: don't update cc_dest in helpers
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 15/52] target-m68k: don't update cc_dest in helpers Laurent Vivier
@ 2016-05-06 16:47   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:47 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/cpu.h       |  1 -
>  target-m68k/helper.c    | 28 ++++++++++++++--------------
>  target-m68k/helper.h    |  2 +-
>  target-m68k/translate.c |  4 ++--
>  4 files changed, 17 insertions(+), 18 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 16/52] target-m68k: update CPU flags management
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 16/52] target-m68k: update CPU flags management Laurent Vivier
@ 2016-05-06 16:47   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:47 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> Copied from target-i386
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/cpu.h       |   5 +-
>  target-m68k/translate.c | 121 +++++++++++++++++++++++++++++++++---------------
>  2 files changed, 86 insertions(+), 40 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 18/52] target-m68k: Some fixes to SR and flags management
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 18/52] target-m68k: Some fixes to SR and flags management Laurent Vivier
@ 2016-05-06 16:49   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:49 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> -uint32_t cpu_m68k_flush_flags(CPUM68KState *env, int op)
> +static uint32_t cpu_m68k_flush_flags(CPUM68KState *env, int op)
>  {
>      int flags;
>      uint32_t src;
> @@ -271,6 +271,18 @@ set_x:
>      return flags;
>  }
>
> +uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
> +{
> +    return cpu_m68k_flush_flags(env, env->cc_op) | env->cc_x * CCF_X;
> +}

This probably ought to get squished into the previous, to avoid thrashing.


r~

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

* Re: [Qemu-devel] [PATCH 19/52] target-m68k: terminate cpu dump with newline
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 19/52] target-m68k: terminate cpu dump with newline Laurent Vivier
@ 2016-05-06 16:49   ` Richard Henderson
  2016-05-06 17:41   ` Andreas Schwab
  1 sibling, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:49 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:11 AM, Laurent Vivier wrote:
> From: Andreas Schwab <schwab@linux-m68k.org>
>
> Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 21/52] target-m68k: Reorg flags handling
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 21/52] target-m68k: Reorg flags handling Laurent Vivier
@ 2016-05-06 16:51   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:51 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:12 AM, Laurent Vivier wrote:
> From: Richard Henderson <rth@twiddle.net>
>
> Separate all ccr bits.  Continue to batch updates via cc_op.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
>
> Fix gen_logic_cc() to really extend the size of the result.
> Fix gen_get_ccr(): update cc_op as it is used by the helper.
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/cpu.c       |   2 +-
>  target-m68k/cpu.h       |  46 +++---
>  target-m68k/helper.c    | 402 +++++++++++++++++++++---------------------------
>  target-m68k/helper.h    |   6 +-
>  target-m68k/op_helper.c |  30 ++--
>  target-m68k/qregs.def   |   6 +-
>  target-m68k/translate.c | 384 ++++++++++++++++++++-------------------------
>  7 files changed, 389 insertions(+), 487 del


Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 26/52] target-m68k: Inline shifts
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 26/52] target-m68k: Inline shifts Laurent Vivier
@ 2016-05-06 16:53   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 16:53 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:12 AM, Laurent Vivier wrote:
> From: Richard Henderson <rth@twiddle.net>
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
>
> fix arithmetical/logical switch
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/helper.c    | 52 ---------------------------
>  target-m68k/helper.h    |  3 --
>  target-m68k/translate.c | 94 +++++++++++++++++++++++++++++++++++++------------
>  3 files changed, 72 insertions(+), 77 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 28/52] target-m68k: add addx/subx/negx ops
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 28/52] target-m68k: add addx/subx/negx ops Laurent Vivier
@ 2016-05-06 17:11   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 17:11 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:12 AM, Laurent Vivier wrote:
> +    tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
> +    gen_ext(QREG_CC_Z, QREG_CC_Z, opsize, 0);

Extending Z after the OR is a bug.

The (old) high bits of Z might be set from a previous word operation (i.e. !Z) 
which is exactly what's supposed to be sticky.

Since N has already been sign-extended, we've already cleared out any garbage 
from the sub-word result.  There's no need to do anything more here.

Same change in negx, addx, subx.

> +    gen_store(s, opsize, addr_dest, QREG_CC_N);
> +}
>  DISAS_INSN(mov3q)

Watch the spacing.


r~

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

* Re: [Qemu-devel] [PATCH 29/52] target-m68k: factorize flags computing
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 29/52] target-m68k: factorize flags computing Laurent Vivier
@ 2016-05-06 17:11   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 17:11 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:12 AM, Laurent Vivier wrote:
> +
> +#define COMPUTE_CCR(op, x, n, z, v, c) {                                   \
> +    switch (op) {                                                          \
> +    case CC_OP_FLAGS:                                                      \

Please do fold this into the previous patch.


r

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

* Re: [Qemu-devel] [PATCH 30/52] target-m68k: add scc/dbcc
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 30/52] target-m68k: add scc/dbcc Laurent Vivier
@ 2016-05-06 17:18   ` Richard Henderson
  2016-05-06 17:44     ` Andreas Schwab
  0 siblings, 1 reply; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 17:18 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:12 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 46 insertions(+)
>
> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
> index 5914185..cd656fe 100644
> --- a/target-m68k/translate.c
> +++ b/target-m68k/translate.c
> @@ -1096,6 +1096,49 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
>      s->is_jmp = DISAS_TB_JUMP;
>  }
>
> +DISAS_INSN(scc_mem)
> +{
> +    TCGLabel *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);

Use setcond + neg to avoid the jump.  Since you are storing a single byte, it 
doesn't matter that the neg produces -1 instead of 0xff.

> +    DEST_EA(env, insn, OS_BYTE, dest, NULL);
> +    tcg_temp_free(dest);
> +}
> +
> +DISAS_INSN(dbcc)
> +{
> +    TCGLabel *l1;
> +    TCGv reg;
> +    TCGv tmp;
> +    int16_t offset;
> +    uint32_t base;
> +
> +    reg = DREG(insn, 0);
> +    base = s->pc;
> +    offset = (int16_t)read_im16(env, s);
> +    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, -1, l1);
> +    update_cc_op(s);
> +    gen_jmp_tb(s, 1, base + offset);
> +    gen_set_label(l1);
> +    update_cc_op(s);
> +    gen_jmp_tb(s, 0, s->pc);

Pull the update_cc_op up to the top, so as to only generate one copy.


r~

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

* Re: [Qemu-devel] [PATCH 31/52] target-m68k: some bit ops cleanup
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 31/52] target-m68k: some bit ops cleanup Laurent Vivier
@ 2016-05-06 17:20   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 17:20 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:12 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 34 +++++++++++++++-------------------
>  1 file changed, 15 insertions(+), 19 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 19/52] target-m68k: terminate cpu dump with newline
  2016-05-04 20:11 ` [Qemu-devel] [PATCH 19/52] target-m68k: terminate cpu dump with newline Laurent Vivier
  2016-05-06 16:49   ` Richard Henderson
@ 2016-05-06 17:41   ` Andreas Schwab
  1 sibling, 0 replies; 131+ messages in thread
From: Andreas Schwab @ 2016-05-06 17:41 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: qemu-devel, gerg, agraf, rth

Laurent Vivier <laurent@vivier.eu> writes:

> From: Andreas Schwab <schwab@linux-m68k.org>
>
> Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
> index ddc3100..37c1b95 100644
> --- a/target-m68k/translate.c
> +++ b/target-m68k/translate.c
> @@ -3142,7 +3142,7 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
>        }
>      cpu_fprintf (f, "PC = %08x   ", env->pc);
>      sr = env->sr | cpu_m68k_get_ccr(env);
> -    cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & CCF_X) ? 'X' : '-',
> +    cpu_fprintf (f, "SR = %04x %c%c%c%c%c\n", sr, (sr & CCF_X) ? 'X' : '-',
>                   (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
>                   (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
>      cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);

This is only useful in the context of the FPU patches which remove the
last line.

Andreas.

-- 
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	[flat|nested] 131+ messages in thread

* Re: [Qemu-devel] [PATCH 30/52] target-m68k: add scc/dbcc
  2016-05-06 17:18   ` Richard Henderson
@ 2016-05-06 17:44     ` Andreas Schwab
  0 siblings, 0 replies; 131+ messages in thread
From: Andreas Schwab @ 2016-05-06 17:44 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Laurent Vivier, qemu-devel, gerg, agraf

Richard Henderson <rth@twiddle.net> writes:

> On 05/04/2016 10:12 AM, Laurent Vivier wrote:
>> +    DEST_EA(env, insn, OS_BYTE, dest, NULL);
>> +    tcg_temp_free(dest);
>> +}
>> +
>> +DISAS_INSN(dbcc)
>> +{
>> +    TCGLabel *l1;
>> +    TCGv reg;
>> +    TCGv tmp;
>> +    int16_t offset;
>> +    uint32_t base;
>> +
>> +    reg = DREG(insn, 0);
>> +    base = s->pc;
>> +    offset = (int16_t)read_im16(env, s);
>> +    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, -1, l1);
>> +    update_cc_op(s);
>> +    gen_jmp_tb(s, 1, base + offset);
>> +    gen_set_label(l1);
>> +    update_cc_op(s);
>> +    gen_jmp_tb(s, 0, s->pc);
>
> Pull the update_cc_op up to the top, so as to only generate one copy.

This misses a followup patch which moves it into gen_jmpcc.  In the
current form this would result in a mistranslation.

Andreas.

-- 
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	[flat|nested] 131+ messages in thread

* Re: [Qemu-devel] [PATCH 32/52] target-m68k: bitfield ops
  2016-05-04 20:12 ` [Qemu-devel] [PATCH 32/52] target-m68k: bitfield ops Laurent Vivier
@ 2016-05-06 19:11   ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 19:11 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: gerg, schwab, agraf

On 05/04/2016 10:12 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/helper.c    |  13 ++
>  target-m68k/helper.h    |   4 +
>  target-m68k/op_helper.c |  68 ++++++
>  target-m68k/translate.c | 560 ++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 645 insertions(+)
>
> diff --git a/target-m68k/helper.c b/target-m68k/helper.c
> index e9e7cee..76dda44 100644
> --- a/target-m68k/helper.c
> +++ b/target-m68k/helper.c
> @@ -267,6 +267,19 @@ 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;

   n = clz32(arg);
   return n < width ? n : width;

> +DEF_HELPER_2(bfffo, i32, i32, i32)

DEF_HELPER_FLAGS_*

> +DEF_HELPER_4(bitfield_load, i64, env, i32, i32, i32)
> +DEF_HELPER_5(bitfield_store, void, env, i32, i32, i32, i64)

Likewise.

> +        bitfield = cpu_ldub_data(env, addr);

Switch to using cpu_ldub_data_ra etc.  That will avoid having to store PC or 
update_cc before calling these helpers.

> +static inline void bcd_add(TCGv src, TCGv dest)

Did the bcd patch get squashed into this one by mistake?

Anyway, it might be nice to take off the inline marker for these, since they're 
fairly large functions.

> +static inline void bcd_neg(TCGv dest, TCGv src)

Likewise wrt inline.

> +    /* compute the 10's complement
> +     *
> +     *    bcd_add(0xff99 - (src + X), 0x0001)
> +     *
> +     *        t1 = 0xF9999999 - src - X)
> +     *        t2 = t1 + 0x06666666
> +     *        t3 = t2 + 0x00000001
> +     *        t4 = t2 ^ 0x00000001
> +     *        t5 = t3 ^ t4
> +     *        t6 = ~t5 & 0x11111110
> +     *        t7 = (t6 >> 2) | (t6 >> 3)
> +     *        return t3 - t7
> +     *
> +     * reduced in:
> +     *
> +     *        t2 = 0xFFFFFFFF + (-src)
> +     *        t3 = (-src)
> +     *        t4 = t2  ^ (X ^ 1)
> +     *        t5 = (t3 - X) ^ t4
> +     *        t6 = ~t5 & 0x11111110
> +     *        t7 = (t6 >> 2) | (t6 >> 3)
> +     *        return (t3 - X) - t7

Is there a reason that you're computing the ten's compliment to 7 digits when 
you're only going to use 3 of them?  Restricting to 3 means that these 
constants become smaller and therefore easier to build on a non-x86 host.

> +DISAS_INSN(abcd_mem)
> +{
> +    TCGv src;
> +    TCGv addr_src;
> +    TCGv dest;
> +    TCGv addr_dest;
> +
> +    gen_flush_flags(s); /* !Z is sticky */
> +
> +    addr_src = AREG(insn, 0);
> +    tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(OS_BYTE));
> +    src = gen_load(s, OS_BYTE, addr_src, 0);
> +
> +    addr_dest = AREG(insn, 9);
> +    tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(OS_BYTE));
> +    dest = gen_load(s, OS_BYTE, addr_dest, 0);
> +
> +    bcd_add(src, dest);
> +
> +    gen_store(s, OS_BYTE, addr_dest, dest);

Surely the write-back to the address registers only happens after any possible 
exception due to the loads.  Otherwise you can't restart the insn after a page 
fault.

> +    set_cc_op(s, CC_OP_FLAGS);

This is redundant with gen_flush_flags.

> +static void bitfield_param(uint16_t ext, TCGv *offset, TCGv *width, TCGv *mask)
> +{
> +    TCGv tmp;
> +
> +    /* offset */
> +
> +    if (ext & 0x0800) {
> +        *offset = tcg_temp_new_i32();
> +        tcg_gen_mov_i32(*offset, DREG(ext, 6));
> +    } else {
> +        *offset = tcg_temp_new_i32();
> +        tcg_gen_movi_i32(*offset, (ext >> 6) & 31);
> +    }

No need to have two copies of the *offset allocation.

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

Less garbage temporaries if you do

   tmp = tcg_const_i32(32);
   tcg_gen_sub_i32(tmp, tmp, *width);
   *mask = tcg_const_i32(-1);
   tcg_gen_shl_i32(*mask, *mask, tmp);
   tcg_temp_free_i32(tmp);

> +    if (ext & 0x0800)
> +        tcg_gen_andi_i32(offset, offset, 31);

Watch the coding style.


> +    if (op == 7) {
> +        TCGv tmp2;
> +
> +        tmp2 = tcg_temp_new_i32();
> +        tcg_gen_sub_i32(tmp2, tcg_const_i32(32), width);
> +        tcg_gen_shl_i32(tmp2, reg2, tmp2);
> +        tcg_gen_and_i32(tmp2, tmp2, mask);
> +        gen_logic_cc(s, tmp2, OS_LONG);

A rotate right of the width is easier to put the field into the most 
significant bits.  Also, you need to do this AND before you rotate the mask.

A comment here that we're computing the flags for BFINS wouldn't go amiss.

> +        tcg_temp_free_i32(tmp1);

tmp2.

> +    } else {
> +        gen_logic_cc(s, tmp1, OS_LONG);
> +    }

I also question the logic of doing

	mask = mask >>> offset;
	tmp = reg & mask
	tmp = tmp <<< offset

when just

	tmp = reg <<< offset;
	tmp = tmp & mask

would do.

Let's assume we make this change, that we align the field at MSB for both reg1 
and reg2.  That gives us

     TCGv tmp = tcg_temp_new();
     bitfield_param(ext, &offset, &width, &mask);

     if (op != 7) { /* All except BFINS */
           tcg_gen_rotl_i32(tmp, reg, offset);
         tcg_gen_and_i32(tmp, tmp, mask);
         gen_logic_cc(s, tmp, OS_LONG);
     }

     switch (op) {
     case 0: /* bftst */
         break;
     case 1: /* bfextu */
         tcg_gen_rotl_i32(reg2, QREG_CC_N, width);
         break;
     case 2: /* bfchg */
         tcg_gen_rotr_i32(mask, mask, offset);
         tcg_gen_xor_i32(reg, reg, mask);
         break;
     case 3: /* bfexts */
         tcg_gen_subfi_i32(width, 32, width);
         tcg_gen_sar_i32(reg2, QREG_CC_N, width);
         break;
     case 4: /* bfclr */
         tcg_gen_rotr_i32(mask, mask, offset);
         tcg_gen_andc_i32(reg, reg, mask);
         break;
     case 5: /* bfffo */
         /* Set all bits outside of mask, so that we find one
            when searching via clz32.  */
         tcg_gen_orc_i32(tmp, QREG_CC_N, mask);
         tcg_gen_shr_i32(tmp, tmp, offset);
         gen_helper_clz(reg2, tmp);
         break;
     case 6: /* bfset */
         tcg_gen_rotr_i32(mask, mask, offset);
         tcg_gen_or_i32(reg, reg, mask);
         break;
     case 7: /* bfins */
         tcg_gen_rotr_i32(tmp, reg2, width);
         tcg_gen_and_i32(tmp, tmp, mask);
         gen_logic_cc(s, tmp, OS_LONG);
         /* ??? If constant offset and constant width,
            and offset + width <= 32, then we can use
            tcg_gen_deposit_i32 here.  */
         tcg_gen_rotr_i32(mask, mask, offset);
         tcg_gen_rotr_i32(tmp, tmp, offset);
         tcg_gen_andc_i32(reg, reg, mask);
         tcg_gen_or_i32(reg, reg, tmp);
         break;
     }
     tcg_temp_free(tmp);

> +    /* tmp = (bitfield << offset) >> 32 */
> +
> +    tcg_gen_shri_i64(tmp64, tmp64, 32ULL);
> +    dest = tcg_temp_new_i32();
> +    tcg_gen_extrl_i64_i32(dest, tmp64);

tcg_gen_extrh_i64_i32.

> +static TCGv_i64 gen_bitfield_mask(TCGv offset, TCGv width)
> +{
> +    TCGv tmp;
> +    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();
> +    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);

Two less instructions with

   mask = -1 << width;
   mask <<= offset;
   mask >>= offset;

That said, similar comments apply to bitfield_mem re keeping the field at the MSB.

> +    gen_helper_bitfield_load(bitfield, cpu_env, src, offset, width);
...
> +        gen_logic_cc(s, val, OS_LONG);
...
> +        gen_helper_bitfield_store(cpu_env, src, offset, width, bitfield);

You risk clobbering CC before the exception if the page isn't writable.

One way to fix this is to have bitfield_load perform a probe_write (or two, if 
the field spans a page boundary).  That way when we come to bitfield_store we 
know that any exception will have already been taken.

Note that you can also make the helpers perform the rotates into and out of the 
MSB.  That off-loads a little of the required tcg code.


r~

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

* Re: [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs
  2016-05-04 21:08 ` [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs Laurent Vivier
                     ` (5 preceding siblings ...)
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 39/52] target-m68k: movem Laurent Vivier
@ 2016-05-06 19:44   ` Richard Henderson
  6 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 19:44 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:08 AM, Laurent Vivier wrote:
> -void HELPER(divu)(CPUM68KState *env, uint32_t word)
> -{
> -    uint32_t num;
> -    uint32_t den;
> -    uint32_t quot;
> -    uint32_t rem;
> -
> -    num = env->div1;
> -    den = env->div2;
> -    /* ??? This needs to make sure the throwing location is accurate.  */
> -    if (den == 0) {
> -        raise_exception(env, EXCP_DIV0);
> -    }

Because of the exception, and required branching, I question taking the 
division operations back inline.  The throwing location is easily fixed; create 
a version of raise_exception that has an argument for GETPC and uses 
cpu_loop_exit_restore.

> @@ -1179,64 +1187,182 @@ DISAS_INSN(mulw)
>
>  DISAS_INSN(divw)
>  {
> +    TCGLabel *l1;
> +    TCGv t0, src;
> +    TCGv quot, rem;
>      int sign;
>
>      sign = (insn & 0x100) != 0;
> +
> +    tcg_gen_movi_i32(QREG_CC_C, 0); /* C is always cleared, use as 0 */
> +
> +    /* dest.l / src.w */
> +
> +    SRC_EA(env, t0, OS_WORD, sign, NULL);
> +
> +    src = tcg_temp_local_new_i32();
> +    tcg_gen_mov_i32(src, t0);
> +    l1 = gen_new_label();
> +    tcg_gen_brcondi_i32(TCG_COND_NE, src, 0, l1);
> +    tcg_gen_movi_i32(QREG_PC, s->insn_pc);
> +    gen_raise_exception(EXCP_DIV0);
> +    gen_set_label(l1);
> +
> +    tcg_gen_movi_i32(QREG_CC_C, 0); /* C is always cleared, use as 0 */

Redundant store to CC_C?  Is that simply so that the 0 is forward propagated 
within the second block by the tcg optimizer?  If so, the comments could be 
clearer.

> +    quot = tcg_temp_new();
> +    rem = tcg_temp_new();
>      if (sign) {
> -        gen_helper_divs(cpu_env, tcg_const_i32(1));
> +        tcg_gen_div_i32(quot, DREG(insn, 9), src);
> +        tcg_gen_rem_i32(rem, DREG(insn, 9), src);
> +        tcg_gen_ext16s_i32(QREG_CC_V, quot);
> +        tcg_gen_movi_i32(src, -1);
> +        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_V,
> +                            QREG_CC_V, quot,
> +                            QREG_CC_C /* 0 */, src /* -1 */);

setcond + neg is better than movcond here.

> +        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_V,
> +                            QREG_CC_V, QREG_CC_C /* 0 */,
> +                            QREG_CC_V /* 0 */, src /* -1 */);

Likewise.

> +    /* result rem:quot */
> +
> +    tcg_gen_ext16u_i32(quot, quot);
> +    tcg_gen_deposit_i32(quot, quot, rem, 16, 16);

The ext16u is redundant with the deposit.

> +    tcg_temp_free(rem);
> +
> +    /* on overflow, operands and flags are unaffected */
> +
> +    tcg_gen_movcond_i32(TCG_COND_EQ, DREG(insn, 9),
> +                        QREG_CC_V, QREG_CC_C /* zero */,
> +                        quot, DREG(insn, 9));
> +    tcg_gen_ext16s_i32(quot, quot);
> +    tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_Z,
> +                        QREG_CC_V, QREG_CC_C /* zero */,
> +                        quot, QREG_CC_Z);
> +    tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_N,
> +                        QREG_CC_V, QREG_CC_C /* zero */,
> +                        quot, QREG_CC_N);
> +    tcg_temp_free(quot);

Interesting.  The manual says "may", as in "may or may not".  Was the existing 
behaviour that didn't have early check for overflow a bug, or simply a bug for 
exactly emulating specific cpu models?

Anyway, this multiplicity of movcond is another reason to consider leaving the 
code out of line in a helper.

>      set_cc_op(s, CC_OP_FLAGS);

This needs to happen before the branch, along with an update_cc_op, surely. 
Otherwise the store to CC_C doesn't necessarily have an effect on the computed 
flags.

> +    if (sign) {
> +        tcg_gen_ext32s_i64(quot64, quot64);
> +        tcg_gen_extrh_i64_i32(rem, quot64);

This is a long way around to simply extract the same sign bit out of quot, i.e.

     tcg_gen_sari_i32(rem, quot, 31);

> +        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_V,
> +                            QREG_CC_V, rem,
> +                            QREG_CC_C /* 0 */, minusone /* -1 */);

Again with setcond + neg vs movcond.


r~

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

* Re: [Qemu-devel] [PATCH 34/52] target-m68k: add 64bit mull
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 34/52] target-m68k: add 64bit mull Laurent Vivier
@ 2016-05-06 19:48     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 19:48 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:08 AM, Laurent Vivier wrote:
> +    if (m68k_feature(s->env, M68K_FEATURE_M68000)) {
> +        if (sign) {
> +            tcg_gen_muls2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12));
> +        } else {
> +            tcg_gen_mulu2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12));
> +        }
> +        tcg_gen_mov_i32(DREG(ext, 12), QREG_CC_N);
> +
> +        tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
> +        tcg_gen_movi_i32(QREG_CC_C, 0);
> +
> +        set_cc_op(s, CC_OP_FLAGS);

Unsigned overflow requires -(QREG_CC_V != 0).
Signed overflow requires -(QREG_CC_V != (QREG_CC_N >> 31)).


r~

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

* Re: [Qemu-devel] [PATCH 35/52] target-m68k: inline rotate ops
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 35/52] target-m68k: inline rotate ops Laurent Vivier
@ 2016-05-06 20:28     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 20:28 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:08 AM, Laurent Vivier wrote:
> +static inline void rotate_x_flags(TCGv reg, int size)
> +{
> +    switch (size) {
> +    case 8:
> +        tcg_gen_ext8s_i32(reg, reg);
> +        break;
> +    case 16:
> +        tcg_gen_ext16s_i32(reg, reg);
> +        break;
> +    default:
> +        break;
> +    }
> +    tcg_gen_mov_i32(QREG_CC_N, reg);
> +    tcg_gen_mov_i32(QREG_CC_Z, reg);
> +    tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);

A comment saying that CC_V has already been set wouldn't go amiss.

Alternately, don't work so hard to re-use CC_V as a zero in the rotate_reg case.

> +            tcg_gen_shli_i32(X, reg, 1);
> +            tcg_gen_or_i32(X, X, QREG_CC_X);

This can clobber CC_X before it's used.

I think you need to be less clever about passing in QREG_CC_X as X in 
rotate*_im and instead always return a temporary.

> +static inline void rotate_x(TCGv dest, TCGv X, TCGv reg, TCGv shift,
> +                            int left, int size)
> +{
> +    TCGv_i64 t0, shift64;

I can't help but think it wouldn't be better to only use 64-bit shifts when 
size == 32.  You can implement the 8- and 16-bit rotates with a 32-bit ro

> +DISAS_INSN(rotate_reg)
> +{
> +    TCGv reg;
> +    TCGv src;
> +    TCGv tmp, t0;
> +    int left = (insn & 0x100);
> +
> +    reg = DREG(insn, 0);
> +    src = DREG(insn, 9);
> +    tmp = tcg_temp_new_i32();
> +    if (insn & 8) {
> +        tcg_gen_andi_i32(tmp, src, 31);
> +        rotate(reg, tmp, left, 32);
> +        /* if shift == 0, clear C */
> +        tcg_gen_andi_i32(tmp, src, 63);

If reg == src, you'll compute the wrong results here.

> +    } else {
> +        TCGv dest, X;
> +        dest = tcg_temp_new();
> +        X = tcg_temp_new();
> +        /* shift in [0..63] */
> +        tcg_gen_andi_i32(tmp, src, 63);
> +        /* modulo 33 */
> +        t0 = tcg_const_i32(33);
> +        tcg_gen_remu_i32(tmp, tmp, t0);
> +        tcg_temp_free(t0);
> +        rotate_x(dest, X, reg, tmp, left, 32);
> +        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_X,
> +                            tmp, QREG_CC_V /* 0 */,
> +                            QREG_CC_X /* 0 */, X);

And here you can't use the mod 33 shift count, but the full mod 64 shift count.

Similarly for the 8 and 16 bit versions.


r~

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

* Re: [Qemu-devel] [PATCH 36/52] target-m68k: inline shift ops
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 36/52] target-m68k: inline shift ops Laurent Vivier
@ 2016-05-06 20:53     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 20:53 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:08 AM, Laurent Vivier wrote:
> -    if (count == 0) {
> -        count = 8;
> -    }
> +    count = ((count - 1) & 0x7) + 1; /* 1..8 */

How is that clearer, or even simpler?

> +                tcg_gen_setcond_i32(TCG_COND_EQ, QREG_CC_V, reg, zero);
> +                /* adjust V: (1,0) -> (0,-1) */
> +                tcg_gen_subi_i32(QREG_CC_V, QREG_CC_V, 1);

Better to use NE and neg.

> +                TCGv t0 = tcg_temp_new();
> +                TCGv t1 = tcg_const_i32(bits - 1 - count);
> +
> +                tcg_gen_shr_i32(QREG_CC_V, reg, t1);
> +                tcg_gen_sar_i32(t0, reg, t1);
> +                tcg_temp_free(t1);
> +                tcg_gen_not_i32(t0, t0);
> +
> +                tcg_gen_setcond_i32(TCG_COND_EQ, QREG_CC_V, QREG_CC_V, zero);
> +                tcg_gen_setcond_i32(TCG_COND_EQ, t0, t0, zero);
> +                tcg_gen_or_i32(QREG_CC_V, QREG_CC_V, t0); /* V is !V here */
> +
> +                tcg_temp_free(t0);
> +
> +                /* adjust V: (1,0) -> (0,-1) */
> +                tcg_gen_subi_i32(QREG_CC_V, QREG_CC_V, 1);

Can this be done more simply by creating a mask of sign bits, i.e.

     tcg_gen_sari_i32(t0, reg, 31);
     tcg_gen_shri_i32(t0, t0, bits - count);
     tcg_gen_shri_i32(t1, reg, bits - count);
     tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, t0, t1);
     tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V);


r~

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

* Re: [Qemu-devel] [PATCH 37/52] target-m68k: add cas/cas2 ops
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 37/52] target-m68k: add cas/cas2 ops Laurent Vivier
@ 2016-05-06 21:29     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:29 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:08 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  linux-user/main.c       | 193 ++++++++++++++++++++++++++++++++++++++++++++++++
>  target-m68k/cpu.h       |   9 +++
>  target-m68k/qregs.def   |   5 ++
>  target-m68k/translate.c | 175 +++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 382 insertions(+)
>
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 74b02c7..3c51afe 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -2994,6 +2994,194 @@ void cpu_loop(CPUMBState *env)
>
>  #ifdef TARGET_M68K
>
> +static int do_cas(CPUM68KState *env)
> +{
> +    int size, is_cas;
> +    int cmp1_reg, upd1_reg;
> +    int cmp2_reg, upd2_reg;
> +    uint32_t dest1, cmp1, addr1;
> +    uint32_t dest2, cmp2, addr2;
> +    int segv = 0;
> +    int z;
> +
> +    start_exclusive();
> +
> +    /* cas_param bits
> +     * 31    -> CAS(0) / CAS2(1)
> +     * 11:13 -> update reg 2
> +     * 8:10  -> cmp reg 2
> +     * 5:7   -> update reg 1
> +     * 2:4   -> cmp reg 1
> +     * 0:1   -> opsize
> +     */
> +
> +    is_cas = (env->cas_param & 0x80000000) == 0;
> +
> +    size = env->cas_param & 0x3;
> +
> +    cmp1_reg = (env->cas_param >> 2) & 7;
> +    upd1_reg = (env->cas_param >> 5) & 7;
> +    cmp2_reg = (env->cas_param >> 8) & 7;
> +    upd2_reg = (env->cas_param >> 11) & 7;
> +
> +    addr1 = env->cas_addr1;
> +    addr2 = env->cas_addr2;
> +
> +    switch (size) {
> +    case OS_BYTE:
> +        segv = get_user_u8(dest1, addr1);
> +        cmp1 = (uint8_t)env->dregs[cmp1_reg];
> +        break;
> +    case OS_WORD:
> +        segv = get_user_u16(dest1, addr1);
> +        cmp1 = (uint16_t)env->dregs[cmp1_reg];
> +        break;
> +    case OS_LONG:
> +    default:
> +        segv = get_user_u32(dest1, addr1);
> +        cmp1 = env->dregs[cmp1_reg];
> +        break;
> +    }
> +    if (segv) {
> +        env->mmu.ar = addr1;
> +        goto done;
> +    }
> +    env->cc_n = dest1;
> +    env->cc_v = cmp1;
> +    z = dest1 - cmp1;
> +    env->cc_op = CC_OP_CMPB + size;

Incorrect setting of CC_* before checking for all of the possible segv?

> +    dest = gen_load(s, opsize, addr, 0);
> +
> +    zero = tcg_const_i32(0);
> +    cmp = gen_extend(DREG(ext, 0), opsize, 0);
> +
> +    /* if  dest - cmp == 0 */
> +
> +    res = tcg_temp_new();
> +    tcg_gen_sub_i32(res, dest, cmp);
> +
> +    /* then dest = update1 */
> +
> +    tcg_gen_movcond_i32(TCG_COND_EQ, dest,
> +                        res, zero,
> +                        DREG(ext, 6), dest);
> +
> +    /* else cmp = dest */
> +
> +    tcg_gen_movcond_i32(TCG_COND_NE, cmp,
> +                        res, zero,
> +                        dest, cmp);

Note that you don't need movcond for cmp here.  If the condition is false, we 
know that cmp == dest anyway.  So just a plain store into cmp.

You also don't need to compute RES, since you can perform the first movcond 
based on dest and cmp directly.  Although this does require an extra temp:

   load = gen_load(...)
   cmp = gen_extend(...)
   store = tcg_temp_new();

   tcg_gen_movcond_i32(TCG_COND_EQ, store, load, cmp, DREG(ext, 6), load);
   tcg_gen_mov_i32(cmp, load);

   gen_partset_reg(..., cmp);
   gen_store(..., store);

> +    gen_logic_cc(s, res, opsize);

gen_logic_cc is wrong, afaics, and clobbers the proper CMPB + opsize that you 
set up earlier.

> +    TCGv cmp1, cmp2;
> +    TCGv dest1, dest2;
> +    TCGv res1, res2;
> +    TCGv zero;
> +    zero = tcg_const_i32(0);
> +    dest1 = gen_load(s, opsize, addr1, 0);
> +    cmp1 = gen_extend(DREG(ext1, 0), opsize, 0);
> +
> +    res1 = tcg_temp_new();
> +    tcg_gen_sub_i32(res1, dest1, cmp1);
> +    dest2 = gen_load(s, opsize, addr2, 0);
> +    cmp2 = gen_extend(DREG(ext2, 0), opsize, 0);
> +
> +    res2 = tcg_temp_new();
> +    tcg_gen_sub_i32(res2, dest2, cmp2);
> +
> +    /* if dest1 - cmp1 == 0 and dest2 - cmp2 == 0 */
> +
> +    tcg_gen_movcond_i32(TCG_COND_EQ, res1,
> +                        res1, zero,
> +                        res2, res1);

   z = (cmp1 - load1) | (cmp2 - load2)

would be a better computation here than sub+sub+movcond.

Of course, we also need to correctly compute N, C and V, so...

   N = (cmp1 == load1 ? cmp2 : cmp1);
   V = (cmp1 == load1 ? load2 : load1);
   cc_op = CC_OP_CMP;

   store1 = (N == V ? update1 : load1);
   store2 = (N == V ? update2 : load2);

   cmp1 = load1;
   cmp2 = load2;

Oh, and we need to think about delaying all flag and register updates until 
after the stores, for both CAS and CAS2.  Otherwise we don't get the right 
results at the exception handler for a write-protected page.


r~

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

* Re: [Qemu-devel] [PATCH 38/52] target-m68k: add linkl
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 38/52] target-m68k: add linkl Laurent Vivier
@ 2016-05-06 21:30     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:30 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:08 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 26 +++++++++++++++++++++-----
>  1 file changed, 21 insertions(+), 5 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 39/52] target-m68k: movem
  2016-05-04 21:08   ` [Qemu-devel] [PATCH 39/52] target-m68k: movem Laurent Vivier
@ 2016-05-06 21:45     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:45 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

A more verbose commit message is required here.

On 05/04/2016 11:08 AM, Laurent Vivier wrote:
> @@ -1724,21 +1726,40 @@ DISAS_INSN(movem)
>      addr = tcg_temp_new();
>      tcg_gen_mov_i32(addr, tmp);
>      is_load = ((insn & 0x0400) != 0);
> -    for (i = 0; i < 16; i++, mask >>= 1) {
> -        if (mask & 1) {
> -            if (i < 8)
> -                reg = DREG(i, 0);
> -            else
> -                reg = AREG(i, 0);
> -            if (is_load) {
> -                tmp = gen_load(s, OS_LONG, addr, 0);
> -                tcg_gen_mov_i32(reg, tmp);
> -            } else {
> -                gen_store(s, OS_LONG, addr, reg);
> -            }
> -            if (mask != 1)
> -                tcg_gen_addi_i32(addr, addr, 4);
> -        }
> +    opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD;
> +    incr = opsize_bytes(opsize);
> +    if (!is_load && (insn & 070) == 040) {
> +       for (i = 15; i >= 0; i--, mask >>= 1) {
> +           if (mask & 1) {
> +               if (i < 8)
> +                   reg = DREG(i, 0);
> +               else
> +                   reg = AREG(i, 0);
> +               gen_store(s, opsize, addr, reg);
> +               if (mask != 1)
> +                   tcg_gen_subi_i32(addr, addr, incr);
> +           }
> +       }
> +       tcg_gen_mov_i32(AREG(insn, 0), addr);

Missing this bit from the manual:

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

You appear to be implementing only the latter.


> +    } else {
> +       for (i = 0; i < 16; i++, mask >>= 1) {
> +           if (mask & 1) {
> +               if (i < 8)
> +                   reg = DREG(i, 0);
> +               else
> +                   reg = AREG(i, 0);
> +               if (is_load) {
> +                   tmp = gen_load(s, opsize, addr, 1);
> +                   tcg_gen_mov_i32(reg, tmp);
> +               } else {
> +                   gen_store(s, opsize, addr, reg);
> +               }
> +               if (mask != 1 || (insn & 070) == 030)
> +                   tcg_gen_addi_i32(addr, addr, incr);
> +           }
> +       }

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


r~

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

* Re: [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops
  2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
                     ` (11 preceding siblings ...)
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 52/52] target-m68k: sr/ccr cleanup Laurent Vivier
@ 2016-05-06 21:47   ` Richard Henderson
  12 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:47 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:20 AM, Laurent Vivier wrote:
> +    case 0x140:
> +        /* exchange Dx and Dy */
> +        src = DREG(insn, 9);
> +        reg = DREG(insn, 0);
> +        tcg_gen_mov_i32(dest, src);
> +        tcg_gen_mov_i32(src, reg);
> +        tcg_gen_mov_i32(reg, dest);
> +        break;
> +    case 0x148:
> +        /* exchange Ax and Ay */
> +        src = AREG(insn, 9);
> +        reg = AREG(insn, 0);
> +        tcg_gen_mov_i32(dest, src);
> +        tcg_gen_mov_i32(src, reg);
> +        tcg_gen_mov_i32(reg, dest);
> +        break;
> +    case 0x188:
> +        /* exchange Dx and Ay */
> +        src = DREG(insn, 9);
> +        reg = AREG(insn, 0);
> +        tcg_gen_mov_i32(dest, src);
> +        tcg_gen_mov_i32(src, reg);
> +        tcg_gen_mov_i32(reg, dest);
> +        break;
> +    }

All of the mov's can surely be shared between these cases.

Otherwise,

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 41/52] target-m68k: add addressing modes to not
  2016-05-04 21:20   ` [Qemu-devel] [PATCH 41/52] target-m68k: add addressing modes to not Laurent Vivier
@ 2016-05-06 21:47     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:47 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:20 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 14 ++++++++++----
>  1 file changed, 10 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 42/52] target-m68k: eor can manage word and byte operands
  2016-05-04 21:20   ` [Qemu-devel] [PATCH 42/52] target-m68k: eor can manage word and byte operands Laurent Vivier
@ 2016-05-06 21:48     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:48 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:20 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 13 +++++++------
>  1 file changed, 7 insertions(+), 6 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 43/52] target-m68k: or can manage word and byte operands
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 43/52] target-m68k: or " Laurent Vivier
@ 2016-05-06 21:49     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:49 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:21 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 14 ++++++++------
>  1 file changed, 8 insertions(+), 6 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 44/52] target-m68k: and can manage word and byte operands
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 44/52] target-m68k: and " Laurent Vivier
@ 2016-05-06 21:49     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:49 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:21 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 16 ++++++++++------
>  1 file changed, 10 insertions(+), 6 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 45/52] target-m68k: suba/adda can manage word operand
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 45/52] target-m68k: suba/adda can manage word operand Laurent Vivier
@ 2016-05-06 21:50     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:50 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:21 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 46/52] target-m68k: introduce byte and word cc_ops
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 46/52] target-m68k: introduce byte and word cc_ops Laurent Vivier
@ 2016-05-06 21:53     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:53 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:21 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/cpu.h       |  6 +--
>  target-m68k/helper.c    | 25 +++++++++----
>  target-m68k/translate.c | 99 ++++++++++++++++++++++++++++++-------------------
>  3 files changed, 80 insertions(+), 50 deletions(-)

I think this ought to be merged back with the other cc_ops patches.

> @@ -864,7 +881,6 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
>          c->v1 = c->v2;
>          tcond = TCG_COND_NEVER;
>          goto done;
> -    case 14: /* GT (!(Z || (N ^ V))) */
>      case 15: /* LE (Z || (N ^ V)) */
>          /* Logic operations clear V, which simplifies LE to (Z || N),
>             and since Z and N are co-located, this becomes a normal

What happened here?


r~

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

* Re: [Qemu-devel] [PATCH 47/52] target-m68k: add addressing modes to neg
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 47/52] target-m68k: add addressing modes to neg Laurent Vivier
@ 2016-05-06 21:54     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:54 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:21 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 20 ++++++++++++--------
>  1 file changed, 12 insertions(+), 8 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 48/52] target-m68k: add/sub manage word and byte operands
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 48/52] target-m68k: add/sub manage word and byte operands Laurent Vivier
@ 2016-05-06 21:57     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:57 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:21 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 71 ++++++++++++++++++++++++++-----------------------
>  1 file changed, 38 insertions(+), 33 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 49/52] target-m68k: cmp manages word and bytes operands
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 49/52] target-m68k: cmp manages word and bytes operands Laurent Vivier
@ 2016-05-06 21:57     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:57 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:21 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 10 ++++------
>  1 file changed, 4 insertions(+), 6 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 50/52] target-m68k: immediate ops manage word and byte operands
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 50/52] target-m68k: immediate ops manage word and byte operands Laurent Vivier
@ 2016-05-06 21:59     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 21:59 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:21 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 57 ++++++++++++++++++++++++++++++-------------------
>  1 file changed, 35 insertions(+), 22 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH 51/52] target-m68k: add cmpm
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 51/52] target-m68k: add cmpm Laurent Vivier
@ 2016-05-06 22:00     ` Richard Henderson
  2016-05-07 19:01       ` Laurent Vivier
  0 siblings, 1 reply; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 22:00 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:21 AM, Laurent Vivier wrote:
> +    reg = AREG(insn, 0);
> +    src = gen_load(s, opsize, reg, 1);
> +    tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
> +
> +    reg = AREG(insn, 9);
> +    dest = gen_load(s, opsize, reg, 1);
> +    tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));

Delay the writeback to the first areg until after the second load.


r~

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

* Re: [Qemu-devel] [PATCH 52/52] target-m68k: sr/ccr cleanup
  2016-05-04 21:21   ` [Qemu-devel] [PATCH 52/52] target-m68k: sr/ccr cleanup Laurent Vivier
@ 2016-05-06 22:02     ` Richard Henderson
  0 siblings, 0 replies; 131+ messages in thread
From: Richard Henderson @ 2016-05-06 22:02 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, gerg, agraf

On 05/04/2016 11:21 AM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 35 ++++++++++++++++++-----------------
>  1 file changed, 18 insertions(+), 17 deletions(-)

Can this be merged with patch 14, which is also cleaning up these same functions?


r~

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

* Re: [Qemu-devel] [PATCH 07/52] target-m68k: add bkpt instruction
  2016-05-06 16:42   ` Richard Henderson
@ 2016-05-07  7:08     ` Laurent Vivier
  0 siblings, 0 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-07  7:08 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: gerg, schwab, agraf



Le 06/05/2016 à 18:42, Richard Henderson a écrit :
> On 05/04/2016 10:11 AM, Laurent Vivier wrote:
>> +    INSN(bkpt,      4848, fff8, M68000);
> 
> Do we care that this comes in with 68010 not 68000?

Yes, you're right: I'm adding M68K_FEATURE_BKPT to enable it only on 68010+

> Otherwise,
> 
> Reviewed-by: Richard Henderson <rth@twiddle.net>
> 
> 
> r~
> 
Thanks,
Laurent

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

* Re: [Qemu-devel] [PATCH 11/52] target-m68k: allow to update flags with operation on words and bytes
  2016-05-06 16:45   ` Richard Henderson
@ 2016-05-07  7:19     ` Laurent Vivier
  0 siblings, 0 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-07  7:19 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: gerg, schwab, agraf



Le 06/05/2016 à 18:45, Richard Henderson a écrit :
> On 05/04/2016 10:11 AM, Laurent Vivier wrote:
>> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
>> ---
>>  target-m68k/cpu.h       |  14 ++++-
>>  target-m68k/helper.c    | 139
>> ++++++++++++++++++++++++++++++++++--------------
>>  target-m68k/translate.c |  82 ++++++++++++++--------------
>>  3 files changed, 151 insertions(+), 84 deletions(-)
> 
> I wonder if this shouldn't just be dropped, or squished into some of the
> other flags-related patches?  That said,

While I was debugging this series it was very helpful to have this patch
separated to bisect where it is broken (as it was in this one).
So I think it is good to have this one separated from the others.

> Reviewed-by: Richard Henderson <rth@twiddle.net>

Thanks,
Laurent

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

* Re: [Qemu-devel] [PATCH 51/52] target-m68k: add cmpm
  2016-05-06 22:00     ` Richard Henderson
@ 2016-05-07 19:01       ` Laurent Vivier
  2016-05-07 21:50         ` Peter Maydell
  0 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-07 19:01 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: schwab, gerg, agraf



Le 07/05/2016 à 00:00, Richard Henderson a écrit :
> On 05/04/2016 11:21 AM, Laurent Vivier wrote:
>> +    reg = AREG(insn, 0);
>> +    src = gen_load(s, opsize, reg, 1);
>> +    tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
>> +
>> +    reg = AREG(insn, 9);
>> +    dest = gen_load(s, opsize, reg, 1);
>> +    tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
> 
> Delay the writeback to the first areg until after the second load.

We can't delay because we can have "cmpm (%a0)+,(%a0)+" that is used to
compare two consecutive memory contents.

Laurent

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

* Re: [Qemu-devel] [PATCH 51/52] target-m68k: add cmpm
  2016-05-07 19:01       ` Laurent Vivier
@ 2016-05-07 21:50         ` Peter Maydell
  2016-05-08  9:07           ` Laurent Vivier
  0 siblings, 1 reply; 131+ messages in thread
From: Peter Maydell @ 2016-05-07 21:50 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: Richard Henderson, QEMU Developers, Andreas Schwab,
	Alexander Graf, Greg Ungerer

On 7 May 2016 at 20:01, Laurent Vivier <laurent@vivier.eu> wrote:
>
>
> Le 07/05/2016 à 00:00, Richard Henderson a écrit :
>> On 05/04/2016 11:21 AM, Laurent Vivier wrote:
>>> +    reg = AREG(insn, 0);
>>> +    src = gen_load(s, opsize, reg, 1);
>>> +    tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
>>> +
>>> +    reg = AREG(insn, 9);
>>> +    dest = gen_load(s, opsize, reg, 1);
>>> +    tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
>>
>> Delay the writeback to the first areg until after the second load.
>
> We can't delay because we can have "cmpm (%a0)+,(%a0)+" that is used to
> compare two consecutive memory contents.

If you write back to the first areg before the second
load, don't you get the wrong value as seen by the
exception handler if the second load faults?

Usually you want to use the updated value for the
purposes of calculating the address to use in the
second load, but you don't want to actually update
the guest CPU register until after the load has
happened, in case it faults.

(Disclaimer: I'm just assuming that on a fault no
registers are updated, but if that wasn't the case the OS
wouldn't be able to cleanly restart the instruction after
fixing up a page fault, so it seems like a good guess.)

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 51/52] target-m68k: add cmpm
  2016-05-07 21:50         ` Peter Maydell
@ 2016-05-08  9:07           ` Laurent Vivier
  2016-05-08 10:44             ` Peter Maydell
  0 siblings, 1 reply; 131+ messages in thread
From: Laurent Vivier @ 2016-05-08  9:07 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Richard Henderson, QEMU Developers, Andreas Schwab,
	Alexander Graf, Greg Ungerer



Le 07/05/2016 à 23:50, Peter Maydell a écrit :
> On 7 May 2016 at 20:01, Laurent Vivier <laurent@vivier.eu> wrote:
>>
>>
>> Le 07/05/2016 à 00:00, Richard Henderson a écrit :
>>> On 05/04/2016 11:21 AM, Laurent Vivier wrote:
>>>> +    reg = AREG(insn, 0);
>>>> +    src = gen_load(s, opsize, reg, 1);
>>>> +    tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
>>>> +
>>>> +    reg = AREG(insn, 9);
>>>> +    dest = gen_load(s, opsize, reg, 1);
>>>> +    tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
>>>
>>> Delay the writeback to the first areg until after the second load.
>>
>> We can't delay because we can have "cmpm (%a0)+,(%a0)+" that is used to
>> compare two consecutive memory contents.
> 
> If you write back to the first areg before the second
> load, don't you get the wrong value as seen by the
> exception handler if the second load faults?
> 
> Usually you want to use the updated value for the
> purposes of calculating the address to use in the
> second load, but you don't want to actually update
> the guest CPU register until after the load has
> happened, in case it faults.
> 
> (Disclaimer: I'm just assuming that on a fault no
> registers are updated, but if that wasn't the case the OS
> wouldn't be able to cleanly restart the instruction after
> fixing up a page fault, so it seems like a good guess.)

You're right.

But I didn't really care here of the page faults because m68k only
supports non privileged instructions: coldfire is used in semi-hosting
mode (no MMU) and 680x0-like machine has no hardware (I use it in
linux-user mode).

I'm working on a Quadra 800 [1] emulation where I have added all the
needed hardware and privileged instructions, and of course, I have to
re-work all the memory access because of what you have described above...

But I'm going to try to update this series taking care of the memory
access fault as much as possible.

Laurent

[1] https://github.com/vivier/qemu-m68k/tree/q800-v2.4.0

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

* Re: [Qemu-devel] [PATCH 51/52] target-m68k: add cmpm
  2016-05-08  9:07           ` Laurent Vivier
@ 2016-05-08 10:44             ` Peter Maydell
  0 siblings, 0 replies; 131+ messages in thread
From: Peter Maydell @ 2016-05-08 10:44 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: Richard Henderson, QEMU Developers, Andreas Schwab,
	Alexander Graf, Greg Ungerer

On 8 May 2016 at 10:07, Laurent Vivier <laurent@vivier.eu> wrote:
> But I didn't really care here of the page faults because m68k only
> supports non privileged instructions: coldfire is used in semi-hosting
> mode (no MMU) and 680x0-like machine has no hardware (I use it in
> linux-user mode).

It does still affect linux-user if your guest program has a
SIGSEGV handler and uses it to fix up and restart faulting
instructions, but I think only a few obscure JIT-type apps do
this.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH] MAINTAINERS: update M68K entry
  2016-05-06 10:30   ` [Qemu-devel] [PATCH] MAINTAINERS: update M68K entry Laurent Vivier
@ 2016-05-12  7:55     ` Thomas Huth
  0 siblings, 0 replies; 131+ messages in thread
From: Thomas Huth @ 2016-05-12  7:55 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: peter.maydell, agraf

On 06.05.2016 12:30, Laurent Vivier wrote:
> Add myself to be the M68K maintainer.
> 
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  MAINTAINERS | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 81e7fac..c79404c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -131,7 +131,8 @@ F: include/hw/lm32/
>  F: tests/tcg/lm32/
>  
>  M68K
> -S: Orphan
> +M: Laurent Vivier <laurent@vivier.eu>
> +S: Maintained
>  F: target-m68k/
>  F: hw/m68k/

Yay, finally a maintainer for m68k, that's cool!

FWIW:
Reviewed-by: Thomas Huth <thuth@tuxfamily.org>

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-06  9:54   ` Laurent Vivier
  2016-05-06 10:15     ` Andreas Schwab
  2016-05-06 11:40     ` John Paul Adrian Glaubitz
@ 2016-05-12 21:17     ` John Paul Adrian Glaubitz
  2016-05-12 21:20       ` Laurent Vivier
       [not found]       ` <D2F89431-FF87-456A-A628-7F8ADCDDAFC7@suse.de>
  2 siblings, 2 replies; 131+ messages in thread
From: John Paul Adrian Glaubitz @ 2016-05-12 21:17 UTC (permalink / raw)
  To: Laurent Vivier, Andreas Schwab; +Cc: qemu-devel, gerg, agraf, rth

Hi!

Now that qemu 2.6.0 has been released, what about making Laurent the
maintainer for the orphaned M68K target so that the 680x0 emulation
support can be merged?

What do the qemu maintainers think? Is there anything which speaks
against my suggestion?

Thanks,
Adrian

On 05/06/2016 11:54 AM, Laurent Vivier wrote:
> 
> 
> Le 06/05/2016 à 11:35, Andreas Schwab a écrit :
>> When I bootstrap gcc with the qemu built from your 680x0-master-dev
>> branch I get a bootstrap comparison failure for a lot of files.
>> Rerunning the stage1 compiler in aranym then produces object files that
>> are identical to what the stage2 compiler produced, thus some insn (or
>> combination thereof) only used in the stage1 compiler (which is built
>> unoptimized) isn't handled correctly yet.
> 
> Yes, I know this is not perfect, but keeping all these patches in my own
> tree doesn't help.
> 
> It's why I try to have them merged.
> 
> BTW, Adrian is using this branch (680x0-master-dev) for months to build
> Debian packages.
> 
> Thanks,
> Laurent
> 


-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
  2016-05-12 21:17     ` John Paul Adrian Glaubitz
@ 2016-05-12 21:20       ` Laurent Vivier
       [not found]       ` <D2F89431-FF87-456A-A628-7F8ADCDDAFC7@suse.de>
  1 sibling, 0 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-12 21:20 UTC (permalink / raw)
  To: John Paul Adrian Glaubitz, Andreas Schwab; +Cc: qemu-devel, gerg, agraf, rth



Le 12/05/2016 à 23:17, John Paul Adrian Glaubitz a écrit :
> Hi!
> 
> Now that qemu 2.6.0 has been released, what about making Laurent the
> maintainer for the orphaned M68K target so that the 680x0 emulation
> support can be merged?
> 
> What do the qemu maintainers think? Is there anything which speaks
> against my suggestion?

I've sent a patch for that :)

https://patchwork.ozlabs.org/patch/619248/

Laurent

> Thanks,
> Adrian
> 
> On 05/06/2016 11:54 AM, Laurent Vivier wrote:
>>
>>
>> Le 06/05/2016 à 11:35, Andreas Schwab a écrit :
>>> When I bootstrap gcc with the qemu built from your 680x0-master-dev
>>> branch I get a bootstrap comparison failure for a lot of files.
>>> Rerunning the stage1 compiler in aranym then produces object files that
>>> are identical to what the stage2 compiler produced, thus some insn (or
>>> combination thereof) only used in the stage1 compiler (which is built
>>> unoptimized) isn't handled correctly yet.
>>
>> Yes, I know this is not perfect, but keeping all these patches in my own
>> tree doesn't help.
>>
>> It's why I try to have them merged.
>>
>> BTW, Adrian is using this branch (680x0-master-dev) for months to build
>> Debian packages.
>>
>> Thanks,
>> Laurent
>>
> 
> 

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
       [not found]       ` <D2F89431-FF87-456A-A628-7F8ADCDDAFC7@suse.de>
@ 2016-05-12 21:25         ` John Paul Adrian Glaubitz
       [not found]           ` <C662446E-C86D-4838-83C5-14E8E6C52D2A@suse.de>
  2016-05-12 21:30         ` Laurent Vivier
  1 sibling, 1 reply; 131+ messages in thread
From: John Paul Adrian Glaubitz @ 2016-05-12 21:25 UTC (permalink / raw)
  To: Alexander Graf; +Cc: Laurent Vivier, Andreas Schwab, qemu-devel, gerg, rth

On 05/12/2016 11:23 PM, Alexander Graf wrote:
> I expect he'll send a v2 of the patch set that fixes all review comments
> and includes the patch to MAINTAINERS. I don't see how applying only the
> MAINTAINERS patch would help anyone? Would it speed up his work to get v2 out? :)

Oh, sorry, I must have missed that part. I wasn't aware that Laurent
already got enough feedback to work on revised version. Then I will
be happy to wait and looking forward to the updated patch set! :-)

Thanks for the heads-up!

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
       [not found]       ` <D2F89431-FF87-456A-A628-7F8ADCDDAFC7@suse.de>
  2016-05-12 21:25         ` John Paul Adrian Glaubitz
@ 2016-05-12 21:30         ` Laurent Vivier
  1 sibling, 0 replies; 131+ messages in thread
From: Laurent Vivier @ 2016-05-12 21:30 UTC (permalink / raw)
  To: Alexander Graf, John Paul Adrian Glaubitz
  Cc: Andreas Schwab, qemu-devel, gerg, rth



Le 12/05/2016 à 23:23, Alexander Graf a écrit :
> 
> 
>> Am 12.05.2016 um 23:17 schrieb John Paul Adrian Glaubitz
>> <glaubitz@physik.fu-berlin.de>:
>> 
>> Hi!
>> 
>> Now that qemu 2.6.0 has been released, what about making Laurent
>> the maintainer for the orphaned M68K target so that the 680x0
>> emulation support can be merged?
>> 
>> What do the qemu maintainers think? Is there anything which speaks 
>> against my suggestion?
> 
> I expect he'll send a v2 of the patch set that fixes all review
> comments and includes the patch to MAINTAINERS. I don't see how
> applying only the MAINTAINERS patch would help anyone? Would it speed
> up his work to get v2 out? :)

I'm not as efficient to fix them as Richard is to review them... but I'm
working on that, and I will add MAINTAINER patch in the series. :)

Thanks,
Laurent

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

* Re: [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation
       [not found]           ` <C662446E-C86D-4838-83C5-14E8E6C52D2A@suse.de>
@ 2016-05-12 21:32             ` John Paul Adrian Glaubitz
  0 siblings, 0 replies; 131+ messages in thread
From: John Paul Adrian Glaubitz @ 2016-05-12 21:32 UTC (permalink / raw)
  To: Alexander Graf; +Cc: Laurent Vivier, Andreas Schwab, qemu-devel, gerg, rth

On 05/12/2016 11:29 PM, Alexander Graf wrote:
> Rest assured that we're all happy to see m68k finally going back to maintained state ;).

Glad to hear that.  Laurent has been doing a fantastic job on m68k and
so far it has been a pleasure to helm him improve the code with tests
and patches.

qemu-m68k has helped us in Debian to have the m68k port keep up with
the rest of the architectures.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

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

end of thread, other threads:[~2016-05-16 17:33 UTC | newest]

Thread overview: 131+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-04 20:11 [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Laurent Vivier
2016-05-04 20:11 ` [Qemu-devel] [PATCH 01/52] target-m68k: fix DEBUG_DISPATCH Laurent Vivier
2016-05-06 16:34   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 02/52] target-m68k: Build the opcode table only once to avoid multithreading issues Laurent Vivier
2016-05-06 16:35   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 03/52] target-m68k: define m680x0 CPUs and features Laurent Vivier
2016-05-06 16:35   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 04/52] target-m68k: manage scaled index Laurent Vivier
2016-05-06 16:36   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 05/52] target-m68k: introduce read_imXX() functions Laurent Vivier
2016-05-06 16:36   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 06/52] target-m68k: set disassembler mode to 680x0 or coldfire Laurent Vivier
2016-05-06 16:37   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 07/52] target-m68k: add bkpt instruction Laurent Vivier
2016-05-06 16:42   ` Richard Henderson
2016-05-07  7:08     ` Laurent Vivier
2016-05-04 20:11 ` [Qemu-devel] [PATCH 08/52] target-m68k: define operand sizes Laurent Vivier
2016-05-06 16:43   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 09/52] target-m68k: set PAGE_BITS to 12 for m68k Laurent Vivier
2016-05-06 16:44   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 10/52] target-m68k: REG() macro cleanup Laurent Vivier
2016-05-06 16:44   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 11/52] target-m68k: allow to update flags with operation on words and bytes Laurent Vivier
2016-05-06 16:45   ` Richard Henderson
2016-05-07  7:19     ` Laurent Vivier
2016-05-04 20:11 ` [Qemu-devel] [PATCH 12/52] target-m68k: Replace helper_xflag_lt with setcond Laurent Vivier
2016-05-04 20:11 ` [Qemu-devel] [PATCH 13/52] target-m68k: update CPU flags management Laurent Vivier
2016-05-06 16:46   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 14/52] target-m68k: update move to/from ccr/sr Laurent Vivier
2016-05-06 16:47   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 15/52] target-m68k: don't update cc_dest in helpers Laurent Vivier
2016-05-06 16:47   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 16/52] target-m68k: update CPU flags management Laurent Vivier
2016-05-06 16:47   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 17/52] target-m68k: Print flags properly Laurent Vivier
2016-05-04 20:11 ` [Qemu-devel] [PATCH 18/52] target-m68k: Some fixes to SR and flags management Laurent Vivier
2016-05-06 16:49   ` Richard Henderson
2016-05-04 20:11 ` [Qemu-devel] [PATCH 19/52] target-m68k: terminate cpu dump with newline Laurent Vivier
2016-05-06 16:49   ` Richard Henderson
2016-05-06 17:41   ` Andreas Schwab
2016-05-04 20:12 ` [Qemu-devel] [PATCH 20/52] target-m68k: Remove incorrect clearing of cc_x Laurent Vivier
2016-05-04 20:12 ` [Qemu-devel] [PATCH 21/52] target-m68k: Reorg flags handling Laurent Vivier
2016-05-06 16:51   ` Richard Henderson
2016-05-04 20:12 ` [Qemu-devel] [PATCH 22/52] target-m68k: Introduce DisasCompare Laurent Vivier
2016-05-04 20:12 ` [Qemu-devel] [PATCH 23/52] target-m68k: Use setcond for scc Laurent Vivier
2016-05-04 20:12 ` [Qemu-devel] [PATCH 24/52] target-m68k: Optimize some comparisons Laurent Vivier
2016-05-04 20:12 ` [Qemu-devel] [PATCH 25/52] target-m68k: Optimize gen_flush_flags Laurent Vivier
2016-05-04 20:12 ` [Qemu-devel] [PATCH 26/52] target-m68k: Inline shifts Laurent Vivier
2016-05-06 16:53   ` Richard Henderson
2016-05-04 20:12 ` [Qemu-devel] [PATCH 27/52] target-m68k: Inline addx, subx, negx Laurent Vivier
2016-05-04 20:12 ` [Qemu-devel] [PATCH 28/52] target-m68k: add addx/subx/negx ops Laurent Vivier
2016-05-06 17:11   ` Richard Henderson
2016-05-04 20:12 ` [Qemu-devel] [PATCH 29/52] target-m68k: factorize flags computing Laurent Vivier
2016-05-06 17:11   ` Richard Henderson
2016-05-04 20:12 ` [Qemu-devel] [PATCH 30/52] target-m68k: add scc/dbcc Laurent Vivier
2016-05-06 17:18   ` Richard Henderson
2016-05-06 17:44     ` Andreas Schwab
2016-05-04 20:12 ` [Qemu-devel] [PATCH 31/52] target-m68k: some bit ops cleanup Laurent Vivier
2016-05-06 17:20   ` Richard Henderson
2016-05-04 20:12 ` [Qemu-devel] [PATCH 32/52] target-m68k: bitfield ops Laurent Vivier
2016-05-06 19:11   ` Richard Henderson
2016-05-04 21:08 ` [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs Laurent Vivier
2016-05-04 21:08   ` [Qemu-devel] [PATCH 34/52] target-m68k: add 64bit mull Laurent Vivier
2016-05-06 19:48     ` Richard Henderson
2016-05-04 21:08   ` [Qemu-devel] [PATCH 35/52] target-m68k: inline rotate ops Laurent Vivier
2016-05-06 20:28     ` Richard Henderson
2016-05-04 21:08   ` [Qemu-devel] [PATCH 36/52] target-m68k: inline shift ops Laurent Vivier
2016-05-06 20:53     ` Richard Henderson
2016-05-04 21:08   ` [Qemu-devel] [PATCH 37/52] target-m68k: add cas/cas2 ops Laurent Vivier
2016-05-06 21:29     ` Richard Henderson
2016-05-04 21:08   ` [Qemu-devel] [PATCH 38/52] target-m68k: add linkl Laurent Vivier
2016-05-06 21:30     ` Richard Henderson
2016-05-04 21:08   ` [Qemu-devel] [PATCH 39/52] target-m68k: movem Laurent Vivier
2016-05-06 21:45     ` Richard Henderson
2016-05-06 19:44   ` [Qemu-devel] [PATCH 33/52] target-m68k: inline divu/divs Richard Henderson
2016-05-04 21:20 ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Laurent Vivier
2016-05-04 21:20   ` [Qemu-devel] [PATCH 41/52] target-m68k: add addressing modes to not Laurent Vivier
2016-05-06 21:47     ` Richard Henderson
2016-05-04 21:20   ` [Qemu-devel] [PATCH 42/52] target-m68k: eor can manage word and byte operands Laurent Vivier
2016-05-06 21:48     ` Richard Henderson
2016-05-04 21:21   ` [Qemu-devel] [PATCH 43/52] target-m68k: or " Laurent Vivier
2016-05-06 21:49     ` Richard Henderson
2016-05-04 21:21   ` [Qemu-devel] [PATCH 44/52] target-m68k: and " Laurent Vivier
2016-05-06 21:49     ` Richard Henderson
2016-05-04 21:21   ` [Qemu-devel] [PATCH 45/52] target-m68k: suba/adda can manage word operand Laurent Vivier
2016-05-06 21:50     ` Richard Henderson
2016-05-04 21:21   ` [Qemu-devel] [PATCH 46/52] target-m68k: introduce byte and word cc_ops Laurent Vivier
2016-05-06 21:53     ` Richard Henderson
2016-05-04 21:21   ` [Qemu-devel] [PATCH 47/52] target-m68k: add addressing modes to neg Laurent Vivier
2016-05-06 21:54     ` Richard Henderson
2016-05-04 21:21   ` [Qemu-devel] [PATCH 48/52] target-m68k: add/sub manage word and byte operands Laurent Vivier
2016-05-06 21:57     ` Richard Henderson
2016-05-04 21:21   ` [Qemu-devel] [PATCH 49/52] target-m68k: cmp manages word and bytes operands Laurent Vivier
2016-05-06 21:57     ` Richard Henderson
2016-05-04 21:21   ` [Qemu-devel] [PATCH 50/52] target-m68k: immediate ops manage word and byte operands Laurent Vivier
2016-05-06 21:59     ` Richard Henderson
2016-05-04 21:21   ` [Qemu-devel] [PATCH 51/52] target-m68k: add cmpm Laurent Vivier
2016-05-06 22:00     ` Richard Henderson
2016-05-07 19:01       ` Laurent Vivier
2016-05-07 21:50         ` Peter Maydell
2016-05-08  9:07           ` Laurent Vivier
2016-05-08 10:44             ` Peter Maydell
2016-05-04 21:21   ` [Qemu-devel] [PATCH 52/52] target-m68k: sr/ccr cleanup Laurent Vivier
2016-05-06 22:02     ` Richard Henderson
2016-05-06 21:47   ` [Qemu-devel] [PATCH 40/52] target-m68k: add exg ops Richard Henderson
2016-05-06  9:35 ` [Qemu-devel] [PATCH 00/52] 680x0 instructions emulation Andreas Schwab
2016-05-06  9:54   ` Laurent Vivier
2016-05-06 10:15     ` Andreas Schwab
2016-05-06 11:40       ` John Paul Adrian Glaubitz
2016-05-06 12:44         ` Andreas Schwab
2016-05-06 13:02           ` John Paul Adrian Glaubitz
2016-05-06 13:24             ` Andreas Schwab
2016-05-06 13:45               ` John Paul Adrian Glaubitz
2016-05-06 13:48                 ` Andreas Schwab
2016-05-06 13:53                   ` John Paul Adrian Glaubitz
2016-05-06 13:53       ` Laurent Vivier
2016-05-06 13:58         ` Andreas Schwab
2016-05-06 14:25         ` Andreas Schwab
2016-05-06 14:47           ` Andreas Schwab
2016-05-06 11:40     ` John Paul Adrian Glaubitz
2016-05-06 11:45       ` Alexander Graf
2016-05-06 11:57         ` Laurent Vivier
2016-05-06 12:03           ` Peter Maydell
2016-05-12 21:17     ` John Paul Adrian Glaubitz
2016-05-12 21:20       ` Laurent Vivier
     [not found]       ` <D2F89431-FF87-456A-A628-7F8ADCDDAFC7@suse.de>
2016-05-12 21:25         ` John Paul Adrian Glaubitz
     [not found]           ` <C662446E-C86D-4838-83C5-14E8E6C52D2A@suse.de>
2016-05-12 21:32             ` John Paul Adrian Glaubitz
2016-05-12 21:30         ` Laurent Vivier
2016-05-06 10:06 ` Alexander Graf
2016-05-06 10:30   ` [Qemu-devel] [PATCH] MAINTAINERS: update M68K entry Laurent Vivier
2016-05-12  7:55     ` Thomas Huth

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.