All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set
@ 2016-10-25 14:49 Laurent Vivier
  2016-10-25 14:49 ` [Qemu-devel] [PATCH 01/23] target-m68k: fix DEBUG_DISPATCH Laurent Vivier
                   ` (23 more replies)
  0 siblings, 24 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:49 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, Laurent Vivier

As I'm not able to manage too large series,
this series is a subset of the series I sent in May:
https://lists.gnu.org/archive/html/qemu-devel/2016-05/msg00501.html

It doesn't introduce any new instructions but:
- introduce the new processors feature flags
- introduce new flags management as proposed by Richard

I've checked it doesn't break coldfire support:
http://wiki.qemu.org/download/coldfire-test-0.1.tar.bz2
but it can't boot a 680x0 processor kernel.

I've fixed some style issues reported by checkpatch.pl and merged
some of the patches cleaning up flags (as suggested by Richard).

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

Laurent Vivier (13):
  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: 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: remove m68k_cpu_exec_enter() and m68k_cpu_exec_exit()
  target-m68k: update move to/from ccr/sr
  target-m68k: don't update cc_dest in helpers
  target-m68k: update CPU flags management

Richard Henderson (9):
  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

 cpu-exec.c              |    6 -
 target-m68k/cpu.c       |   67 +++-
 target-m68k/cpu.h       |   72 +++-
 target-m68k/helper.c    |  319 +++++++--------
 target-m68k/helper.h    |    5 +-
 target-m68k/op_helper.c |   35 +-
 target-m68k/qregs.def   |    6 +-
 target-m68k/translate.c | 1027 ++++++++++++++++++++++++++++-------------------
 8 files changed, 880 insertions(+), 657 deletions(-)

-- 
2.7.4

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

* [Qemu-devel] [PATCH 01/23] target-m68k: fix DEBUG_DISPATCH
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
@ 2016-10-25 14:49 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 02/23] target-m68k: Build the opcode table only once to avoid multithreading issues Laurent Vivier
                   ` (22 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:49 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 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 ecd5e5c..deb5a58 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -170,7 +170,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.7.4

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

* [Qemu-devel] [PATCH 02/23] target-m68k: Build the opcode table only once to avoid multithreading issues
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
  2016-10-25 14:49 ` [Qemu-devel] [PATCH 01/23] target-m68k: fix DEBUG_DISPATCH Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 03/23] target-m68k: define m680x0 CPUs and features Laurent Vivier
                   ` (21 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: schwab, agraf, Richard Henderson, gerg,
	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>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 target-m68k/translate.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index deb5a58..eecb32b 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2841,6 +2841,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.7.4

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

* [Qemu-devel] [PATCH 03/23] target-m68k: define m680x0 CPUs and features
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
  2016-10-25 14:49 ` [Qemu-devel] [PATCH 01/23] target-m68k: fix DEBUG_DISPATCH Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 02/23] target-m68k: Build the opcode table only once to avoid multithreading issues Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 04/23] target-m68k: manage scaled index Laurent Vivier
                   ` (20 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, Laurent Vivier

This patch defines height 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
    - M68K_FEATURE_BKPT, bkpt instruction

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

diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 17e4be2..800e8f0 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -98,6 +98,57 @@ 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);
+    m68k_set_feature(env, M68K_FEATURE_BKPT);
+}
+#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);
+    m68k_set_feature(env, M68K_FEATURE_BKPT);
+}
+
 static void m5208_cpu_initfn(Object *obj)
 {
     M68kCPU *cpu = M68K_CPU(obj);
@@ -148,6 +199,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 471f490..8333e1e 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -215,6 +215,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).  */
@@ -225,7 +226,15 @@ 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,
+    M68K_FEATURE_BKPT,
 };
 
 static inline int m68k_feature(CPUM68KState *env, int feature)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index eecb32b..3773fb4 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2846,90 +2846,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);
@@ -2948,12 +2976,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.7.4

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

* [Qemu-devel] [PATCH 04/23] target-m68k: manage scaled index
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (2 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 03/23] target-m68k: define m680x0 CPUs and features Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 05/23] target-m68k: introduce read_imXX() functions Laurent Vivier
                   ` (19 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, 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>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 target-m68k/translate.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 3773fb4..d73350c 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -315,6 +315,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.7.4

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

* [Qemu-devel] [PATCH 05/23] target-m68k: introduce read_imXX() functions
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (3 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 04/23] target-m68k: manage scaled index Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 06/23] target-m68k: set disassembler mode to 680x0 or coldfire Laurent Vivier
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, 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>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 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 d73350c..a8ff5de 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -268,14 +268,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;
 }
 
@@ -309,8 +322,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;
@@ -328,8 +340,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);
             }
@@ -377,8 +388,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);
                 }
@@ -530,8 +540,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.  */
@@ -540,16 +549,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);
@@ -656,19 +663,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);
@@ -961,8 +966,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;
@@ -1113,8 +1117,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);
@@ -1157,8 +1160,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;
@@ -1411,8 +1413,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
@@ -1535,8 +1536,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;
@@ -1677,8 +1677,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);
     }
@@ -1962,14 +1961,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;
@@ -2036,8 +2033,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);
@@ -2063,8 +2059,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);
@@ -2130,8 +2125,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:
@@ -2413,8 +2407,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();
@@ -2539,8 +2532,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);
@@ -3011,8 +3003,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.7.4

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

* [Qemu-devel] [PATCH 06/23] target-m68k: set disassembler mode to 680x0 or coldfire
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (4 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 05/23] target-m68k: introduce read_imXX() functions Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 07/23] target-m68k: define operand sizes Laurent Vivier
                   ` (17 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 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 800e8f0..f925e26 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -64,9 +64,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.7.4

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

* [Qemu-devel] [PATCH 07/23] target-m68k: define operand sizes
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (5 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 06/23] target-m68k: set disassembler mode to 680x0 or coldfire Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 08/23] target-m68k: set PAGE_BITS to 12 for m68k Laurent Vivier
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, Laurent Vivier

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

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 8333e1e..133852a 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -30,6 +30,14 @@
 #include "cpu-qom.h"
 #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 a8ff5de..639db76 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -154,12 +154,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
@@ -453,6 +447,19 @@ 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();
     }
@@ -1330,19 +1337,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));
 }
@@ -1486,19 +1481,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.7.4

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

* [Qemu-devel] [PATCH 08/23] target-m68k: set PAGE_BITS to 12 for m68k
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (6 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 07/23] target-m68k: define operand sizes Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 09/23] target-m68k: REG() macro cleanup Laurent Vivier
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 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 133852a..fa1d027 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -255,8 +255,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.7.4

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

* [Qemu-devel] [PATCH 09/23] target-m68k: REG() macro cleanup
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (7 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 08/23] target-m68k: set PAGE_BITS to 12 for m68k Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 10/23] target-m68k: allow to update flags with operation on words and bytes Laurent Vivier
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 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 639db76..50c55a4 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -59,9 +59,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.7.4

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

* [Qemu-devel] [PATCH 10/23] target-m68k: allow to update flags with operation on words and bytes
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (8 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 09/23] target-m68k: REG() macro cleanup Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 11/23] target-m68k: Replace helper_xflag_lt with setcond Laurent Vivier
                   ` (13 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, 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 fa1d027..18b6930 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -173,13 +173,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 89bbe6d..4fe36b8 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -140,22 +140,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;
@@ -165,46 +206,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 50c55a4..e2f176e 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -428,10 +428,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)
@@ -933,8 +946,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)
@@ -1103,7 +1115,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)
@@ -1228,11 +1240,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);
@@ -1250,7 +1262,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);
@@ -1307,7 +1319,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);
     }
 }
 
@@ -1340,7 +1352,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)
@@ -1427,7 +1439,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)
@@ -1442,7 +1454,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(pea)
@@ -1474,7 +1486,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)
@@ -1484,7 +1496,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)
@@ -1506,7 +1518,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);
 }
@@ -1531,7 +1543,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)
@@ -1689,7 +1701,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)
@@ -1705,7 +1717,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)
@@ -1726,7 +1738,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)
@@ -1759,40 +1771,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)
@@ -1812,7 +1808,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)
@@ -1826,7 +1822,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);
 }
 
@@ -1848,7 +1844,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)
@@ -1923,7 +1919,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.7.4

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

* [Qemu-devel] [PATCH 11/23] target-m68k: Replace helper_xflag_lt with setcond
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (9 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 10/23] target-m68k: allow to update flags with operation on words and bytes Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 12/23] target-m68k: remove m68k_cpu_exec_enter() and m68k_cpu_exec_exit() Laurent Vivier
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, 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 4fe36b8..dc55a7a 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -464,11 +464,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 e2f176e..650c141 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1032,10 +1032,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;
     }
@@ -1248,7 +1248,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;
@@ -1257,7 +1257,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 */
@@ -1387,7 +1387,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;
 }
 
@@ -1633,12 +1633,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.7.4

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

* [Qemu-devel] [PATCH 12/23] target-m68k: remove m68k_cpu_exec_enter() and m68k_cpu_exec_exit()
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (10 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 11/23] target-m68k: Replace helper_xflag_lt with setcond Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 13/23] target-m68k: update move to/from ccr/sr Laurent Vivier
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, Laurent Vivier

Update cc_op directly from tcg_gen_insn_start() and
restore_state_to_opc()

Copied from target-i386

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

diff --git a/cpu-exec.c b/cpu-exec.c
index e114fcd..e1bc368 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -151,12 +151,6 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
         && qemu_log_in_addr_range(itb->pc)) {
 #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.c b/target-m68k/cpu.c
index f925e26..ef02d9f 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -281,8 +281,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 18b6930..f055ef6 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -61,6 +61,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];
@@ -149,9 +150,6 @@ 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);
-
 void m68k_tcg_init(void);
 void m68k_cpu_init_gdb(M68kCPU *cpu);
 M68kCPU *cpu_m68k_init(const char *cpu_model);
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index dc55a7a..92d1ded 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -922,23 +922,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 650c141..681f3a8 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3025,7 +3025,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))) {
@@ -3119,5 +3119,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.7.4

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

* [Qemu-devel] [PATCH 13/23] target-m68k: update move to/from ccr/sr
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (11 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 12/23] target-m68k: remove m68k_cpu_exec_enter() and m68k_cpu_exec_exit() Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 14/23] target-m68k: don't update cc_dest in helpers Laurent Vivier
                   ` (10 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 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 681f3a8..37faefe 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1368,12 +1368,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)
@@ -1400,37 +1398,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)
@@ -1957,16 +1949,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)
@@ -1975,7 +1965,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);
 }
 
@@ -2872,6 +2862,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.7.4

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

* [Qemu-devel] [PATCH 14/23] target-m68k: don't update cc_dest in helpers
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (12 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 13/23] target-m68k: update move to/from ccr/sr Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 15/23] target-m68k: update CPU flags management Laurent Vivier
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, Laurent Vivier

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 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 f055ef6..72a939e 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -158,7 +158,6 @@ M68kCPU *cpu_m68k_init(const char *cpu_model);
    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);
 
 
 /* Instead of computing the condition codes after each m68k instruction,
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 92d1ded..0a1ff11 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -132,9 +132,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;
@@ -202,7 +201,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;
@@ -268,10 +267,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)
@@ -422,20 +420,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;
@@ -445,20 +444,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;
@@ -790,9 +790,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 37faefe..3db7918 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -424,7 +424,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;
 }
 
@@ -719,6 +719,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);
@@ -1673,7 +1674,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.7.4

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

* [Qemu-devel] [PATCH 15/23] target-m68k: update CPU flags management
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (13 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 14/23] target-m68k: don't update cc_dest in helpers Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 16/23] target-m68k: Print flags properly Laurent Vivier
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, Laurent Vivier

Copied from target-i386

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 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 72a939e..f0f670c 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -167,7 +167,7 @@ int cpu_m68k_signal_handler(int host_signum, void *pinfo,
  * using this information. Condition codes are not generated if they
  * are only needed for conditional branches.
  */
-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 */
@@ -188,7 +188,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 3db7918..edd8744 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -133,7 +133,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;
@@ -175,6 +175,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)
@@ -411,31 +458,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(); \
     } \
@@ -719,7 +763,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);
@@ -836,7 +880,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;
 }
@@ -844,7 +888,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;
 }
@@ -852,14 +896,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));
 }
@@ -977,7 +1021,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)
@@ -1009,7 +1053,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)
@@ -1034,11 +1078,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) {
@@ -1225,7 +1269,6 @@ DISAS_INSN(bitop_im)
         DEST_EA(env, insn, opsize, tmp, &addr);
     }
 }
-
 DISAS_INSN(arith_im)
 {
     int op;
@@ -1252,14 +1295,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);
@@ -1269,7 +1312,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();
@@ -1384,10 +1427,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)
@@ -1397,6 +1439,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)
@@ -1628,11 +1671,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);
     }
@@ -1678,11 +1721,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);
     }
 }
@@ -1858,7 +1904,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.  */
@@ -1883,7 +1928,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)
@@ -1904,7 +1949,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)
@@ -2716,7 +2761,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)
@@ -3047,20 +3092,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.7.4

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

* [Qemu-devel] [PATCH 16/23] target-m68k: Print flags properly
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (14 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 15/23] target-m68k: update CPU flags management Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 17/23] target-m68k: Some fixes to SR and flags management Laurent Vivier
                   ` (7 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, 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 | 14 +++++++-------
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index f0f670c..2f08a2c 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -158,6 +158,7 @@ M68kCPU *cpu_m68k_init(const char *cpu_model);
    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);
 
 
 /* Instead of computing the condition codes after each m68k instruction,
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 0a1ff11..d9ea830 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -132,7 +132,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 edd8744..cecd12c 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3140,15 +3140,15 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
     for (i = 0; i < 8; i++)
       {
         u.d = env->fregs[i];
-        cpu_fprintf (f, "D%d = %08x   A%d = %08x   F%d = %08x%08x (%12g)\n",
-                     i, env->dregs[i], i, env->aregs[i],
-                     i, u.l.upper, u.l.lower, *(double *)&u.d);
+        cpu_fprintf(f, "D%d = %08x   A%d = %08x   F%d = %08x%08x (%12g)\n",
+                    i, env->dregs[i], i, env->aregs[i],
+                    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 & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
-                 (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
+    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.7.4

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

* [Qemu-devel] [PATCH 17/23] target-m68k: Some fixes to SR and flags management
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (15 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 16/23] target-m68k: Print flags properly Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 18/23] target-m68k: Remove incorrect clearing of cc_x Laurent Vivier
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, 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 2f08a2c..c0de978 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -158,7 +158,8 @@ M68kCPU *cpu_m68k_init(const char *cpu_model);
    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);
 
 
 /* Instead of computing the condition codes after each m68k instruction,
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index d9ea830..1a54e66 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -132,7 +132,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;
@@ -272,6 +272,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);
@@ -466,7 +478,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 e41ae46..af36177 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -63,9 +63,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)
@@ -112,6 +112,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 cecd12c..73f9e9f 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3145,7 +3145,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.7.4

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

* [Qemu-devel] [PATCH 18/23] target-m68k: Remove incorrect clearing of cc_x
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (16 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 17/23] target-m68k: Some fixes to SR and flags management Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 19/23] target-m68k: Reorg flags handling Laurent Vivier
                   ` (5 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, 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 1a54e66..a9974b1 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -207,19 +207,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.7.4

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

* [Qemu-devel] [PATCH 19/23] target-m68k: Reorg flags handling
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (17 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 18/23] target-m68k: Remove incorrect clearing of cc_x Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 20/23] target-m68k: Introduce DisasCompare Laurent Vivier
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, 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.
Factorize flags computing and src/ccr cleanup

Signed-off-by: Laurent Vivier <laurent@vivier.eu>

target-m68k: sr/ccr cleanup

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

diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index ef02d9f..ba17480 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -58,7 +58,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 c0de978..48c5b81 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -75,9 +75,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;
@@ -170,27 +172,23 @@ void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t);
  * are only needed for conditional branches.
  */
 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 a9974b1..094a7e5 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -132,151 +132,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);
@@ -413,59 +268,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;
+        new_x = (res < 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;
 }
 
@@ -478,73 +326,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;
 }
 
@@ -796,9 +624,92 @@ void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
     }
 }
 
-uint32_t HELPER(flush_flags)(CPUM68KState *env, uint32_t op)
+
+#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)
 {
-    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;
+
+    COMPUTE_CCR(env->cc_op, x, n, z, v, c);
+
+    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;
+
+    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;
 }
 
 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 af36177..48e02e4 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -185,7 +185,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;
@@ -195,16 +194,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)
@@ -213,7 +210,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;
@@ -222,14 +218,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 73f9e9f..85d5c95 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -134,6 +134,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;
@@ -175,49 +176,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);
     }
 }
@@ -460,41 +456,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;
+    }
+
+    /* Note that flush_flags also assigned to env->cc_op.  */
+    s->cc_op = CC_OP_FLAGS;
+    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();
     }
-    set_cc_op(s, CC_OP_FLAGS);
 }
 
-#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)
+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)
@@ -550,36 +584,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,
@@ -758,7 +762,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.  */
@@ -767,97 +772,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)
@@ -1021,6 +986,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);
 }
 
@@ -1116,42 +1082,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)
@@ -1159,7 +1126,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);
 }
 
@@ -1231,28 +1198,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);
@@ -1267,8 +1226,10 @@ DISAS_INSN(bitop_im)
             break;
         }
         DEST_EA(env, insn, opsize, tmp, &addr);
+        tcg_temp_free(tmp);
     }
 }
+
 DISAS_INSN(arith_im)
 {
     int op;
@@ -1292,7 +1253,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);
@@ -1301,7 +1262,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 */
@@ -1309,10 +1270,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();
@@ -1404,9 +1363,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;
 }
 
@@ -1428,45 +1387,47 @@ 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)
+static void gen_set_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
+                       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) {
-        gen_helper_set_sr(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 {
+        disas_undef(env, s, insn);
     }
 }
 
-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);
-}
-
 
 DISAS_INSN(move_to_ccr)
 {
-    gen_move_to_sr(env, s, insn, 1);
+    gen_set_sr(env, s, insn, 1);
 }
 
 DISAS_INSN(not)
@@ -1670,10 +1631,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);
         }
@@ -1717,18 +1678,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);
     }
 }
@@ -1817,16 +1776,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)
@@ -1834,7 +1790,6 @@ DISAS_INSN(cmpa)
     int opsize;
     TCGv src;
     TCGv reg;
-    TCGv dest;
 
     if (insn & 0x100) {
         opsize = OS_LONG;
@@ -1843,10 +1798,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)
@@ -1913,6 +1866,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)
@@ -1928,7 +1883,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)
@@ -1938,8 +1892,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 {
@@ -1949,7 +1901,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)
@@ -2010,7 +1962,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);
 }
 
@@ -2759,8 +2711,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);
+    TCGv tmp = tcg_temp_new();
+    tcg_gen_andi_i32(tmp, QREG_MACSR, 0xf);
+    gen_helper_set_sr(cpu_env, tmp);
+    tcg_temp_free(tmp);
     set_cc_op(s, CC_OP_FLAGS);
 }
 
@@ -3044,6 +2998,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.7.4

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

* [Qemu-devel] [PATCH 20/23] target-m68k: Introduce DisasCompare
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (18 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 19/23] target-m68k: Reorg flags handling Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 21/23] target-m68k: Use setcond for scc Laurent Vivier
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, 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 85d5c95..4a650e1 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -759,8 +759,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;
@@ -768,61 +775,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)
@@ -1678,7 +1716,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.7.4

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

* [Qemu-devel] [PATCH 21/23] target-m68k: Use setcond for scc
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (19 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 20/23] target-m68k: Introduce DisasCompare Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 22/23] target-m68k: Optimize some comparisons Laurent Vivier
                   ` (2 subsequent siblings)
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, 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 4a650e1..5cc5e14 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -865,19 +865,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.7.4

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

* [Qemu-devel] [PATCH 22/23] target-m68k: Optimize some comparisons
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (20 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 21/23] target-m68k: Use setcond for scc Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 17:41   ` Richard Henderson
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 23/23] target-m68k: Optimize gen_flush_flags Laurent Vivier
  2016-10-25 17:45 ` [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Richard Henderson
  23 siblings, 1 reply; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, 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 5cc5e14..b5e2995 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -771,10 +771,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;
@@ -785,7 +818,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();
@@ -833,10 +930,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.7.4

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

* [Qemu-devel] [PATCH 23/23] target-m68k: Optimize gen_flush_flags
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (21 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 22/23] target-m68k: Optimize some comparisons Laurent Vivier
@ 2016-10-25 14:50 ` Laurent Vivier
  2016-10-25 17:45 ` [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Richard Henderson
  23 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 14:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: schwab, agraf, Richard Henderson, gerg, 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 b5e2995..7ab544d 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -458,18 +458,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.7.4

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

* Re: [Qemu-devel] [PATCH 22/23] target-m68k: Optimize some comparisons
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 22/23] target-m68k: Optimize some comparisons Laurent Vivier
@ 2016-10-25 17:41   ` Richard Henderson
  0 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-10-25 17:41 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, agraf, gerg

On 10/25/2016 07:50 AM, Laurent Vivier wrote:
> +    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;
> +        }

This should be

    c->v1 = c->v2;
    goto done;

as with the F case above.  Probably my error...


r~

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

* Re: [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set
  2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
                   ` (22 preceding siblings ...)
  2016-10-25 14:50 ` [Qemu-devel] [PATCH 23/23] target-m68k: Optimize gen_flush_flags Laurent Vivier
@ 2016-10-25 17:45 ` Richard Henderson
  2016-10-25 17:53   ` Laurent Vivier
  23 siblings, 1 reply; 27+ messages in thread
From: Richard Henderson @ 2016-10-25 17:45 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: schwab, agraf, gerg, Peter Maydell

On 10/25/2016 07:49 AM, Laurent Vivier wrote:
> As I'm not able to manage too large series,
> this series is a subset of the series I sent in May:
> https://lists.gnu.org/archive/html/qemu-devel/2016-05/msg00501.html

We're fond of smaller series too.  ;-)

> 
> It doesn't introduce any new instructions but:
> - introduce the new processors feature flags
> - introduce new flags management as proposed by Richard
> 
> I've checked it doesn't break coldfire support:
> http://wiki.qemu.org/download/coldfire-test-0.1.tar.bz2
> but it can't boot a 680x0 processor kernel.
> 
> I've fixed some style issues reported by checkpatch.pl and merged
> some of the patches cleaning up flags (as suggested by Richard).

It looks as if I've reviewed everything in here already.  I'm perfectly happy
for this to be merged now.

Do you have a gpg key with signatures valid for Peter to do a signed pull?
Otherwise, Peter, are you happy to merge this by hand or should I create a
branch from which you can pull?


r~

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

* Re: [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set
  2016-10-25 17:45 ` [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Richard Henderson
@ 2016-10-25 17:53   ` Laurent Vivier
  0 siblings, 0 replies; 27+ messages in thread
From: Laurent Vivier @ 2016-10-25 17:53 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: schwab, agraf, gerg, Peter Maydell



Le 25/10/2016 à 19:45, Richard Henderson a écrit :
> On 10/25/2016 07:49 AM, Laurent Vivier wrote:
>> As I'm not able to manage too large series,
>> this series is a subset of the series I sent in May:
>> https://lists.gnu.org/archive/html/qemu-devel/2016-05/msg00501.html
> 
> We're fond of smaller series too.  ;-)
> 
>>
>> It doesn't introduce any new instructions but:
>> - introduce the new processors feature flags
>> - introduce new flags management as proposed by Richard
>>
>> I've checked it doesn't break coldfire support:
>> http://wiki.qemu.org/download/coldfire-test-0.1.tar.bz2
>> but it can't boot a 680x0 processor kernel.
>>
>> I've fixed some style issues reported by checkpatch.pl and merged
>> some of the patches cleaning up flags (as suggested by Richard).
> 
> It looks as if I've reviewed everything in here already.  I'm perfectly happy
> for this to be merged now.
> Do you have a gpg key with signatures valid for Peter to do a signed pull?
> Otherwise, Peter, are you happy to merge this by hand or should I create a
> branch from which you can pull?

I have a key with signatures and I can send signed pull request.

Thanks,
Laurent

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

end of thread, other threads:[~2016-10-25 17:54 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-25 14:49 [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Laurent Vivier
2016-10-25 14:49 ` [Qemu-devel] [PATCH 01/23] target-m68k: fix DEBUG_DISPATCH Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 02/23] target-m68k: Build the opcode table only once to avoid multithreading issues Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 03/23] target-m68k: define m680x0 CPUs and features Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 04/23] target-m68k: manage scaled index Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 05/23] target-m68k: introduce read_imXX() functions Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 06/23] target-m68k: set disassembler mode to 680x0 or coldfire Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 07/23] target-m68k: define operand sizes Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 08/23] target-m68k: set PAGE_BITS to 12 for m68k Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 09/23] target-m68k: REG() macro cleanup Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 10/23] target-m68k: allow to update flags with operation on words and bytes Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 11/23] target-m68k: Replace helper_xflag_lt with setcond Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 12/23] target-m68k: remove m68k_cpu_exec_enter() and m68k_cpu_exec_exit() Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 13/23] target-m68k: update move to/from ccr/sr Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 14/23] target-m68k: don't update cc_dest in helpers Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 15/23] target-m68k: update CPU flags management Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 16/23] target-m68k: Print flags properly Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 17/23] target-m68k: Some fixes to SR and flags management Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 18/23] target-m68k: Remove incorrect clearing of cc_x Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 19/23] target-m68k: Reorg flags handling Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 20/23] target-m68k: Introduce DisasCompare Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 21/23] target-m68k: Use setcond for scc Laurent Vivier
2016-10-25 14:50 ` [Qemu-devel] [PATCH 22/23] target-m68k: Optimize some comparisons Laurent Vivier
2016-10-25 17:41   ` Richard Henderson
2016-10-25 14:50 ` [Qemu-devel] [PATCH 23/23] target-m68k: Optimize gen_flush_flags Laurent Vivier
2016-10-25 17:45 ` [Qemu-devel] [PATCH 00/23] target-m68k: prepare to introduce 680x0 instruction set Richard Henderson
2016-10-25 17:53   ` Laurent Vivier

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.