All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation
@ 2015-08-09 20:13 Laurent Vivier
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 01/30] m68k: define m680x0 CPUs and features Laurent Vivier
                   ` (30 more replies)
  0 siblings, 31 replies; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

Current QEMU m68k emulation only supports ColdFire processors.

This series adds compatibility with 680x0 processors.

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

Once this series included in the QEMU mainline I will send a new series
with FPU instructions. With it, we can start a debian etch-m68k
container (init and all the bazaar).

Laurent Vivier (30):
  m68k: define m680x0 CPUs and features
  m68k: manage scaled index
  m68k: introduce read_imXX() functions
  m68k: set disassembler mode to 680x0 or coldfire
  m68k: define operand sizes
  m68k: REG() macro cleanup
  m68k: allow to update flags with operation on words and bytes
  m68k: update CPU flags management
  m68k: add X flag helpers
  m68k: tst bugfix
  m68k: improve clr/moveq
  m68k: Manage divw overflow
  m68k: set Z and N on divu/muls overflow as a real 68040
  m68k: allow adda/suba to add/sub word
  m68k: add more modes to movem
  m68k: Add all access modes and data sizes to some 680x0 instructions
  m68k: ori/andi/subi/addi/eori/cmpi can modify SR/CCR
  m68k: addq/subq can work with all the data sizes.
  m68k: add cmpm
  m68k: add exg
  m68k: add bkpt
  m68k: add cas instruction
  m68k: add linkl
  m68k: add DBcc and Scc (memory operand)
  m68k: add abcd, sbcd, nbcd instructions
  m68k: add mull/divl
  m68k: add addx/subx/negx
  m68k: shift/rotate bytes and words
  m68k: add rol/rox/ror/roxr
  m68k: add bitfield instructions

 cpu-exec.c              |    6 -
 disas.c                 |    4 +
 target-m68k/cpu.c       |   56 +-
 target-m68k/cpu.h       |   33 +-
 target-m68k/helper.c    |  817 +++++++++++++----
 target-m68k/helper.h    |   56 +-
 target-m68k/op_helper.c |  179 +++-
 target-m68k/qregs.def   |    1 +
 target-m68k/translate.c | 2259 ++++++++++++++++++++++++++++++++++++++---------
 9 files changed, 2781 insertions(+), 630 deletions(-)

-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 01/30] m68k: define m680x0 CPUs and features
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-11 23:13   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 02/30] m68k: manage scaled index Laurent Vivier
                   ` (29 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

This patch defines five new Motorola 680x0 family CPUs:

    - M68K_CPUID_M68000,
    - M68K_CPUID_M68020,
    - M68K_CPUID_M68030,
    - M68K_CPUID_M68040,
    - M68K_CPUID_M68060

And seven new features:

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

Original patche from Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.c       | 54 ++++++++++++++++++++++++++++++++++++++
 target-m68k/cpu.h       | 10 ++++++-
 target-m68k/translate.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 133 insertions(+), 1 deletion(-)

diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 4f246da..f3f4b71 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -90,6 +90,55 @@ static void m5206_cpu_initfn(Object *obj)
     m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
 }
 
+static void m68000_cpu_initfn(Object *obj)
+{
+    M68kCPU *cpu = M68K_CPU(obj);
+    CPUM68KState *env = &cpu->env;
+
+    m68k_set_feature(env, M68K_FEATURE_M68000);
+    m68k_set_feature(env, M68K_FEATURE_USP);
+    m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+}
+
+static void m68020_cpu_initfn(Object *obj)
+{
+    M68kCPU *cpu = M68K_CPU(obj);
+    CPUM68KState *env = &cpu->env;
+
+    m68k_set_feature(env, M68K_FEATURE_M68000);
+    m68k_set_feature(env, M68K_FEATURE_USP);
+    m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+    m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV);
+    m68k_set_feature(env, M68K_FEATURE_BRAL);
+    m68k_set_feature(env, M68K_FEATURE_BCCL);
+    m68k_set_feature(env, M68K_FEATURE_BITFIELD);
+    m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
+    m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
+    m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV);
+    m68k_set_feature(env, M68K_FEATURE_FPU);
+    m68k_set_feature(env, M68K_FEATURE_CAS);
+}
+#define m68030_cpu_initfn m68020_cpu_initfn
+#define m68040_cpu_initfn m68020_cpu_initfn
+
+static void m68060_cpu_initfn(Object *obj)
+{
+    M68kCPU *cpu = M68K_CPU(obj);
+    CPUM68KState *env = &cpu->env;
+
+    m68k_set_feature(env, M68K_FEATURE_M68000);
+    m68k_set_feature(env, M68K_FEATURE_USP);
+    m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+    m68k_set_feature(env, M68K_FEATURE_BRAL);
+    m68k_set_feature(env, M68K_FEATURE_BCCL);
+    m68k_set_feature(env, M68K_FEATURE_BITFIELD);
+    m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
+    m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
+    m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV);
+    m68k_set_feature(env, M68K_FEATURE_FPU);
+    m68k_set_feature(env, M68K_FEATURE_CAS);
+}
+
 static void m5208_cpu_initfn(Object *obj)
 {
     M68kCPU *cpu = M68K_CPU(obj);
@@ -140,6 +189,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 9a62f6c..bcfd864 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -179,6 +179,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).  */
@@ -189,7 +190,14 @@ enum m68k_features {
     M68K_FEATURE_CF_EMAC_B, /* Revision B EMAC (dual accumulate).  */
     M68K_FEATURE_USP, /* User Stack Pointer.  (ISA A+, B or C).  */
     M68K_FEATURE_EXT_FULL, /* 68020+ full extension word.  */
-    M68K_FEATURE_WORD_INDEX /* word sized address index registers.  */
+    M68K_FEATURE_WORD_INDEX, /* word sized address index registers.  */
+    M68K_FEATURE_SCALED_INDEX, /* scaled address index registers.  */
+    M68K_FEATURE_LONG_MULDIV, /* 32 bit multiply/divide. */
+    M68K_FEATURE_QUAD_MULDIV, /* 64 bit multiply/divide. */
+    M68K_FEATURE_BCCL,        /* Long conditional branches.  */
+    M68K_FEATURE_BITFIELD,    /* Bit field insns.  */
+    M68K_FEATURE_FPU,
+    M68K_FEATURE_CAS
 };
 
 static inline int m68k_feature(CPUM68KState *env, int feature)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index a57d241..ca8d10c 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2832,85 +2832,148 @@ void register_m68k_insns (CPUM68KState *env)
         register_opcode(disas_##name, 0x##opcode, 0x##mask); \
     } while(0)
     INSN(undef,     0000, 0000, CF_ISA_A);
+    INSN(undef,     0000, 0000, M68000);
     INSN(arith_im,  0080, fff8, CF_ISA_A);
+    INSN(arith_im,  0000, ff00, M68000);
+    INSN(undef,     00c0, ffc0, M68000);
     INSN(bitrev,    00c0, fff8, CF_ISA_APLUSC);
     INSN(bitop_reg, 0100, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 0100, f1c0, M68000);
     INSN(bitop_reg, 0140, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 0140, f1c0, M68000);
     INSN(bitop_reg, 0180, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 0180, f1c0, M68000);
     INSN(bitop_reg, 01c0, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 01c0, f1c0, M68000);
     INSN(arith_im,  0280, fff8, CF_ISA_A);
+    INSN(arith_im,  0200, ff00, M68000);
+    INSN(undef,     02c0, ffc0, M68000);
     INSN(byterev,   02c0, fff8, CF_ISA_APLUSC);
     INSN(arith_im,  0480, fff8, CF_ISA_A);
+    INSN(arith_im,  0400, ff00, M68000);
+    INSN(undef,     04c0, ffc0, M68000);
+    INSN(arith_im,  0600, ff00, M68000);
+    INSN(undef,     06c0, ffc0, M68000);
     INSN(ff1,       04c0, fff8, CF_ISA_APLUSC);
     INSN(arith_im,  0680, fff8, CF_ISA_A);
     INSN(bitop_im,  0800, ffc0, CF_ISA_A);
+    INSN(bitop_im,  0800, ffc0, M68000);
     INSN(bitop_im,  0840, ffc0, CF_ISA_A);
+    INSN(bitop_im,  0840, ffc0, M68000);
     INSN(bitop_im,  0880, ffc0, CF_ISA_A);
+    INSN(bitop_im,  0880, ffc0, M68000);
     INSN(bitop_im,  08c0, ffc0, CF_ISA_A);
+    INSN(bitop_im,  08c0, ffc0, M68000);
     INSN(arith_im,  0a80, fff8, CF_ISA_A);
+    INSN(arith_im,  0a00, ff00, M68000);
+    INSN(undef,     0ac0, ffc0, M68000);
     INSN(arith_im,  0c00, ff38, CF_ISA_A);
+    INSN(arith_im,  0c00, ff00, M68000);
+    INSN(undef,     0cc0, ffc0, M68000);
     INSN(move,      1000, f000, CF_ISA_A);
+    INSN(move,      1000, f000, M68000);
     INSN(move,      2000, f000, CF_ISA_A);
+    INSN(move,      2000, f000, M68000);
     INSN(move,      3000, f000, CF_ISA_A);
+    INSN(move,      3000, f000, M68000);
     INSN(strldsr,   40e7, ffff, CF_ISA_APLUSC);
     INSN(negx,      4080, fff8, CF_ISA_A);
     INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
+    INSN(move_from_sr, 40c0, ffc0, M68000);
     INSN(lea,       41c0, f1c0, CF_ISA_A);
+    INSN(lea,       41c0, f1c0, M68000);
     INSN(clr,       4200, ff00, CF_ISA_A);
+    INSN(clr,       4200, ff00, M68000);
     INSN(undef,     42c0, ffc0, CF_ISA_A);
+    INSN(undef,     42c0, ffc0, M68000);
     INSN(move_from_ccr, 42c0, fff8, CF_ISA_A);
     INSN(neg,       4480, fff8, CF_ISA_A);
+    INSN(neg,       4400, ff00, M68000);
+    INSN(undef,     44c0, ffc0, M68000);
     INSN(move_to_ccr, 44c0, ffc0, CF_ISA_A);
+    INSN(move_to_ccr, 44c0, ffc0, M68000);
     INSN(not,       4680, fff8, CF_ISA_A);
+    INSN(not,       4600, ff00, M68000);
+    INSN(undef,     46c0, ffc0, M68000);
     INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
     INSN(pea,       4840, ffc0, CF_ISA_A);
+    INSN(pea,       4840, ffc0, M68000);
     INSN(swap,      4840, fff8, CF_ISA_A);
+    INSN(swap,      4840, fff8, M68000);
     INSN(movem,     48c0, fbc0, CF_ISA_A);
+    INSN(movem,     48c0, fbc0, M68000);
     INSN(ext,       4880, fff8, CF_ISA_A);
+    INSN(ext,       4880, fff8, M68000);
     INSN(ext,       48c0, fff8, CF_ISA_A);
+    INSN(ext,       48c0, fff8, M68000);
     INSN(ext,       49c0, fff8, CF_ISA_A);
+    INSN(ext,       49c0, fff8, M68000);
     INSN(tst,       4a00, ff00, CF_ISA_A);
+    INSN(tst,       4a00, ff00, M68000);
     INSN(tas,       4ac0, ffc0, CF_ISA_B);
+    INSN(tas,       4ac0, ffc0, M68000);
     INSN(halt,      4ac8, ffff, CF_ISA_A);
     INSN(pulse,     4acc, ffff, CF_ISA_A);
     INSN(illegal,   4afc, ffff, CF_ISA_A);
+    INSN(illegal,   4afc, ffff, M68000);
     INSN(mull,      4c00, ffc0, CF_ISA_A);
+    INSN(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(trap,      4e40, fff0, M68000);
     INSN(link,      4e50, fff8, CF_ISA_A);
+    INSN(link,      4e50, fff8, M68000);
     INSN(unlk,      4e58, fff8, CF_ISA_A);
+    INSN(unlk,      4e58, fff8, M68000);
     INSN(move_to_usp, 4e60, fff8, USP);
     INSN(move_from_usp, 4e68, fff8, USP);
     INSN(nop,       4e71, ffff, CF_ISA_A);
+    INSN(nop,       4e71, ffff, M68000);
     INSN(stop,      4e72, ffff, CF_ISA_A);
+    INSN(stop,      4e72, ffff, M68000);
     INSN(rte,       4e73, ffff, CF_ISA_A);
+    INSN(rte,       4e73, ffff, M68000);
     INSN(rts,       4e75, ffff, CF_ISA_A);
+    INSN(rts,       4e75, ffff, M68000);
     INSN(movec,     4e7b, ffff, CF_ISA_A);
     INSN(jump,      4e80, ffc0, CF_ISA_A);
+    INSN(jump,      4e80, ffc0, M68000);
     INSN(jump,      4ec0, ffc0, CF_ISA_A);
     INSN(addsubq,   5180, f1c0, CF_ISA_A);
+    INSN(jump,      4ec0, ffc0, M68000);
+    INSN(addsubq,   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);
+    INSN(branch,    6000, f000, M68000);
     /* Disable long branch instructions, then add back the ones we want.  */
     INSN(undef,     60ff, f0ff, CF_ISA_A); /* All long branches.  */
+    INSN(undef,     60ff, f0ff, M68000);
     INSN(branch,    60ff, f0ff, CF_ISA_B);
     INSN(undef,     60ff, ffff, CF_ISA_B); /* bra.l */
     INSN(branch,    60ff, ffff, BRAL);
+    INSN(branch,    60ff, f0ff, BCCL);
 
     INSN(moveq,     7000, f100, CF_ISA_A);
+    INSN(moveq,     7000, f100, M68000);
     INSN(mvzs,      7100, f100, CF_ISA_B);
     INSN(or,        8000, f000, CF_ISA_A);
+    INSN(or,        8000, f000, M68000);
     INSN(divw,      80c0, f0c0, CF_ISA_A);
+    INSN(divw,      80c0, f0c0, M68000);
     INSN(addsub,    9000, f000, CF_ISA_A);
+    INSN(addsub,    9000, f000, M68000);
     INSN(subx,      9180, f1f8, CF_ISA_A);
     INSN(suba,      91c0, f1c0, CF_ISA_A);
 
     INSN(undef_mac, a000, f000, CF_ISA_A);
+    INSN(undef_mac, a000, f000, M68000);
     INSN(mac,       a000, f100, CF_EMAC);
     INSN(from_mac,  a180, f9b0, CF_EMAC);
     INSN(move_mac,  a110, f9fc, CF_EMAC);
@@ -2929,12 +2992,19 @@ 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(and,       c000, f000, M68000);
     INSN(mulw,      c0c0, f0c0, CF_ISA_A);
+    INSN(mulw,      c0c0, f0c0, M68000);
     INSN(addsub,    d000, f000, CF_ISA_A);
+    INSN(addsub,    d000, f000, M68000);
     INSN(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.4.3

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

* [Qemu-devel] [PATCH for-2.5 02/30] m68k: manage scaled index
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 01/30] m68k: define m680x0 CPUs and features Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12  3:42   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 03/30] m68k: introduce read_imXX() functions Laurent Vivier
                   ` (28 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

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

Ignore it:

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

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

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index ca8d10c..f190f19 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -307,6 +307,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.4.3

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

* [Qemu-devel] [PATCH for-2.5 03/30] m68k: introduce read_imXX() functions
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 01/30] m68k: define m680x0 CPUs and features Laurent Vivier
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 02/30] m68k: manage scaled index Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-09 21:12   ` Andreas Schwab
  2015-08-12  3:54   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 04/30] m68k: set disassembler mode to 680x0 or coldfire Laurent Vivier
                   ` (27 subsequent siblings)
  30 siblings, 2 replies; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

Read a 8, 16 or 32bit immediat constant.

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

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index f190f19..3b87b0c 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -260,16 +260,30 @@ static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
     }
 }
 
-/* Read a 32-bit immediate constant.  */
-static inline uint32_t read_im32(CPUM68KState *env, DisasContext *s)
+/* Read an 8-bit immediate constant */
+static inline uint32_t read_im8(CPUM68KState *env, DisasContext *s)
 {
     uint32_t im;
-    im = ((uint32_t)cpu_lduw_code(env, s->pc)) << 16;
+    im = cpu_ldsb_code(env, s->pc + 1);
     s->pc += 2;
-    im |= cpu_lduw_code(env, s->pc);
+    return im;
+}
+/* Read a 16-bit immediate constant */
+static inline uint32_t read_im16(CPUM68KState *env, DisasContext *s)
+{
+    uint32_t im;
+    im = cpu_ldsw_code(env, s->pc);
     s->pc += 2;
     return im;
 }
+/* Read a 32-bit immediate constant.  */
+static inline uint32_t read_im32(CPUM68KState *env, DisasContext *s)
+{
+    uint32_t im;
+    im = read_im16(env, s) << 16;
+    im |= 0xffff & read_im16(env, s);
+    return im;
+}
 
 /* Calculate and address index.  */
 static TCGv gen_addr_index(uint16_t ext, TCGv tmp)
@@ -301,8 +315,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;
@@ -320,8 +333,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);
             }
@@ -369,8 +381,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);
                 }
@@ -522,8 +533,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.  */
@@ -947,8 +957,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;
@@ -1099,8 +1108,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);
@@ -1143,8 +1151,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;
@@ -1397,8 +1404,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
@@ -1521,8 +1527,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;
@@ -1948,14 +1953,12 @@ DISAS_INSN(strldsr)
     uint32_t addr;
 
     addr = s->pc - 2;
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
     if (ext != 0x46FC) {
         gen_exception(s, addr, EXCP_UNSUPPORTED);
         return;
     }
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
     if (IS_USER(s) || (ext & SR_S) == 0) {
         gen_exception(s, addr, EXCP_PRIVILEGE);
         return;
@@ -2022,8 +2025,7 @@ DISAS_INSN(stop)
         return;
     }
 
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
 
     gen_set_sr_im(s, ext, 0);
     tcg_gen_movi_i32(cpu_halted, 1);
@@ -2049,8 +2051,7 @@ DISAS_INSN(movec)
         return;
     }
 
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
 
     if (ext & 0x8000) {
         reg = AREG(ext, 12);
@@ -2116,8 +2117,7 @@ DISAS_INSN(fpu)
     int set_dest;
     int opsize;
 
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
     opmode = ext & 0x7f;
     switch ((ext >> 13) & 7) {
     case 0: case 2:
@@ -2399,8 +2399,7 @@ DISAS_INSN(fbcc)
     offset = cpu_ldsw_code(env, s->pc);
     s->pc += 2;
     if (insn & (1 << 6)) {
-        offset = (offset << 16) | cpu_lduw_code(env, s->pc);
-        s->pc += 2;
+        offset = (offset << 16) | read_im16(env, s);
     }
 
     l1 = gen_new_label();
@@ -2525,8 +2524,7 @@ DISAS_INSN(mac)
         s->done_mac = 1;
     }
 
-    ext = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    ext = read_im16(env, s);
 
     acc = ((insn >> 7) & 1) | ((ext >> 3) & 2);
     dual = ((insn & 0x30) != 0 && (ext & 3) != 0);
@@ -3034,8 +3032,7 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
         tcg_gen_debug_insn_start(s->pc);
     }
 
-    insn = cpu_lduw_code(env, s->pc);
-    s->pc += 2;
+    insn = read_im16(env, s);
 
     opcode_table[insn](env, s, insn);
 }
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 04/30] m68k: set disassembler mode to 680x0 or coldfire
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (2 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 03/30] m68k: introduce read_imXX() functions Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12  3:57   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 05/30] m68k: define operand sizes Laurent Vivier
                   ` (26 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

diff --git a/disas.c b/disas.c
index 69a6066..2512001 100644
--- a/disas.c
+++ b/disas.c
@@ -185,6 +185,7 @@ static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
     i386 - 1 means 16 bit code, 2 means 64 bit code
     ppc  - bits 0:15 specify (optionally) the machine instruction set;
            bit 16 indicates little endian.
+    m68k - 1 means 680x0 family, otherwise coldfire
     other targets - unused
  */
 void target_disas(FILE *out, CPUState *cpu, target_ulong code,
@@ -245,6 +246,9 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code,
     s.info.print_insn = print_insn_ppc;
 #elif defined(TARGET_M68K)
     s.info.print_insn = print_insn_m68k;
+    if (flags) {
+        s.info.mach = bfd_mach_m68040;
+    }
 #elif defined(TARGET_MIPS)
 #ifdef TARGET_WORDS_BIGENDIAN
     s.info.print_insn = print_insn_big_mips;
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 3b87b0c..6ba71a2 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3139,9 +3139,10 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
 
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        int flags = m68k_feature(env, M68K_FEATURE_M68000);
         qemu_log("----------------\n");
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
+        log_target_disas(cs, pc_start, dc->pc - pc_start, flags);
         qemu_log("\n");
     }
 #endif
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 05/30] m68k: define operand sizes
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (3 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 04/30] m68k: set disassembler mode to 680x0 or coldfire Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12  4:07   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 06/30] m68k: REG() macro cleanup Laurent Vivier
                   ` (25 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 6ba71a2..eb7f503 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -146,11 +146,13 @@ 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
+#define OS_BYTE     1
+#define OS_WORD     2
+#define OS_LONG     3
+#define OS_SINGLE   4
+#define OS_DOUBLE   5
+#define OS_EXTENDED 6
+#define OS_PACKED   7
 
 typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t insn);
 
@@ -446,11 +448,49 @@ 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, int pos)
+{
+    switch ((insn >> pos) & 3) {
+    case 0:
+        return OS_BYTE;
+    case 1:
+        return OS_WORD;
+    case 2:
+        return OS_LONG;
+    default:
+        abort();
+    }
+}
+
+static inline int ext_opsize(int ext, int pos)
+{
+    switch ((ext >> pos) & 7) {
+    case 0:
+        return OS_LONG;
+    case 1:
+        return OS_SINGLE;
+    case 2:
+        return OS_EXTENDED;
+    case 3:
+        return OS_PACKED;
+    case 4:
+        return OS_WORD;
+    case 5:
+        return OS_DOUBLE;
+    case 6:
+        return OS_BYTE;
+    default:
+        abort();
+    }
+}
+
 /* Assign value to a register.  If the width is less than the register width
    only the low part of the register is set.  */
 static void gen_partset_reg(int opsize, TCGv reg, TCGv val)
@@ -1321,19 +1361,7 @@ DISAS_INSN(clr)
 {
     int opsize;
 
-    switch ((insn >> 6) & 3) {
-    case 0: /* clr.b */
-        opsize = OS_BYTE;
-        break;
-    case 1: /* clr.w */
-        opsize = OS_WORD;
-        break;
-    case 2: /* clr.l */
-        opsize = OS_LONG;
-        break;
-    default:
-        abort();
-    }
+    opsize = insn_opsize(insn, 6);
     DEST_EA(env, insn, opsize, tcg_const_i32(0), NULL);
     gen_logic_cc(s, tcg_const_i32(0));
 }
@@ -1477,19 +1505,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, 6);
     SRC_EA(env, tmp, opsize, 1, NULL);
     gen_logic_cc(s, tmp);
 }
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 06/30] m68k: REG() macro cleanup
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (4 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 05/30] m68k: define operand sizes Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12  4:11   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 07/30] m68k: allow to update flags with operation on words and bytes Laurent Vivier
                   ` (24 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index eb7f503..f22155d 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -56,9 +56,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.4.3

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

* [Qemu-devel] [PATCH for-2.5 07/30] m68k: allow to update flags with operation on words and bytes
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (5 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 06/30] m68k: REG() macro cleanup Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12  4:28   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 08/30] m68k: update CPU flags management Laurent Vivier
                   ` (23 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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 bcfd864..d1c182b 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -128,13 +128,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 2a35de3..200e3fc 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -143,22 +143,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;
@@ -168,46 +209,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 f22155d..27cb89c 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -429,10 +429,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)
@@ -957,8 +970,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)
@@ -1127,7 +1139,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)
@@ -1252,11 +1264,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);
@@ -1274,7 +1286,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);
@@ -1331,7 +1343,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);
     }
 }
 
@@ -1364,7 +1376,7 @@ DISAS_INSN(clr)
 
     opsize = insn_opsize(insn, 6);
     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)
@@ -1451,7 +1463,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)
@@ -1466,7 +1478,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)
@@ -1498,7 +1510,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)
@@ -1508,7 +1520,7 @@ DISAS_INSN(tst)
 
     opsize = insn_opsize(insn, 6);
     SRC_EA(env, tmp, opsize, 1, NULL);
-    gen_logic_cc(s, tmp);
+    gen_logic_cc(s, tmp, opsize);
 }
 
 DISAS_INSN(pulse)
@@ -1530,7 +1542,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);
 }
@@ -1555,7 +1567,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)
@@ -1714,7 +1726,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)
@@ -1730,7 +1742,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)
@@ -1751,7 +1763,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)
@@ -1784,40 +1796,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, 6);
+    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)
@@ -1837,7 +1833,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)
@@ -1851,7 +1847,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);
 }
 
@@ -1873,7 +1869,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)
@@ -1948,7 +1944,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.4.3

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

* [Qemu-devel] [PATCH for-2.5 08/30] m68k: update CPU flags management
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (6 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 07/30] m68k: allow to update flags with operation on words and bytes Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12  5:12   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 09/30] m68k: add X flag helpers Laurent Vivier
                   ` (22 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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       |   6 +-
 target-m68k/helper.c    |  34 ++-------
 target-m68k/helper.h    |   2 +-
 target-m68k/translate.c | 195 +++++++++++++++++++++++++++++++-----------------
 6 files changed, 136 insertions(+), 109 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index 75694f3..4138c27 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -184,12 +184,6 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)
     if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
 #if defined(TARGET_I386)
         log_cpu_state(cpu, CPU_DUMP_CCOP);
-#elif defined(TARGET_M68K)
-        /* ??? Should not modify env state for dumping.  */
-        cpu_m68k_flush_flags(env, env->cc_op);
-        env->cc_op = CC_OP_FLAGS;
-        env->sr = (env->sr & 0xffe0) | env->cc_dest | (env->cc_x << 4);
-        log_cpu_state(cpu, 0);
 #else
         log_cpu_state(cpu, 0);
 #endif
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index f3f4b71..d4d8c12 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -260,8 +260,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;
 
     dc->vmsd = &vmstate_m68k_cpu;
     cc->gdb_num_core_regs = 18;
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index d1c182b..6d1a140 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -123,9 +123,8 @@ int cpu_m68k_exec(CPUState *cpu);
    is returned if the signal was handled by the virtual CPU.  */
 int cpu_m68k_signal_handler(int host_signum, void *pinfo,
                            void *puc);
-void cpu_m68k_flush_flags(CPUM68KState *, int);
 
-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 */
@@ -146,7 +145,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/helper.c b/target-m68k/helper.c
index 200e3fc..c6f5cc0 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -135,9 +135,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;
@@ -205,7 +204,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;
@@ -271,10 +270,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)
@@ -798,9 +796,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)
@@ -930,23 +928,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/helper.h b/target-m68k/helper.h
index f4e5fdf..81c8e79 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -46,5 +46,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 27cb89c..80ac63a 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -68,6 +68,8 @@ static TCGv NULL_QREG;
 /* Used to distinguish stores from bad addressing modes.  */
 static TCGv store_dummy;
 
+static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
+
 #include "exec/gen-icount.h"
 
 void m68k_tcg_init(void)
@@ -125,7 +127,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 +177,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)
@@ -412,31 +461,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(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(); \
     } \
@@ -865,7 +911,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;
 }
@@ -873,7 +919,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;
 }
@@ -881,14 +927,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));
 }
@@ -1000,7 +1046,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)
@@ -1032,7 +1078,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)
@@ -1057,11 +1103,11 @@ DISAS_INSN(addsub)
     if (add) {
         tcg_gen_add_i32(dest, tmp, src);
         gen_helper_xflag_lt(QREG_CC_X, dest, src);
-        s->cc_op = CC_OP_ADD;
+        set_cc_op(s, CC_OP_ADD);
     } else {
         gen_helper_xflag_lt(QREG_CC_X, tmp, src);
         tcg_gen_sub_i32(dest, tmp, src);
-        s->cc_op = CC_OP_SUB;
+        set_cc_op(s, CC_OP_SUB);
     }
     gen_update_cc_add(dest, src);
     if (insn & 0x100) {
@@ -1248,7 +1294,6 @@ DISAS_INSN(bitop_im)
         DEST_EA(env, insn, opsize, tmp, &addr);
     }
 }
-
 DISAS_INSN(arith_im)
 {
     int op;
@@ -1275,14 +1320,14 @@ DISAS_INSN(arith_im)
         gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im));
         tcg_gen_subi_i32(dest, dest, im);
         gen_update_cc_add(dest, tcg_const_i32(im));
-        s->cc_op = CC_OP_SUB;
+        set_cc_op(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));
         gen_helper_xflag_lt(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);
@@ -1292,7 +1337,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();
@@ -1409,10 +1454,10 @@ 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;
+    set_cc_op(s, CC_OP_SUB);
     gen_update_cc_add(reg, src1);
     gen_helper_xflag_lt(QREG_CC_X, tcg_const_i32(0), src1);
-    s->cc_op = CC_OP_SUB;
+    set_cc_op(s, CC_OP_SUB);
 }
 
 static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
@@ -1422,39 +1467,33 @@ 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(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)
@@ -1659,11 +1698,11 @@ DISAS_INSN(addsubq)
         if (insn & 0x0100) {
             gen_helper_xflag_lt(QREG_CC_X, dest, src2);
             tcg_gen_subi_i32(dest, dest, val);
-            s->cc_op = CC_OP_SUB;
+            set_cc_op(s, CC_OP_SUB);
         } else {
             tcg_gen_addi_i32(dest, dest, val);
             gen_helper_xflag_lt(QREG_CC_X, dest, src2);
-            s->cc_op = CC_OP_ADD;
+            set_cc_op(s, CC_OP_ADD);
         }
         gen_update_cc_add(dest, src2);
     }
@@ -1706,16 +1745,18 @@ 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();
         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);
     }
 }
@@ -1891,7 +1932,7 @@ 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;
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 /* TODO: This could be implemented without helper functions.  */
@@ -1916,7 +1957,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)
@@ -1937,7 +1978,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)
@@ -1982,16 +2023,14 @@ DISAS_INSN(strldsr)
 
 DISAS_INSN(move_from_sr)
 {
-    TCGv reg;
     TCGv sr;
 
-    if (IS_USER(s)) {
+    if (IS_USER(s)) {    /* FIXME: not privileged on 68000 */
         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)
@@ -2000,7 +2039,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);
 }
 
@@ -2751,7 +2790,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)
@@ -3107,6 +3146,7 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
                     tcg_ctx.gen_opc_instr_start[lj++] = 0;
             }
             tcg_ctx.gen_opc_pc[lj] = dc->pc;
+            gen_opc_cc_op[lj] = dc->cc_op;
             tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
@@ -3126,20 +3166,20 @@ gen_intermediate_code_internal(M68kCPU *cpu, 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;
@@ -3168,9 +3208,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
         tb->size = dc->pc - pc_start;
         tb->icount = num_insns;
     }
-
-    //optimize_flags();
-    //expand_target_qops();
 }
 
 void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
@@ -3208,5 +3245,25 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
 
 void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb, int pc_pos)
 {
+    int cc_op;
+#ifdef DEBUG_DISAS
+    if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
+        int i;
+        qemu_log("RESTORE:\n");
+        for (i = 0; i <= pc_pos; i++) {
+            if (tcg_ctx.gen_opc_instr_start[i]) {
+                qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
+                        tcg_ctx.gen_opc_pc[i]);
+            }
+        }
+        qemu_log("pc_pos=0x%x pc=" TARGET_FMT_lx " CC_OP %d\n",
+                pc_pos, tcg_ctx.gen_opc_pc[pc_pos],
+                gen_opc_cc_op[pc_pos]);
+    }
+#endif
     env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+    cc_op = gen_opc_cc_op[pc_pos];
+    if (cc_op != CC_OP_DYNAMIC) {
+        env->cc_op = cc_op;
+    }
 }
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 09/30] m68k: add X flag helpers
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (7 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 08/30] m68k: update CPU flags management Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12  5:18   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 10/30] m68k: tst bugfix Laurent Vivier
                   ` (21 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    | 12 +++++++++++-
 target-m68k/helper.h    |  4 +++-
 target-m68k/translate.c | 29 +++++++++++++++++++++--------
 3 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index c6f5cc0..8c10fbc 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -465,7 +465,17 @@ 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)
+uint32_t HELPER(xflag_lt_i8)(uint32_t a, uint32_t b)
+{
+    return (uint8_t)a < (uint8_t)b;
+}
+
+uint32_t HELPER(xflag_lt_i16)(uint32_t a, uint32_t b)
+{
+    return (uint16_t)a < (uint16_t)b;
+}
+
+uint32_t HELPER(xflag_lt_i32)(uint32_t a, uint32_t b)
 {
     return a < b;
 }
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index 81c8e79..81fb7db 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -8,7 +8,9 @@ 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(xflag_lt_i8, i32, i32, i32)
+DEF_HELPER_2(xflag_lt_i16, i32, i32, i32)
+DEF_HELPER_2(xflag_lt_i32, 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 80ac63a..5fa39db 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -488,6 +488,19 @@ static inline void gen_flush_flags(DisasContext *s)
     } \
 } while (0)
 
+#define SET_X_FLAG(opsize, a, b) do { \
+    switch (opsize) { \
+    case OS_BYTE: \
+        gen_helper_xflag_lt_i8(QREG_CC_X, a, b); break; \
+    case OS_WORD: \
+        gen_helper_xflag_lt_i16(QREG_CC_X, a, b); break; \
+    case OS_LONG: \
+        gen_helper_xflag_lt_i32(QREG_CC_X, a, b); break; \
+    default: \
+        abort(); \
+    } \
+} while (0)
+
 static void gen_logic_cc(DisasContext *s, TCGv val, int opsize)
 {
     tcg_gen_mov_i32(QREG_CC_DEST, val);
@@ -1102,10 +1115,10 @@ DISAS_INSN(addsub)
     }
     if (add) {
         tcg_gen_add_i32(dest, tmp, src);
-        gen_helper_xflag_lt(QREG_CC_X, dest, src);
+        SET_X_FLAG(OS_LONG, dest, src);
         set_cc_op(s, CC_OP_ADD);
     } else {
-        gen_helper_xflag_lt(QREG_CC_X, tmp, src);
+        SET_X_FLAG(OS_LONG, tmp, src);
         tcg_gen_sub_i32(dest, tmp, src);
         set_cc_op(s, CC_OP_SUB);
     }
@@ -1317,7 +1330,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));
+        SET_X_FLAG(OS_LONG, dest, tcg_const_i32(im));
         tcg_gen_subi_i32(dest, dest, im);
         gen_update_cc_add(dest, tcg_const_i32(im));
         set_cc_op(s, CC_OP_SUB);
@@ -1326,7 +1339,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));
+        SET_X_FLAG(OS_LONG, dest, tcg_const_i32(im));
         set_cc_op(s, CC_OP_ADD);
         break;
     case 5: /* eori */
@@ -1456,7 +1469,7 @@ DISAS_INSN(neg)
     tcg_gen_neg_i32(reg, src1);
     set_cc_op(s, CC_OP_SUB);
     gen_update_cc_add(reg, src1);
-    gen_helper_xflag_lt(QREG_CC_X, tcg_const_i32(0), src1);
+    SET_X_FLAG(OS_LONG, tcg_const_i32(0), src1);
     set_cc_op(s, CC_OP_SUB);
 }
 
@@ -1696,13 +1709,13 @@ DISAS_INSN(addsubq)
     } else {
         src2 = tcg_const_i32(val);
         if (insn & 0x0100) {
-            gen_helper_xflag_lt(QREG_CC_X, dest, src2);
+            SET_X_FLAG(OS_LONG, dest, tcg_const_i32(val));
             tcg_gen_subi_i32(dest, dest, val);
             set_cc_op(s, CC_OP_SUB);
         } else {
             tcg_gen_addi_i32(dest, dest, val);
-            gen_helper_xflag_lt(QREG_CC_X, dest, src2);
-            set_cc_op(s, CC_OP_ADD);
+            SET_X_FLAG(OS_LONG, dest, tcg_const_i32(val));
+            SET_CC_OP(OS_LONG, ADD);
         }
         gen_update_cc_add(dest, src2);
     }
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 10/30] m68k: tst bugfix
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (8 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 09/30] m68k: add X flag helpers Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12  5:18   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 11/30] m68k: improve clr/moveq Laurent Vivier
                   ` (20 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

The operand is signed.

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 5fa39db..359c761 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1571,7 +1571,7 @@ DISAS_INSN(tst)
     TCGv tmp;
 
     opsize = insn_opsize(insn, 6);
-    SRC_EA(env, tmp, opsize, 1, NULL);
+    SRC_EA(env, tmp, opsize, -1, NULL);
     gen_logic_cc(s, tmp, opsize);
 }
 
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 11/30] m68k: improve clr/moveq
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (9 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 10/30] m68k: tst bugfix Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12  5:20   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 12/30] m68k: Manage divw overflow Laurent Vivier
                   ` (19 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

Generate the TCG constant and use it twice, instead
of generating the TCG constant twice to use it twice.

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 359c761..8a3d315 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1431,10 +1431,13 @@ DISAS_INSN(lea)
 DISAS_INSN(clr)
 {
     int opsize;
+    TCGv zero;
+
+    zero = tcg_const_i32(0);
 
     opsize = insn_opsize(insn, 6);
-    DEST_EA(env, insn, opsize, tcg_const_i32(0), NULL);
-    gen_logic_cc(s, tcg_const_i32(0), opsize);
+    DEST_EA(env, insn, opsize, zero, NULL);
+    gen_logic_cc(s, zero, opsize);
 }
 
 static TCGv gen_get_ccr(DisasContext *s)
@@ -1776,11 +1779,11 @@ DISAS_INSN(branch)
 
 DISAS_INSN(moveq)
 {
-    uint32_t val;
+    TCGv val;
 
-    val = (int8_t)insn;
-    tcg_gen_movi_i32(DREG(insn, 9), val);
-    gen_logic_cc(s, tcg_const_i32(val), OS_LONG);
+    val = tcg_const_i32((int8_t)insn);
+    tcg_gen_mov_i32(DREG(insn, 9), val);
+    gen_logic_cc(s, val, OS_LONG);
 }
 
 DISAS_INSN(mvzs)
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 12/30] m68k: Manage divw overflow
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (10 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 11/30] m68k: improve clr/moveq Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12  6:03   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 13/30] m68k: set Z and N on divu/muls overflow as a real 68040 Laurent Vivier
                   ` (18 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

"Overflow may be detected and set before the instruction completes.
If the instruction detects an overflow, it sets the overflow condition
code, and the operands are unaffected."

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 8a3d315..370a2f0 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1034,32 +1034,40 @@ DISAS_INSN(mulw)
 
 DISAS_INSN(divw)
 {
-    TCGv reg;
+    TCGv dest;
     TCGv tmp;
     TCGv src;
     int sign;
+    TCGLabel *l1;
 
     sign = (insn & 0x100) != 0;
-    reg = DREG(insn, 9);
-    if (sign) {
-        tcg_gen_ext16s_i32(QREG_DIV1, reg);
-    } else {
-        tcg_gen_ext16u_i32(QREG_DIV1, reg);
-    }
+
+    /* dest.l / src.w */
+
+    dest = DREG(insn, 9);
+    tcg_gen_mov_i32(QREG_DIV1, dest);
+
     SRC_EA(env, src, OS_WORD, sign, NULL);
     tcg_gen_mov_i32(QREG_DIV2, src);
+
+    /* div1 / div2 */
+
     if (sign) {
         gen_helper_divs(cpu_env, tcg_const_i32(1));
     } else {
         gen_helper_divu(cpu_env, tcg_const_i32(1));
     }
 
+    set_cc_op(s, CC_OP_FLAGS);
+
+    l1 = gen_new_label();
+    gen_jmpcc(s, 9 /* V */, l1);
     tmp = tcg_temp_new();
     src = tcg_temp_new();
     tcg_gen_ext16u_i32(tmp, QREG_DIV1);
     tcg_gen_shli_i32(src, QREG_DIV2, 16);
-    tcg_gen_or_i32(reg, tmp, src);
-    set_cc_op(s, CC_OP_FLAGS);
+    tcg_gen_or_i32(dest, tmp, src);
+    gen_set_label(l1);
 }
 
 DISAS_INSN(divl)
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 13/30] m68k: set Z and N on divu/muls overflow as a real 68040
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (11 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 12/30] m68k: Manage divw overflow Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12  6:29   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 14/30] m68k: allow adda/suba to add/sub word Laurent Vivier
                   ` (17 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

This allows to compare simulation results with a real 68040.

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

diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 1af0ca6..71641bf 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -193,12 +193,19 @@ 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;
+    if (word && quot > 0xffff) {
+        /* real 68040 keep Z and N on overflow,
+         * whereas documentation says "undefined"
+         */
+        flags |= CCF_V | (env->cc_dest & (CCF_Z|CCF_N));
+    } else {
+        if (quot == 0) {
+            flags |= CCF_Z;
+        } else if ((int16_t)quot < 0) {
+            flags |= CCF_N;
+        }
+    }
+
     env->div1 = quot;
     env->div2 = rem;
     env->cc_dest = flags;
@@ -220,12 +227,19 @@ 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;
+    if (word && quot != (int16_t)quot) {
+        /* real 68040 keep Z and N on overflow,
+         * whereas documentation says "undefined"
+         */
+        flags |= CCF_V | (env->cc_dest & (CCF_Z|CCF_N));
+    } else {
+        if (quot == 0) {
+            flags |= CCF_Z;
+        } else if ((int16_t)quot < 0) {
+            flags |= CCF_N;
+        }
+    }
+
     env->div1 = quot;
     env->div2 = rem;
     env->cc_dest = flags;
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 14/30] m68k: allow adda/suba to add/sub word
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (12 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 13/30] m68k: set Z and N on divu/muls overflow as a real 68040 Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12  7:32   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 15/30] m68k: add more modes to movem Laurent Vivier
                   ` (16 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 370a2f0..f52aca3 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1836,7 +1836,7 @@ DISAS_INSN(suba)
     TCGv src;
     TCGv reg;
 
-    SRC_EA(env, src, OS_LONG, 0, NULL);
+    SRC_EA(env, src, (insn & 0x100) ? OS_LONG : OS_WORD, -1, NULL);
     reg = AREG(insn, 9);
     tcg_gen_sub_i32(reg, reg, src);
 }
@@ -1942,7 +1942,7 @@ DISAS_INSN(adda)
     TCGv src;
     TCGv reg;
 
-    SRC_EA(env, src, OS_LONG, 0, NULL);
+    SRC_EA(env, src, (insn & 0x100) ? OS_LONG : OS_WORD, -1, NULL);
     reg = AREG(insn, 9);
     tcg_gen_add_i32(reg, reg, src);
 }
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 15/30] m68k: add more modes to movem
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (13 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 14/30] m68k: allow adda/suba to add/sub word Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12  7:54   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 16/30] m68k: Add all access modes and data sizes to some 680x0 instructions Laurent Vivier
                   ` (15 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

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

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

* [Qemu-devel] [PATCH for-2.5 16/30] m68k: Add all access modes and data sizes to some 680x0 instructions
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (14 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 15/30] m68k: add more modes to movem Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 16:25   ` Richard Henderson
  2015-08-12 16:27   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 17/30] m68k: ori/andi/subi/addi/eori/cmpi can modify SR/CCR Laurent Vivier
                   ` (14 subsequent siblings)
  30 siblings, 2 replies; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

The following instruction can use all access modes and data sizes:

add, sub, neg, not, and, or, eor, ori, andi, subi, addi, eori, cmpi, swap

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index d3a3695..6a426e1 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1110,31 +1110,33 @@ DISAS_INSN(addsub)
     TCGv tmp;
     TCGv addr;
     int add;
+    int opsize;
 
     add = (insn & 0x4000) != 0;
+    opsize = insn_opsize(insn, 6);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     if (insn & 0x100) {
-        SRC_EA(env, tmp, OS_LONG, 0, &addr);
+        SRC_EA(env, tmp, opsize, -1, &addr);
         src = reg;
     } else {
         tmp = reg;
-        SRC_EA(env, src, OS_LONG, 0, NULL);
+        SRC_EA(env, src, opsize, -1, NULL);
     }
     if (add) {
         tcg_gen_add_i32(dest, tmp, src);
-        SET_X_FLAG(OS_LONG, dest, src);
-        set_cc_op(s, CC_OP_ADD);
+        SET_X_FLAG(opsize, dest, src);
+        SET_CC_OP(opsize, ADD);
     } else {
-        SET_X_FLAG(OS_LONG, tmp, src);
+        SET_X_FLAG(opsize, tmp, src);
         tcg_gen_sub_i32(dest, tmp, src);
-        set_cc_op(s, CC_OP_SUB);
+        SET_CC_OP(opsize, SUB);
     }
     gen_update_cc_add(dest, src);
     if (insn & 0x100) {
-        DEST_EA(env, insn, OS_LONG, dest, &addr);
+        DEST_EA(env, insn, opsize, dest, &addr);
     } else {
-        tcg_gen_mov_i32(reg, dest);
+        gen_partset_reg(opsize, reg, dest);
     }
 }
 
@@ -1348,50 +1350,62 @@ DISAS_INSN(arith_im)
     TCGv src1;
     TCGv dest;
     TCGv addr;
+    int opsize;
 
     op = (insn >> 9) & 7;
-    SRC_EA(env, src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
-    im = read_im32(env, s);
+    opsize = insn_opsize(insn, 6);
+    switch (opsize) {
+    case OS_BYTE:
+        im = read_im8(env, s);
+        break;
+    case OS_WORD:
+        im = read_im16(env, s);
+        break;
+    case OS_LONG:
+        im = read_im32(env, s);
+        break;
+    default:
+       abort();
+    }
+    SRC_EA(env, src1, opsize, -1, (op == 6) ? NULL : &addr);
     dest = tcg_temp_new();
     switch (op) {
     case 0: /* ori */
         tcg_gen_ori_i32(dest, src1, im);
-        gen_logic_cc(s, dest, OS_LONG);
+        gen_logic_cc(s, dest, opsize);
         break;
     case 1: /* andi */
         tcg_gen_andi_i32(dest, src1, im);
-        gen_logic_cc(s, dest, OS_LONG);
+        gen_logic_cc(s, dest, opsize);
         break;
     case 2: /* subi */
         tcg_gen_mov_i32(dest, src1);
-        SET_X_FLAG(OS_LONG, dest, tcg_const_i32(im));
+        SET_X_FLAG(opsize, dest, tcg_const_i32(im));
         tcg_gen_subi_i32(dest, dest, im);
         gen_update_cc_add(dest, tcg_const_i32(im));
-        set_cc_op(s, CC_OP_SUB);
+        SET_CC_OP(opsize, SUB);
         break;
     case 3: /* addi */
         tcg_gen_mov_i32(dest, src1);
         tcg_gen_addi_i32(dest, dest, im);
         gen_update_cc_add(dest, tcg_const_i32(im));
-        SET_X_FLAG(OS_LONG, dest, tcg_const_i32(im));
-        set_cc_op(s, CC_OP_ADD);
+        SET_X_FLAG(opsize, dest, tcg_const_i32(im));
+        SET_CC_OP(opsize, ADD);
         break;
     case 5: /* eori */
         tcg_gen_xori_i32(dest, src1, im);
-        gen_logic_cc(s, dest, OS_LONG);
+        gen_logic_cc(s, dest, opsize);
         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);
+        SET_CC_OP(opsize, SUB);
         break;
     default:
         abort();
     }
-    if (op != 6) {
-        DEST_EA(env, insn, OS_LONG, dest, &addr);
-    }
+    DEST_EA(env, insn, opsize, dest, &addr);
 }
 
 DISAS_INSN(byterev)
@@ -1497,17 +1511,19 @@ DISAS_INSN(move_from_ccr)
 
 DISAS_INSN(neg)
 {
-    TCGv reg;
     TCGv src1;
+    TCGv dest;
+    TCGv addr;
+    int opsize;
 
-    reg = DREG(insn, 0);
-    src1 = tcg_temp_new();
-    tcg_gen_mov_i32(src1, reg);
-    tcg_gen_neg_i32(reg, src1);
-    set_cc_op(s, CC_OP_SUB);
-    gen_update_cc_add(reg, src1);
-    SET_X_FLAG(OS_LONG, tcg_const_i32(0), src1);
-    set_cc_op(s, CC_OP_SUB);
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(env, src1, opsize, -1, &addr);
+    dest = tcg_temp_new();
+    tcg_gen_neg_i32(dest, src1);
+    SET_CC_OP(opsize, SUB);
+    gen_update_cc_add(dest, src1);
+    SET_X_FLAG(opsize, tcg_const_i32(0), dest);
+    DEST_EA(env, insn, opsize, dest, &addr);
 }
 
 static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
@@ -1548,11 +1564,17 @@ DISAS_INSN(move_to_ccr)
 
 DISAS_INSN(not)
 {
-    TCGv reg;
+    TCGv src1;
+    TCGv dest;
+    TCGv addr;
+    int opsize;
 
-    reg = DREG(insn, 0);
-    tcg_gen_not_i32(reg, reg);
-    gen_logic_cc(s, reg, OS_LONG);
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(env, src1, opsize, -1, &addr);
+    dest = tcg_temp_new();
+    tcg_gen_not_i32(dest, src1);
+    DEST_EA(env, insn, opsize, dest, &addr);
+    gen_logic_cc(s, dest, opsize);
 }
 
 DISAS_INSN(swap)
@@ -1842,19 +1864,21 @@ DISAS_INSN(or)
     TCGv dest;
     TCGv src;
     TCGv addr;
+    int opsize;
 
+    opsize = insn_opsize(insn, 6);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     if (insn & 0x100) {
-        SRC_EA(env, src, OS_LONG, 0, &addr);
+        SRC_EA(env, src, opsize, -1, &addr);
         tcg_gen_or_i32(dest, src, reg);
-        DEST_EA(env, insn, OS_LONG, dest, &addr);
+        DEST_EA(env, insn, opsize, dest, &addr);
     } else {
-        SRC_EA(env, src, OS_LONG, 0, NULL);
+        SRC_EA(env, src, opsize, -1, NULL);
         tcg_gen_or_i32(dest, src, reg);
-        tcg_gen_mov_i32(reg, dest);
+        gen_partset_reg(opsize, reg, dest);
     }
-    gen_logic_cc(s, dest, OS_LONG);
+    gen_logic_cc(s, dest, opsize);
 }
 
 DISAS_INSN(suba)
@@ -1933,13 +1957,16 @@ DISAS_INSN(eor)
     TCGv reg;
     TCGv dest;
     TCGv addr;
+    int opsize;
 
-    SRC_EA(env, src, OS_LONG, 0, &addr);
+    opsize = insn_opsize(insn, 6);
+
+    SRC_EA(env, src, opsize, -1, &addr);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     tcg_gen_xor_i32(dest, src, reg);
-    gen_logic_cc(s, dest, OS_LONG);
-    DEST_EA(env, insn, OS_LONG, dest, &addr);
+    gen_logic_cc(s, dest, opsize);
+    DEST_EA(env, insn, opsize, dest, &addr);
 }
 
 DISAS_INSN(and)
@@ -1948,19 +1975,21 @@ DISAS_INSN(and)
     TCGv reg;
     TCGv dest;
     TCGv addr;
+    int opsize;
 
+    opsize = insn_opsize(insn, 6);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     if (insn & 0x100) {
-        SRC_EA(env, src, OS_LONG, 0, &addr);
+        SRC_EA(env, src, opsize, -1, &addr);
         tcg_gen_and_i32(dest, src, reg);
-        DEST_EA(env, insn, OS_LONG, dest, &addr);
+        DEST_EA(env, insn, opsize, dest, &addr);
     } else {
-        SRC_EA(env, src, OS_LONG, 0, NULL);
+        SRC_EA(env, src, opsize, -1, NULL);
         tcg_gen_and_i32(dest, src, reg);
-        tcg_gen_mov_i32(reg, dest);
+        gen_partset_reg(opsize, reg, dest);
     }
-    gen_logic_cc(s, dest, OS_LONG);
+    gen_logic_cc(s, dest, opsize);
 }
 
 DISAS_INSN(adda)
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 17/30] m68k: ori/andi/subi/addi/eori/cmpi can modify SR/CCR
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (15 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 16/30] m68k: Add all access modes and data sizes to some 680x0 instructions Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 16:44   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 18/30] m68k: addq/subq can work with all the data sizes Laurent Vivier
                   ` (13 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 6a426e1..9e379b3 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1343,6 +1343,42 @@ DISAS_INSN(bitop_im)
         DEST_EA(env, insn, opsize, tmp, &addr);
     }
 }
+
+static TCGv gen_get_ccr(DisasContext *s)
+{
+    TCGv dest;
+
+    gen_flush_flags(s);
+    dest = tcg_temp_new();
+    tcg_gen_shli_i32(dest, QREG_CC_X, 4);
+    tcg_gen_or_i32(dest, dest, QREG_CC_DEST);
+    return dest;
+}
+
+static TCGv gen_get_sr(DisasContext *s)
+{
+    TCGv ccr;
+    TCGv sr;
+
+    ccr = gen_get_ccr(s);
+    sr = tcg_temp_new();
+    tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
+    tcg_gen_or_i32(sr, sr, ccr);
+    return sr;
+}
+
+static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only)
+{
+    TCGv tmp;
+    tmp = tcg_temp_new();
+    tcg_gen_andi_i32(QREG_CC_DEST, val, 0xf);
+    tcg_gen_shri_i32(tmp, val, 4);
+    tcg_gen_andi_i32(QREG_CC_X, tmp, 1);
+    if (!ccr_only) {
+        gen_helper_set_sr(cpu_env, val);
+    }
+}
+
 DISAS_INSN(arith_im)
 {
     int op;
@@ -1367,7 +1403,20 @@ DISAS_INSN(arith_im)
     default:
        abort();
     }
-    SRC_EA(env, src1, opsize, -1, (op == 6) ? NULL : &addr);
+    if ((op == 0 || op == 1) &&
+        (insn & 0x3f) == 0x3c) {
+        if (opsize == OS_BYTE) {
+            src1 = gen_get_ccr(s);
+        } else {
+            if (IS_USER(s)) {
+                gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
+                return;
+            }
+            src1 = gen_get_sr(s);
+        }
+    } else {
+        SRC_EA(env, src1, opsize, -1, (op == 6) ? NULL : &addr);
+    }
     dest = tcg_temp_new();
     switch (op) {
     case 0: /* ori */
@@ -1405,7 +1454,14 @@ DISAS_INSN(arith_im)
     default:
         abort();
     }
-    DEST_EA(env, insn, opsize, dest, &addr);
+    if (op != 6) {
+        if ((op == 0 || op == 1) &&
+            (insn & 0x3f) == 0x3c) {
+            gen_set_sr(s, dest, opsize == OS_BYTE);
+        } else {
+            DEST_EA(env, insn, opsize, dest, &addr);
+        }
+    }
 }
 
 DISAS_INSN(byterev)
@@ -1488,17 +1544,6 @@ DISAS_INSN(clr)
     gen_logic_cc(s, zero, opsize);
 }
 
-static TCGv gen_get_ccr(DisasContext *s)
-{
-    TCGv dest;
-
-    gen_flush_flags(s);
-    dest = tcg_temp_new();
-    tcg_gen_shli_i32(dest, QREG_CC_X, 4);
-    tcg_gen_or_i32(dest, dest, QREG_CC_DEST);
-    return dest;
-}
-
 DISAS_INSN(move_from_ccr)
 {
     TCGv reg;
@@ -1536,18 +1581,6 @@ static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
     set_cc_op(s, CC_OP_FLAGS);
 }
 
-static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only)
-{
-    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);
-    }
-}
-
 static void gen_move_to_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
                            int ccr_only)
 {
@@ -2068,18 +2101,6 @@ DISAS_INSN(ff1)
     gen_helper_ff1(reg, reg);
 }
 
-static TCGv gen_get_sr(DisasContext *s)
-{
-    TCGv ccr;
-    TCGv sr;
-
-    ccr = gen_get_ccr(s);
-    sr = tcg_temp_new();
-    tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
-    tcg_gen_or_i32(sr, sr, ccr);
-    return sr;
-}
-
 DISAS_INSN(strldsr)
 {
     uint16_t ext;
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 18/30] m68k: addq/subq can work with all the data sizes.
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (16 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 17/30] m68k: ori/andi/subi/addi/eori/cmpi can modify SR/CCR Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 16:48   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 19/30] m68k: add cmpm Laurent Vivier
                   ` (12 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

Improve TCG constant use by creating only once for several uses.

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 9e379b3..ae57792 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1778,40 +1778,48 @@ DISAS_INSN(jump)
 
 DISAS_INSN(addsubq)
 {
-    TCGv src1;
-    TCGv src2;
+    TCGv src;
     TCGv dest;
-    int val;
+    TCGv val;
+    int imm;
     TCGv addr;
+    int opsize;
 
-    SRC_EA(env, src1, OS_LONG, 0, &addr);
-    val = (insn >> 9) & 7;
-    if (val == 0)
-        val = 8;
+    if ((insn & 070) == 010) {
+        /* Operation on address register is always long.  */
+        opsize = OS_LONG;
+    } else {
+        opsize = insn_opsize(insn, 6);
+    }
+    SRC_EA(env, src, opsize, -1, &addr);
+    imm = (insn >> 9) & 7;
+    if (imm == 0) {
+        imm = 8;
+    }
+    val = tcg_const_i32(imm);
     dest = tcg_temp_new();
-    tcg_gen_mov_i32(dest, src1);
+    tcg_gen_mov_i32(dest, src);
     if ((insn & 0x38) == 0x08) {
         /* Don't update condition codes if the destination is an
            address register.  */
         if (insn & 0x0100) {
-            tcg_gen_subi_i32(dest, dest, val);
+            tcg_gen_sub_i32(dest, dest, val);
         } else {
-            tcg_gen_addi_i32(dest, dest, val);
+            tcg_gen_add_i32(dest, dest, val);
         }
     } else {
-        src2 = tcg_const_i32(val);
         if (insn & 0x0100) {
-            SET_X_FLAG(OS_LONG, dest, tcg_const_i32(val));
-            tcg_gen_subi_i32(dest, dest, val);
-            set_cc_op(s, CC_OP_SUB);
+            SET_X_FLAG(opsize, dest, val);
+            tcg_gen_sub_i32(dest, dest, val);
+            SET_CC_OP(opsize, SUB);
         } else {
-            tcg_gen_addi_i32(dest, dest, val);
-            SET_X_FLAG(OS_LONG, dest, tcg_const_i32(val));
-            SET_CC_OP(OS_LONG, ADD);
+            tcg_gen_add_i32(dest, dest, val);
+            SET_X_FLAG(opsize, dest, val);
+            SET_CC_OP(opsize, ADD);
         }
-        gen_update_cc_add(dest, src2);
+        gen_update_cc_add(dest, val);
     }
-    DEST_EA(env, insn, OS_LONG, dest, &addr);
+    DEST_EA(env, insn, opsize, dest, &addr);
 }
 
 DISAS_INSN(tpf)
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 19/30] m68k: add cmpm
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (17 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 18/30] m68k: addq/subq can work with all the data sizes Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 17:00   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 20/30] m68k: add exg Laurent Vivier
                   ` (11 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index ae57792..adf4521 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2002,6 +2002,24 @@ DISAS_INSN(eor)
 
     opsize = insn_opsize(insn, 6);
 
+    if (((insn >> 3) & 7) == 1) {
+        /* cmpm */
+        reg = AREG(insn, 0);
+        src = gen_load(s, opsize, reg, 1);
+        tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
+
+        reg = AREG(insn, 9);
+        dest = gen_load(s, opsize, reg, 1);
+        tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
+
+        reg = tcg_temp_new();
+        tcg_gen_sub_i32(reg, dest, src);
+        gen_update_cc_add(reg, src);
+        SET_CC_OP(opsize, SUB);
+
+        return;
+    }
+
     SRC_EA(env, src, opsize, -1, &addr);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 20/30] m68k: add exg
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (18 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 19/30] m68k: add cmpm Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 17:05   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 21/30] m68k: add bkpt Laurent Vivier
                   ` (10 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index adf4521..b7d15e9 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2035,10 +2035,42 @@ DISAS_INSN(and)
     TCGv dest;
     TCGv addr;
     int opsize;
+    int exg_mode;
 
+    dest = tcg_temp_new();
+
+    /* exg */
+
+    exg_mode = insn & 0x1f8;
+    if (exg_mode == 0x140) {
+        /* exchange Dx and Dy */
+        src = DREG(insn, 9);
+        reg = DREG(insn, 0);
+        tcg_gen_mov_i32(dest, src);
+        tcg_gen_mov_i32(src, reg);
+        tcg_gen_mov_i32(reg, dest);
+        return;
+    } else if (exg_mode == 0x148) {
+        /* exchange Ax and Ay */
+        src = AREG(insn, 9);
+        reg = AREG(insn, 0);
+        tcg_gen_mov_i32(dest, src);
+        tcg_gen_mov_i32(src, reg);
+        tcg_gen_mov_i32(reg, dest);
+        return;
+    } else if (exg_mode == 0x188) {
+        /* exchange Dx and Ay */
+        src = DREG(insn, 9);
+        reg = AREG(insn, 0);
+        tcg_gen_mov_i32(dest, src);
+        tcg_gen_mov_i32(src, reg);
+        tcg_gen_mov_i32(reg, dest);
+        return;
+    }
+    /* and */
     opsize = insn_opsize(insn, 6);
     reg = DREG(insn, 9);
-    dest = tcg_temp_new();
+
     if (insn & 0x100) {
         SRC_EA(env, src, opsize, -1, &addr);
         tcg_gen_and_i32(dest, src, reg);
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 21/30] m68k: add bkpt
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (19 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 20/30] m68k: add exg Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 17:07   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 22/30] m68k: add cas instruction Laurent Vivier
                   ` (9 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index b7d15e9..add3b69 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1625,6 +1625,11 @@ DISAS_INSN(swap)
     gen_logic_cc(s, reg, OS_LONG);
 }
 
+DISAS_INSN(bkpt)
+{
+    gen_exception(s, s->pc - 2, EXCP_DEBUG);
+}
+
 DISAS_INSN(pea)
 {
     TCGv tmp;
@@ -3113,6 +3118,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(pea,       4840, ffc0, M68000);
     INSN(swap,      4840, fff8, CF_ISA_A);
     INSN(swap,      4840, fff8, M68000);
+    INSN(bkpt,      4848, fff8, M68000);
     INSN(movem,     48c0, fbc0, CF_ISA_A);
     INSN(movem,     48c0, fbc0, M68000);
     INSN(ext,       4880, fff8, CF_ISA_A);
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 22/30] m68k: add cas instruction
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (20 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 21/30] m68k: add bkpt Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 17:14   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 23/30] m68k: add linkl Laurent Vivier
                   ` (8 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index add3b69..9a7558a 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1464,6 +1464,70 @@ DISAS_INSN(arith_im)
     }
 }
 
+DISAS_INSN(cas)
+{
+    int opsize;
+    TCGv dest;
+    TCGv tmp;
+    TCGv cmp;
+    TCGv update;
+    TCGv taddr;
+    TCGv addr;
+    TCGv res;
+    uint16_t ext;
+    TCGLabel *l1, *l2;
+
+    if ((insn & 0x3f) == 0x3c) {
+        /* CAS2: Not yet implemented */
+        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+    }
+
+    switch ((insn >> 9) & 3) {
+    case 1:
+        opsize = OS_BYTE;
+        break;
+    case 2:
+        opsize = OS_WORD;
+        break;
+    case 3:
+        opsize = OS_LONG;
+        break;
+    default:
+        abort();
+    }
+
+    ext = read_im16(env, s);
+    taddr = gen_lea(env, s, insn, opsize);
+    if (IS_NULL_QREG(taddr)) {
+        gen_addr_fault(s);
+        return;
+    }
+
+    cmp = DREG(ext, 0);
+    update = DREG(ext, 6);
+    tmp = gen_load(s, opsize, taddr, 0);
+    dest = tcg_temp_local_new();
+    tcg_gen_mov_i32(dest, tmp);
+    addr = tcg_temp_local_new();
+    tcg_gen_mov_i32(addr, taddr);
+
+    res = tcg_temp_new();
+    tcg_gen_sub_i32(res, dest, cmp);
+    gen_logic_cc(s, res, opsize);
+
+    l1 = gen_new_label();
+    l2 = gen_new_label();
+
+    gen_jmpcc(s, 6 /* !Z */, l1);
+    gen_store(s, opsize, addr, update);
+    tcg_gen_br(l2);
+    gen_set_label(l1);
+    tcg_gen_mov_i32(cmp, dest);
+    gen_set_label(l2);
+    tcg_temp_free(dest);
+    tcg_temp_free(addr);
+}
+
 DISAS_INSN(byterev)
 {
     TCGv reg;
@@ -3080,6 +3144,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(bitop_im,  0840, ffc0, M68000);
     INSN(bitop_im,  0880, ffc0, CF_ISA_A);
     INSN(bitop_im,  0880, ffc0, M68000);
+    INSN(cas,       08c0, f9c0, CAS);
     INSN(bitop_im,  08c0, ffc0, CF_ISA_A);
     INSN(bitop_im,  08c0, ffc0, M68000);
     INSN(arith_im,  0a80, fff8, CF_ISA_A);
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 23/30] m68k: add linkl
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (21 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 22/30] m68k: add cas instruction Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 17:33   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 24/30] m68k: add DBcc and Scc (memory operand) Laurent Vivier
                   ` (7 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 9a7558a..95d58d1 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1789,8 +1789,24 @@ DISAS_INSN(link)
     TCGv reg;
     TCGv tmp;
 
-    offset = cpu_ldsw_code(env, s->pc);
-    s->pc += 2;
+    offset = read_im16(env, s);
+    reg = AREG(insn, 0);
+    tmp = tcg_temp_new();
+    tcg_gen_subi_i32(tmp, QREG_SP, 4);
+    gen_store(s, OS_LONG, tmp, reg);
+    if ((insn & 7) != 7) {
+        tcg_gen_mov_i32(reg, tmp);
+    }
+    tcg_gen_addi_i32(QREG_SP, tmp, offset);
+}
+
+DISAS_INSN(linkl)
+{
+    int32_t offset;
+    TCGv reg;
+    TCGv tmp;
+
+    offset = read_im32(env, s);
     reg = AREG(insn, 0);
     tmp = tcg_temp_new();
     tcg_gen_subi_i32(tmp, QREG_SP, 4);
@@ -3179,6 +3195,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(not,       4600, ff00, M68000);
     INSN(undef,     46c0, ffc0, M68000);
     INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
+    INSN(linkl,     4808, fff8, M68000);
     INSN(pea,       4840, ffc0, CF_ISA_A);
     INSN(pea,       4840, ffc0, M68000);
     INSN(swap,      4840, fff8, CF_ISA_A);
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 24/30] m68k: add DBcc and Scc (memory operand)
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (22 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 23/30] m68k: add linkl Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 17:49   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 25/30] m68k: add abcd, sbcd, nbcd instructions Laurent Vivier
                   ` (6 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 95d58d1..cb746d7 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -994,6 +994,50 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
     s->is_jmp = DISAS_TB_JUMP;
 }
 
+DISAS_INSN(scc_mem)
+{
+    TCGLabel *l1;
+    int cond;
+    TCGv dest;
+
+    l1 = gen_new_label();
+    cond = (insn >> 8) & 0xf;
+    dest = tcg_temp_local_new();
+    tcg_gen_movi_i32(dest, 0);
+    gen_jmpcc(s, cond ^ 1, l1);
+    tcg_gen_movi_i32(dest, 0xff);
+    gen_set_label(l1);
+    DEST_EA(env, insn, OS_BYTE, dest, NULL);
+    tcg_temp_free(dest);
+}
+
+DISAS_INSN(dbcc)
+{
+    TCGLabel *l1;
+    TCGv reg;
+    TCGv tmp;
+    int16_t offset;
+    uint32_t base;
+
+    reg = DREG(insn, 0);
+    base = s->pc;
+    offset = cpu_ldsw_code(env, s->pc);
+    s->pc += 2;
+    l1 = gen_new_label();
+    gen_jmpcc(s, (insn >> 8) & 0xf, l1);
+
+    tmp = tcg_temp_new();
+    tcg_gen_ext16s_i32(tmp, reg);
+    tcg_gen_addi_i32(tmp, tmp, -1);
+    gen_partset_reg(OS_WORD, reg, tmp);
+    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, -1, l1);
+    update_cc_op(s);
+    gen_jmp_tb(s, 1, base + offset);
+    gen_set_label(l1);
+    update_cc_op(s);
+    gen_jmp_tb(s, 0, s->pc);
+}
+
 DISAS_INSN(undef_mac)
 {
     gen_exception(s, s->pc - 2, EXCP_LINEA);
@@ -3248,6 +3292,9 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(addsubq,   5080, f0c0, M68000);
     INSN(scc,       50c0, f0f8, CF_ISA_A);
     INSN(addsubq,   5080, f1c0, CF_ISA_A);
+    INSN(scc_mem,   50c0, f0c0, M68000);
+    INSN(scc,       50c0, f0f8, M68000);
+    INSN(dbcc,      50c8, f0f8, M68000);
     INSN(tpf,       51f8, fff8, CF_ISA_A);
 
     /* Branch instructions.  */
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 25/30] m68k: add abcd, sbcd, nbcd instructions
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (23 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 24/30] m68k: add DBcc and Scc (memory operand) Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 17:57   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 26/30] m68k: add mull/divl Laurent Vivier
                   ` (5 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    | 91 +++++++++++++++++++++++++++++++++++++++++++++++++
 target-m68k/helper.h    |  3 ++
 target-m68k/translate.c | 82 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 176 insertions(+)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 8c10fbc..f4be52b 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -938,3 +938,94 @@ void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
     res |= (uint64_t)(val & 0xffff0000) << 16;
     env->macc[acc + 1] = res;
 }
+
+uint32_t HELPER(abcd_cc)(CPUM68KState *env, uint32_t src, uint32_t dest)
+{
+    uint16_t hi, lo;
+    uint16_t res;
+    uint32_t flags;
+    int extend = 0;
+
+    flags = env->cc_dest;
+    flags &= ~CCF_C;
+
+    lo = (src & 0x0f) + (dest & 0x0f);
+    if (env->cc_x) {
+        lo++;
+    }
+    hi = (src & 0xf0) + (dest & 0xf0);
+
+    res = hi + lo;
+    if (lo > 9) {
+        res += 0x06;
+    }
+
+    /* C and X flags: set if decimal carry, cleared otherwise */
+
+    if ((res & 0x3F0) > 0x90) {
+        res += 0x60;
+        flags |= CCF_C;
+        extend = 1;
+    }
+
+    /* Z flag: cleared if nonzero */
+
+    if (res & 0xff) {
+        flags &= ~CCF_Z;
+    }
+
+    dest = (dest & 0xffffff00) | (res & 0xff);
+
+    env->cc_x = extend;
+    env->cc_dest = flags;
+
+    return dest;
+}
+
+uint32_t HELPER(sbcd_cc)(CPUM68KState *env, uint32_t src, uint32_t dest)
+{
+    uint16_t hi, lo;
+    uint16_t res;
+    uint32_t flags;
+    int bcd = 0, carry = 0, extend = 0;
+
+    flags = env->cc_dest;
+    flags &= CCF_C;
+
+    if (env->cc_x) {
+        carry = 1;
+    }
+
+    lo = (dest & 0x0f) - (src & 0x0f) - carry;
+    hi = (dest & 0xf0) - (src & 0xf0);
+
+    res = hi + lo;
+    if (lo & 0xf0) {
+        res -= 0x06;
+        bcd = 0x06;
+    }
+
+    if ((((dest & 0xff) - (src & 0xff) - carry) & 0x100) > 0xff) {
+        res -= 0x60;
+    }
+
+    /* C and X flags: set if decimal carry, cleared otherwise */
+
+    if ((((dest & 0xff) - (src & 0xff) - (bcd + carry)) & 0x300) > 0xff) {
+        flags |= CCF_C;
+        extend = 1;
+    }
+
+    /* Z flag: cleared if nonzero */
+
+    if (res & 0xff) {
+        flags &= ~CCF_Z;
+    }
+
+    dest = (dest & 0xffffff00) | (res & 0xff);
+
+    env->cc_x = extend;
+    env->cc_dest = flags;
+
+    return dest;
+}
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index 81fb7db..9b54ebf 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -50,3 +50,6 @@ DEF_HELPER_3(set_mac_extu, void, env, i32, i32)
 
 DEF_HELPER_2(flush_flags, i32, env, i32)
 DEF_HELPER_2(raise_exception, void, env, i32)
+
+DEF_HELPER_3(abcd_cc, i32, env, i32, i32)
+DEF_HELPER_3(sbcd_cc, i32, env, i32, i32)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index cb746d7..67527fe 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1146,6 +1146,83 @@ DISAS_INSN(divl)
     set_cc_op(s, CC_OP_FLAGS);
 }
 
+DISAS_INSN(abcd_reg)
+{
+    TCGv src;
+    TCGv dest;
+
+    src = DREG(insn, 0);
+    dest = DREG(insn, 9);
+    gen_flush_flags(s);
+    gen_helper_abcd_cc(dest, cpu_env, src, dest);
+}
+
+DISAS_INSN(abcd_mem)
+{
+    TCGv src;
+    TCGv addr_src;
+    TCGv dest;
+    TCGv addr_dest;
+
+    addr_src = AREG(insn, 0);
+    tcg_gen_subi_i32(addr_src, addr_src, OS_BYTE);
+    src = gen_load(s, OS_BYTE, addr_src, 0);
+
+    addr_dest = AREG(insn, 9);
+    tcg_gen_subi_i32(addr_dest, addr_dest, OS_BYTE);
+    dest = gen_load(s, OS_BYTE, addr_dest, 0);
+
+    gen_flush_flags(s);
+    gen_helper_abcd_cc(dest, cpu_env, src, dest);
+
+    gen_store(s, OS_BYTE, addr_dest, dest);
+}
+
+DISAS_INSN(sbcd_reg)
+{
+    TCGv src;
+    TCGv dest;
+
+    src = DREG(insn, 0);
+    dest = DREG(insn, 9);
+    gen_flush_flags(s);
+    gen_helper_sbcd_cc(dest, cpu_env, src, dest);
+}
+
+DISAS_INSN(sbcd_mem)
+{
+    TCGv src;
+    TCGv addr_src;
+    TCGv dest;
+    TCGv addr_dest;
+
+    addr_src = AREG(insn, 0);
+    tcg_gen_subi_i32(addr_src, addr_src, OS_BYTE);
+    src = gen_load(s, OS_BYTE, addr_src, 0);
+
+    addr_dest = AREG(insn, 9);
+    tcg_gen_subi_i32(addr_dest, addr_dest, OS_BYTE);
+    dest = gen_load(s, OS_BYTE, addr_dest, 0);
+
+    gen_flush_flags(s);
+    gen_helper_sbcd_cc(dest, cpu_env, src, dest);
+
+    gen_store(s, OS_BYTE, addr_dest, dest);
+}
+
+DISAS_INSN(nbcd)
+{
+    TCGv dest;
+    TCGv addr;
+
+    SRC_EA(env, dest, OS_BYTE, -1, &addr);
+
+    gen_flush_flags(s);
+    gen_helper_sbcd_cc(dest, cpu_env, dest, tcg_const_i32(0));
+
+    DEST_EA(env, insn, OS_BYTE, dest, &addr);
+}
+
 DISAS_INSN(addsub)
 {
     TCGv reg;
@@ -3239,6 +3316,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(not,       4600, ff00, M68000);
     INSN(undef,     46c0, ffc0, M68000);
     INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
+    INSN(nbcd,      4800, ffc0, M68000);
     INSN(linkl,     4808, fff8, M68000);
     INSN(pea,       4840, ffc0, CF_ISA_A);
     INSN(pea,       4840, ffc0, M68000);
@@ -3315,6 +3393,8 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(or,        8000, f000, M68000);
     INSN(divw,      80c0, f0c0, CF_ISA_A);
     INSN(divw,      80c0, f0c0, M68000);
+    INSN(sbcd_reg,  8100, f1f8, M68000);
+    INSN(sbcd_mem,  8108, f1f8, M68000);
     INSN(addsub,    9000, f000, CF_ISA_A);
     INSN(addsub,    9000, f000, M68000);
     INSN(subx,      9180, f1f8, CF_ISA_A);
@@ -3348,6 +3428,8 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(and,       c000, f000, M68000);
     INSN(mulw,      c0c0, f0c0, CF_ISA_A);
     INSN(mulw,      c0c0, f0c0, M68000);
+    INSN(abcd_reg,  c100, f1f8, M68000);
+    INSN(abcd_mem,  c108, f1f8, M68000);
     INSN(addsub,    d000, f000, CF_ISA_A);
     INSN(addsub,    d000, f000, M68000);
     INSN(addx,      d180, f1f8, CF_ISA_A);
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 26/30] m68k: add mull/divl
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (24 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 25/30] m68k: add abcd, sbcd, nbcd instructions Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 18:36   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 27/30] m68k: add addx/subx/negx Laurent Vivier
                   ` (4 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/cpu.h       |   3 +
 target-m68k/helper.h    |   6 ++
 target-m68k/op_helper.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++
 target-m68k/qregs.def   |   1 +
 target-m68k/translate.c |  65 ++++++++++++++++++----
 5 files changed, 208 insertions(+), 10 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 6d1a140..a261680 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -90,6 +90,9 @@ typedef struct CPUM68KState {
     uint32_t div1;
     uint32_t div2;
 
+    /* Upper 32 bits of a 64bit operand for quad MUL/DIV.  */
+    uint32_t quadh;
+
     /* MMU status.  */
     struct {
         uint32_t ar;
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index 9b54ebf..de4d84d 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -3,6 +3,12 @@ DEF_HELPER_1(ff1, i32, i32)
 DEF_HELPER_2(sats, i32, i32, i32)
 DEF_HELPER_2(divu, void, env, i32)
 DEF_HELPER_2(divs, void, env, i32)
+DEF_HELPER_1(divu64, void, env)
+DEF_HELPER_1(divs64, void, env)
+DEF_HELPER_3(mulu32_cc, i32, env, i32, i32)
+DEF_HELPER_3(muls32_cc, i32, env, i32, i32)
+DEF_HELPER_3(mulu64, i32, env, i32, i32)
+DEF_HELPER_3(muls64, i32, env, i32, i32)
 DEF_HELPER_3(addx_cc, i32, env, i32, i32)
 DEF_HELPER_3(subx_cc, i32, env, i32, i32)
 DEF_HELPER_3(shl_cc, i32, env, i32, i32)
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 71641bf..8ecbf8a 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -244,3 +244,146 @@ void HELPER(divs)(CPUM68KState *env, uint32_t word)
     env->div2 = rem;
     env->cc_dest = flags;
 }
+
+void HELPER(divu64)(CPUM68KState *env)
+{
+    uint32_t num;
+    uint32_t den;
+    uint64_t quot;
+    uint32_t rem;
+    uint32_t flags;
+    uint64_t quad;
+
+    num = env->div1;
+    den = env->div2;
+    /* ??? This needs to make sure the throwing location is accurate.  */
+    if (den == 0) {
+        raise_exception(env, EXCP_DIV0);
+    }
+    quad = num | ((uint64_t)env->quadh << 32);
+    quot = quad / den;
+    rem = quad % den;
+    if (quot > 0xffffffffULL) {
+        flags = (env->cc_dest & ~CCF_C) | CCF_V;
+    } else {
+        flags = 0;
+        if (quot == 0) {
+            flags |= CCF_Z;
+        } else if ((int32_t)quot < 0) {
+            flags |= CCF_N;
+        }
+        env->div1 = quot;
+        env->quadh = rem;
+    }
+    env->cc_dest = flags;
+}
+
+void HELPER(divs64)(CPUM68KState *env)
+{
+    uint32_t num;
+    int32_t den;
+    int64_t quot;
+    int32_t rem;
+    int32_t flags;
+    int64_t quad;
+
+    num = env->div1;
+    den = env->div2;
+    if (den == 0) {
+        raise_exception(env, EXCP_DIV0);
+    }
+    quad = num | ((int64_t)env->quadh << 32);
+    quot = quad / (int64_t)den;
+    rem = quad % (int64_t)den;
+
+    if ((quot & 0xffffffff80000000ULL) &&
+        (quot & 0xffffffff80000000ULL) != 0xffffffff80000000ULL) {
+        flags = (env->cc_dest & ~CCF_C) | CCF_V;
+    } else {
+        flags = 0;
+        if (quot == 0) {
+            flags |= CCF_Z;
+        } else if ((int32_t)quot < 0) {
+            flags |= CCF_N;
+        }
+        env->div1 = quot;
+        env->quadh = rem;
+    }
+    env->cc_dest = flags;
+}
+
+uint32_t HELPER(mulu32_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
+{
+    uint64_t res = (uint32_t)op1 * op2;
+    uint32_t flags;
+
+    flags = 0;
+    if (res >> 32) {
+        flags |= CCF_V;
+    }
+    if ((uint32_t)res == 0) {
+        flags |= CCF_Z;
+    }
+    if ((int32_t)res < 0) {
+        flags |= CCF_N;
+    }
+    env->cc_dest = flags;
+
+    return res;
+}
+
+uint32_t HELPER(muls32_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
+{
+    int64_t res = (int32_t)op1 * (int32_t)op2;
+    uint32_t flags;
+
+    flags = 0;
+    if (res != (int64_t)(int32_t)res) {
+        flags |= CCF_V;
+    }
+    if ((uint32_t)res == 0) {
+        flags |= CCF_Z;
+    }
+    if ((int32_t)res < 0) {
+        flags |= CCF_N;
+    }
+    env->cc_dest = flags;
+
+    return res;
+}
+
+uint32_t HELPER(mulu64)(CPUM68KState *env, uint32_t op1, uint32_t op2)
+{
+    uint64_t res = (uint64_t)op1 * op2;
+    uint32_t flags;
+
+    env->quadh = res >> 32;
+    flags = 0;
+    if (res == 0) {
+        flags |= CCF_Z;
+    }
+    if ((int64_t)res < 0) {
+        flags |= CCF_N;
+    }
+    env->cc_dest = flags;
+
+    return res;
+}
+
+uint32_t HELPER(muls64)(CPUM68KState *env, uint32_t op1, uint32_t op2)
+{
+    int64_t res = (uint64_t)(int32_t)op1 * (int32_t)op2;
+    uint32_t flags;
+
+    env->quadh = res >> 32;
+    flags = 0;
+    if (res == 0) {
+        flags |= CCF_Z;
+    }
+    if (res < 0) {
+        flags |= CCF_N;
+    }
+    env->cc_dest = flags;
+
+    return res;
+}
diff --git a/target-m68k/qregs.def b/target-m68k/qregs.def
index 204663e..aba6c9a 100644
--- a/target-m68k/qregs.def
+++ b/target-m68k/qregs.def
@@ -7,5 +7,6 @@ DEFO32(CC_SRC, cc_src)
 DEFO32(CC_X, cc_x)
 DEFO32(DIV1, div1)
 DEFO32(DIV2, div2)
+DEFO32(QUADH, quadh)
 DEFO32(MACSR, macsr)
 DEFO32(MAC_MASK, mac_mask)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 67527fe..ad11457 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1122,8 +1122,27 @@ DISAS_INSN(divl)
     uint16_t ext;
 
     ext = read_im16(env, s);
-    if (ext & 0x87f8) {
-        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+    if (ext & 0x400) {
+        if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
+            gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+            return;
+        }
+        num = DREG(ext, 12);
+        reg = DREG(ext, 0);
+        tcg_gen_mov_i32(QREG_DIV1, num);
+        tcg_gen_mov_i32(QREG_QUADH, reg);
+        SRC_EA(env, den, OS_LONG, 0, NULL);
+        tcg_gen_mov_i32(QREG_DIV2, den);
+        if (ext & 0x0800) {
+            gen_helper_divs64(cpu_env);
+        } else {
+            gen_helper_divu64(cpu_env);
+        }
+        tcg_gen_mov_i32(num, QREG_DIV1);
+        if (!TCGV_EQUAL(num, reg)) {
+            tcg_gen_mov_i32(reg, QREG_QUADH);
+        }
+        set_cc_op(s, CC_OP_FLAGS);
         return;
     }
     num = DREG(ext, 12);
@@ -1136,10 +1155,12 @@ DISAS_INSN(divl)
     } else {
         gen_helper_divu(cpu_env, tcg_const_i32(0));
     }
-    if ((ext & 7) == ((ext >> 12) & 7)) {
+    if (TCGV_EQUAL(num, reg) ||
+        m68k_feature(s->env, M68K_FEATURE_LONG_MULDIV)) {
         /* div */
-        tcg_gen_mov_i32 (reg, QREG_DIV1);
-    } else {
+        tcg_gen_mov_i32(num, QREG_DIV1);
+    }
+    if (!TCGV_EQUAL(num, reg)) {
         /* rem */
         tcg_gen_mov_i32 (reg, QREG_DIV2);
     }
@@ -1887,21 +1908,45 @@ DISAS_INSN(mull)
     TCGv reg;
     TCGv src1;
     TCGv dest;
+    TCGv regh;
 
     /* The upper 32 bits of the product are discarded, so
        muls.l and mulu.l are functionally equivalent.  */
     ext = read_im16(env, s);
-    if (ext & 0x87ff) {
-        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+    if (ext & 0x400) {
+        if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
+            gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+            return;
+        }
+        reg = DREG(ext, 12);
+        regh = DREG(ext, 0);
+        SRC_EA(env, src1, OS_LONG, 0, NULL);
+        dest = tcg_temp_new();
+        if (ext & 0x800) {
+            gen_helper_muls64(dest, cpu_env, src1, reg);
+        } else {
+            gen_helper_mulu64(dest, cpu_env, src1, reg);
+        }
+        tcg_gen_mov_i32(reg, dest);
+        tcg_gen_mov_i32(regh, QREG_QUADH);
+        set_cc_op(s, CC_OP_FLAGS);
         return;
     }
     reg = DREG(ext, 12);
     SRC_EA(env, src1, OS_LONG, 0, NULL);
     dest = tcg_temp_new();
-    tcg_gen_mul_i32(dest, src1, reg);
-    tcg_gen_mov_i32(reg, dest);
-    /* Unlike m68k, coldfire always clears the overflow bit.  */
+    if (m68k_feature(s->env, M68K_FEATURE_M68000)) {
+        if (ext & 0x800) {
+            gen_helper_muls32_cc(dest, cpu_env, src1, reg);
+        } else {
+            gen_helper_mulu32_cc(dest, cpu_env, src1, reg);
+        }
+        set_cc_op(s, CC_OP_FLAGS);
+    } else {
+        tcg_gen_mul_i32(dest, src1, reg);
+    }
     gen_logic_cc(s, dest, OS_LONG);
+    tcg_gen_mov_i32(reg, dest);
 }
 
 DISAS_INSN(link)
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 27/30] m68k: add addx/subx/negx
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (25 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 26/30] m68k: add mull/divl Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 18:46   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 28/30] m68k: shift/rotate bytes and words Laurent Vivier
                   ` (3 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    |  96 ++++++++++++++++++---------------
 target-m68k/helper.h    |   8 ++-
 target-m68k/translate.c | 141 ++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 192 insertions(+), 53 deletions(-)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index f4be52b..1360b2c 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -419,52 +419,64 @@ uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
     return val;
 }
 
-uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
-{
-    uint32_t res;
-    uint32_t old_flags;
-
-    old_flags = env->cc_dest;
-    if (env->cc_x) {
-        env->cc_x = (op1 <= op2);
-        env->cc_op = CC_OP_SUBX;
-        res = op1 - (op2 + 1);
-    } else {
-        env->cc_x = (op1 < op2);
-        env->cc_op = CC_OP_SUB;
-        res = op1 - op2;
-    }
-    env->cc_dest = res;
-    env->cc_src = op2;
-    cpu_m68k_flush_flags(env, env->cc_op);
-    /* !Z is sticky.  */
-    env->cc_dest &= (old_flags | ~CCF_Z);
-    return res;
+#define HELPER_SUBX(type, bits, size) \
+uint32_t HELPER(glue(glue(subx, bits), _cc))(CPUM68KState *env,         \
+                                            uint32_t op1, uint32_t op2) \
+{                                                                       \
+    type res;                                                           \
+    uint32_t old_flags;                                                 \
+    int op;                                                             \
+    old_flags = env->cc_dest;                                           \
+    if (env->cc_x) {                                                    \
+        env->cc_x = ((type)op1 <= (type)op2);                           \
+        op = glue(CC_OP_SUBX, size);                                    \
+        res = (type)op1 - ((type)op2 + 1);                              \
+    } else {                                                            \
+        env->cc_x = ((type)op1 < (type)op2);                            \
+        op = glue(CC_OP_SUB, size);                                     \
+        res = (type)op1 - (type)op2;                                    \
+    }                                                                   \
+    env->cc_dest = res;                                                 \
+    env->cc_src = (type)op2;                                            \
+    env->cc_dest = cpu_m68k_flush_flags(env, op);                       \
+    /* !Z is sticky.  */                                                \
+    env->cc_dest &= (old_flags | ~CCF_Z);                               \
+    return (op1 & ~((1UL << bits) - 1)) | res;                          \
 }
 
-uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
-{
-    uint32_t res;
-    uint32_t old_flags;
-
-    old_flags = env->cc_dest;
-    if (env->cc_x) {
-        res = op1 + op2 + 1;
-        env->cc_x = (res <= op2);
-        env->cc_op = CC_OP_ADDX;
-    } else {
-        res = op1 + op2;
-        env->cc_x = (res < op2);
-        env->cc_op = CC_OP_ADD;
-    }
-    env->cc_dest = res;
-    env->cc_src = op2;
-    cpu_m68k_flush_flags(env, env->cc_op);
-    /* !Z is sticky.  */
-    env->cc_dest &= (old_flags | ~CCF_Z);
-    return res;
+HELPER_SUBX(uint8_t, 8, B)
+HELPER_SUBX(uint16_t, 16, W)
+HELPER_SUBX(uint32_t, 32, )
+
+#define HELPER_ADDX(type, bits, size) \
+uint32_t HELPER(glue(glue(addx, bits), _cc))(CPUM68KState *env,         \
+                                            uint32_t op1, uint32_t op2) \
+{                                                                       \
+    type res;                                                           \
+    uint32_t old_flags;                                                 \
+    int op;                                                             \
+    old_flags = env->cc_dest;                                           \
+    if (env->cc_x) {                                                    \
+        res = (type)op1 + (type)op2 + 1;                                \
+        env->cc_x = (res <= (type)op2);                                 \
+        op = glue(CC_OP_ADDX, size);                                    \
+    } else {                                                            \
+        res = (type)op1 + (type)op2;                                    \
+        env->cc_x = (res < (type)op2);                                  \
+        op = glue(CC_OP_ADD, size);                                     \
+    }                                                                   \
+    env->cc_dest = res;                                                 \
+    env->cc_src = (type)op2;                                            \
+    env->cc_dest = cpu_m68k_flush_flags(env, op);                       \
+    /* !Z is sticky.  */                                                \
+    env->cc_dest &= (old_flags | ~CCF_Z);                               \
+    return (op1 & ~((1UL << bits) - 1)) | res;                          \
 }
 
+HELPER_ADDX(uint8_t, 8, B)
+HELPER_ADDX(uint16_t, 16, W)
+HELPER_ADDX(uint32_t, 32, )
+
 uint32_t HELPER(xflag_lt_i8)(uint32_t a, uint32_t b)
 {
     return (uint8_t)a < (uint8_t)b;
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index de4d84d..61e335d 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -9,8 +9,12 @@ DEF_HELPER_3(mulu32_cc, i32, env, i32, i32)
 DEF_HELPER_3(muls32_cc, i32, env, i32, i32)
 DEF_HELPER_3(mulu64, i32, env, i32, i32)
 DEF_HELPER_3(muls64, i32, env, i32, i32)
-DEF_HELPER_3(addx_cc, i32, env, i32, i32)
-DEF_HELPER_3(subx_cc, i32, env, i32, i32)
+DEF_HELPER_3(addx8_cc, i32, env, i32, i32)
+DEF_HELPER_3(addx16_cc, i32, env, i32, i32)
+DEF_HELPER_3(addx32_cc, i32, env, i32, i32)
+DEF_HELPER_3(subx8_cc, i32, env, i32, i32)
+DEF_HELPER_3(subx16_cc, i32, env, i32, i32)
+DEF_HELPER_3(subx32_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)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index ad11457..bac33ef 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1717,11 +1717,28 @@ DISAS_INSN(move)
 
 DISAS_INSN(negx)
 {
-    TCGv reg;
+    TCGv src;
+    TCGv dest;
+    TCGv addr;
+    int opsize;
 
+    opsize = insn_opsize(insn, 6);
     gen_flush_flags(s);
-    reg = DREG(insn, 0);
-    gen_helper_subx_cc(reg, cpu_env, tcg_const_i32(0), reg);
+    SRC_EA(env, src, opsize, -1, &addr);
+    dest = tcg_temp_new();
+    switch (opsize) {
+    case OS_BYTE:
+        gen_helper_subx8_cc(dest, cpu_env, tcg_const_i32(0), src);
+        break;
+    case OS_WORD:
+        gen_helper_subx16_cc(dest, cpu_env, tcg_const_i32(0), src);
+        break;
+    case OS_LONG:
+        gen_helper_subx32_cc(dest, cpu_env, tcg_const_i32(0), src);
+        break;
+    }
+    DEST_EA(env, insn, opsize, dest, &addr);
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 DISAS_INSN(lea)
@@ -2183,15 +2200,65 @@ DISAS_INSN(suba)
     tcg_gen_sub_i32(reg, reg, src);
 }
 
-DISAS_INSN(subx)
+DISAS_INSN(subx_reg)
 {
     TCGv reg;
     TCGv src;
+    int opsize;
+
+    opsize = insn_opsize(insn, 6);
 
     gen_flush_flags(s);
     reg = DREG(insn, 9);
     src = DREG(insn, 0);
-    gen_helper_subx_cc(reg, cpu_env, reg, src);
+    switch (opsize) {
+    case OS_BYTE:
+        gen_helper_subx8_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_WORD:
+        gen_helper_subx16_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_LONG:
+        gen_helper_subx32_cc(reg, cpu_env, reg, src);
+        break;
+    }
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(subx_mem)
+{
+    TCGv src;
+    TCGv addr_src;
+    TCGv reg;
+    TCGv addr_reg;
+    int opsize;
+
+    opsize = insn_opsize(insn, 6);
+
+    gen_flush_flags(s);
+
+    addr_src = AREG(insn, 0);
+    tcg_gen_subi_i32(addr_src, addr_src, opsize);
+    src = gen_load(s, opsize, addr_src, 0);
+
+    addr_reg = AREG(insn, 9);
+    tcg_gen_subi_i32(addr_reg, addr_reg, opsize);
+    reg = gen_load(s, opsize, addr_reg, 0);
+
+    switch (opsize) {
+    case OS_BYTE:
+        gen_helper_subx8_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_WORD:
+        gen_helper_subx16_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_LONG:
+        gen_helper_subx32_cc(reg, cpu_env, reg, src);
+        break;
+    }
+    set_cc_op(s, CC_OP_FLAGS);
+
+    gen_store(s, opsize, addr_reg, reg);
 }
 
 DISAS_INSN(mov3q)
@@ -2344,15 +2411,64 @@ DISAS_INSN(adda)
     tcg_gen_add_i32(reg, reg, src);
 }
 
-DISAS_INSN(addx)
+DISAS_INSN(addx_reg)
 {
     TCGv reg;
     TCGv src;
+    int opsize;
+
+    opsize = insn_opsize(insn, 6);
 
     gen_flush_flags(s);
     reg = DREG(insn, 9);
     src = DREG(insn, 0);
-    gen_helper_addx_cc(reg, cpu_env, reg, src);
+    switch (opsize) {
+    case OS_BYTE:
+        gen_helper_addx8_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_WORD:
+        gen_helper_addx16_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_LONG:
+        gen_helper_addx32_cc(reg, cpu_env, reg, src);
+        break;
+    }
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(addx_mem)
+{
+    TCGv src;
+    TCGv addr_src;
+    TCGv reg;
+    TCGv addr_reg;
+    int opsize;
+
+    opsize = insn_opsize(insn, 6);
+
+    gen_flush_flags(s);
+
+    addr_src = AREG(insn, 0);
+    tcg_gen_subi_i32(addr_src, addr_src, opsize);
+    src = gen_load(s, opsize, addr_src, 0);
+
+    addr_reg = AREG(insn, 9);
+    tcg_gen_subi_i32(addr_reg, addr_reg, opsize);
+    reg = gen_load(s, opsize, addr_reg, 0);
+
+    switch (opsize) {
+    case OS_BYTE:
+        gen_helper_addx8_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_WORD:
+        gen_helper_addx16_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_LONG:
+        gen_helper_addx32_cc(reg, cpu_env, reg, src);
+        break;
+    }
+
+    gen_store(s, opsize, addr_reg, reg);
     set_cc_op(s, CC_OP_FLAGS);
 }
 
@@ -3343,6 +3459,8 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(move,      3000, f000, M68000);
     INSN(strldsr,   40e7, ffff, CF_ISA_APLUSC);
     INSN(negx,      4080, fff8, CF_ISA_A);
+    INSN(negx,      4000, ff00, M68000);
+    INSN(undef,     40c0, ffc0, M68000);
     INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
     INSN(move_from_sr, 40c0, ffc0, M68000);
     INSN(lea,       41c0, f1c0, CF_ISA_A);
@@ -3442,8 +3560,11 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(sbcd_mem,  8108, f1f8, M68000);
     INSN(addsub,    9000, f000, CF_ISA_A);
     INSN(addsub,    9000, f000, M68000);
-    INSN(subx,      9180, f1f8, CF_ISA_A);
+    INSN(subx_reg,  9180, f1f8, CF_ISA_A);
+    INSN(subx_reg,  9100, f138, M68000);
+    INSN(subx_mem,  9108, f138, M68000);
     INSN(suba,      91c0, f1c0, CF_ISA_A);
+    INSN(suba,      90c0, f0c0, M68000);
 
     INSN(undef_mac, a000, f000, CF_ISA_A);
     INSN(undef_mac, a000, f000, M68000);
@@ -3477,7 +3598,9 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(abcd_mem,  c108, f1f8, M68000);
     INSN(addsub,    d000, f000, CF_ISA_A);
     INSN(addsub,    d000, f000, M68000);
-    INSN(addx,      d180, f1f8, CF_ISA_A);
+    INSN(addx_reg,  d180, f1f8, CF_ISA_A);
+    INSN(addx_reg,  d100, f138, M68000);
+    INSN(addx_mem,  d108, f138, M68000);
     INSN(adda,      d1c0, f1c0, CF_ISA_A);
     INSN(adda,      d0c0, f0c0, M68000);
     INSN(shift_im,  e080, f0f0, CF_ISA_A);
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 28/30] m68k: shift/rotate bytes and words
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (26 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 27/30] m68k: add addx/subx/negx Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 19:11   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 29/30] m68k: add rol/rox/ror/roxr Laurent Vivier
                   ` (2 subsequent siblings)
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

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

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 1360b2c..16fca70 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -498,78 +498,142 @@ void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
     m68k_switch_sp(env);
 }
 
-uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
-{
-    uint32_t result;
-    uint32_t cf;
-
-    shift &= 63;
-    if (shift == 0) {
-        result = val;
-        cf = env->cc_src & CCF_C;
-    } else if (shift < 32) {
-        result = val << shift;
-        cf = (val >> (32 - shift)) & 1;
-    } else if (shift == 32) {
-        result = 0;
-        cf = val & 1;
-    } else /* shift > 32 */ {
-        result = 0;
-        cf = 0;
-    }
-    env->cc_src = cf;
-    env->cc_x = (cf != 0);
-    env->cc_dest = result;
-    return result;
+#define HELPER_SHL(type, bits) \
+uint32_t HELPER(glue(glue(shl, bits), _cc))(CPUM68KState *env, \
+                                            uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t cf; \
+    shift &= 63; \
+    if (shift == 0) { \
+        result = (type)val; \
+        cf = 0; \
+    } else if (shift < bits) { \
+        result = (type)val << shift; \
+        cf = ((type)val >> (bits - shift)) & 1; \
+    } else if (shift == bits) { \
+        result = 0; \
+        cf = val & 1; \
+    } else { \
+        result = 0; \
+        cf = 0; \
+    } \
+    env->cc_src = cf ? CCF_C : 0; \
+    if (shift) { \
+        env->cc_x = (cf != 0); \
+    } \
+    env->cc_dest = result; \
+    return result; \
 }
 
-uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
-{
-    uint32_t result;
-    uint32_t cf;
-
-    shift &= 63;
-    if (shift == 0) {
-        result = val;
-        cf = env->cc_src & CCF_C;
-    } else if (shift < 32) {
-        result = val >> shift;
-        cf = (val >> (shift - 1)) & 1;
-    } else if (shift == 32) {
-        result = 0;
-        cf = val >> 31;
-    } else /* shift > 32 */ {
-        result = 0;
-        cf = 0;
-    }
-    env->cc_src = cf;
-    env->cc_x = (cf != 0);
-    env->cc_dest = result;
-    return result;
+HELPER_SHL(uint8_t, 8)
+HELPER_SHL(uint16_t, 16)
+HELPER_SHL(uint32_t, 32)
+
+#define HELPER_SHR(type, bits) \
+uint32_t HELPER(glue(glue(shr, bits), _cc))(CPUM68KState *env, \
+                                            uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t cf; \
+    shift &= 63; \
+    if (shift == 0) { \
+        result = (type)val; \
+        cf = 0; \
+    } else if (shift < bits) { \
+        result = (type)val >> shift; \
+        cf = ((type)val >> (shift - 1)) & 1; \
+    } else if (shift == bits) { \
+        result = 0; \
+        cf = (type)val >> (bits - 1); \
+    } else { \
+        result = 0; \
+        cf = 0; \
+    } \
+    env->cc_src = cf ? CCF_C : 0; \
+    if (shift) { \
+        env->cc_x = (cf != 0); \
+    } \
+    env->cc_dest = result; \
+    return result; \
 }
 
-uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
-{
-    uint32_t result;
-    uint32_t cf;
-
-    shift &= 63;
-    if (shift == 0) {
-        result = val;
-        cf = (env->cc_src & CCF_C) != 0;
-    } else if (shift < 32) {
-        result = (int32_t)val >> shift;
-        cf = (val >> (shift - 1)) & 1;
-    } else /* shift >= 32 */ {
-        result = (int32_t)val >> 31;
-        cf = val >> 31;
-    }
-    env->cc_src = cf;
-    env->cc_x = cf;
-    env->cc_dest = result;
-    return result;
+HELPER_SHR(uint8_t, 8)
+HELPER_SHR(uint16_t, 16)
+HELPER_SHR(uint32_t, 32)
+
+#define HELPER_SAL(type, bits) \
+uint32_t HELPER(glue(glue(sal, bits), _cc))(CPUM68KState *env, \
+                                            uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t cf; \
+    uint32_t vf; \
+    uint32_t m; \
+    shift &= 63; \
+    if (shift == 0) { \
+        vf = 0; \
+    } else if (shift < bits) { \
+        m = ((1llu << (shift + 1)) - 1) << (bits - shift - 1); \
+        vf = (val & m) != m && (val & m) != 0; \
+    } else { \
+        m = (1llu << bits) - 1; \
+        vf = (val & m) != 0; \
+    } \
+    if (shift == 0) { \
+        result = (type)val; \
+        cf = 0; \
+    } else if (shift < bits) { \
+        result = (type)val << shift; \
+        cf = ((type)val >> (bits - shift)) & 1; \
+    } else if (shift == bits) { \
+        result = 0; \
+        cf = val & 1; \
+    } else { \
+        result = 0; \
+        cf = 0; \
+    } \
+    env->cc_src = (cf ? CCF_C : 0) | (vf ? CCF_V : 0); \
+    if (shift) { \
+        env->cc_x = (cf != 0); \
+    } \
+    env->cc_dest = result; \
+    return result; \
 }
 
+HELPER_SAL(int8_t, 8)
+HELPER_SAL(int16_t, 16)
+HELPER_SAL(int32_t, 32)
+
+#define HELPER_SAR(type, bits) \
+uint32_t HELPER(glue(glue(sar, bits), _cc))(CPUM68KState *env, \
+                                            uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t cf; \
+    shift &= 63; \
+    if (shift == 0) { \
+        result = (type)val; \
+        cf = 0; \
+    } else if (shift < bits) { \
+        result = (type)val >> shift; \
+        cf = ((type)val >> (shift - 1)) & 1; \
+    } else { \
+        result = (type)val >> (bits - 1); \
+        cf = (type)val >> (bits - 1); \
+    } \
+    env->cc_src = cf ? CCF_C : 0; \
+    if (shift) { \
+        env->cc_x = (cf != 0); \
+    } \
+    env->cc_dest = result; \
+    return result; \
+}
+
+HELPER_SAR(int8_t, 8)
+HELPER_SAR(int16_t, 16)
+HELPER_SAR(int32_t, 32)
+
 /* FPU helpers.  */
 uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
 {
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index 61e335d..a39ee7d 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -15,9 +15,18 @@ DEF_HELPER_3(addx32_cc, i32, env, i32, i32)
 DEF_HELPER_3(subx8_cc, i32, env, i32, i32)
 DEF_HELPER_3(subx16_cc, i32, env, i32, i32)
 DEF_HELPER_3(subx32_cc, i32, env, i32, i32)
-DEF_HELPER_3(shl_cc, i32, env, i32, i32)
-DEF_HELPER_3(shr_cc, i32, env, i32, i32)
-DEF_HELPER_3(sar_cc, i32, env, i32, i32)
+DEF_HELPER_3(shl8_cc, i32, env, i32, i32)
+DEF_HELPER_3(shl16_cc, i32, env, i32, i32)
+DEF_HELPER_3(shl32_cc, i32, env, i32, i32)
+DEF_HELPER_3(shr8_cc, i32, env, i32, i32)
+DEF_HELPER_3(shr16_cc, i32, env, i32, i32)
+DEF_HELPER_3(shr32_cc, i32, env, i32, i32)
+DEF_HELPER_3(sal8_cc, i32, env, i32, i32)
+DEF_HELPER_3(sal16_cc, i32, env, i32, i32)
+DEF_HELPER_3(sal32_cc, i32, env, i32, i32)
+DEF_HELPER_3(sar8_cc, i32, env, i32, i32)
+DEF_HELPER_3(sar16_cc, i32, env, i32, i32)
+DEF_HELPER_3(sar32_cc, i32, env, i32, i32)
 DEF_HELPER_2(xflag_lt_i8, i32, i32, i32)
 DEF_HELPER_2(xflag_lt_i16, i32, i32, i32)
 DEF_HELPER_2(xflag_lt_i32, i32, i32, i32)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index bac33ef..22d4296 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2473,6 +2473,74 @@ DISAS_INSN(addx_mem)
 }
 
 /* TODO: This could be implemented without helper functions.  */
+DISAS_INSN(shift8_im)
+{
+    TCGv reg;
+    int tmp;
+    TCGv shift;
+    TCGv dest;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0) {
+        tmp = 8;
+    }
+    shift = tcg_const_i32(tmp);
+    dest = tcg_temp_new_i32();
+    /* No need to flush flags becuse we know we will set C flag.  */
+    if (insn & 0x100) {
+        if (insn & 8) {
+            gen_helper_shl8_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_sal8_cc(dest, cpu_env, reg, shift);
+        }
+    } else {
+        if (insn & 8) {
+            gen_helper_shr8_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_sar8_cc(dest, cpu_env, reg, shift);
+        }
+    }
+    gen_partset_reg(OS_BYTE, reg, dest);
+    set_cc_op(s, CC_OP_SHIFTB);
+}
+
+/* TODO: This could be implemented without helper functions.  */
+DISAS_INSN(shift16_im)
+{
+    TCGv reg;
+    int tmp;
+    TCGv shift;
+    TCGv dest;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0) {
+        tmp = 8;
+    }
+    shift = tcg_const_i32(tmp);
+    dest = tcg_temp_new_i32();
+    /* No need to flush flags becuse we know we will set C flag.  */
+    if (insn & 0x100) {
+        if (insn & 8) {
+            gen_helper_shl16_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_sal16_cc(dest, cpu_env, reg, shift);
+        }
+    } else {
+        if (insn & 8) {
+            gen_helper_shr16_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_sar16_cc(dest, cpu_env, reg, shift);
+        }
+    }
+    gen_partset_reg(OS_WORD, reg, dest);
+    set_cc_op(s, CC_OP_SHIFTW);
+}
+
+
+/* TODO: This could be implemented without helper functions.  */
+
 DISAS_INSN(shift_im)
 {
     TCGv reg;
@@ -2481,22 +2549,87 @@ DISAS_INSN(shift_im)
 
     reg = DREG(insn, 0);
     tmp = (insn >> 9) & 7;
-    if (tmp == 0)
+    if (tmp == 0) {
         tmp = 8;
+    }
     shift = tcg_const_i32(tmp);
     /* No need to flush flags becuse we know we will set C flag.  */
     if (insn & 0x100) {
-        gen_helper_shl_cc(reg, cpu_env, reg, shift);
+        if (insn & 8) {
+            gen_helper_shl32_cc(reg, cpu_env, reg, shift);
+        } else {
+            gen_helper_sal32_cc(reg, cpu_env, reg, shift);
+        }
     } else {
         if (insn & 8) {
-            gen_helper_shr_cc(reg, cpu_env, reg, shift);
+            gen_helper_shr32_cc(reg, cpu_env, reg, shift);
         } else {
-            gen_helper_sar_cc(reg, cpu_env, reg, shift);
+            gen_helper_sar32_cc(reg, cpu_env, reg, shift);
         }
     }
     set_cc_op(s, CC_OP_SHIFT);
 }
 
+DISAS_INSN(shift8_reg)
+{
+    TCGv reg;
+    TCGv shift;
+    TCGv dest;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    shift = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, shift, 63);
+    dest = tcg_temp_new_i32();
+    /* Shift by zero leaves C flag unmodified.   */
+    if (insn & 0x100) {
+        if (insn & 8) {
+            gen_helper_shl8_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_sal8_cc(dest, cpu_env, reg, tmp);
+        }
+    } else {
+        if (insn & 8) {
+            gen_helper_shr8_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_sar8_cc(dest, cpu_env, reg, tmp);
+        }
+    }
+    gen_partset_reg(OS_BYTE, reg, dest);
+    set_cc_op(s, CC_OP_SHIFTB);
+}
+
+DISAS_INSN(shift16_reg)
+{
+    TCGv reg;
+    TCGv shift;
+    TCGv dest;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    shift = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, shift, 63);
+    dest = tcg_temp_new_i32();
+    /* Shift by zero leaves C flag unmodified.   */
+    if (insn & 0x100) {
+        if (insn & 8) {
+            gen_helper_shl16_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_sal16_cc(dest, cpu_env, reg, tmp);
+        }
+    } else {
+        if (insn & 8) {
+            gen_helper_shr16_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_sar16_cc(dest, cpu_env, reg, tmp);
+        }
+    }
+    gen_partset_reg(OS_WORD, reg, dest);
+    set_cc_op(s, CC_OP_SHIFTW);
+}
+
 DISAS_INSN(shift_reg)
 {
     TCGv reg;
@@ -2505,19 +2638,46 @@ 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);
+        if (insn & 8) {
+            gen_helper_shl32_cc(reg, cpu_env, reg, shift);
+        } else {
+            gen_helper_sal32_cc(reg, cpu_env, reg, shift);
+        }
     } else {
         if (insn & 8) {
-            gen_helper_shr_cc(reg, cpu_env, reg, shift);
+            gen_helper_shr32_cc(reg, cpu_env, reg, shift);
         } else {
-            gen_helper_sar_cc(reg, cpu_env, reg, shift);
+            gen_helper_sar32_cc(reg, cpu_env, reg, shift);
         }
     }
     set_cc_op(s, CC_OP_SHIFT);
 }
 
+DISAS_INSN(shift_mem)
+{
+    TCGv src;
+    TCGv dest;
+    TCGv addr;
+    TCGv shift;
+
+    SRC_EA(env, src, OS_WORD, 0, &addr);
+    dest = tcg_temp_new_i32();
+    shift = tcg_const_i32(1);
+    if (insn & 0x100) {
+        gen_helper_shl16_cc(dest, cpu_env, src, shift);
+    } else {
+        if (insn & 8) {
+            gen_helper_shr16_cc(dest, cpu_env, src, shift);
+        } else {
+            gen_helper_sar16_cc(dest, cpu_env, src, shift);
+        }
+    }
+    DEST_EA(env, insn, OS_WORD, dest, &addr);
+    set_cc_op(s, CC_OP_SHIFTW);
+}
+
+
 DISAS_INSN(ff1)
 {
     TCGv reg;
@@ -3605,6 +3765,13 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(adda,      d0c0, f0c0, M68000);
     INSN(shift_im,  e080, f0f0, CF_ISA_A);
     INSN(shift_reg, e0a0, f0f0, CF_ISA_A);
+    INSN(shift8_im, e000, f0f0, M68000);
+    INSN(shift16_im, e040, f0f0, M68000);
+    INSN(shift_im,  e080, f0f0, M68000);
+    INSN(shift8_reg, e020, f0f0, M68000);
+    INSN(shift16_reg, e060, f0f0, M68000);
+    INSN(shift_reg, e0a0, f0f0, M68000);
+    INSN(shift_mem, e0c0, fcc0, M68000);
     INSN(undef_fpu, f000, f000, CF_ISA_A);
     INSN(fpu,       f200, ffc0, CF_FPU);
     INSN(fbcc,      f280, ffc0, CF_FPU);
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 29/30] m68k: add rol/rox/ror/roxr
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (27 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 28/30] m68k: shift/rotate bytes and words Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 19:40   ` Richard Henderson
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 30/30] m68k: add bitfield instructions Laurent Vivier
  2015-08-13  2:22 ` [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Richard Henderson
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    | 212 ++++++++++++++++++++++++++++++++++++++++++++++++
 target-m68k/helper.h    |  14 ++++
 target-m68k/translate.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 433 insertions(+)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 16fca70..532f366 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -25,6 +25,42 @@
 
 #define SIGNBIT (1u << 31)
 
+/* modulo 33 table */
+const uint8_t rox32_table[64] = {
+    0,  1,  2,  3,  4,  5,  6,  7,
+    8,  9, 10, 11, 12, 13, 14, 15,
+   16, 17, 18, 19, 20, 21, 22, 23,
+   24, 25, 26, 27, 28, 29, 30, 31,
+   32,  0,  1,  2,  3,  4,  5,  6,
+    7,  8,  9, 10, 11, 12, 13, 14,
+   15, 16, 17, 18, 19, 20, 21, 22,
+   23, 24, 25, 26, 27, 28, 29, 30,
+};
+
+/* modulo 17 table */
+const uint8_t rox16_table[64] = {
+    0,  1,  2,  3,  4,  5,  6,  7,
+    8,  9, 10, 11, 12, 13, 14, 15,
+   16,  0,  1,  2,  3,  4,  5,  6,
+    7,  8,  9, 10, 11, 12, 13, 14,
+   15, 16,  0,  1,  2,  3,  4,  5,
+    6,  7,  8,  9, 10, 11, 12, 13,
+   14, 15, 16,  0,  1, 2,   3,  4,
+    5,  6,  7,  8,  9, 10, 11, 12,
+};
+
+/* modulo 9 table */
+const uint8_t rox8_table[64] = {
+    0, 1, 2, 3, 4, 5, 6, 7,
+    8, 0, 1, 2, 3, 4, 5, 6,
+    7, 8, 0, 1, 2, 3, 4, 5,
+    6, 7, 8, 0, 1, 2, 3, 4,
+    5, 6, 7, 8, 0, 1, 2, 3,
+    4, 5, 6, 7, 8, 0, 1, 2,
+    3, 4, 5, 6, 7, 8, 0, 1,
+    2, 3, 4, 5, 6, 7, 8, 0,
+};
+
 /* Sort alphabetically, except for "any". */
 static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
 {
@@ -411,6 +447,26 @@ uint32_t HELPER(ff1)(uint32_t x)
     return n;
 }
 
+uint32_t HELPER(rol32)(uint32_t val, uint32_t shift)
+{
+    uint32_t result;
+    if (shift == 0 || shift == 32) {
+        return val;
+    }
+    result = (val << shift) | (val >> (32 - shift));
+    return result;
+}
+
+uint32_t HELPER(ror32)(uint32_t val, uint32_t shift)
+{
+    uint32_t result;
+    if (shift == 0 || shift == 32) {
+        return val;
+    }
+    result = (val >> shift) | (val << (32 - shift));
+    return result;
+}
+
 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
 {
     /* The result has the opposite sign to the original value.  */
@@ -634,6 +690,162 @@ HELPER_SAR(int8_t, 8)
 HELPER_SAR(int16_t, 16)
 HELPER_SAR(int32_t, 32)
 
+#define HELPER_ROL(type, bits) \
+uint32_t HELPER(glue(glue(rol, bits), _cc))(CPUM68KState *env, \
+                                            uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t flags; \
+    int count = shift & (bits - 1); \
+    if (count) { \
+        result = ((type)val << count) | ((type)val >> (bits - count)); \
+    } else { \
+        result = (type)val; \
+    } \
+    flags = 0; \
+    if (result == 0) { \
+        flags |= CCF_Z; \
+    } \
+    if (result & (1 << (bits - 1))) { \
+        flags |= CCF_N; \
+    } \
+    if (shift && result & 1) { \
+        flags |= CCF_C; \
+    } \
+    env->cc_dest = flags; \
+    return result; \
+}
+
+HELPER_ROL(uint8_t, 8)
+HELPER_ROL(uint16_t, 16)
+HELPER_ROL(uint32_t, 32)
+
+#define HELPER_ROR(type, bits) \
+uint32_t HELPER(glue(glue(ror, bits), _cc))(CPUM68KState *env, \
+                                            uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t flags; \
+    int count = shift & (bits - 1); \
+    if (count) { \
+        result = ((type)val >> count) | ((type)val << (bits - count)); \
+    } else { \
+        result = (type)val; \
+    } \
+    flags = 0; \
+    if (result == 0) { \
+        flags |= CCF_Z; \
+    } \
+    if (result & (1 << (bits - 1))) { \
+        flags |= CCF_N; \
+    } \
+    if (shift && result & (1 << (bits - 1))) { \
+        flags |= CCF_C; \
+    } \
+    env->cc_dest = flags; \
+    return result; \
+}
+
+HELPER_ROR(uint8_t, 8)
+HELPER_ROR(uint16_t, 16)
+HELPER_ROR(uint32_t, 32)
+
+#define HELPER_ROXR(type, bits) \
+uint32_t HELPER(glue(glue(roxr, bits), _cc))(CPUM68KState *env, \
+                                             uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t flags; \
+    int count = shift; \
+    if (bits == 8) { \
+        count = rox8_table[count]; \
+    } \
+    if (bits == 16) { \
+        count = rox16_table[count]; \
+    } \
+    if (bits == 32) { \
+        count = rox32_table[count]; \
+    } \
+    if (count) { \
+        if (count == bits) { \
+            result = ((type)env->cc_x << (bits - count));\
+        } else { \
+            result = ((type)val >> count) | \
+                     ((type)env->cc_x << (bits - count));\
+        } \
+        if (count > 1) { \
+            result |= (type)val << (bits + 1 - count); \
+        } \
+        env->cc_x = ((type)val >> (count - 1)) & 1; \
+    } else { \
+        result = (type)val; \
+    } \
+    flags = 0; \
+    if (result == 0) { \
+        flags |= CCF_Z; \
+    } \
+    if (result & (1 << (bits - 1))) { \
+        flags |= CCF_N; \
+    } \
+    if (env->cc_x) { \
+        flags |= CCF_C; \
+    } \
+    env->cc_dest = flags; \
+    return result; \
+}
+
+HELPER_ROXR(uint8_t, 8)
+HELPER_ROXR(uint16_t, 16)
+HELPER_ROXR(uint32_t, 32)
+
+#define HELPER_ROXL(type, bits) \
+uint32_t HELPER(glue(glue(roxl, bits), _cc))(CPUM68KState *env, \
+                                             uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t flags; \
+    int count; \
+    count = shift; \
+    if (bits == 8) { \
+        count = rox8_table[count]; \
+    } \
+    if (bits == 16) { \
+        count = rox16_table[count]; \
+    } \
+    if (bits == 32) { \
+        count = rox32_table[count]; \
+    } \
+    if (count) { \
+        if (count == bits) { \
+            result = ((type)env->cc_x << (count - 1)); \
+        } else { \
+            result = ((type)val << count) | ((type)env->cc_x << (count - 1)); \
+        } \
+        if (count > 1) { \
+            result |= (type)val >> (bits + 1 - count); \
+        } \
+        env->cc_x = ((type)val >> (bits - count)) & 1; \
+    } else { \
+        result = (type)val; \
+    } \
+    flags = 0; \
+    if (result == 0) { \
+        flags |= CCF_Z; \
+    } \
+    if (result & (1 << (bits - 1))) { \
+        flags |= CCF_N; \
+    } \
+    if (env->cc_x) { \
+        flags |= CCF_C; \
+    } \
+    env->cc_dest = flags; \
+    return result; \
+}
+
+HELPER_ROXL(uint8_t, 8)
+HELPER_ROXL(uint16_t, 16)
+HELPER_ROXL(uint32_t, 32)
+
 /* FPU helpers.  */
 uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
 {
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index a39ee7d..209064c 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -1,5 +1,7 @@
 DEF_HELPER_1(bitrev, i32, i32)
 DEF_HELPER_1(ff1, i32, i32)
+DEF_HELPER_2(rol32, i32, i32, i32)
+DEF_HELPER_2(ror32, i32, i32, i32)
 DEF_HELPER_2(sats, i32, i32, i32)
 DEF_HELPER_2(divu, void, env, i32)
 DEF_HELPER_2(divs, void, env, i32)
@@ -27,6 +29,18 @@ DEF_HELPER_3(sal32_cc, i32, env, i32, i32)
 DEF_HELPER_3(sar8_cc, i32, env, i32, i32)
 DEF_HELPER_3(sar16_cc, i32, env, i32, i32)
 DEF_HELPER_3(sar32_cc, i32, env, i32, i32)
+DEF_HELPER_3(rol8_cc, i32, env, i32, i32)
+DEF_HELPER_3(rol16_cc, i32, env, i32, i32)
+DEF_HELPER_3(rol32_cc, i32, env, i32, i32)
+DEF_HELPER_3(ror8_cc, i32, env, i32, i32)
+DEF_HELPER_3(ror16_cc, i32, env, i32, i32)
+DEF_HELPER_3(ror32_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxr8_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxr16_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxr32_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxl8_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxl16_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxl32_cc, i32, env, i32, i32)
 DEF_HELPER_2(xflag_lt_i8, i32, i32, i32)
 DEF_HELPER_2(xflag_lt_i16, i32, i32, i32)
 DEF_HELPER_2(xflag_lt_i32, i32, i32, i32)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 22d4296..5fc7a11 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2677,6 +2677,206 @@ DISAS_INSN(shift_mem)
     set_cc_op(s, CC_OP_SHIFTW);
 }
 
+DISAS_INSN(rotate_im)
+{
+    TCGv reg;
+    TCGv shift;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0) {
+        tmp = 8;
+    }
+    shift = tcg_const_i32(tmp);
+    if (insn & 8) {
+        if (insn & 0x100) {
+            gen_helper_rol32_cc(reg, cpu_env, reg, shift);
+        } else {
+            gen_helper_ror32_cc(reg, cpu_env, reg, shift);
+        }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl32_cc(reg, cpu_env, reg, shift);
+        } else {
+            gen_helper_roxr32_cc(reg, cpu_env, reg, shift);
+        }
+    }
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(rotate8_im)
+{
+    TCGv reg;
+    TCGv dest;
+    TCGv shift;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0) {
+        tmp = 8;
+    }
+    dest = tcg_temp_new_i32();
+    shift = tcg_const_i32(tmp);
+    if (insn & 8) {
+        if (insn & 0x100) {
+            gen_helper_rol8_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_ror8_cc(dest, cpu_env, reg, shift);
+        }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl8_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_roxr8_cc(dest, cpu_env, reg, shift);
+        }
+    }
+    gen_partset_reg(OS_BYTE, reg, dest);
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(rotate16_im)
+{
+    TCGv reg;
+    TCGv dest;
+    TCGv shift;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0) {
+        tmp = 8;
+    }
+    dest = tcg_temp_new_i32();
+    shift = tcg_const_i32(tmp);
+    if (insn & 8) {
+        if (insn & 0x100) {
+            gen_helper_rol16_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_ror16_cc(dest, cpu_env, reg, shift);
+        }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl16_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_roxr16_cc(dest, cpu_env, reg, shift);
+        }
+    }
+    gen_partset_reg(OS_WORD, reg, dest);
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(rotate_reg)
+{
+    TCGv reg;
+    TCGv src;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, src, 63);
+    if (insn & 8) {
+        if (insn & 0x100) {
+            gen_helper_rol32_cc(reg, cpu_env, reg, tmp);
+        } else {
+            gen_helper_ror32_cc(reg, cpu_env, reg, tmp);
+        }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl32_cc(reg, cpu_env, reg, tmp);
+        } else {
+            gen_helper_roxr32_cc(reg, cpu_env, reg, tmp);
+        }
+    }
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(rotate8_reg)
+{
+    TCGv reg;
+    TCGv src;
+    TCGv dest;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, src, 63);
+    dest = tcg_temp_new_i32();
+    if (insn & 8) {
+        if (insn & 0x100) {
+            gen_helper_rol8_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_ror8_cc(dest, cpu_env, reg, tmp);
+        }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl8_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_roxr8_cc(dest, cpu_env, reg, tmp);
+        }
+    }
+    gen_partset_reg(OS_BYTE, reg, dest);
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(rotate16_reg)
+{
+    TCGv reg;
+    TCGv src;
+    TCGv dest;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, src, 63);
+    dest = tcg_temp_new_i32();
+    if (insn & 8) {
+        if (insn & 0x100) {
+            gen_helper_rol16_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_ror16_cc(dest, cpu_env, reg, tmp);
+        }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl16_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_roxr16_cc(dest, cpu_env, reg, tmp);
+        }
+    }
+    gen_partset_reg(OS_WORD, reg, dest);
+    set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(rotate_mem)
+{
+    TCGv src;
+    TCGv dest;
+    TCGv addr;
+    TCGv shift;
+
+    SRC_EA(env, src, OS_WORD, 0, &addr);
+    dest = tcg_temp_new_i32();
+    shift = tcg_const_i32(1);
+    if (insn & 8) {
+        if (insn & 0x100) {
+            gen_helper_rol16_cc(dest, cpu_env, src, shift);
+        } else {
+            gen_helper_ror16_cc(dest, cpu_env, src, shift);
+        }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl16_cc(dest, cpu_env, src, shift);
+        } else {
+            gen_helper_roxr16_cc(dest, cpu_env, src, shift);
+        }
+    }
+    DEST_EA(env, insn, OS_WORD, dest, &addr);
+    set_cc_op(s, CC_OP_FLAGS);
+}
 
 DISAS_INSN(ff1)
 {
@@ -3772,6 +3972,13 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(shift16_reg, e060, f0f0, M68000);
     INSN(shift_reg, e0a0, f0f0, M68000);
     INSN(shift_mem, e0c0, fcc0, M68000);
+    INSN(rotate_im, e090, f0f0, M68000);
+    INSN(rotate8_im, e010, f0f0, M68000);
+    INSN(rotate16_im, e050, f0f0, M68000);
+    INSN(rotate_reg, e0b0, f0f0, M68000);
+    INSN(rotate8_reg, e030, f0f0, M68000);
+    INSN(rotate16_reg, e070, f0f0, M68000);
+    INSN(rotate_mem, e4c0, fcc0, M68000);
     INSN(undef_fpu, f000, f000, CF_ISA_A);
     INSN(fpu,       f200, ffc0, CF_FPU);
     INSN(fbcc,      f280, ffc0, CF_FPU);
-- 
2.4.3

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

* [Qemu-devel] [PATCH for-2.5 30/30] m68k: add bitfield instructions
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (28 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 29/30] m68k: add rol/rox/ror/roxr Laurent Vivier
@ 2015-08-09 20:13 ` Laurent Vivier
  2015-08-12 21:05   ` Richard Henderson
  2015-08-13  2:22 ` [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Richard Henderson
  30 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-09 20:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, Laurent Vivier, gerg

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    |  61 +++++++++
 target-m68k/helper.h    |   4 +
 target-m68k/translate.c | 331 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 396 insertions(+)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 532f366..aceeee4 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -447,6 +447,20 @@ uint32_t HELPER(ff1)(uint32_t x)
     return n;
 }
 
+uint32_t HELPER(bfffo)(uint32_t arg, uint32_t width)
+{
+    int n;
+    uint32_t mask;
+    mask = 0x80000000;
+    for (n = 0; n < width; n++) {
+        if (arg & mask) {
+            break;
+        }
+        mask >>= 1;
+    }
+    return n;
+}
+
 uint32_t HELPER(rol32)(uint32_t val, uint32_t shift)
 {
     uint32_t result;
@@ -1227,6 +1241,53 @@ void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
     env->macc[acc + 1] = res;
 }
 
+/* load from a bitfield */
+
+uint64_t HELPER(bitfield_load)(uint32_t addr, uint32_t offset, uint32_t width)
+{
+    uint8_t data[8];
+    uint64_t bitfield;
+    int size;
+    int i;
+
+    size = (offset + width + 7) >> 3;
+#if defined(CONFIG_USER_ONLY)
+    cpu_memory_rw_debug(NULL, (target_ulong)addr, data, size, 0);
+#else
+    cpu_physical_memory_rw(addr, data, size, 0);
+#endif
+
+    bitfield = data[0];
+    for (i = 1; i < 8; i++) {
+        bitfield = (bitfield << 8) | data[i];
+    }
+
+    return bitfield;
+}
+
+/* store to a bitfield */
+
+void HELPER(bitfield_store)(uint32_t addr, uint32_t offset, uint32_t width,
+                            uint64_t bitfield)
+{
+    uint8_t data[8];
+    int size;
+    int i;
+
+    size = (offset + width + 7) >> 3;
+
+    for (i = 0; i < 8; i++) {
+        data[7 - i] = bitfield;
+        bitfield >>= 8;
+    }
+
+#if defined(CONFIG_USER_ONLY)
+    cpu_memory_rw_debug(NULL, (target_ulong)addr, data, size, 1);
+#else
+    cpu_physical_memory_rw(addr, data, size, 1);
+#endif
+}
+
 uint32_t HELPER(abcd_cc)(CPUM68KState *env, uint32_t src, uint32_t dest)
 {
     uint16_t hi, lo;
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index 209064c..5db4278 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -1,5 +1,6 @@
 DEF_HELPER_1(bitrev, i32, i32)
 DEF_HELPER_1(ff1, i32, i32)
+DEF_HELPER_2(bfffo, i32, i32, i32)
 DEF_HELPER_2(rol32, i32, i32, i32)
 DEF_HELPER_2(ror32, i32, i32, i32)
 DEF_HELPER_2(sats, i32, i32, i32)
@@ -84,5 +85,8 @@ DEF_HELPER_3(set_mac_extu, void, env, i32, i32)
 DEF_HELPER_2(flush_flags, i32, env, i32)
 DEF_HELPER_2(raise_exception, void, env, i32)
 
+DEF_HELPER_3(bitfield_load, i64, i32, i32, i32)
+DEF_HELPER_4(bitfield_store, void, i32, i32, i32, i64)
+
 DEF_HELPER_3(abcd_cc, i32, env, i32, i32)
 DEF_HELPER_3(sbcd_cc, i32, env, i32, i32)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 5fc7a11..2725a9f 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2878,6 +2878,335 @@ DISAS_INSN(rotate_mem)
     set_cc_op(s, CC_OP_FLAGS);
 }
 
+static void bitfield_param(uint16_t ext, TCGv *offset, TCGv *width, TCGv *mask)
+{
+    TCGv tmp;
+
+    /* offset */
+
+    if (ext & 0x0800) {
+        *offset = tcg_temp_new_i32();
+        tcg_gen_mov_i32(*offset, DREG(ext, 6));
+    } else {
+        *offset = tcg_temp_new_i32();
+        tcg_gen_movi_i32(*offset, (ext >> 6) & 31);
+    }
+
+    /* width */
+
+    if (ext & 0x0020) {
+        *width = tcg_temp_new_i32();
+        tcg_gen_subi_i32(*width, DREG(ext, 0), 1);
+        tcg_gen_andi_i32(*width, *width, 31);
+        tcg_gen_addi_i32(*width, *width, 1);
+    } else {
+        *width = tcg_temp_new_i32();
+        tcg_gen_movi_i32(*width, ((ext - 1) & 31) + 1);
+    }
+
+    /* mask */
+
+    tmp = tcg_temp_new_i32();
+    tcg_gen_sub_i32(tmp, tcg_const_i32(32), *width);
+    *mask = tcg_temp_new_i32();
+    tcg_gen_shl_i32(*mask, tcg_const_i32(0xffffffff), tmp);
+}
+
+DISAS_INSN(bitfield_reg)
+{
+    uint16_t ext;
+    TCGv tmp;
+    TCGv tmp1;
+    TCGv reg;
+    TCGv offset;
+    TCGv width;
+    int op;
+    TCGv reg2;
+    TCGv mask;
+
+    reg = DREG(insn, 0);
+    op = (insn >> 8) & 7;
+    ext = read_im16(env, s);
+
+    bitfield_param(ext, &offset, &width, &mask);
+
+    if (ext & 0x0800) {
+        tcg_gen_andi_i32(offset, offset, 31);
+    }
+    gen_helper_ror32(mask, mask, offset);
+
+    /* reg & mask */
+
+    tmp = tcg_temp_new_i32();
+    tcg_gen_and_i32(tmp, reg, mask);
+
+    tmp1 = tcg_temp_new_i32();
+    gen_helper_rol32(tmp1, tmp, offset);
+
+    reg2 = DREG(ext, 12);
+    if (op == 7) {
+        TCGv tmp2;
+
+        tmp2 = tcg_temp_new_i32();
+        tcg_gen_sub_i32(tmp2, tcg_const_i32(32), width);
+        tcg_gen_shl_i32(tmp2, reg2, tmp2);
+        tcg_gen_and_i32(tmp2, tmp2, mask);
+        gen_logic_cc(s, tmp2, OS_LONG);
+
+        tcg_temp_free_i32(tmp1);
+    } else {
+        gen_logic_cc(s, tmp1, OS_LONG);
+    }
+
+    switch (op) {
+    case 0: /* bftst */
+        break;
+    case 1: /* bfextu */
+        tcg_gen_add_i32(tmp1, offset, width);
+        tcg_gen_andi_i32(tmp1, tmp1, 31);
+        gen_helper_rol32(reg2, tmp, tmp1);
+        break;
+    case 2: /* bfchg */
+        tcg_gen_xor_i32(reg, reg, mask);
+        break;
+    case 3: /* bfexts */
+        gen_helper_rol32(reg2, tmp, offset);
+        tcg_gen_sub_i32(width, tcg_const_i32(32), width);
+        tcg_gen_sar_i32(reg2, reg2, width);
+        break;
+    case 4: /* bfclr */
+        tcg_gen_not_i32(mask, mask);
+        tcg_gen_and_i32(reg, reg, mask);
+        break;
+    case 5: /* bfffo */
+        gen_helper_rol32(reg2, tmp, offset);
+        gen_helper_bfffo(tmp, tmp, width);
+        tcg_gen_add_i32(reg2, tmp, offset);
+        break;
+    case 6: /* bfset */
+        tcg_gen_or_i32(reg, reg, mask);
+        break;
+    case 7: /* bfins */
+        tcg_gen_shl_i32(tmp1, tcg_const_i32(1), width);
+        tcg_gen_subi_i32(tmp1, tmp1, 1);
+        tcg_gen_and_i32(tmp, reg2, tmp1);
+        tcg_gen_add_i32(tmp1, offset, width);
+        tcg_gen_andi_i32(tmp1, tmp1, 31);
+        gen_helper_ror32(tmp, tmp, tmp1);
+        tcg_gen_not_i32(mask, mask);
+        tcg_gen_and_i32(reg, reg, mask);
+        tcg_gen_or_i32(reg, reg, tmp);
+        break;
+    }
+}
+
+static TCGv gen_bitfield_cc(DisasContext *s,
+                            TCGv offset, TCGv mask_cc, TCGv_i64 bitfield)
+{
+    TCGv dest;
+    TCGv_i64 tmp64;
+
+    /* move bitfield to a 32bit */
+
+    tmp64 = tcg_temp_new_i64();
+
+    tcg_gen_extu_i32_i64(tmp64, offset);
+
+    /* tmp64 = bitfield << offset */
+
+    tcg_gen_shl_i64(tmp64, bitfield, tmp64);
+
+    /* tmp = (bitfield << offset) >> 32 */
+
+    tcg_gen_shri_i64(tmp64, tmp64, 32ULL);
+    dest = tcg_temp_new_i32();
+    tcg_gen_trunc_i64_i32(dest, tmp64);
+    tcg_gen_and_i32(dest, dest, mask_cc);
+
+    return dest;
+}
+
+static TCGv_i64 gen_bitfield_mask(TCGv offset, TCGv width)
+{
+    TCGv tmp;
+    TCGv_i64 mask;
+    TCGv_i64 shift;
+
+    mask = tcg_temp_new_i64();
+
+    /* mask = (1u << width) - 1; */
+
+    tcg_gen_extu_i32_i64(mask, width);
+    tcg_gen_shl_i64(mask, tcg_const_i64(1), mask);
+    tcg_gen_subi_i64(mask, mask, 1);
+
+    /* shift = 64 - (width + offset); */
+
+    tmp = tcg_temp_new_i32();
+    tcg_gen_add_i32(tmp, offset, width);
+    tcg_gen_sub_i32(tmp, tcg_const_i32(64), tmp);
+    shift = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(shift, tmp);
+
+    /* mask <<= shift */
+
+    tcg_gen_shl_i64(mask, mask, shift);
+
+    return mask;
+}
+
+static void gen_bitfield_ins(TCGv offset, TCGv width, TCGv src,
+                                 TCGv_i64 val)
+{
+    TCGv_i64 insert;
+    TCGv_i64 shift;
+    TCGv tmp;
+
+    tmp = tcg_temp_new_i32();
+
+    /* tmp = (1u << width) - 1; */
+
+    /* width is between 1 and 32
+     * tcg_gen_shl_i32() cannot manage value 32
+     */
+    tcg_gen_subi_i32(tmp, width, 1);
+    tcg_gen_shl_i32(tmp, tcg_const_i32(2), tmp);
+    tcg_gen_subi_i32(tmp, tmp, 1);
+
+    /* tmp = tmp & src; */
+
+    tcg_gen_and_i32(tmp, tmp, src);
+
+    /* insert = (i64)tmp; */
+
+    insert = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(insert, tmp);
+
+    /* tmp = 64 - (width + offset); */
+
+    tcg_gen_add_i32(tmp, offset, width);
+    tcg_gen_sub_i32(tmp, tcg_const_i32(64), tmp);
+    shift = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(shift, tmp);
+
+    /* insert <<= shift */
+
+    tcg_gen_shl_i64(insert, insert, shift);
+
+    /* val |=  select */
+
+    tcg_gen_or_i64(val, val, insert);
+}
+
+DISAS_INSN(bitfield_mem)
+{
+    uint16_t ext;
+    int op;
+    TCGv_i64 bitfield;
+    TCGv_i64 mask_bitfield;
+    TCGv mask_cc;
+    TCGv shift;
+    TCGv val;
+    TCGv src;
+    TCGv offset;
+    TCGv width;
+    TCGv reg;
+    TCGv tmp;
+
+    op = (insn >> 8) & 7;
+    ext = read_im16(env, s);
+    src = gen_lea(env, s, insn, OS_LONG);
+    if (IS_NULL_QREG(src)) {
+        gen_addr_fault(s);
+        return;
+    }
+
+    bitfield_param(ext, &offset, &width, &mask_cc);
+
+    /* adjust src and offset */
+
+    /* src += offset >> 3; */
+
+    tmp = tcg_temp_new_i32();
+    tcg_gen_shri_i32(tmp, offset, 3);
+    tcg_gen_add_i32(src, src, tmp);
+
+    /* offset &= 7; */
+
+    tcg_gen_andi_i32(offset, offset, 7);
+
+    /* load */
+
+    bitfield = tcg_temp_new_i64();
+    gen_helper_bitfield_load(bitfield, src, offset, width);
+
+    /* compute CC and move bitfield into a 32bit */
+
+    val = gen_bitfield_cc(s, offset, mask_cc, bitfield);
+
+    /* execute operation */
+
+    reg = DREG(ext, 12);
+
+    if (op == 7) {
+        TCGv tmp1;
+
+        tmp1 = tcg_temp_new_i32();
+        tcg_gen_sub_i32(tmp1, tcg_const_i32(32), width);
+        tcg_gen_shl_i32(tmp1, reg, tmp1);
+        tcg_gen_and_i32(tmp1, tmp1, mask_cc);
+        gen_logic_cc(s, tmp1, OS_LONG);
+
+        tcg_temp_free_i32(tmp1);
+    } else {
+        gen_logic_cc(s, val, OS_LONG);
+    }
+
+    switch (op) {
+    case 0: /* bftst */
+        break;
+    case 1: /* bfextu */
+        shift = tcg_temp_new_i32();
+        tcg_gen_sub_i32(shift, tcg_const_i32(32), width);
+        tcg_gen_shr_i32(reg, val, shift);
+        break;
+    case 2: /* bfchg */
+        mask_bitfield = gen_bitfield_mask(offset, width);
+        tcg_gen_xor_i64(bitfield, bitfield, mask_bitfield);
+        gen_helper_bitfield_store(src, offset, width, bitfield);
+        break;
+    case 3: /* bfexts */
+        shift = tcg_temp_new_i32();
+        tcg_gen_sub_i32(shift, tcg_const_i32(32), width);
+        tcg_gen_sar_i32(reg, val, shift);
+        break;
+    case 4: /* bfclr */
+        mask_bitfield = gen_bitfield_mask(offset, width);
+        tcg_gen_not_i64(mask_bitfield, mask_bitfield);
+        tcg_gen_and_i64(bitfield, bitfield, mask_bitfield);
+        gen_helper_bitfield_store(src, offset, width, bitfield);
+        break;
+    case 5: /* bfffo */
+        gen_helper_bfffo(val, val, width);
+        tcg_gen_add_i32(reg, val, offset);
+        break;
+    case 6: /* bfset */
+        mask_bitfield = gen_bitfield_mask(offset, width);
+        tcg_gen_or_i64(bitfield, bitfield, mask_bitfield);
+        gen_helper_bitfield_store(src, offset, width, bitfield);
+        break;
+    case 7: /* bfins */
+        /* clear */
+        mask_bitfield = gen_bitfield_mask(offset, width);
+        tcg_gen_not_i64(mask_bitfield, mask_bitfield);
+        tcg_gen_and_i64(bitfield, bitfield, mask_bitfield);
+        /* insert */
+        gen_bitfield_ins(offset, width, reg, bitfield);
+        gen_helper_bitfield_store(src, offset, width, bitfield);
+        break;
+    }
+}
+
 DISAS_INSN(ff1)
 {
     TCGv reg;
@@ -3979,6 +4308,8 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(rotate8_reg, e030, f0f0, M68000);
     INSN(rotate16_reg, e070, f0f0, M68000);
     INSN(rotate_mem, e4c0, fcc0, M68000);
+    INSN(bitfield_mem, e8c0, f8c0, BITFIELD);
+    INSN(bitfield_reg, e8c0, f8f8, BITFIELD);
     INSN(undef_fpu, f000, f000, CF_ISA_A);
     INSN(fpu,       f200, ffc0, CF_FPU);
     INSN(fbcc,      f280, ffc0, CF_FPU);
-- 
2.4.3

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

* Re: [Qemu-devel] [PATCH for-2.5 03/30] m68k: introduce read_imXX() functions
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 03/30] m68k: introduce read_imXX() functions Laurent Vivier
@ 2015-08-09 21:12   ` Andreas Schwab
  2015-08-12  3:54   ` Richard Henderson
  1 sibling, 0 replies; 78+ messages in thread
From: Andreas Schwab @ 2015-08-09 21:12 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: peter.maydell, peter.crosthwaite, qemu-devel, gerg

Laurent Vivier <laurent@vivier.eu> writes:

> Read a 8, 16 or 32bit immediat constant.
>
> An Immediat constant is stored in the instruction opcode and

s/Immediat/immediate/

Andreas.

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

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

* Re: [Qemu-devel] [PATCH for-2.5 01/30] m68k: define m680x0 CPUs and features
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 01/30] m68k: define m680x0 CPUs and features Laurent Vivier
@ 2015-08-11 23:13   ` Richard Henderson
  2015-08-12  8:01     ` Laurent Vivier
  0 siblings, 1 reply; 78+ messages in thread
From: Richard Henderson @ 2015-08-11 23:13 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>      INSN(undef,     0000, 0000, CF_ISA_A);
> +    INSN(undef,     0000, 0000, M68000);
>      INSN(arith_im,  0080, fff8, CF_ISA_A);
> +    INSN(arith_im,  0000, ff00, M68000);
> +    INSN(undef,     00c0, ffc0, M68000);
>      INSN(bitrev,    00c0, fff8, CF_ISA_APLUSC);
>      INSN(bitop_reg, 0100, f1c0, CF_ISA_A);
> +    INSN(bitop_reg, 0100, f1c0, M68000);
>      INSN(bitop_reg, 0140, f1c0, CF_ISA_A);
> +    INSN(bitop_reg, 0140, f1c0, M68000);

There's a *lot* of repetition in here.

Can we also introduce a BASE() macro that's like INSN() except that it doesn't
bother checking m68k_feature?  That way if both CF_ISA_A and M68000 are set, we
don't have to duplicate the entry.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 02/30] m68k: manage scaled index
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 02/30] m68k: manage scaled index Laurent Vivier
@ 2015-08-12  3:42   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  3:42 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

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

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


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 03/30] m68k: introduce read_imXX() functions
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 03/30] m68k: introduce read_imXX() functions Laurent Vivier
  2015-08-09 21:12   ` Andreas Schwab
@ 2015-08-12  3:54   ` Richard Henderson
  1 sibling, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  3:54 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> Read a 8, 16 or 32bit immediat constant.
>
> An Immediat constant is stored in the instruction opcode and
> can be in one or two extension words.
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>   target-m68k/translate.c | 73 ++++++++++++++++++++++++-------------------------
>   1 file changed, 35 insertions(+), 38 deletions(-)
>
> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
> index f190f19..3b87b0c 100644
> --- a/target-m68k/translate.c
> +++ b/target-m68k/translate.c
> @@ -260,16 +260,30 @@ static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
>       }
>   }
>
> -/* Read a 32-bit immediate constant.  */
> -static inline uint32_t read_im32(CPUM68KState *env, DisasContext *s)
> +/* Read an 8-bit immediate constant */
> +static inline uint32_t read_im8(CPUM68KState *env, DisasContext *s)
>   {
>       uint32_t im;
> -    im = ((uint32_t)cpu_lduw_code(env, s->pc)) << 16;
> +    im = cpu_ldsb_code(env, s->pc + 1);
>       s->pc += 2;
> -    im |= cpu_lduw_code(env, s->pc);
> +    return im;
> +}
> +/* Read a 16-bit immediate constant */
> +static inline uint32_t read_im16(CPUM68KState *env, DisasContext *s)
> +{
> +    uint32_t im;
> +    im = cpu_ldsw_code(env, s->pc);
>       s->pc += 2;
>       return im;
>   }
> +/* Read a 32-bit immediate constant.  */
> +static inline uint32_t read_im32(CPUM68KState *env, DisasContext *s)
> +{
> +    uint32_t im;
> +    im = read_im16(env, s) << 16;
> +    im |= 0xffff & read_im16(env, s);
> +    return im;
> +}

Watch the spacing between functions.  It's probably better to have the return 
types match the function -- int8_t, int16_t, int32_t.  Finally, read_im8 might 
as well call read_im16 and truncate the result via return type.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 04/30] m68k: set disassembler mode to 680x0 or coldfire
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 04/30] m68k: set disassembler mode to 680x0 or coldfire Laurent Vivier
@ 2015-08-12  3:57   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  3:57 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier<laurent@vivier.eu>
> ---
>   disas.c                 | 4 ++++
>   target-m68k/translate.c | 3 ++-
>   2 files changed, 6 insertions(+), 1 deletion(-)


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


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 05/30] m68k: define operand sizes
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 05/30] m68k: define operand sizes Laurent Vivier
@ 2015-08-12  4:07   ` Richard Henderson
  2015-08-12  8:44     ` Laurent Vivier
  0 siblings, 1 reply; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  4:07 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> -#define OS_BYTE 0
> -#define OS_WORD 1
> -#define OS_LONG 2
> -#define OS_SINGLE 4
> -#define OS_DOUBLE 5
> +#define OS_BYTE     1
> +#define OS_WORD     2
> +#define OS_LONG     3
> +#define OS_SINGLE   4
> +#define OS_DOUBLE   5
> +#define OS_EXTENDED 6
> +#define OS_PACKED   7
>

Is there a reason you've skipped the 0 value when adding the new values?

> +static inline int insn_opsize(int insn, int pos)
> +{
> +    switch ((insn >> pos) & 3) {


In particular, that change means that insn_opsize is more complicated than 
needed.  Further, is there any reason for POS to be a varable?  Isn't it at the 
same place for all insns?

> +static inline int ext_opsize(int ext, int pos)

This should probably wait until the fp insns get added.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 06/30] m68k: REG() macro cleanup
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 06/30] m68k: REG() macro cleanup Laurent Vivier
@ 2015-08-12  4:11   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  4:11 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

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


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


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 07/30] m68k: allow to update flags with operation on words and bytes
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 07/30] m68k: allow to update flags with operation on words and bytes Laurent Vivier
@ 2015-08-12  4:28   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  4:28 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> @@ -168,46 +209,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:

Drop the break after goto.

> +        if (!m68k_feature(env, M68K_FEATURE_M68000)) {
> +            /* Unlike m68k, coldfire always clears the overflow bit.  */
> +            env->cc_x = 0;
> +        }

Err.. that's not the overflow bit.
But yes, it's different between CF and m68k.

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

If OS_BYTE == 0, then this can just be CC_OP_##op##B + opsize.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 08/30] m68k: update CPU flags management
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 08/30] m68k: update CPU flags management Laurent Vivier
@ 2015-08-12  5:12   ` Richard Henderson
  2015-08-12 20:56     ` Laurent Vivier
  2015-08-13 18:09     ` Laurent Vivier
  0 siblings, 2 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  5:12 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> @@ -798,9 +796,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);
>   }

Since this function no longer modifies ENV, it probably deserves a better name 
than "flush_flags".  FWIW cc_compute_all isn't a bad name, if you're copying 
i386 anyway...

> -DEF_HELPER_2(flush_flags, void, env, i32)
> +DEF_HELPER_2(flush_flags, i32, env, i32)

Modify to use DEF_HELPER_FLAGS while you're at it.  At the moment it reads some 
globals, but doesn't write any, or have any other side effects.

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

That const needs to be freed.

> @@ -1248,7 +1294,6 @@ DISAS_INSN(bitop_im)
>           DEST_EA(env, insn, opsize, tmp, &addr);
>       }
>   }
> -
>   DISAS_INSN(arith_im)
>   {
>       int op;

Careful with the errant whitespace changes.

> @@ -1706,16 +1745,18 @@ 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();
>           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);

Ideally you'd do this only once, before the jmpcc.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 09/30] m68k: add X flag helpers
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 09/30] m68k: add X flag helpers Laurent Vivier
@ 2015-08-12  5:18   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  5:18 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> +#define SET_X_FLAG(opsize, a, b) do { \
> +    switch (opsize) { \
> +    case OS_BYTE: \
> +        gen_helper_xflag_lt_i8(QREG_CC_X, a, b); break; \
> +    case OS_WORD: \
> +        gen_helper_xflag_lt_i16(QREG_CC_X, a, b); break; \
> +    case OS_LONG: \
> +        gen_helper_xflag_lt_i32(QREG_CC_X, a, b); break; \
> +    default: \
> +        abort(); \
> +    } \
> +} while (0)

No need for these helpers.  Just use setcond now, with sign-extensions as 
required for the opsize.  And perhaps not make this a macro, but a function.

Also watch all of the tcg_const_i32 without freeing the temp after.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 10/30] m68k: tst bugfix
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 10/30] m68k: tst bugfix Laurent Vivier
@ 2015-08-12  5:18   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  5:18 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> The operand is signed.
>
> Signed-off-by: Laurent Vivier<laurent@vivier.eu>
> ---
>   target-m68k/translate.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)

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


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 11/30] m68k: improve clr/moveq
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 11/30] m68k: improve clr/moveq Laurent Vivier
@ 2015-08-12  5:20   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  5:20 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> Generate the TCG constant and use it twice, instead
> of generating the TCG constant twice to use it twice.
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>   target-m68k/translate.c | 15 +++++++++------
>   1 file changed, 9 insertions(+), 6 deletions(-)
>
> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
> index 359c761..8a3d315 100644
> --- a/target-m68k/translate.c
> +++ b/target-m68k/translate.c
> @@ -1431,10 +1431,13 @@ DISAS_INSN(lea)
>   DISAS_INSN(clr)
>   {
>       int opsize;
> +    TCGv zero;
> +
> +    zero = tcg_const_i32(0);

Ideally, on one line.  And it still needs to be freed.

>   DISAS_INSN(moveq)
>   {
> -    uint32_t val;
> +    TCGv val;
>
> +    val = tcg_const_i32((int8_t)insn);

Likewise.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 12/30] m68k: Manage divw overflow
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 12/30] m68k: Manage divw overflow Laurent Vivier
@ 2015-08-12  6:03   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  6:03 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> "Overflow may be detected and set before the instruction completes.
> If the instruction detects an overflow, it sets the overflow condition
> code, and the operands are unaffected."

May also implies may not.  I presume this is important for matching hardware? 
Is there some program you know of that depends on this?

> +    /* dest.l / src.w */
> +
> +    dest = DREG(insn, 9);
> +    tcg_gen_mov_i32(QREG_DIV1, dest);
> +
>       SRC_EA(env, src, OS_WORD, sign, NULL);
>       tcg_gen_mov_i32(QREG_DIV2, src);
> +
> +    /* div1 / div2 */
> +
>       if (sign) {
>           gen_helper_divs(cpu_env, tcg_const_i32(1));
>       } else {
>           gen_helper_divu(cpu_env, tcg_const_i32(1));
>       }
>
> +    set_cc_op(s, CC_OP_FLAGS);
> +
> +    l1 = gen_new_label();
> +    gen_jmpcc(s, 9 /* V */, l1);
>       tmp = tcg_temp_new();
>       src = tcg_temp_new();
>       tcg_gen_ext16u_i32(tmp, QREG_DIV1);
>       tcg_gen_shli_i32(src, QREG_DIV2, 16);
> -    tcg_gen_or_i32(reg, tmp, src);
> -    set_cc_op(s, CC_OP_FLAGS);
> +    tcg_gen_or_i32(dest, tmp, src);
> +    gen_set_label(l1);

All that said, it's possible to implement this branch inside the helper via 
exception.  Or simply return the inputs to effect no change.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 13/30] m68k: set Z and N on divu/muls overflow as a real 68040
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 13/30] m68k: set Z and N on divu/muls overflow as a real 68040 Laurent Vivier
@ 2015-08-12  6:29   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  6:29 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> This allows to compare simulation results with a real 68040.
>
> Signed-off-by: Laurent Vivier<laurent@vivier.eu>
> ---
>   target-m68k/op_helper.c | 38 ++++++++++++++++++++++++++------------
>   1 file changed, 26 insertions(+), 12 deletions(-)

A good incentive, yes, but...  hmm.  Certainly another incentive to split 
helpers, rather than pass in "word".

I don't have a way to review this though, so the best I can do is

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


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 14/30] m68k: allow adda/suba to add/sub word
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 14/30] m68k: allow adda/suba to add/sub word Laurent Vivier
@ 2015-08-12  7:32   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  7:32 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier<laurent@vivier.eu>
> ---
>   target-m68k/translate.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)

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

r~

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

* Re: [Qemu-devel] [PATCH for-2.5 15/30] m68k: add more modes to movem
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 15/30] m68k: add more modes to movem Laurent Vivier
@ 2015-08-12  7:54   ` Richard Henderson
  2015-08-12  8:07     ` Andreas Schwab
  0 siblings, 1 reply; 78+ messages in thread
From: Richard Henderson @ 2015-08-12  7:54 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> +    opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD;
> +    incr = opsize_bytes(opsize);
> +    if (!is_load && (insn & 070) == 040) {
> +        for (i = 15; i >= 0; i--, mask >>= 1) {

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


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 01/30] m68k: define m680x0 CPUs and features
  2015-08-11 23:13   ` Richard Henderson
@ 2015-08-12  8:01     ` Laurent Vivier
  0 siblings, 0 replies; 78+ messages in thread
From: Laurent Vivier @ 2015-08-12  8:01 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg



Le 12/08/2015 01:13, Richard Henderson a écrit :
> On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>>      INSN(undef,     0000, 0000, CF_ISA_A);
>> +    INSN(undef,     0000, 0000, M68000);
>>      INSN(arith_im,  0080, fff8, CF_ISA_A);
>> +    INSN(arith_im,  0000, ff00, M68000);
>> +    INSN(undef,     00c0, ffc0, M68000);
>>      INSN(bitrev,    00c0, fff8, CF_ISA_APLUSC);
>>      INSN(bitop_reg, 0100, f1c0, CF_ISA_A);
>> +    INSN(bitop_reg, 0100, f1c0, M68000);
>>      INSN(bitop_reg, 0140, f1c0, CF_ISA_A);
>> +    INSN(bitop_reg, 0140, f1c0, M68000);
> 
> There's a *lot* of repetition in here.
> 
> Can we also introduce a BASE() macro that's like INSN() except that it doesn't
> bother checking m68k_feature?  That way if both CF_ISA_A and M68000 are set, we
> don't have to duplicate the entry.

Thank you, good idea.

Laurent

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

* Re: [Qemu-devel] [PATCH for-2.5 15/30] m68k: add more modes to movem
  2015-08-12  7:54   ` Richard Henderson
@ 2015-08-12  8:07     ` Andreas Schwab
  2015-08-12 15:13       ` Richard Henderson
  0 siblings, 1 reply; 78+ messages in thread
From: Andreas Schwab @ 2015-08-12  8:07 UTC (permalink / raw)
  To: Richard Henderson
  Cc: peter.maydell, peter.crosthwaite, gerg, Laurent Vivier, qemu-devel

Richard Henderson <rth@twiddle.net> writes:

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

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

Andreas.

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

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

* Re: [Qemu-devel] [PATCH for-2.5 05/30] m68k: define operand sizes
  2015-08-12  4:07   ` Richard Henderson
@ 2015-08-12  8:44     ` Laurent Vivier
  2015-08-12  8:52       ` Andreas Schwab
  0 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-12  8:44 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg



Le 12/08/2015 06:07, Richard Henderson a écrit :
> On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>> -#define OS_BYTE 0
>> -#define OS_WORD 1
>> -#define OS_LONG 2
>> -#define OS_SINGLE 4
>> -#define OS_DOUBLE 5
>> +#define OS_BYTE     1
>> +#define OS_WORD     2
>> +#define OS_LONG     3
>> +#define OS_SINGLE   4
>> +#define OS_DOUBLE   5
>> +#define OS_EXTENDED 6
>> +#define OS_PACKED   7
>>
> 
> Is there a reason you've skipped the 0 value when adding the new values?

I think there is no reason, but if I change the value I have to update
abdc_mem, sbcd_mem instructions as they use it as an
incrementer/decrementer. I agree, it's a strange idea.

> 
>> +static inline int insn_opsize(int insn, int pos)
>> +{
>> +    switch ((insn >> pos) & 3) {
> 
> 
> In particular, that change means that insn_opsize is more complicated
> than needed.  Further, is there any reason for POS to be a varable? 
> Isn't it at the same place for all insns?
> 
>> +static inline int ext_opsize(int ext, int pos)
> 
> This should probably wait until the fp insns get added.

Yes.

Laurent

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

* Re: [Qemu-devel] [PATCH for-2.5 05/30] m68k: define operand sizes
  2015-08-12  8:44     ` Laurent Vivier
@ 2015-08-12  8:52       ` Andreas Schwab
  0 siblings, 0 replies; 78+ messages in thread
From: Andreas Schwab @ 2015-08-12  8:52 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: peter.maydell, peter.crosthwaite, gerg, qemu-devel, Richard Henderson

Laurent Vivier <laurent@vivier.eu> writes:

> Le 12/08/2015 06:07, Richard Henderson a écrit :
>> Is there a reason you've skipped the 0 value when adding the new values?
>
> I think there is no reason, but if I change the value I have to update
> abdc_mem, sbcd_mem instructions as they use it as an
> incrementer/decrementer. I agree, it's a strange idea.

Those uses are really opsize_bytes(OS_BYTE), technically.

Andreas.

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

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

* Re: [Qemu-devel] [PATCH for-2.5 15/30] m68k: add more modes to movem
  2015-08-12  8:07     ` Andreas Schwab
@ 2015-08-12 15:13       ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 15:13 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: peter.maydell, peter.crosthwaite, gerg, Laurent Vivier, qemu-devel

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

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


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 16/30] m68k: Add all access modes and data sizes to some 680x0 instructions
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 16/30] m68k: Add all access modes and data sizes to some 680x0 instructions Laurent Vivier
@ 2015-08-12 16:25   ` Richard Henderson
  2015-08-12 16:27   ` Richard Henderson
  1 sibling, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 16:25 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: peter.maydell, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>      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);
> +        SET_CC_OP(opsize, SUB);
>          break;
>      default:
>          abort();
>      }
> -    if (op != 6) {
> -        DEST_EA(env, insn, OS_LONG, dest, &addr);
> -    }
> +    DEST_EA(env, insn, opsize, dest, &addr);

It appears you've lost the if that doesn't write back the result of compare.
Did you intend to change the case 6 break to a return?


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 16/30] m68k: Add all access modes and data sizes to some 680x0 instructions
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 16/30] m68k: Add all access modes and data sizes to some 680x0 instructions Laurent Vivier
  2015-08-12 16:25   ` Richard Henderson
@ 2015-08-12 16:27   ` Richard Henderson
  1 sibling, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 16:27 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> -        SRC_EA(env, tmp, OS_LONG, 0, &addr);
> +        SRC_EA(env, tmp, opsize, -1, &addr);

Oh, I'm also wondering why you changed all of the inputs from unsigned to
signed.  It appears to be unrelated to updating the modes, and unnecessary.

I'm all for reducing churn and doing both at once, so long as you say why.  But
at present it looks like a mistake.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 17/30] m68k: ori/andi/subi/addi/eori/cmpi can modify SR/CCR
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 17/30] m68k: ori/andi/subi/addi/eori/cmpi can modify SR/CCR Laurent Vivier
@ 2015-08-12 16:44   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 16:44 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 95 ++++++++++++++++++++++++++++++-------------------
>  1 file changed, 58 insertions(+), 37 deletions(-)
> 
> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
> index 6a426e1..9e379b3 100644
> --- a/target-m68k/translate.c
> +++ b/target-m68k/translate.c
> @@ -1343,6 +1343,42 @@ DISAS_INSN(bitop_im)
>          DEST_EA(env, insn, opsize, tmp, &addr);
>      }
>  }
> +
> +static TCGv gen_get_ccr(DisasContext *s)
> +{
> +    TCGv dest;
> +
> +    gen_flush_flags(s);
> +    dest = tcg_temp_new();
> +    tcg_gen_shli_i32(dest, QREG_CC_X, 4);
> +    tcg_gen_or_i32(dest, dest, QREG_CC_DEST);
> +    return dest;
> +}
> +
> +static TCGv gen_get_sr(DisasContext *s)
> +{
> +    TCGv ccr;
> +    TCGv sr;
> +
> +    ccr = gen_get_ccr(s);
> +    sr = tcg_temp_new();
> +    tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
> +    tcg_gen_or_i32(sr, sr, ccr);
> +    return sr;
> +}

Leaking the temporary produced by gen_get_ccr.

> +
> +static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only)
> +{
> +    TCGv tmp;
> +    tmp = tcg_temp_new();
> +    tcg_gen_andi_i32(QREG_CC_DEST, val, 0xf);
> +    tcg_gen_shri_i32(tmp, val, 4);
> +    tcg_gen_andi_i32(QREG_CC_X, tmp, 1);
> +    if (!ccr_only) {
> +        gen_helper_set_sr(cpu_env, val);
> +    }
> +}

Leaking tmp.  And you don't even need to allocate it -- perform the shift into
QREG_CC_X.

> +
>  DISAS_INSN(arith_im)
>  {
>      int op;
> @@ -1367,7 +1403,20 @@ DISAS_INSN(arith_im)
>      default:
>         abort();
>      }
> -    SRC_EA(env, src1, opsize, -1, (op == 6) ? NULL : &addr);
> +    if ((op == 0 || op == 1) &&

The subject line is surely misleading, as this is only ANDI/ORI, right?  Again,
some more commentary would be helpful.

> +        (insn & 0x3f) == 0x3c) {
> +        if (opsize == OS_BYTE) {
> +            src1 = gen_get_ccr(s);
> +        } else {
> +            if (IS_USER(s)) {
> +                gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
> +                return;
> +            }
> +            src1 = gen_get_sr(s);
> +        }
> +    } else {
> +        SRC_EA(env, src1, opsize, -1, (op == 6) ? NULL : &addr);
> +    }
>      dest = tcg_temp_new();
>      switch (op) {
>      case 0: /* ori */
> @@ -1405,7 +1454,14 @@ DISAS_INSN(arith_im)
>      default:
>          abort();
>      }
> -    DEST_EA(env, insn, opsize, dest, &addr);
> +    if (op != 6) {
> +        if ((op == 0 || op == 1) &&
> +            (insn & 0x3f) == 0x3c) {
> +            gen_set_sr(s, dest, opsize == OS_BYTE);
> +        } else {
> +            DEST_EA(env, insn, opsize, dest, &addr);
> +        }
> +    }

That said, I think this code should be rearranged so that you don't have to
replicate so many conditionals.  In particular, the only thing of use in the
middle of import for the ccr insns are two lines: tcg_gen_andi/ori_tl.

I think it would be better to structure as

  if ((insn & 0x3f) == 0x3c && (op == 0 || op == 1)) {
    if (opsize == OS_BYTE) {
      src1 = gen_get_ccr ();
    } else {
      ...
    }
    if (op == 0) {
      tcg_gen_ori_i32 ...
    } else {
      tcg_gen_andi_i32 ...
    }
    gen_set_sr(s, dest, opsize == OS_BYTE);
    return;
  }

  // existing code


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 18/30] m68k: addq/subq can work with all the data sizes.
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 18/30] m68k: addq/subq can work with all the data sizes Laurent Vivier
@ 2015-08-12 16:48   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 16:48 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> Improve TCG constant use by creating only once for several uses.
> 
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 46 +++++++++++++++++++++++++++-------------------
>  1 file changed, 27 insertions(+), 19 deletions(-)
> 
> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
> index 9e379b3..ae57792 100644
> --- a/target-m68k/translate.c
> +++ b/target-m68k/translate.c
> @@ -1778,40 +1778,48 @@ DISAS_INSN(jump)
>  
>  DISAS_INSN(addsubq)
>  {
> -    TCGv src1;
> -    TCGv src2;
> +    TCGv src;
>      TCGv dest;
> -    int val;
> +    TCGv val;
> +    int imm;
>      TCGv addr;
> +    int opsize;
>  
> -    SRC_EA(env, src1, OS_LONG, 0, &addr);
> -    val = (insn >> 9) & 7;
> -    if (val == 0)
> -        val = 8;
> +    if ((insn & 070) == 010) {
> +        /* Operation on address register is always long.  */
> +        opsize = OS_LONG;
> +    } else {
> +        opsize = insn_opsize(insn, 6);
> +    }
> +    SRC_EA(env, src, opsize, -1, &addr);
> +    imm = (insn >> 9) & 7;
> +    if (imm == 0) {
> +        imm = 8;
> +    }
> +    val = tcg_const_i32(imm);
>      dest = tcg_temp_new();
> -    tcg_gen_mov_i32(dest, src1);
> +    tcg_gen_mov_i32(dest, src);
>      if ((insn & 0x38) == 0x08) {
>          /* Don't update condition codes if the destination is an
>             address register.  */
>          if (insn & 0x0100) {
> -            tcg_gen_subi_i32(dest, dest, val);
> +            tcg_gen_sub_i32(dest, dest, val);
>          } else {
> -            tcg_gen_addi_i32(dest, dest, val);
> +            tcg_gen_add_i32(dest, dest, val);
>          }
>      } else {
> -        src2 = tcg_const_i32(val);
>          if (insn & 0x0100) {
> -            SET_X_FLAG(OS_LONG, dest, tcg_const_i32(val));
> -            tcg_gen_subi_i32(dest, dest, val);
> -            set_cc_op(s, CC_OP_SUB);
> +            SET_X_FLAG(opsize, dest, val);
> +            tcg_gen_sub_i32(dest, dest, val);
> +            SET_CC_OP(opsize, SUB);
>          } else {
> -            tcg_gen_addi_i32(dest, dest, val);
> -            SET_X_FLAG(OS_LONG, dest, tcg_const_i32(val));
> -            SET_CC_OP(OS_LONG, ADD);
> +            tcg_gen_add_i32(dest, dest, val);
> +            SET_X_FLAG(opsize, dest, val);
> +            SET_CC_OP(opsize, ADD);
>          }
> -        gen_update_cc_add(dest, src2);
> +        gen_update_cc_add(dest, val);
>      }

You do need to free val here.

> -    DEST_EA(env, insn, OS_LONG, dest, &addr);
> +    DEST_EA(env, insn, opsize, dest, &addr);
>  }
>  
>  DISAS_INSN(tpf)
> 

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

* Re: [Qemu-devel] [PATCH for-2.5 19/30] m68k: add cmpm
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 19/30] m68k: add cmpm Laurent Vivier
@ 2015-08-12 17:00   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 17:00 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: peter.maydell, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
> index ae57792..adf4521 100644
> --- a/target-m68k/translate.c
> +++ b/target-m68k/translate.c
> @@ -2002,6 +2002,24 @@ DISAS_INSN(eor)
>  
>      opsize = insn_opsize(insn, 6);
>  
> +    if (((insn >> 3) & 7) == 1) {
> +        /* cmpm */

Surely this can be separated out from EOR via masks at register_opcode time.
And since this isn't a coldfire instruction...

> +        reg = AREG(insn, 0);
> +        src = gen_load(s, opsize, reg, 1);
> +        tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
> +
> +        reg = AREG(insn, 9);
> +        dest = gen_load(s, opsize, reg, 1);
> +        tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
> +
> +        reg = tcg_temp_new();
> +        tcg_gen_sub_i32(reg, dest, src);
> +        gen_update_cc_add(reg, src);

No need for the extra temp, reg.  Simply modify dest.

> +        SET_CC_OP(opsize, SUB);
> +
> +        return;
> +    }
> +
>      SRC_EA(env, src, opsize, -1, &addr);
>      reg = DREG(insn, 9);
>      dest = tcg_temp_new();
> 

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

* Re: [Qemu-devel] [PATCH for-2.5 20/30] m68k: add exg
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 20/30] m68k: add exg Laurent Vivier
@ 2015-08-12 17:05   ` Richard Henderson
  2015-08-12 22:43     ` Laurent Vivier
  0 siblings, 1 reply; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 17:05 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 34 +++++++++++++++++++++++++++++++++-
>  1 file changed, 33 insertions(+), 1 deletion(-)
> 
> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
> index adf4521..b7d15e9 100644
> --- a/target-m68k/translate.c
> +++ b/target-m68k/translate.c
> @@ -2035,10 +2035,42 @@ DISAS_INSN(and)
>      TCGv dest;
>      TCGv addr;
>      int opsize;
> +    int exg_mode;
>  
> +    dest = tcg_temp_new();
> +
> +    /* exg */
> +
> +    exg_mode = insn & 0x1f8;

Likewise, surely we can decode EXG separately from AND, and avoid doing so for
coldfire.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 21/30] m68k: add bkpt
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 21/30] m68k: add bkpt Laurent Vivier
@ 2015-08-12 17:07   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 17:07 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: peter.maydell, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 6 ++++++
>  1 file changed, 6 insertions(+)

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


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 22/30] m68k: add cas instruction
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 22/30] m68k: add cas instruction Laurent Vivier
@ 2015-08-12 17:14   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 17:14 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: peter.maydell, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> +    gen_logic_cc(s, res, opsize);
> +
> +    l1 = gen_new_label();
> +    l2 = gen_new_label();
> +
> +    gen_jmpcc(s, 6 /* !Z */, l1);
> +    gen_store(s, opsize, addr, update);
> +    tcg_gen_br(l2);
> +    gen_set_label(l1);
> +    tcg_gen_mov_i32(cmp, dest);
> +    gen_set_label(l2);
> +    tcg_temp_free(dest);
> +    tcg_temp_free(addr);

I would suggest writing this with movcond.  It avoids the branch, which is
requiring the use of the local temps.



r~

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

* Re: [Qemu-devel] [PATCH for-2.5 23/30] m68k: add linkl
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 23/30] m68k: add linkl Laurent Vivier
@ 2015-08-12 17:33   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 17:33 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/translate.c | 21 +++++++++++++++++++--
>  1 file changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
> index 9a7558a..95d58d1 100644
> --- a/target-m68k/translate.c
> +++ b/target-m68k/translate.c
> @@ -1789,8 +1789,24 @@ DISAS_INSN(link)
>      TCGv reg;
>      TCGv tmp;
>  
> -    offset = cpu_ldsw_code(env, s->pc);
> -    s->pc += 2;
> +    offset = read_im16(env, s);
> +    reg = AREG(insn, 0);
> +    tmp = tcg_temp_new();
> +    tcg_gen_subi_i32(tmp, QREG_SP, 4);
> +    gen_store(s, OS_LONG, tmp, reg);
> +    if ((insn & 7) != 7) {
> +        tcg_gen_mov_i32(reg, tmp);
> +    }
> +    tcg_gen_addi_i32(QREG_SP, tmp, offset);
> +}
> +
> +DISAS_INSN(linkl)
> +{
> +    int32_t offset;
> +    TCGv reg;
> +    TCGv tmp;
> +
> +    offset = read_im32(env, s);
>      reg = AREG(insn, 0);
>      tmp = tcg_temp_new();
>      tcg_gen_subi_i32(tmp, QREG_SP, 4);

Surely you can share most of the code via a subroutine,
since the only difference is the size of the immediate.

> @@ -3179,6 +3195,7 @@ void register_m68k_insns (CPUM68KState *env)
>      INSN(not,       4600, ff00, M68000);
>      INSN(undef,     46c0, ffc0, M68000);
>      INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
> +    INSN(linkl,     4808, fff8, M68000);
>      INSN(pea,       4840, ffc0, CF_ISA_A);
>      INSN(pea,       4840, ffc0, M68000);
>      INSN(swap,      4840, fff8, CF_ISA_A);
> 

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

* Re: [Qemu-devel] [PATCH for-2.5 24/30] m68k: add DBcc and Scc (memory operand)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 24/30] m68k: add DBcc and Scc (memory operand) Laurent Vivier
@ 2015-08-12 17:49   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 17:49 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> +DISAS_INSN(scc_mem)
> +{
> +    TCGLabel *l1;
> +    int cond;
> +    TCGv dest;
> +
> +    l1 = gen_new_label();
> +    cond = (insn >> 8) & 0xf;
> +    dest = tcg_temp_local_new();
> +    tcg_gen_movi_i32(dest, 0);
> +    gen_jmpcc(s, cond ^ 1, l1);
> +    tcg_gen_movi_i32(dest, 0xff);
> +    gen_set_label(l1);
> +    DEST_EA(env, insn, OS_BYTE, dest, NULL);
> +    tcg_temp_free(dest);
> +}

It seems like this could just as easily be shared with scc?
DEST_EA handles a byte store into a register just fine.

I suppose the real ugliness at the moment is the tcg branch;
if you were using setcond instead that would help matters.
Adjusting the code surrounding gen_jmpcc is a larger task,
but it really would help a lot.  There are several examples
of how to organize such a thing...

> +DISAS_INSN(dbcc)
> +{
> +    TCGLabel *l1;
> +    TCGv reg;
> +    TCGv tmp;
> +    int16_t offset;
> +    uint32_t base;
> +
> +    reg = DREG(insn, 0);
> +    base = s->pc;
> +    offset = cpu_ldsw_code(env, s->pc);
> +    s->pc += 2;

read_im16?

> +    l1 = gen_new_label();
> +    gen_jmpcc(s, (insn >> 8) & 0xf, l1);
> +
> +    tmp = tcg_temp_new();
> +    tcg_gen_ext16s_i32(tmp, reg);
> +    tcg_gen_addi_i32(tmp, tmp, -1);
> +    gen_partset_reg(OS_WORD, reg, tmp);
> +    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, -1, l1);
> +    update_cc_op(s);
> +    gen_jmp_tb(s, 1, base + offset);
> +    gen_set_label(l1);
> +    update_cc_op(s);

Move the update_cc_op calls before the first branch.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 25/30] m68k: add abcd, sbcd, nbcd instructions
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 25/30] m68k: add abcd, sbcd, nbcd instructions Laurent Vivier
@ 2015-08-12 17:57   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 17:57 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: peter.maydell, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/helper.c    | 91 +++++++++++++++++++++++++++++++++++++++++++++++++
>  target-m68k/helper.h    |  3 ++
>  target-m68k/translate.c | 82 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 176 insertions(+)
> 
> diff --git a/target-m68k/helper.c b/target-m68k/helper.c
> index 8c10fbc..f4be52b 100644
> --- a/target-m68k/helper.c
> +++ b/target-m68k/helper.c
> @@ -938,3 +938,94 @@ void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
>      res |= (uint64_t)(val & 0xffff0000) << 16;
>      env->macc[acc + 1] = res;
>  }
> +
> +uint32_t HELPER(abcd_cc)(CPUM68KState *env, uint32_t src, uint32_t dest)
> +{
> +    uint16_t hi, lo;
> +    uint16_t res;
> +    uint32_t flags;
> +    int extend = 0;
> +
> +    flags = env->cc_dest;
> +    flags &= ~CCF_C;
> +
> +    lo = (src & 0x0f) + (dest & 0x0f);
> +    if (env->cc_x) {
> +        lo++;
> +    }

A nit: Since CC_X == 0 or 1, you can just add it.

> +uint32_t HELPER(sbcd_cc)(CPUM68KState *env, uint32_t src, uint32_t dest)
> +{
> +    uint16_t hi, lo;
> +    uint16_t res;
> +    uint32_t flags;
> +    int bcd = 0, carry = 0, extend = 0;
> +
> +    flags = env->cc_dest;
> +    flags &= CCF_C;
> +
> +    if (env->cc_x) {
> +        carry = 1;
> +    }

Likewise with subtracting it.  carry == env->cc_x.

> +DISAS_INSN(nbcd)
> +{
> +    TCGv dest;
> +    TCGv addr;
> +
> +    SRC_EA(env, dest, OS_BYTE, -1, &addr);
> +
> +    gen_flush_flags(s);
> +    gen_helper_sbcd_cc(dest, cpu_env, dest, tcg_const_i32(0));

Free the zero temp.

r~

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

* Re: [Qemu-devel] [PATCH for-2.5 26/30] m68k: add mull/divl
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 26/30] m68k: add mull/divl Laurent Vivier
@ 2015-08-12 18:36   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 18:36 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: peter.maydell, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/cpu.h       |   3 +
>  target-m68k/helper.h    |   6 ++
>  target-m68k/op_helper.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++
>  target-m68k/qregs.def   |   1 +
>  target-m68k/translate.c |  65 ++++++++++++++++++----
>  5 files changed, 208 insertions(+), 10 deletions(-)
> 
> diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
> index 6d1a140..a261680 100644
> --- a/target-m68k/cpu.h
> +++ b/target-m68k/cpu.h
> @@ -90,6 +90,9 @@ typedef struct CPUM68KState {
>      uint32_t div1;
>      uint32_t div2;
>  
> +    /* Upper 32 bits of a 64bit operand for quad MUL/DIV.  */
> +    uint32_t quadh;

This is a poor choice, IMO.

> +void HELPER(divu64)(CPUM68KState *env)
> +{
> +    uint32_t num;
> +    uint32_t den;
> +    uint64_t quot;
> +    uint32_t rem;
> +    uint32_t flags;
> +    uint64_t quad;
> +
> +    num = env->div1;
> +    den = env->div2;
> +    /* ??? This needs to make sure the throwing location is accurate.  */
> +    if (den == 0) {
> +        raise_exception(env, EXCP_DIV0);
> +    }
> +    quad = num | ((uint64_t)env->quadh << 32);

Pass in the numerator as a 64-bit argument, and avoid the quadh input.

> +    quot = quad / den;
> +    rem = quad % den;
> +    if (quot > 0xffffffffULL) {
> +        flags = (env->cc_dest & ~CCF_C) | CCF_V;
> +    } else {
> +        flags = 0;
> +        if (quot == 0) {
> +            flags |= CCF_Z;
> +        } else if ((int32_t)quot < 0) {
> +            flags |= CCF_N;
> +        }
> +        env->div1 = quot;
> +        env->quadh = rem;

Return a 64-bit result with the quot/rem packed into the high/low.

> +void HELPER(divs64)(CPUM68KState *env)

Similarly.

> +    if ((quot & 0xffffffff80000000ULL) &&
> +        (quot & 0xffffffff80000000ULL) != 0xffffffff80000000ULL) {

Possibly more concisely written as

  !((quot >> 31) == 0 || (quot >> 31) == -1)

> +uint32_t HELPER(mulu32_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
> +uint32_t HELPER(muls32_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
> +uint32_t HELPER(mulu64)(CPUM68KState *env, uint32_t op1, uint32_t op2)
> +uint32_t HELPER(muls64)(CPUM68KState *env, uint32_t op1, uint32_t op2)

It's much easier to do all of the multiplication inline now.  I suppose the
opcodes involved didn't exist when this patch was written.  See below.

It's probably better to split this patch in two as well, one part for division
and the other for multiplication.

> @@ -1122,8 +1122,27 @@ DISAS_INSN(divl)
>      uint16_t ext;
>  
>      ext = read_im16(env, s);
> -    if (ext & 0x87f8) {
> -        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
> +    if (ext & 0x400) {
> +        if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
> +            gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
> +            return;
> +        }
> +        num = DREG(ext, 12);
> +        reg = DREG(ext, 0);
> +        tcg_gen_mov_i32(QREG_DIV1, num);
> +        tcg_gen_mov_i32(QREG_QUADH, reg);

This then becomes

           TCGv_i64 t64 = tcg_temp_new_i64();
           tcg_gen_concat_i32_i64(t64, num, reg);

> +        SRC_EA(env, den, OS_LONG, 0, NULL);
> +        tcg_gen_mov_i32(QREG_DIV2, den);
> +        if (ext & 0x0800) {
> +            gen_helper_divs64(cpu_env);
> +        } else {
> +            gen_helper_divu64(cpu_env);

               gen_helper_divu64(t64, cpu_env, t64, den);

> +        }

           TCGv_i32 q = tcg_temp_new();
           TCGv_i32 r = tcg_temp_new();
           tcg_gen_extr_i64_i32(q, r, t64);
           tcg_temp_free_i64(t64);

> +        tcg_gen_mov_i32(num, QREG_DIV1);
> +        if (!TCGV_EQUAL(num, reg)) {
> +            tcg_gen_mov_i32(reg, QREG_QUADH);
> +        }

Depending on how common this is, or isn't, it's probably cleaner to trust the
tcg optimizer to delete the dead code:

	   /* If Dq and Dr are the same, the quotient is returned.
              therefore we set Dq last.  */
           tcg_gen_mov_i32(reg, r);
           tcg_gen_mov_i32(num, q);

> @@ -1887,21 +1908,45 @@ DISAS_INSN(mull)
>      TCGv reg;
>      TCGv src1;
>      TCGv dest;
> +    TCGv regh;
>  
>      /* The upper 32 bits of the product are discarded, so
>         muls.l and mulu.l are functionally equivalent.  */
>      ext = read_im16(env, s);
> -    if (ext & 0x87ff) {
> -        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
> +    if (ext & 0x400) {
> +        if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
> +            gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
> +            return;
> +        }
> +        reg = DREG(ext, 12);
> +        regh = DREG(ext, 0);
> +        SRC_EA(env, src1, OS_LONG, 0, NULL);
> +        dest = tcg_temp_new();
> +        if (ext & 0x800) {
> +            gen_helper_muls64(dest, cpu_env, src1, reg);

	tcg_gen_muls2_i32(reg, dest, reg, src1);
	set_cc_op(s, CC_OP_MULQ);
	tcg_gen_mov_i32(QREG_CC_DEST, dest);
	tcg_gen_mov_i32(QREG_CC_SRC, reg);
	tcg_gen_mov_i32(regh, dest);

where MULQ sets N = (CC_DEST < 0) and Z = ((CC_DEST | CC_SRC) == 0).

> +        } else {
> +            gen_helper_mulu64(dest, cpu_env, src1, reg);

Similarly with tcg_gen_mulu2_i32.

> -    tcg_gen_mul_i32(dest, src1, reg);
> -    tcg_gen_mov_i32(reg, dest);
> -    /* Unlike m68k, coldfire always clears the overflow bit.  */
> +    if (m68k_feature(s->env, M68K_FEATURE_M68000)) {
> +        if (ext & 0x800) {
> +            gen_helper_muls32_cc(dest, cpu_env, src1, reg);

	tcg_gen_muls2_i32(reg, QREG_CC_DEST, reg, src1);
	set_cc_op(s, CC_OP_MULQ_V);
	tcg_gen_mov_i32(QREG_CC_SRC, reg);

where MULQ_V is like MULQ, except that it also sets
V = (DEST != (SRC >> 31)).

> +        } else {
> +            gen_helper_mulu32_cc(dest, cpu_env, src1, reg);

	tcg_gen_mulu2_i32(reg, QREG_CC_DEST, reg, src1);
	set_cc_op(s, CC_OP_MULQ);
	tcg_gen_mov_i32(QREG_CC_SRC, reg);


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 27/30] m68k: add addx/subx/negx
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 27/30] m68k: add addx/subx/negx Laurent Vivier
@ 2015-08-12 18:46   ` Richard Henderson
  2015-08-13  0:11     ` Laurent Vivier
  0 siblings, 1 reply; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 18:46 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> +    return (op1 & ~((1UL << bits) - 1)) | res;                          \

deposit32(op1, res, bits, 0)

Otherwise,

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


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 28/30] m68k: shift/rotate bytes and words
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 28/30] m68k: shift/rotate bytes and words Laurent Vivier
@ 2015-08-12 19:11   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 19:11 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> +#define HELPER_SHL(type, bits) \
> +uint32_t HELPER(glue(glue(shl, bits), _cc))(CPUM68KState *env, \
> +                                            uint32_t val, uint32_t shift) \
> +{ \
> +    type result; \
> +    uint32_t cf; \
> +    shift &= 63; \
> +    if (shift == 0) { \
> +        result = (type)val; \
> +        cf = 0; \
> +    } else if (shift < bits) { \
> +        result = (type)val << shift; \
> +        cf = ((type)val >> (bits - shift)) & 1; \
> +    } else if (shift == bits) { \
> +        result = 0; \
> +        cf = val & 1; \
> +    } else { \
> +        result = 0; \
> +        cf = 0; \
> +    } \

Perhaps this would be cleaner to simply operate on a 64-bit type.

	uint64_t res = (type)val;
        res <<= shift & 63;
	cf = (res >> bits) & 1;

For shift == 0, we've not set bit BITS, so it's zero.
For shift <= BITS, we've obviously got the correct data.
For shift > BITS, we've shifted val all the way past and again have zero.

> +#define HELPER_SHR(type, bits) \
> +uint32_t HELPER(glue(glue(shr, bits), _cc))(CPUM68KState *env, \
> +                                            uint32_t val, uint32_t shift) \
> +{ \
> +    type result; \
> +    uint32_t cf; \
> +    shift &= 63; \
> +    if (shift == 0) { \
> +        result = (type)val; \
> +        cf = 0; \
> +    } else if (shift < bits) { \
> +        result = (type)val >> shift; \
> +        cf = ((type)val >> (shift - 1)) & 1; \
> +    } else if (shift == bits) { \
> +        result = 0; \
> +        cf = (type)val >> (bits - 1); \
> +    } else { \
> +        result = 0; \
> +        cf = 0; \
> +    } \

Similarly.

> +#define HELPER_SAL(type, bits) \
> +uint32_t HELPER(glue(glue(sal, bits), _cc))(CPUM68KState *env, \
> +                                            uint32_t val, uint32_t shift) \
> +{ \
> +    type result; \
> +    uint32_t cf; \
> +    uint32_t vf; \
> +    uint32_t m; \
> +    shift &= 63; \
> +    if (shift == 0) { \
> +        vf = 0; \
> +    } else if (shift < bits) { \
> +        m = ((1llu << (shift + 1)) - 1) << (bits - shift - 1); \
> +        vf = (val & m) != m && (val & m) != 0; \
> +    } else { \
> +        m = (1llu << bits) - 1; \
> +        vf = (val & m) != 0; \
> +    } \

This computation of VF seems overly complex.  It's just

  (type)(val ^ result) < 0

for all cases.

> +DISAS_INSN(shift8_im)
> +DISAS_INSN(shift16_im)
>  DISAS_INSN(shift_im)
...
> +DISAS_INSN(shift8_reg)
> +DISAS_INSN(shift16_reg)
>  DISAS_INSN(shift_reg)
...
> +DISAS_INSN(shift_mem)

Surely some code could be shared here...


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 29/30] m68k: add rol/rox/ror/roxr
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 29/30] m68k: add rol/rox/ror/roxr Laurent Vivier
@ 2015-08-12 19:40   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 19:40 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  target-m68k/helper.c    | 212 ++++++++++++++++++++++++++++++++++++++++++++++++
>  target-m68k/helper.h    |  14 ++++
>  target-m68k/translate.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 433 insertions(+)
> 
> diff --git a/target-m68k/helper.c b/target-m68k/helper.c
> index 16fca70..532f366 100644
> --- a/target-m68k/helper.c
> +++ b/target-m68k/helper.c
> @@ -25,6 +25,42 @@
>  
>  #define SIGNBIT (1u << 31)
>  
> +/* modulo 33 table */
> +const uint8_t rox32_table[64] = {
> +    0,  1,  2,  3,  4,  5,  6,  7,
> +    8,  9, 10, 11, 12, 13, 14, 15,
> +   16, 17, 18, 19, 20, 21, 22, 23,
> +   24, 25, 26, 27, 28, 29, 30, 31,
> +   32,  0,  1,  2,  3,  4,  5,  6,
> +    7,  8,  9, 10, 11, 12, 13, 14,
> +   15, 16, 17, 18, 19, 20, 21, 22,
> +   23, 24, 25, 26, 27, 28, 29, 30,
> +};
> +
> +/* modulo 17 table */
> +const uint8_t rox16_table[64] = {
> +    0,  1,  2,  3,  4,  5,  6,  7,
> +    8,  9, 10, 11, 12, 13, 14, 15,
> +   16,  0,  1,  2,  3,  4,  5,  6,
> +    7,  8,  9, 10, 11, 12, 13, 14,
> +   15, 16,  0,  1,  2,  3,  4,  5,
> +    6,  7,  8,  9, 10, 11, 12, 13,
> +   14, 15, 16,  0,  1, 2,   3,  4,
> +    5,  6,  7,  8,  9, 10, 11, 12,
> +};
> +
> +/* modulo 9 table */
> +const uint8_t rox8_table[64] = {
> +    0, 1, 2, 3, 4, 5, 6, 7,
> +    8, 0, 1, 2, 3, 4, 5, 6,
> +    7, 8, 0, 1, 2, 3, 4, 5,
> +    6, 7, 8, 0, 1, 2, 3, 4,
> +    5, 6, 7, 8, 0, 1, 2, 3,
> +    4, 5, 6, 7, 8, 0, 1, 2,
> +    3, 4, 5, 6, 7, 8, 0, 1,
> +    2, 3, 4, 5, 6, 7, 8, 0,
> +};

Why would you have these tables as opposed to just using the C modulo operator?

> +uint32_t HELPER(rol32)(uint32_t val, uint32_t shift)
> +{
> +    uint32_t result;
> +    if (shift == 0 || shift == 32) {
> +        return val;
> +    }
> +    result = (val << shift) | (val >> (32 - shift));
> +    return result;
> +}
> +
> +uint32_t HELPER(ror32)(uint32_t val, uint32_t shift)
> +{
> +    uint32_t result;
> +    if (shift == 0 || shift == 32) {
> +        return val;
> +    }
> +    result = (val >> shift) | (val << (32 - shift));
> +    return result;
> +}

Easily done in tcg directly.  But aren't these are actually unused?

> +#define HELPER_ROXR(type, bits) \
> +uint32_t HELPER(glue(glue(roxr, bits), _cc))(CPUM68KState *env, \
> +                                             uint32_t val, uint32_t shift) \
> +{ \

Again, I think perhaps a 64-bit shift type might help clean up these cases.
Start by forming the 34-bit quantity (X : VAL : 0); end by extracting bits
[32:1] as the result and bit 0 as X.

> +DISAS_INSN(rotate_im)
...
> +DISAS_INSN(rotate_reg)

Again, surely you can share code.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 08/30] m68k: update CPU flags management
  2015-08-12  5:12   ` Richard Henderson
@ 2015-08-12 20:56     ` Laurent Vivier
  2015-08-12 21:19       ` Richard Henderson
  2015-08-13 18:09     ` Laurent Vivier
  1 sibling, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-12 20:56 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: peter.maydell, Andreas Schwab, gerg



Le 12/08/2015 07:12, Richard Henderson a écrit :
> On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>> @@ -798,9 +796,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);
>>   }
> 
> Since this function no longer modifies ENV, it probably deserves a
> better name than "flush_flags".  FWIW cc_compute_all isn't a bad name,
> if you're copying i386 anyway...
> 
>> -DEF_HELPER_2(flush_flags, void, env, i32)
>> +DEF_HELPER_2(flush_flags, i32, env, i32)
> 
> Modify to use DEF_HELPER_FLAGS while you're at it.  At the moment it
> reads some globals, but doesn't write any, or have any other side effects.

It writes "env->cc_x", so I guess I can't use DEF_HELPER_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(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));
>> +    }
> 
> That const needs to be freed.

perhaps I'm wrong, what I had understood is:

tcg_const_i32() creates a tcg_temp_new_i32(), and tcg_temp_new_i32() are
automatically freed at end of tcg block (whereas tcg_const_local adn
tcg_temp_local are not).

>> @@ -1248,7 +1294,6 @@ DISAS_INSN(bitop_im)
>>           DEST_EA(env, insn, opsize, tmp, &addr);
>>       }
>>   }
>> -
>>   DISAS_INSN(arith_im)
>>   {
>>       int op;
> 
> Careful with the errant whitespace changes.
> 
>> @@ -1706,16 +1745,18 @@ 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();
>>           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);
> 
> Ideally you'd do this only once, before the jmpcc.
> 
> 
> r~

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

* Re: [Qemu-devel] [PATCH for-2.5 30/30] m68k: add bitfield instructions
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 30/30] m68k: add bitfield instructions Laurent Vivier
@ 2015-08-12 21:05   ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 21:05 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>  uint32_t HELPER(rol32)(uint32_t val, uint32_t shift)
>  {
>      uint32_t result;
> @@ -1227,6 +1241,53 @@ void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
>      env->macc[acc + 1] = res;
>  }
>  
> +/* load from a bitfield */
> +
> +uint64_t HELPER(bitfield_load)(uint32_t addr, uint32_t offset, uint32_t width)
> +{
> +    uint8_t data[8];
> +    uint64_t bitfield;
> +    int size;
> +    int i;
> +
> +    size = (offset + width + 7) >> 3;
> +#if defined(CONFIG_USER_ONLY)
> +    cpu_memory_rw_debug(NULL, (target_ulong)addr, data, size, 0);
> +#else
> +    cpu_physical_memory_rw(addr, data, size, 0);
> +#endif

Err, this bypasses virtual memory.  Definitely not correct.

You'll need to use cpu_ld*_data instead.

> +DISAS_INSN(bitfield_reg)
> +{
> +    uint16_t ext;
> +    TCGv tmp;
> +    TCGv tmp1;
> +    TCGv reg;
> +    TCGv offset;
> +    TCGv width;
> +    int op;
> +    TCGv reg2;
> +    TCGv mask;
> +
> +    reg = DREG(insn, 0);
> +    op = (insn >> 8) & 7;
> +    ext = read_im16(env, s);
> +
> +    bitfield_param(ext, &offset, &width, &mask);
> +
> +    if (ext & 0x0800) {
> +        tcg_gen_andi_i32(offset, offset, 31);
> +    }
> +    gen_helper_ror32(mask, mask, offset);

Ah, the curious unused helpers.  Anyway, tcg_gen_rotr_i32.

Anyway, there's so much redundant computation in here let's name some
sub-expressions, and give them their own temporaries.  Let the tcg optimizer do
its job if they turn out to be unused for a specific case.

  mask_msb = mask before the rotate (at msb).
  mask_inp = mask after the rotate (in place).

> +    tmp = tcg_temp_new_i32();
> +    tcg_gen_and_i32(tmp, reg, mask);

  oldf_inp = tmp (old field in place).

> +
> +    tmp1 = tcg_temp_new_i32();
> +    gen_helper_rol32(tmp1, tmp, offset);

  oldf_msb = tmp1 (old field at msb).

> +        tcg_gen_sub_i32(tmp2, tcg_const_i32(32), width);

  comp_width = tmp2 (compliment of width).

Use tcg_gen_subfi so you won't leak the const.
Compute this once for all of the sub-cases.

> +    switch (op) {
> +    case 0: /* bftst */
> +        break;
> +    case 1: /* bfextu */
> +        tcg_gen_add_i32(tmp1, offset, width);
> +        tcg_gen_andi_i32(tmp1, tmp1, 31);
> +        gen_helper_rol32(reg2, tmp, tmp1);

  tcg_gen_shr_i32(reg2, oldf_msb, comp_width);

> +        break;
> +    case 2: /* bfchg */
> +        tcg_gen_xor_i32(reg, reg, mask);
> +        break;
> +    case 3: /* bfexts */
> +        gen_helper_rol32(reg2, tmp, offset);
> +        tcg_gen_sub_i32(width, tcg_const_i32(32), width);
> +        tcg_gen_sar_i32(reg2, reg2, width);

  tcg_gen_sar_i32(reg2, oldf_msb, comp_width);

> +    case 4: /* bfclr */
> +        tcg_gen_not_i32(mask, mask);
> +        tcg_gen_and_i32(reg, reg, mask);

  tcg_gen_andc_i32(reg, reg, mask_inp);

> +        break;
> +    case 5: /* bfffo */
> +        gen_helper_rol32(reg2, tmp, offset);
> +        gen_helper_bfffo(tmp, tmp, width);
> +        tcg_gen_add_i32(reg2, tmp, offset);

There's a typo here if you look close.  That said,

  tcg_gen_orc_i32(tmp, oldf_msb, mask_msb);
  gen_helper_clo32(tmp, tmp);
  tcg_gen_add_i32(reg2, tmp, offset);

with

uint32_t helper_clo32(uint32_t x)
{
  return clo32(x);
}

The first opcode sets all bits outside the field, so that (if the field is
smaller than 32 bits) we're guaranteed to find a one.  At which point there's
really very little that needs doing in the helper.

> +    case 6: /* bfset */
> +        tcg_gen_or_i32(reg, reg, mask);
> +        break;

  tcg_gen_or_i32(reg, reg, mask_inp);

> +    case 7: /* bfins */
> +        tcg_gen_shl_i32(tmp1, tcg_const_i32(1), width);

Undefined if width == 32.  That said...

> +        tcg_gen_subi_i32(tmp1, tmp1, 1);
> +        tcg_gen_and_i32(tmp, reg2, tmp1);
> +        tcg_gen_add_i32(tmp1, offset, width);
> +        tcg_gen_andi_i32(tmp1, tmp1, 31);
> +        gen_helper_ror32(tmp, tmp, tmp1);
> +        tcg_gen_not_i32(mask, mask);
> +        tcg_gen_and_i32(reg, reg, mask);
> +        tcg_gen_or_i32(reg, reg, tmp);
> +        break;

  /* Rotate the source so that the field is at msb.  */
  tcg_gen_rotr_i32(tmp, reg2, width);

  /* Isolate the field and set flags.  */
  tcg_gen_and_i32(tmp, tmp, mask_msb);
  gen_logic_cc(s, tmp, OS_LONG);

  /* Rotate the field into position.  */
  tcg_gen_rotr_i32(tmp, tmp, offset);

  /* Merge field into destination.  */
  tcg_gen_andc_i32(reg, reg, mask_inp);
  tcg_gen_or_i32(reg, reg, tmp);
  return;

Handle the non-bfins after the switch with

  gen_logic_cc(s, oldf_msb, OS_LONG);

> +DISAS_INSN(bitfield_mem)
> +{
> +    uint16_t ext;
> +    int op;
> +    TCGv_i64 bitfield;
> +    TCGv_i64 mask_bitfield;
> +    TCGv mask_cc;
> +    TCGv shift;
> +    TCGv val;
> +    TCGv src;
> +    TCGv offset;
> +    TCGv width;
> +    TCGv reg;
> +    TCGv tmp;
> +
> +    op = (insn >> 8) & 7;
> +    ext = read_im16(env, s);
> +    src = gen_lea(env, s, insn, OS_LONG);
> +    if (IS_NULL_QREG(src)) {
> +        gen_addr_fault(s);
> +        return;
> +    }
> +
> +    bitfield_param(ext, &offset, &width, &mask_cc);
> +
> +    /* adjust src and offset */
> +
> +    /* src += offset >> 3; */
> +
> +    tmp = tcg_temp_new_i32();
> +    tcg_gen_shri_i32(tmp, offset, 3);
> +    tcg_gen_add_i32(src, src, tmp);
> +
> +    /* offset &= 7; */
> +
> +    tcg_gen_andi_i32(offset, offset, 7);
> +
> +    /* load */
> +
> +    bitfield = tcg_temp_new_i64();
> +    gen_helper_bitfield_load(bitfield, src, offset, width);

Surely better to load the value from memory such that the field is positioned
at the MSB, share code with bitfield_reg for the actual computation of flags
and result, and then store the value back from the temporary at MSB as needed.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 08/30] m68k: update CPU flags management
  2015-08-12 20:56     ` Laurent Vivier
@ 2015-08-12 21:19       ` Richard Henderson
  2015-08-12 21:21         ` Laurent Vivier
  0 siblings, 1 reply; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 21:19 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: peter.maydell, Andreas Schwab, gerg

On 08/12/2015 01:56 PM, Laurent Vivier wrote:
>>> -DEF_HELPER_2(flush_flags, void, env, i32)
>>> +DEF_HELPER_2(flush_flags, i32, env, i32)
>>
>> Modify to use DEF_HELPER_FLAGS while you're at it.  At the moment it
>> reads some globals, but doesn't write any, or have any other side effects.
>
> It writes "env->cc_x", so I guess I can't use DEF_HELPER_FLAGS ?

Ah, missed that.  So, no, not usefully.

>> That const needs to be freed.
>
> perhaps I'm wrong, what I had understood is:
>
> tcg_const_i32() creates a tcg_temp_new_i32(), and tcg_temp_new_i32() are
> automatically freed at end of tcg block (whereas tcg_const_local adn
> tcg_temp_local are not).

They are freed at the end of a basic block.  But the total number of temps 
affects the speed of the tcg code generator.  So you can improve the speed of 
qemu by freeing temporaries that are no longer needed.


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 08/30] m68k: update CPU flags management
  2015-08-12 21:19       ` Richard Henderson
@ 2015-08-12 21:21         ` Laurent Vivier
  0 siblings, 0 replies; 78+ messages in thread
From: Laurent Vivier @ 2015-08-12 21:21 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: peter.maydell, Andreas Schwab, gerg



Le 12/08/2015 23:19, Richard Henderson a écrit :
> On 08/12/2015 01:56 PM, Laurent Vivier wrote:
>>>> -DEF_HELPER_2(flush_flags, void, env, i32)
>>>> +DEF_HELPER_2(flush_flags, i32, env, i32)
>>>
>>> Modify to use DEF_HELPER_FLAGS while you're at it.  At the moment it
>>> reads some globals, but doesn't write any, or have any other side
>>> effects.
>>
>> It writes "env->cc_x", so I guess I can't use DEF_HELPER_FLAGS ?
> 
> Ah, missed that.  So, no, not usefully.
> 
>>> That const needs to be freed.
>>
>> perhaps I'm wrong, what I had understood is:
>>
>> tcg_const_i32() creates a tcg_temp_new_i32(), and tcg_temp_new_i32() are
>> automatically freed at end of tcg block (whereas tcg_const_local adn
>> tcg_temp_local are not).
> 
> They are freed at the end of a basic block.  But the total number of
> temps affects the speed of the tcg code generator.  So you can improve
> the speed of qemu by freeing temporaries that are no longer needed.

OK, thank you. I was wondering if it is useful to free temp or not...

Laurent

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

* Re: [Qemu-devel] [PATCH for-2.5 20/30] m68k: add exg
  2015-08-12 17:05   ` Richard Henderson
@ 2015-08-12 22:43     ` Laurent Vivier
  2015-08-12 23:09       ` Richard Henderson
  0 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-12 22:43 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg



Le 12/08/2015 19:05, Richard Henderson a écrit :
> On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
>> ---
>>  target-m68k/translate.c | 34 +++++++++++++++++++++++++++++++++-
>>  1 file changed, 33 insertions(+), 1 deletion(-)
>>
>> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
>> index adf4521..b7d15e9 100644
>> --- a/target-m68k/translate.c
>> +++ b/target-m68k/translate.c
>> @@ -2035,10 +2035,42 @@ DISAS_INSN(and)
>>      TCGv dest;
>>      TCGv addr;
>>      int opsize;
>> +    int exg_mode;
>>  
>> +    dest = tcg_temp_new();
>> +
>> +    /* exg */
>> +
>> +    exg_mode = insn & 0x1f8;
> 
> Likewise, surely we can decode EXG separately from AND, and avoid doing so for
> coldfire.

I agree for CMPM, not for EXG.

Let's have a look to instructions encoding :)

AND       1100dddooommmrrr

  ddd       data register number
  ooo       opmode,  invalid: 011, 111
  mmmrrr    ea mode, if ooo = { 000, 001, 010} invalid: 001000 .. 001111
                     if ooo = { 100, 101, 110} invalid; 000000 .. 001111

EXG       1100xxx1oooooyyy

  xxx       register
  ooooo     valid: 01000, 01001, 10001
  yyy       register

So, EXG is an AND with

  ooo 101, 110
  mmm 000, 001

which are invalid combinations for AND.

IMHO, EXG looks like a wart on the AND and should be decoded like that...

I don't know how to add this easily in the table... except by adding 3
entries to decode 1 instruction. Is it acceptable ?

Laurent

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

* Re: [Qemu-devel] [PATCH for-2.5 20/30] m68k: add exg
  2015-08-12 22:43     ` Laurent Vivier
@ 2015-08-12 23:09       ` Richard Henderson
  2015-08-12 23:10         ` Laurent Vivier
  0 siblings, 1 reply; 78+ messages in thread
From: Richard Henderson @ 2015-08-12 23:09 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/12/2015 03:43 PM, Laurent Vivier wrote:
>
>
> Le 12/08/2015 19:05, Richard Henderson a écrit :
>> On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>>> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
>>> ---
>>>   target-m68k/translate.c | 34 +++++++++++++++++++++++++++++++++-
>>>   1 file changed, 33 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
>>> index adf4521..b7d15e9 100644
>>> --- a/target-m68k/translate.c
>>> +++ b/target-m68k/translate.c
>>> @@ -2035,10 +2035,42 @@ DISAS_INSN(and)
>>>       TCGv dest;
>>>       TCGv addr;
>>>       int opsize;
>>> +    int exg_mode;
>>>
>>> +    dest = tcg_temp_new();
>>> +
>>> +    /* exg */
>>> +
>>> +    exg_mode = insn & 0x1f8;
>>
>> Likewise, surely we can decode EXG separately from AND, and avoid doing so for
>> coldfire.
>
> I agree for CMPM, not for EXG.
>
> Let's have a look to instructions encoding :)
>
> AND       1100dddooommmrrr
>
>    ddd       data register number
>    ooo       opmode,  invalid: 011, 111
>    mmmrrr    ea mode, if ooo = { 000, 001, 010} invalid: 001000 .. 001111
>                       if ooo = { 100, 101, 110} invalid; 000000 .. 001111
>
> EXG       1100xxx1oooooyyy
>
>    xxx       register
>    ooooo     valid: 01000, 01001, 10001
>    yyy       register
>
> So, EXG is an AND with
>
>    ooo 101, 110
>    mmm 000, 001
>
> which are invalid combinations for AND.
>
> IMHO, EXG looks like a wart on the AND and should be decoded like that...

Hmm, perhaps you're right.  On the other hand, maybe we should rename the 
function and_exg, and also properly check for M68000 before accepting exg?


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 20/30] m68k: add exg
  2015-08-12 23:09       ` Richard Henderson
@ 2015-08-12 23:10         ` Laurent Vivier
  0 siblings, 0 replies; 78+ messages in thread
From: Laurent Vivier @ 2015-08-12 23:10 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: peter.maydell, Andreas Schwab, gerg



Le 13/08/2015 01:09, Richard Henderson a écrit :
> On 08/12/2015 03:43 PM, Laurent Vivier wrote:
>>
>>
>> Le 12/08/2015 19:05, Richard Henderson a écrit :
>>> On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>>>> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
>>>> ---
>>>>   target-m68k/translate.c | 34 +++++++++++++++++++++++++++++++++-
>>>>   1 file changed, 33 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
>>>> index adf4521..b7d15e9 100644
>>>> --- a/target-m68k/translate.c
>>>> +++ b/target-m68k/translate.c
>>>> @@ -2035,10 +2035,42 @@ DISAS_INSN(and)
>>>>       TCGv dest;
>>>>       TCGv addr;
>>>>       int opsize;
>>>> +    int exg_mode;
>>>>
>>>> +    dest = tcg_temp_new();
>>>> +
>>>> +    /* exg */
>>>> +
>>>> +    exg_mode = insn & 0x1f8;
>>>
>>> Likewise, surely we can decode EXG separately from AND, and avoid
>>> doing so for
>>> coldfire.
>>
>> I agree for CMPM, not for EXG.
>>
>> Let's have a look to instructions encoding :)
>>
>> AND       1100dddooommmrrr
>>
>>    ddd       data register number
>>    ooo       opmode,  invalid: 011, 111
>>    mmmrrr    ea mode, if ooo = { 000, 001, 010} invalid: 001000 .. 001111
>>                       if ooo = { 100, 101, 110} invalid; 000000 .. 001111
>>
>> EXG       1100xxx1oooooyyy
>>
>>    xxx       register
>>    ooooo     valid: 01000, 01001, 10001
>>    yyy       register
>>
>> So, EXG is an AND with
>>
>>    ooo 101, 110
>>    mmm 000, 001
>>
>> which are invalid combinations for AND.
>>
>> IMHO, EXG looks like a wart on the AND and should be decoded like that...
> 
> Hmm, perhaps you're right.  On the other hand, maybe we should rename
> the function and_exg, and also properly check for M68000 before
> accepting exg?

I agree.

Thank you for all your comments.
Laurent

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

* Re: [Qemu-devel] [PATCH for-2.5 27/30] m68k: add addx/subx/negx
  2015-08-12 18:46   ` Richard Henderson
@ 2015-08-13  0:11     ` Laurent Vivier
  2015-08-13  2:23       ` Richard Henderson
  0 siblings, 1 reply; 78+ messages in thread
From: Laurent Vivier @ 2015-08-13  0:11 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg



Le 12/08/2015 20:46, Richard Henderson a écrit :
> On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>> +    return (op1 & ~((1UL << bits) - 1)) | res; \
> 
> deposit32(op1, res, bits, 0)
> 

You mean: deposit32(op1, 0, bits, res) ?

Laurent

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

* Re: [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation
  2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
                   ` (29 preceding siblings ...)
  2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 30/30] m68k: add bitfield instructions Laurent Vivier
@ 2015-08-13  2:22 ` Richard Henderson
  30 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-13  2:22 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: peter.maydell, Andreas Schwab, gerg

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>    m68k: allow to update flags with operation on words and bytes
>    m68k: update CPU flags management
>    m68k: add X flag helpers

I wonder if we can talk about a different mechanism for tracking flags.

The x86 scheme tracks flags with 3 words: { op, dest, src }.  This is easy to 
handle arithmetic, logicals, and comparisons.  But shifts and other weird 
things require complex helpers.

The m68k scheme, which you're enhancing, is the same, except with an additional 
word for X.  It's this extra X flag that complicates things.

The arm scheme tracks 4 flags with 4 individual words.  This is more 
complicated for arithmetic (especially computing overflow), but it rarely 
requires complicated helpers.

I propose using a hybrid between the two, using 6 words: { op, c, v, z, n, x }.

op = OP_FLAGS (i.e. fully computed state)

   X = cc_x is 0/1
   C = cc_c is 0/1
   V = cc_v < 0
   N = cc_n < 0
   Z = cc_z == 0

op = OP_ADD

   X = C = cc_x is 0/1

   cc_n = result
   cc_v = src1
   cc_c = unused
   cc_z = unused

   N = cc_n < 0
   Z = cc_n == 0
   V = ((result ^ src1) & ~((result - src1) ^ src1)) < 0

op = OP_SUB

   like OP_ADD, except
   V = ((result ^ src1) & (src1 ^ (src1 - result))) < 0

op = OP_LOGIC

   X = cc_x is 0/1
   C = 0
   V = 0

   cc_n = result
   N = cc_n < 0
   Z = cc_n == 0

All of the byte and word variants are handled by sign-extending the quantities.

This keeps X up-to-date at all times.  It minimizes the amount to data that 
needs to be synced back to env before memory operations.  It leaves enough data 
to easily compute signed comparisons.

The more complicated cases of addx and shifts, now simply operate in OP_FLAGS 
mode and don't require helpers.

I'll follow up with some patches...


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 27/30] m68k: add addx/subx/negx
  2015-08-13  0:11     ` Laurent Vivier
@ 2015-08-13  2:23       ` Richard Henderson
  0 siblings, 0 replies; 78+ messages in thread
From: Richard Henderson @ 2015-08-13  2:23 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel
  Cc: peter.maydell, peter.crosthwaite, Andreas Schwab, gerg

On 08/12/2015 05:11 PM, Laurent Vivier wrote:
>
>
> Le 12/08/2015 20:46, Richard Henderson a écrit :
>> On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>>> +    return (op1 & ~((1UL << bits) - 1)) | res; \
>>
>> deposit32(op1, res, bits, 0)
>>
>
> You mean: deposit32(op1, 0, bits, res) ?

Yes, sorry.  The operand order is different for tcg_gen_deposit_i32.  ;-)


r~

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

* Re: [Qemu-devel] [PATCH for-2.5 08/30] m68k: update CPU flags management
  2015-08-12  5:12   ` Richard Henderson
  2015-08-12 20:56     ` Laurent Vivier
@ 2015-08-13 18:09     ` Laurent Vivier
  1 sibling, 0 replies; 78+ messages in thread
From: Laurent Vivier @ 2015-08-13 18:09 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: peter.maydell, Andreas Schwab, gerg



Le 12/08/2015 07:12, Richard Henderson a écrit :
> On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>> @@ -798,9 +796,9 @@ void HELPER(mac_set_flags)(CPUM68KState *env,
> 
>> @@ -1706,16 +1745,18 @@ 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();
>>           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);
> 
> Ideally you'd do this only once, before the jmpcc.

This breaks something.

I think we can't do update_cc_op() before gen_jmpcc() because
gen_jmpcc() calls gen_flush_flags().

Laurent

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

end of thread, other threads:[~2015-08-13 18:09 UTC | newest]

Thread overview: 78+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 01/30] m68k: define m680x0 CPUs and features Laurent Vivier
2015-08-11 23:13   ` Richard Henderson
2015-08-12  8:01     ` Laurent Vivier
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 02/30] m68k: manage scaled index Laurent Vivier
2015-08-12  3:42   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 03/30] m68k: introduce read_imXX() functions Laurent Vivier
2015-08-09 21:12   ` Andreas Schwab
2015-08-12  3:54   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 04/30] m68k: set disassembler mode to 680x0 or coldfire Laurent Vivier
2015-08-12  3:57   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 05/30] m68k: define operand sizes Laurent Vivier
2015-08-12  4:07   ` Richard Henderson
2015-08-12  8:44     ` Laurent Vivier
2015-08-12  8:52       ` Andreas Schwab
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 06/30] m68k: REG() macro cleanup Laurent Vivier
2015-08-12  4:11   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 07/30] m68k: allow to update flags with operation on words and bytes Laurent Vivier
2015-08-12  4:28   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 08/30] m68k: update CPU flags management Laurent Vivier
2015-08-12  5:12   ` Richard Henderson
2015-08-12 20:56     ` Laurent Vivier
2015-08-12 21:19       ` Richard Henderson
2015-08-12 21:21         ` Laurent Vivier
2015-08-13 18:09     ` Laurent Vivier
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 09/30] m68k: add X flag helpers Laurent Vivier
2015-08-12  5:18   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 10/30] m68k: tst bugfix Laurent Vivier
2015-08-12  5:18   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 11/30] m68k: improve clr/moveq Laurent Vivier
2015-08-12  5:20   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 12/30] m68k: Manage divw overflow Laurent Vivier
2015-08-12  6:03   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 13/30] m68k: set Z and N on divu/muls overflow as a real 68040 Laurent Vivier
2015-08-12  6:29   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 14/30] m68k: allow adda/suba to add/sub word Laurent Vivier
2015-08-12  7:32   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 15/30] m68k: add more modes to movem Laurent Vivier
2015-08-12  7:54   ` Richard Henderson
2015-08-12  8:07     ` Andreas Schwab
2015-08-12 15:13       ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 16/30] m68k: Add all access modes and data sizes to some 680x0 instructions Laurent Vivier
2015-08-12 16:25   ` Richard Henderson
2015-08-12 16:27   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 17/30] m68k: ori/andi/subi/addi/eori/cmpi can modify SR/CCR Laurent Vivier
2015-08-12 16:44   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 18/30] m68k: addq/subq can work with all the data sizes Laurent Vivier
2015-08-12 16:48   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 19/30] m68k: add cmpm Laurent Vivier
2015-08-12 17:00   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 20/30] m68k: add exg Laurent Vivier
2015-08-12 17:05   ` Richard Henderson
2015-08-12 22:43     ` Laurent Vivier
2015-08-12 23:09       ` Richard Henderson
2015-08-12 23:10         ` Laurent Vivier
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 21/30] m68k: add bkpt Laurent Vivier
2015-08-12 17:07   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 22/30] m68k: add cas instruction Laurent Vivier
2015-08-12 17:14   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 23/30] m68k: add linkl Laurent Vivier
2015-08-12 17:33   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 24/30] m68k: add DBcc and Scc (memory operand) Laurent Vivier
2015-08-12 17:49   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 25/30] m68k: add abcd, sbcd, nbcd instructions Laurent Vivier
2015-08-12 17:57   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 26/30] m68k: add mull/divl Laurent Vivier
2015-08-12 18:36   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 27/30] m68k: add addx/subx/negx Laurent Vivier
2015-08-12 18:46   ` Richard Henderson
2015-08-13  0:11     ` Laurent Vivier
2015-08-13  2:23       ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 28/30] m68k: shift/rotate bytes and words Laurent Vivier
2015-08-12 19:11   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 29/30] m68k: add rol/rox/ror/roxr Laurent Vivier
2015-08-12 19:40   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 30/30] m68k: add bitfield instructions Laurent Vivier
2015-08-12 21:05   ` Richard Henderson
2015-08-13  2:22 ` [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Richard Henderson

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.