* [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support @ 2009-05-29 22:41 Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32() Laurent Vivier ` (2 more replies) 0 siblings, 3 replies; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel This series of patches is a port to Qemu 0.10 of Andreas Schwab M68K patch to support Motorola 680x0 CPU family. It has been tested with some commands from a debian m68k lenny disk. Commands like "uname", "date", "ls", "more", "grep" work well. [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32() [PATCH 02/17] m68k: add tcg_gen_debug_insn_start() [PATCH 03/17] m68k: define m680x0 CPUs and features [PATCH 04/17] m68k: add missing accessing modes for some instructions. [PATCH 05/17] m68k: add Motorola 680x0 family common instructions. [PATCH 06/17] m68k: add Scc instruction with memory operand. [PATCH 07/17] m68k: add DBcc instruction. [PATCH 08/17] m68k: modify movem instruction to manage word [PATCH 09/17] m68k: add 64bit divide. [PATCH 10/17] m68k: add 32bit and 64bit multiply [PATCH 11/17] m68k: add word data size for suba/adda [PATCH 12/17] m68k: add fpu [PATCH 13/17] m68k: add "byte", "word" and memory shift [PATCH 14/17] m68k: add "byte", "word" and memory rotate. [PATCH 15/17] m68k: add bitfield_mem, bitfield_reg [PATCH 16/17] m68k: add variable offset/width to bitfield_reg/bitfield_mem [PATCH 17/17] m68k: add cas ^ permalink raw reply [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32() 2009-05-29 22:41 [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 02/17] m68k: add tcg_gen_debug_insn_start() Laurent Vivier 2009-05-30 17:31 ` [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support François Revol 2009-09-21 2:56 ` Rob Landley 2 siblings, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Laurent Vivier Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/translate.c | 43 ++++++++++++++++++++----------------------- 1 files changed, 20 insertions(+), 23 deletions(-) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 422f0a4..521891f 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -172,9 +172,6 @@ typedef void (*disas_proc)(DisasContext *, uint16_t); static void disas_##name (DisasContext *s, uint16_t insn) #endif -/* FIXME: Remove this. */ -#define gen_im32(val) tcg_const_i32(val) - /* Generate a load from the specified address. Narrow values are sign extended to full register width. */ static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int sign) @@ -340,7 +337,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) if ((ext & 0x80) == 0) { /* base not suppressed */ if (IS_NULL_QREG(base)) { - base = gen_im32(offset + bd); + base = tcg_const_i32(offset + bd); bd = 0; } if (!IS_NULL_QREG(add)) { @@ -356,7 +353,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) add = tmp; } } else { - add = gen_im32(bd); + add = tcg_const_i32(bd); } if ((ext & 3) != 0) { /* memory indirect */ @@ -537,16 +534,16 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize) case 0: /* Absolute short. */ offset = ldsw_code(s->pc); s->pc += 2; - return gen_im32(offset); + return tcg_const_i32(offset); case 1: /* Absolute long. */ offset = read_im32(s); - return gen_im32(offset); + return tcg_const_i32(offset); case 2: /* pc displacement */ tmp = tcg_temp_new(); offset = s->pc; offset += ldsw_code(s->pc); s->pc += 2; - return gen_im32(offset); + return tcg_const_i32(offset); case 3: /* pc index+displacement. */ return gen_lea_indexed(s, opsize, NULL_QREG); case 4: /* Immediate. */ @@ -1211,16 +1208,16 @@ DISAS_INSN(arith_im) break; case 2: /* subi */ tcg_gen_mov_i32(dest, src1); - gen_helper_xflag_lt(QREG_CC_X, dest, gen_im32(im)); + gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im)); tcg_gen_subi_i32(dest, dest, im); - gen_update_cc_add(dest, gen_im32(im)); + gen_update_cc_add(dest, tcg_const_i32(im)); s->cc_op = CC_OP_SUB; break; case 3: /* addi */ tcg_gen_mov_i32(dest, src1); tcg_gen_addi_i32(dest, dest, im); - gen_update_cc_add(dest, gen_im32(im)); - gen_helper_xflag_lt(QREG_CC_X, dest, gen_im32(im)); + gen_update_cc_add(dest, tcg_const_i32(im)); + gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im)); s->cc_op = CC_OP_ADD; break; case 5: /* eori */ @@ -1230,7 +1227,7 @@ DISAS_INSN(arith_im) case 6: /* cmpi */ tcg_gen_mov_i32(dest, src1); tcg_gen_subi_i32(dest, dest, im); - gen_update_cc_add(dest, gen_im32(im)); + gen_update_cc_add(dest, tcg_const_i32(im)); s->cc_op = CC_OP_SUB; break; default: @@ -1326,8 +1323,8 @@ DISAS_INSN(clr) default: abort(); } - DEST_EA(insn, opsize, gen_im32(0), NULL); - gen_logic_cc(s, gen_im32(0)); + DEST_EA(insn, opsize, tcg_const_i32(0), NULL); + gen_logic_cc(s, tcg_const_i32(0)); } static TCGv gen_get_ccr(DisasContext *s) @@ -1591,7 +1588,7 @@ DISAS_INSN(jump) } if ((insn & 0x40) == 0) { /* jsr */ - gen_push(s, gen_im32(s->pc)); + gen_push(s, tcg_const_i32(s->pc)); } gen_jmp(s, tmp); } @@ -1619,7 +1616,7 @@ DISAS_INSN(addsubq) tcg_gen_addi_i32(dest, dest, val); } } else { - src2 = gen_im32(val); + src2 = tcg_const_i32(val); if (insn & 0x0100) { gen_helper_xflag_lt(QREG_CC_X, dest, src2); tcg_gen_subi_i32(dest, dest, val); @@ -1668,7 +1665,7 @@ DISAS_INSN(branch) } if (op == 1) { /* bsr */ - gen_push(s, gen_im32(s->pc)); + gen_push(s, tcg_const_i32(s->pc)); } gen_flush_cc_op(s); if (op > 1) { @@ -1759,7 +1756,7 @@ DISAS_INSN(mov3q) val = (insn >> 9) & 7; if (val == 0) val = -1; - src = gen_im32(val); + src = tcg_const_i32(val); gen_logic_cc(s, src); DEST_EA(insn, OS_LONG, src, NULL); } @@ -1885,7 +1882,7 @@ DISAS_INSN(shift_im) tmp = (insn >> 9) & 7; if (tmp == 0) tmp = 8; - shift = gen_im32(tmp); + shift = tcg_const_i32(tmp); /* No need to flush flags becuse we know we will set C flag. */ if (insn & 0x100) { gen_helper_shl_cc(reg, cpu_env, reg, shift); @@ -2193,7 +2190,7 @@ DISAS_INSN(fpu) switch ((ext >> 10) & 7) { case 4: /* FPCR */ /* Not implemented. Always return zero. */ - tmp32 = gen_im32(0); + tmp32 = tcg_const_i32(0); break; case 1: /* FPIAR */ case 2: /* FPSR */ @@ -2594,7 +2591,7 @@ DISAS_INSN(mac) /* Skip the accumulate if the value is already saturated. */ l1 = gen_new_label(); tmp = tcg_temp_new(); - gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc)); + gen_op_and32(tmp, QREG_MACSR, tcg_const_i32(MACSR_PAV0 << acc)); gen_op_jmp_nz32(tmp, l1); } #endif @@ -2628,7 +2625,7 @@ DISAS_INSN(mac) /* Skip the accumulate if the value is already saturated. */ l1 = gen_new_label(); tmp = tcg_temp_new(); - gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc)); + gen_op_and32(tmp, QREG_MACSR, tcg_const_i32(MACSR_PAV0 << acc)); gen_op_jmp_nz32(tmp, l1); } #endif -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 02/17] m68k: add tcg_gen_debug_insn_start() 2009-05-29 22:41 ` [Qemu-devel] [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32() Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 03/17] m68k: define m680x0 CPUs and features Laurent Vivier 0 siblings, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier This patch add debug info by writing the PC of the corresponing CPU instruction of an TCG opcode. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/translate.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 521891f..dc34a2a 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2950,6 +2950,9 @@ static void disas_m68k_insn(CPUState * env, DisasContext *s) { uint16_t insn; + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) + tcg_gen_debug_insn_start(s->pc); + insn = lduw_code(s->pc); s->pc += 2; -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 03/17] m68k: define m680x0 CPUs and features 2009-05-29 22:41 ` [Qemu-devel] [PATCH 02/17] m68k: add tcg_gen_debug_insn_start() Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Laurent Vivier 0 siblings, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier This patch defines four new Motorola 680x0 family CPUs: - M68K_CPUID_M68000, - M68K_CPUID_M68020, - M68K_CPUID_M68040, - M68K_CPUID_M68060 And six new features: - M68K_FEATURE_SCALED_INDEX, scaled address index register - M68K_FEATURE_LONG_MULDIV, 32bit multiply/divide - M68K_FEATURE_QUAD_MULDIV, 64bit multiply/divide - M68K_FEATURE_BCCL, long conditional branches - M68K_FEATURE_BITFIELD, bit field instructions - M68K_FEATURE_FPU, FPU instructions Following patches implement them... Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/cpu.h | 13 ++++++++++--- target-m68k/helper.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index feffb6b..eb18e9e 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -181,6 +181,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr); ISA revisions mentioned. */ enum m68k_features { + M68K_FEATURE_M68000, M68K_FEATURE_CF_ISA_A, M68K_FEATURE_CF_ISA_B, /* (ISA B or C). */ M68K_FEATURE_CF_ISA_APLUSC, /* BIT/BITREV, FF1, STRLDSR (ISA A+ or C). */ @@ -191,7 +192,13 @@ enum m68k_features { M68K_FEATURE_CF_EMAC_B, /* Revision B EMAC (dual accumulate). */ M68K_FEATURE_USP, /* User Stack Pointer. (ISA A+, B or C). */ M68K_FEATURE_EXT_FULL, /* 68020+ full extension word. */ - M68K_FEATURE_WORD_INDEX /* word sized address index registers. */ + M68K_FEATURE_WORD_INDEX, /* word sized address index registers. */ + M68K_FEATURE_SCALED_INDEX, /* scaled address index registers. */ + M68K_FEATURE_LONG_MULDIV, /* 32 bit multiply/divide. */ + M68K_FEATURE_QUAD_MULDIV, /* 64 bit multiply/divide. */ + M68K_FEATURE_BCCL, /* Long conditional branches. */ + M68K_FEATURE_BITFIELD, /* Bit field insns. */ + M68K_FEATURE_FPU }; static inline int m68k_feature(CPUM68KState *env, int feature) @@ -204,8 +211,8 @@ void m68k_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); void register_m68k_insns (CPUM68KState *env); #ifdef CONFIG_USER_ONLY -/* Linux uses 8k pages. */ -#define TARGET_PAGE_BITS 13 +/* Linux uses 4k pages. */ +#define TARGET_PAGE_BITS 12 #else /* Smallest TLB entry size is 1k. */ #define TARGET_PAGE_BITS 10 diff --git a/target-m68k/helper.c b/target-m68k/helper.c index af9ce22..a22dc97 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -33,6 +33,10 @@ #define SIGNBIT (1u << 31) enum m68k_cpuid { + M68K_CPUID_M68000, + M68K_CPUID_M68020, + M68K_CPUID_M68040, + M68K_CPUID_M68060, M68K_CPUID_M5206, M68K_CPUID_M5208, M68K_CPUID_CFV4E, @@ -47,6 +51,10 @@ struct m68k_def_t { }; static m68k_def_t m68k_cpu_defs[] = { + {"m68000", M68K_CPUID_M68000}, + {"m68020", M68K_CPUID_M68020}, + {"m68040", M68K_CPUID_M68040}, + {"m68060", M68K_CPUID_M68060}, {"m5206", M68K_CPUID_M5206}, {"m5208", M68K_CPUID_M5208}, {"cfv4e", M68K_CPUID_CFV4E}, @@ -107,12 +115,30 @@ static int cpu_m68k_set_model(CPUM68KState *env, const char *name) return -1; switch (def->id) { + case M68K_CPUID_M68020: + case M68K_CPUID_M68040: + m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV); + case M68K_CPUID_M68060: + m68k_set_feature(env, M68K_FEATURE_BRAL); + m68k_set_feature(env, M68K_FEATURE_BCCL); + m68k_set_feature(env, M68K_FEATURE_BITFIELD); + m68k_set_feature(env, M68K_FEATURE_EXT_FULL); + m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX); + m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV); + m68k_set_feature(env, M68K_FEATURE_FPU); + case M68K_CPUID_M68000: + m68k_set_feature(env, M68K_FEATURE_M68000); + m68k_set_feature(env, M68K_FEATURE_USP); + m68k_set_feature(env, M68K_FEATURE_WORD_INDEX); + break; case M68K_CPUID_M5206: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); + m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX); break; case M68K_CPUID_M5208: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC); + m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX); m68k_set_feature(env, M68K_FEATURE_BRAL); m68k_set_feature(env, M68K_FEATURE_CF_EMAC); m68k_set_feature(env, M68K_FEATURE_USP); @@ -120,16 +146,19 @@ static int cpu_m68k_set_model(CPUM68KState *env, const char *name) case M68K_CPUID_CFV4E: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); + m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX); m68k_set_feature(env, M68K_FEATURE_BRAL); m68k_set_feature(env, M68K_FEATURE_CF_FPU); m68k_set_feature(env, M68K_FEATURE_CF_EMAC); m68k_set_feature(env, M68K_FEATURE_USP); break; case M68K_CPUID_ANY: + m68k_set_feature(env, M68K_FEATURE_M68000); m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC); m68k_set_feature(env, M68K_FEATURE_BRAL); + m68k_set_feature(env, M68K_FEATURE_BCCL); m68k_set_feature(env, M68K_FEATURE_CF_FPU); /* MAC and EMAC are mututally exclusive, so pick EMAC. It's mostly backwards compatible. */ @@ -137,7 +166,11 @@ static int cpu_m68k_set_model(CPUM68KState *env, const char *name) m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B); m68k_set_feature(env, M68K_FEATURE_USP); m68k_set_feature(env, M68K_FEATURE_EXT_FULL); + m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX); m68k_set_feature(env, M68K_FEATURE_WORD_INDEX); + m68k_set_feature(env, M68K_FEATURE_BITFIELD); + m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV); + m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV); break; } -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions. 2009-05-29 22:41 ` [Qemu-devel] [PATCH 03/17] m68k: define m680x0 CPUs and features Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 05/17] m68k: add Motorola 680x0 family common instructions Laurent Vivier 2009-05-31 2:06 ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Stuart Brady 0 siblings, 2 replies; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier This patch modifies following instructions to allow them to manage data size other than "long", by adding "byte" and "word" data size: "addsub", "arith_im", "addsubq", "or", "eor", "and". This patch modifies following instructions to use EA to access data: "neg", "not". Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/cpu.h | 10 ++- target-m68k/helper.c | 74 ++++++++++++----- target-m68k/translate.c | 202 +++++++++++++++++++++++++++-------------------- 3 files changed, 177 insertions(+), 109 deletions(-) diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index eb18e9e..240d75f 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -131,11 +131,17 @@ enum { CC_OP_DYNAMIC, /* Use env->cc_op */ CC_OP_FLAGS, /* CC_DEST = CVZN, CC_SRC = unused */ CC_OP_LOGIC, /* CC_DEST = result, CC_SRC = unused */ + CC_OP_ADDB, /* CC_DEST = result, CC_SRC = source */ + CC_OP_ADDW, /* CC_DEST = result, CC_SRC = source */ CC_OP_ADD, /* CC_DEST = result, CC_SRC = source */ + CC_OP_SUBB, /* CC_DEST = result, CC_SRC = source */ + CC_OP_SUBW, /* CC_DEST = result, CC_SRC = source */ CC_OP_SUB, /* CC_DEST = result, CC_SRC = source */ - CC_OP_CMPB, /* CC_DEST = result, CC_SRC = source */ - CC_OP_CMPW, /* CC_DEST = result, CC_SRC = source */ + CC_OP_ADDXB, /* CC_DEST = result, CC_SRC = source */ + CC_OP_ADDXW, /* CC_DEST = result, CC_SRC = source */ CC_OP_ADDX, /* CC_DEST = result, CC_SRC = source */ + CC_OP_SUBXB, /* CC_DEST = result, CC_SRC = source */ + CC_OP_SUBXW, /* CC_DEST = result, CC_SRC = source */ CC_OP_SUBX, /* CC_DEST = result, CC_SRC = source */ CC_OP_SHIFT, /* CC_DEST = result, CC_SRC = carry */ }; diff --git a/target-m68k/helper.c b/target-m68k/helper.c index a22dc97..bcd73d5 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -256,6 +256,33 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) flags |= CCF_V; \ } while (0) +#define SET_FLAGS_ADD(type, utype) do { \ + SET_NZ((type)dest); \ + if ((utype) dest < (utype) src) \ + flags |= CCF_C; \ + tmp = dest - src; \ + if ((1u << (sizeof(type) * 8 - 1)) & (src ^ dest) & (tmp ^ src)) \ + flags |= CCF_V; \ + } while (0) + +#define SET_FLAGS_ADDX(type, utype) do { \ + SET_NZ((type)dest); \ + if ((utype) dest <= (utype) src) \ + flags |= CCF_C; \ + tmp = dest - src - 1; \ + if ((1u << (sizeof(type) * 8 - 1)) & (src ^ dest) & (tmp ^ src)) \ + flags |= CCF_V; \ + } while (0) + +#define SET_FLAGS_SUBX(type, utype) do { \ + SET_NZ((type)dest); \ + tmp = dest + src + 1; \ + if ((utype) dest <= (utype) src) \ + flags |= CCF_C; \ + if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \ + flags |= CCF_V; \ + } while (0) + flags = 0; src = env->cc_src; dest = env->cc_dest; @@ -266,38 +293,41 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) case CC_OP_LOGIC: SET_NZ(dest); break; + case CC_OP_ADDB: + SET_FLAGS_ADD(int8_t, uint8_t); + break; + case CC_OP_ADDW: + SET_FLAGS_ADD(int16_t, uint16_t); + break; case CC_OP_ADD: - SET_NZ(dest); - if (dest < src) - flags |= CCF_C; - tmp = dest - src; - if (HIGHBIT & (src ^ dest) & ~(tmp ^ src)) - flags |= CCF_V; + SET_FLAGS_ADD(int32_t, uint32_t); + break; + case CC_OP_SUBB: + SET_FLAGS_SUB(int8_t, uint8_t); + break; + case CC_OP_SUBW: + SET_FLAGS_SUB(int16_t, uint16_t); break; case CC_OP_SUB: SET_FLAGS_SUB(int32_t, uint32_t); break; - case CC_OP_CMPB: - SET_FLAGS_SUB(int8_t, uint8_t); + case CC_OP_ADDXB: + SET_FLAGS_ADDX(int8_t, uint8_t); break; - case CC_OP_CMPW: - SET_FLAGS_SUB(int16_t, uint16_t); + case CC_OP_ADDXW: + SET_FLAGS_ADDX(int16_t, uint16_t); break; case CC_OP_ADDX: - SET_NZ(dest); - if (dest <= src) - flags |= CCF_C; - tmp = dest - src - 1; - if (HIGHBIT & (src ^ dest) & ~(tmp ^ src)) - flags |= CCF_V; + SET_FLAGS_ADDX(int32_t, uint32_t); + break; + case CC_OP_SUBXB: + SET_FLAGS_SUBX(int8_t, uint8_t); + break; + case CC_OP_SUBXW: + SET_FLAGS_SUBX(int16_t, uint16_t); break; case CC_OP_SUBX: - SET_NZ(dest); - tmp = dest + src + 1; - if (tmp <= src) - flags |= CCF_C; - if (HIGHBIT & (tmp ^ dest) & (tmp ^ src)) - flags |= CCF_V; + SET_FLAGS_SUBX(int32_t, uint32_t); break; case CC_OP_SHIFT: SET_NZ(dest); diff --git a/target-m68k/translate.c b/target-m68k/translate.c index dc34a2a..1bf7169 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -264,6 +264,22 @@ static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val, } } +/* Read a 8-bit immediat constant */ +static inline uint32_t read_im8(DisasContext *s) +{ + uint32_t im; + im = ldsb_code(s->pc + 1); + s->pc += 2; + return im; +} +/* Read a 16-bit immediat constant */ +static inline uint32_t read_im16(DisasContext *s) +{ + uint32_t im; + im = ldsw_code(s->pc); + s->pc += 2; + return im; +} /* Read a 32-bit immediate constant. */ static inline uint32_t read_im32(DisasContext *s) { @@ -440,6 +456,25 @@ static inline int opsize_bytes(int opsize) } } +static inline int insn_opsize(int insn, int pos) +{ + switch ((insn >> pos) & 3) { + case 0: return OS_BYTE; + case 1: return OS_WORD; + case 2: return OS_LONG; + default: abort(); + } +} + +#define SET_CC_OP(opsize, op) do { \ + switch (opsize) { \ + case OS_BYTE: s->cc_op = CC_OP_##op##B; break; \ + case OS_WORD: s->cc_op = CC_OP_##op##W; break; \ + case OS_LONG: s->cc_op = CC_OP_##op; break; \ + default: abort(); \ + } \ +} while (0) + /* Assign value to a register. If the width is less than the register width only the low part of the register is set. */ static void gen_partset_reg(int opsize, TCGv reg, TCGv val) @@ -977,31 +1012,33 @@ DISAS_INSN(addsub) TCGv tmp; TCGv addr; int add; + int opsize; add = (insn & 0x4000) != 0; + opsize = insn_opsize(insn, 6); reg = DREG(insn, 9); dest = tcg_temp_new(); if (insn & 0x100) { - SRC_EA(tmp, OS_LONG, 0, &addr); + SRC_EA(tmp, opsize, -1, &addr); src = reg; } else { tmp = reg; - SRC_EA(src, OS_LONG, 0, NULL); + SRC_EA(src, opsize, -1, NULL); } if (add) { tcg_gen_add_i32(dest, tmp, src); gen_helper_xflag_lt(QREG_CC_X, dest, src); - s->cc_op = CC_OP_ADD; + SET_CC_OP(opsize, ADD); } else { gen_helper_xflag_lt(QREG_CC_X, tmp, src); tcg_gen_sub_i32(dest, tmp, src); - s->cc_op = CC_OP_SUB; + SET_CC_OP(opsize, SUB); } gen_update_cc_add(dest, src); if (insn & 0x100) { - DEST_EA(insn, OS_LONG, dest, &addr); + DEST_EA(insn, opsize, dest, &addr); } else { - tcg_gen_mov_i32(reg, dest); + gen_partset_reg(opsize, reg, dest); } } @@ -1192,10 +1229,24 @@ DISAS_INSN(arith_im) TCGv src1; TCGv dest; TCGv addr; + int opsize; op = (insn >> 9) & 7; - SRC_EA(src1, OS_LONG, 0, (op == 6) ? NULL : &addr); - im = read_im32(s); + opsize = insn_opsize(insn, 6); + switch (opsize) { + case OS_BYTE: + im = read_im8(s); + break; + case OS_WORD: + im = read_im16(s); + break; + case OS_LONG: + im = read_im32(s); + break; + default: + abort(); + } + SRC_EA(src1, opsize, -1, (op == 6) ? NULL : &addr); dest = tcg_temp_new(); switch (op) { case 0: /* ori */ @@ -1211,14 +1262,14 @@ DISAS_INSN(arith_im) gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im)); tcg_gen_subi_i32(dest, dest, im); gen_update_cc_add(dest, tcg_const_i32(im)); - s->cc_op = CC_OP_SUB; + SET_CC_OP(opsize, SUB); break; case 3: /* addi */ tcg_gen_mov_i32(dest, src1); tcg_gen_addi_i32(dest, dest, im); gen_update_cc_add(dest, tcg_const_i32(im)); gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im)); - s->cc_op = CC_OP_ADD; + SET_CC_OP(opsize, ADD); break; case 5: /* eori */ tcg_gen_xori_i32(dest, src1, im); @@ -1228,13 +1279,13 @@ DISAS_INSN(arith_im) tcg_gen_mov_i32(dest, src1); tcg_gen_subi_i32(dest, dest, im); gen_update_cc_add(dest, tcg_const_i32(im)); - s->cc_op = CC_OP_SUB; + SET_CC_OP(opsize, SUB); break; default: abort(); } if (op != 6) { - DEST_EA(insn, OS_LONG, dest, &addr); + DEST_EA(insn, opsize, dest, &addr); } } @@ -1310,19 +1361,7 @@ DISAS_INSN(clr) { int opsize; - switch ((insn >> 6) & 3) { - case 0: /* clr.b */ - opsize = OS_BYTE; - break; - case 1: /* clr.w */ - opsize = OS_WORD; - break; - case 2: /* clr.l */ - opsize = OS_LONG; - break; - default: - abort(); - } + opsize = insn_opsize(insn, 6); DEST_EA(insn, opsize, tcg_const_i32(0), NULL); gen_logic_cc(s, tcg_const_i32(0)); } @@ -1350,17 +1389,20 @@ DISAS_INSN(move_from_ccr) DISAS_INSN(neg) { - TCGv reg; TCGv src1; + TCGv dest; + TCGv addr; + int opsize; - reg = DREG(insn, 0); - src1 = tcg_temp_new(); - tcg_gen_mov_i32(src1, reg); - tcg_gen_neg_i32(reg, src1); - s->cc_op = CC_OP_SUB; - gen_update_cc_add(reg, src1); - gen_helper_xflag_lt(QREG_CC_X, tcg_const_i32(0), src1); - s->cc_op = CC_OP_SUB; + opsize = insn_opsize(insn, 6); + SRC_EA(src1, opsize, -1, &addr); + dest = tcg_temp_new(); + tcg_gen_neg_i32(dest, src1); + DEST_EA(insn, opsize, dest, &addr); + SET_CC_OP(opsize, SUB); + gen_update_cc_add(src1, dest); + gen_helper_xflag_lt(QREG_CC_X, tcg_const_i32(0), dest); + SET_CC_OP(opsize, SUB); } static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only) @@ -1407,11 +1449,17 @@ DISAS_INSN(move_to_ccr) DISAS_INSN(not) { - TCGv reg; + TCGv src1; + TCGv dest; + TCGv addr; + int opsize; - reg = DREG(insn, 0); - tcg_gen_not_i32(reg, reg); - gen_logic_cc(s, reg); + opsize = insn_opsize(insn, 6); + SRC_EA(src1, opsize, -1, &addr); + dest = tcg_temp_new(); + tcg_gen_not_i32(dest, src1); + DEST_EA(insn, opsize, dest, &addr); + gen_logic_cc(s, dest); } DISAS_INSN(swap) @@ -1466,20 +1514,8 @@ DISAS_INSN(tst) int opsize; TCGv tmp; - switch ((insn >> 6) & 3) { - case 0: /* tst.b */ - opsize = OS_BYTE; - break; - case 1: /* tst.w */ - opsize = OS_WORD; - break; - case 2: /* tst.l */ - opsize = OS_LONG; - break; - default: - abort(); - } - SRC_EA(tmp, opsize, 1, NULL); + opsize = insn_opsize(insn, 6); + SRC_EA(tmp, opsize, -1, NULL); gen_logic_cc(s, tmp); } @@ -1600,8 +1636,14 @@ DISAS_INSN(addsubq) TCGv dest; int val; TCGv addr; + int opsize; - SRC_EA(src1, OS_LONG, 0, &addr); + if ((insn & 070) == 010) { + /* Operation on address register is always long. */ + opsize = OS_LONG; + } else + opsize = insn_opsize(insn, 6); + SRC_EA(src1, opsize, -1, &addr); val = (insn >> 9) & 7; if (val == 0) val = 8; @@ -1620,11 +1662,11 @@ DISAS_INSN(addsubq) if (insn & 0x0100) { gen_helper_xflag_lt(QREG_CC_X, dest, src2); tcg_gen_subi_i32(dest, dest, val); - s->cc_op = CC_OP_SUB; + SET_CC_OP(opsize, SUB); } else { tcg_gen_addi_i32(dest, dest, val); gen_helper_xflag_lt(QREG_CC_X, dest, src2); - s->cc_op = CC_OP_ADD; + SET_CC_OP(opsize, ADD); } gen_update_cc_add(dest, src2); } @@ -1712,17 +1754,19 @@ DISAS_INSN(or) TCGv dest; TCGv src; TCGv addr; + int opsize; + opsize = insn_opsize(insn, 6); reg = DREG(insn, 9); dest = tcg_temp_new(); if (insn & 0x100) { - SRC_EA(src, OS_LONG, 0, &addr); + SRC_EA(src, opsize, -1, &addr); tcg_gen_or_i32(dest, src, reg); - DEST_EA(insn, OS_LONG, dest, &addr); + DEST_EA(insn, opsize, dest, &addr); } else { - SRC_EA(src, OS_LONG, 0, NULL); + SRC_EA(src, opsize, -1, NULL); tcg_gen_or_i32(dest, src, reg); - tcg_gen_mov_i32(reg, dest); + gen_partset_reg(opsize, reg, dest); } gen_logic_cc(s, dest); } @@ -1763,34 +1807,18 @@ DISAS_INSN(mov3q) DISAS_INSN(cmp) { - int op; TCGv src; TCGv reg; TCGv dest; int opsize; - op = (insn >> 6) & 3; - switch (op) { - case 0: /* cmp.b */ - opsize = OS_BYTE; - s->cc_op = CC_OP_CMPB; - break; - case 1: /* cmp.w */ - opsize = OS_WORD; - s->cc_op = CC_OP_CMPW; - break; - case 2: /* cmp.l */ - opsize = OS_LONG; - s->cc_op = CC_OP_SUB; - break; - default: - abort(); - } - SRC_EA(src, opsize, 1, NULL); + opsize = insn_opsize(insn, 6); + SRC_EA(src, opsize, -1, NULL); reg = DREG(insn, 9); dest = tcg_temp_new(); tcg_gen_sub_i32(dest, reg, src); gen_update_cc_add(dest, src); + SET_CC_OP(opsize, SUB); } DISAS_INSN(cmpa) @@ -1810,7 +1838,7 @@ DISAS_INSN(cmpa) dest = tcg_temp_new(); tcg_gen_sub_i32(dest, reg, src); gen_update_cc_add(dest, src); - s->cc_op = CC_OP_SUB; + SET_CC_OP(opsize, SUB); } DISAS_INSN(eor) @@ -1819,13 +1847,15 @@ DISAS_INSN(eor) TCGv reg; TCGv dest; TCGv addr; + int opsize; - SRC_EA(src, OS_LONG, 0, &addr); + opsize = insn_opsize(insn, 6); + SRC_EA(src, opsize, -1, &addr); reg = DREG(insn, 9); dest = tcg_temp_new(); tcg_gen_xor_i32(dest, src, reg); gen_logic_cc(s, dest); - DEST_EA(insn, OS_LONG, dest, &addr); + DEST_EA(insn, opsize, dest, &addr); } DISAS_INSN(and) @@ -1834,17 +1864,19 @@ DISAS_INSN(and) TCGv reg; TCGv dest; TCGv addr; + int opsize; + opsize = insn_opsize(insn, 6); reg = DREG(insn, 9); dest = tcg_temp_new(); if (insn & 0x100) { - SRC_EA(src, OS_LONG, 0, &addr); + SRC_EA(src, opsize, -1, &addr); tcg_gen_and_i32(dest, src, reg); - DEST_EA(insn, OS_LONG, dest, &addr); + DEST_EA(insn, opsize, dest, &addr); } else { - SRC_EA(src, OS_LONG, 0, NULL); + SRC_EA(src, opsize, -1, NULL); tcg_gen_and_i32(dest, src, reg); - tcg_gen_mov_i32(reg, dest); + gen_partset_reg(opsize, reg, dest); } gen_logic_cc(s, dest); } -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 05/17] m68k: add Motorola 680x0 family common instructions. 2009-05-29 22:41 ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 06/17] m68k: add Scc instruction with memory operand Laurent Vivier 2009-05-31 2:06 ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Stuart Brady 1 sibling, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier This patch declares existing ISA instructions belonging to previously defined 680x0 familty new features: - modify gen_lea_indexed() to manage scaled index, - declare M68000 instructions: arith_im, bitop_reg, arith_im, bitop_im, move, negx, move_from_sr, lea, clr, neg, move_to_ccr, not, pea, swap, ext, tas, tst, illegal, trap, link, unlk, nop, stop, rte, rts, jump, addsubq, scc, branch, moveq, or, divw, addsub, subx, cmp, cmpa, eor, and, mulw, addx, shift_im, shift_reg. - declare FPU instructions: fbcc, frestore, fsave, - declare long branch instructions: branch. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/translate.c | 89 ++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 85 insertions(+), 4 deletions(-) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 1bf7169..cd46651 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -327,6 +327,9 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX)) return NULL_QREG; + if (!m68k_feature(s->env, M68K_FEATURE_SCALED_INDEX)) + ext &= ~(3 << 9); + if (ext & 0x100) { /* full extension word format */ if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL)) @@ -335,7 +338,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) if ((ext & 0x30) > 0x10) { /* base displacement */ if ((ext & 0x30) == 0x20) { - bd = (int16_t)lduw_code(s->pc); + bd = ldsw_code(s->pc); s->pc += 2; } else { bd = read_im32(s); @@ -384,7 +387,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) if ((ext & 3) > 1) { /* outer displacement */ if ((ext & 3) == 2) { - od = (int16_t)lduw_code(s->pc); + od = ldsw_code(s->pc); s->pc += 2; } else { od = read_im32(s); @@ -2859,85 +2862,149 @@ void register_m68k_insns (CPUM68KState *env) register_opcode(disas_##name, 0x##opcode, 0x##mask); \ } while(0) INSN(undef, 0000, 0000, CF_ISA_A); + INSN(undef, 0000, 0000, M68000); INSN(arith_im, 0080, fff8, CF_ISA_A); + INSN(arith_im, 0000, ff00, M68000); + INSN(undef, 00c0, ffc0, M68000); INSN(bitrev, 00c0, fff8, CF_ISA_APLUSC); INSN(bitop_reg, 0100, f1c0, CF_ISA_A); + INSN(bitop_reg, 0100, f1c0, M68000); INSN(bitop_reg, 0140, f1c0, CF_ISA_A); + INSN(bitop_reg, 0140, f1c0, M68000); INSN(bitop_reg, 0180, f1c0, CF_ISA_A); + INSN(bitop_reg, 0180, f1c0, M68000); INSN(bitop_reg, 01c0, f1c0, CF_ISA_A); + INSN(bitop_reg, 01c0, f1c0, M68000); INSN(arith_im, 0280, fff8, CF_ISA_A); + INSN(arith_im, 0200, ff00, M68000); + INSN(undef, 02c0, ffc0, M68000); INSN(byterev, 02c0, fff8, CF_ISA_APLUSC); INSN(arith_im, 0480, fff8, CF_ISA_A); + INSN(arith_im, 0400, ff00, M68000); + INSN(undef, 04c0, ffc0, M68000); + INSN(arith_im, 0600, ff00, M68000); + INSN(undef, 06c0, ffc0, M68000); INSN(ff1, 04c0, fff8, CF_ISA_APLUSC); INSN(arith_im, 0680, fff8, CF_ISA_A); INSN(bitop_im, 0800, ffc0, CF_ISA_A); + INSN(bitop_im, 0800, ffc0, M68000); INSN(bitop_im, 0840, ffc0, CF_ISA_A); + INSN(bitop_im, 0840, ffc0, M68000); INSN(bitop_im, 0880, ffc0, CF_ISA_A); + INSN(bitop_im, 0880, ffc0, M68000); INSN(bitop_im, 08c0, ffc0, CF_ISA_A); + INSN(bitop_im, 08c0, ffc0, M68000); INSN(arith_im, 0a80, fff8, CF_ISA_A); + INSN(arith_im, 0a00, ff00, M68000); + INSN(undef, 0ac0, ffc0, M68000); INSN(arith_im, 0c00, ff38, CF_ISA_A); + INSN(arith_im, 0c00, ff00, M68000); + INSN(undef, 0cc0, ffc0, M68000); INSN(move, 1000, f000, CF_ISA_A); + INSN(move, 1000, f000, M68000); INSN(move, 2000, f000, CF_ISA_A); + INSN(move, 2000, f000, M68000); INSN(move, 3000, f000, CF_ISA_A); + INSN(move, 3000, f000, M68000); INSN(strldsr, 40e7, ffff, CF_ISA_APLUSC); INSN(negx, 4080, fff8, CF_ISA_A); + INSN(negx, 4080, fff8, M68000); + INSN(undef, 40c0, ffc0, M68000); INSN(move_from_sr, 40c0, fff8, CF_ISA_A); + INSN(move_from_sr, 40c0, fff8, M68000); INSN(lea, 41c0, f1c0, CF_ISA_A); + INSN(lea, 41c0, f1c0, M68000); INSN(clr, 4200, ff00, CF_ISA_A); + INSN(clr, 4200, ff00, M68000); INSN(undef, 42c0, ffc0, CF_ISA_A); + INSN(undef, 42c0, ffc0, M68000); INSN(move_from_ccr, 42c0, fff8, CF_ISA_A); INSN(neg, 4480, fff8, CF_ISA_A); + INSN(neg, 4400, ff00, M68000); + INSN(undef, 44c0, ffc0, M68000); INSN(move_to_ccr, 44c0, ffc0, CF_ISA_A); + INSN(move_to_ccr, 44c0, ffc0, M68000); INSN(not, 4680, fff8, CF_ISA_A); + INSN(not, 4600, ff00, M68000); + INSN(undef, 46c0, ffc0, M68000); INSN(move_to_sr, 46c0, ffc0, CF_ISA_A); INSN(pea, 4840, ffc0, CF_ISA_A); + INSN(pea, 4840, ffc0, M68000); INSN(swap, 4840, fff8, CF_ISA_A); + INSN(swap, 4840, fff8, M68000); INSN(movem, 48c0, fbc0, CF_ISA_A); INSN(ext, 4880, fff8, CF_ISA_A); + INSN(ext, 4880, fff8, M68000); INSN(ext, 48c0, fff8, CF_ISA_A); + INSN(ext, 48c0, fff8, M68000); INSN(ext, 49c0, fff8, CF_ISA_A); + INSN(ext, 49c0, fff8, M68000); INSN(tst, 4a00, ff00, CF_ISA_A); + INSN(tst, 4a00, ff00, M68000); INSN(tas, 4ac0, ffc0, CF_ISA_B); + INSN(tas, 4ac0, ffc0, M68000); INSN(halt, 4ac8, ffff, CF_ISA_A); INSN(pulse, 4acc, ffff, CF_ISA_A); INSN(illegal, 4afc, ffff, CF_ISA_A); + INSN(illegal, 4afc, ffff, M68000); INSN(mull, 4c00, ffc0, CF_ISA_A); INSN(divl, 4c40, ffc0, CF_ISA_A); INSN(sats, 4c80, fff8, CF_ISA_B); INSN(trap, 4e40, fff0, CF_ISA_A); + INSN(trap, 4e40, fff0, M68000); INSN(link, 4e50, fff8, CF_ISA_A); + INSN(link, 4e50, fff8, M68000); INSN(unlk, 4e58, fff8, CF_ISA_A); + INSN(unlk, 4e58, fff8, M68000); INSN(move_to_usp, 4e60, fff8, USP); INSN(move_from_usp, 4e68, fff8, USP); INSN(nop, 4e71, ffff, CF_ISA_A); + INSN(nop, 4e71, ffff, M68000); INSN(stop, 4e72, ffff, CF_ISA_A); + INSN(stop, 4e72, ffff, M68000); INSN(rte, 4e73, ffff, CF_ISA_A); + INSN(rte, 4e73, ffff, M68000); INSN(rts, 4e75, ffff, CF_ISA_A); + INSN(rts, 4e75, ffff, M68000); INSN(movec, 4e7b, ffff, CF_ISA_A); INSN(jump, 4e80, ffc0, CF_ISA_A); + INSN(jump, 4e80, ffc0, M68000); INSN(jump, 4ec0, ffc0, CF_ISA_A); - INSN(addsubq, 5180, f1c0, CF_ISA_A); + INSN(jump, 4ec0, ffc0, M68000); + INSN(addsubq, 5080, f0c0, CF_ISA_A); + INSN(addsubq, 5000, f080, M68000); + INSN(addsubq, 5080, f0c0, M68000); INSN(scc, 50c0, f0f8, CF_ISA_A); - INSN(addsubq, 5080, f1c0, CF_ISA_A); + INSN(scc, 50c0, f0f8, M68000); INSN(tpf, 51f8, fff8, CF_ISA_A); /* Branch instructions. */ INSN(branch, 6000, f000, CF_ISA_A); + INSN(branch, 6000, f000, M68000); /* Disable long branch instructions, then add back the ones we want. */ INSN(undef, 60ff, f0ff, CF_ISA_A); /* All long branches. */ + INSN(undef, 60ff, f0ff, M68000); /* All long branches. */ INSN(branch, 60ff, f0ff, CF_ISA_B); INSN(undef, 60ff, ffff, CF_ISA_B); /* bra.l */ INSN(branch, 60ff, ffff, BRAL); + INSN(branch, 60ff, f0ff, BCCL); INSN(moveq, 7000, f100, CF_ISA_A); + INSN(moveq, 7000, f100, M68000); INSN(mvzs, 7100, f100, CF_ISA_B); INSN(or, 8000, f000, CF_ISA_A); + INSN(or, 8000, f000, M68000); INSN(divw, 80c0, f0c0, CF_ISA_A); + INSN(divw, 80c0, f0c0, M68000); INSN(addsub, 9000, f000, CF_ISA_A); + INSN(addsub, 9000, f000, M68000); + INSN(undef, 90c0, f0c0, CF_ISA_A); INSN(subx, 9180, f1f8, CF_ISA_A); + INSN(subx, 9100, f138, M68000); INSN(suba, 91c0, f1c0, CF_ISA_A); INSN(undef_mac, a000, f000, CF_ISA_A); + INSN(undef_mac, a000, f000, M68000); INSN(mac, a000, f100, CF_EMAC); INSN(from_mac, a180, f9b0, CF_EMAC); INSN(move_mac, a110, f9fc, CF_EMAC); @@ -2956,19 +3023,33 @@ void register_m68k_insns (CPUM68KState *env) INSN(cmpa, b0c0, f1c0, CF_ISA_B); /* cmpa.w */ INSN(cmp, b080, f1c0, CF_ISA_A); INSN(cmpa, b1c0, f1c0, CF_ISA_A); + INSN(cmp, b000, f100, M68000); + INSN(cmpa, b0c0, f0c0, M68000); INSN(eor, b180, f1c0, CF_ISA_A); + INSN(eor, b180, f1c0, M68000); INSN(and, c000, f000, CF_ISA_A); + INSN(and, c000, f000, M68000); INSN(mulw, c0c0, f0c0, CF_ISA_A); + INSN(mulw, c0c0, f0c0, M68000); INSN(addsub, d000, f000, CF_ISA_A); + INSN(addsub, d000, f000, M68000); + INSN(undef, d0c0, f0c0, CF_ISA_A); INSN(addx, d180, f1f8, CF_ISA_A); + INSN(addx, d100, f138, M68000); INSN(adda, d1c0, f1c0, CF_ISA_A); INSN(shift_im, e080, f0f0, CF_ISA_A); INSN(shift_reg, e0a0, f0f0, CF_ISA_A); + INSN(shift_im, e080, f0f0, M68000); + INSN(shift_reg, e0a0, f0f0, M68000); INSN(undef_fpu, f000, f000, CF_ISA_A); + INSN(undef_fpu, f000, f000, M68000); INSN(fpu, f200, ffc0, CF_FPU); INSN(fbcc, f280, ffc0, CF_FPU); INSN(frestore, f340, ffc0, CF_FPU); INSN(fsave, f340, ffc0, CF_FPU); + INSN(fbcc, f280, ffc0, FPU); + INSN(frestore, f340, ffc0, FPU); + INSN(fsave, f340, ffc0, FPU); INSN(intouch, f340, ffc0, CF_ISA_A); INSN(cpushl, f428, ff38, CF_ISA_A); INSN(wddata, fb00, ff00, CF_ISA_A); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 06/17] m68k: add Scc instruction with memory operand. 2009-05-29 22:41 ` [Qemu-devel] [PATCH 05/17] m68k: add Motorola 680x0 family common instructions Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 07/17] m68k: add DBcc instruction Laurent Vivier 0 siblings, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier This patch defines Scc instruction for M68000 feature accessing destination operand using an effective address (existing Scc instruction manages only data registers). Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/translate.c | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index cd46651..d08e1c8 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -906,6 +906,23 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest) s->is_jmp = DISAS_TB_JUMP; } +DISAS_INSN(scc_mem) +{ + int l1; + int cond; + TCGv dest; + + l1 = gen_new_label(); + cond = (insn >> 8) & 0xf; + dest = tcg_temp_local_new(); + tcg_gen_movi_i32(dest, 0); + gen_jmpcc(s, cond ^ 1, l1); + tcg_gen_movi_i32(dest, 0xff); + gen_set_label(l1); + DEST_EA(insn, OS_BYTE, dest, NULL); + tcg_temp_free(dest); +} + DISAS_INSN(undef_mac) { gen_exception(s, s->pc - 2, EXCP_LINEA); @@ -2975,6 +2992,7 @@ void register_m68k_insns (CPUM68KState *env) INSN(addsubq, 5000, f080, M68000); INSN(addsubq, 5080, f0c0, M68000); INSN(scc, 50c0, f0f8, CF_ISA_A); + INSN(scc_mem, 50c0, f0c0, M68000); INSN(scc, 50c0, f0f8, M68000); INSN(tpf, 51f8, fff8, CF_ISA_A); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 07/17] m68k: add DBcc instruction. 2009-05-29 22:41 ` [Qemu-devel] [PATCH 06/17] m68k: add Scc instruction with memory operand Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 08/17] m68k: modify movem instruction to manage word Laurent Vivier 2009-05-30 22:00 ` [Qemu-devel] Re: [PATCH 07/17] m68k: add DBcc instruction Andreas Schwab 0 siblings, 2 replies; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier Define DBcc instruction and attach it to M68000 feature. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/translate.c | 26 ++++++++++++++++++++++++++ 1 files changed, 26 insertions(+), 0 deletions(-) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index d08e1c8..f2a0c92 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -923,6 +923,31 @@ DISAS_INSN(scc_mem) tcg_temp_free(dest); } +DISAS_INSN(dbcc) +{ + int l1; + TCGv reg; + TCGv tmp; + int16_t offset; + uint32_t base; + + reg = DREG(insn, 0); + base = s->pc; + offset = ldsw_code(s->pc); + s->pc += 2; + l1 = gen_new_label(); + gen_jmpcc(s, (insn >> 8) & 0xf, l1); + + tmp = tcg_temp_new(); + tcg_gen_ext16s_i32(tmp, reg); + tcg_gen_addi_i32(tmp, tmp, -1); + gen_partset_reg(OS_WORD, reg, tmp); + tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); + gen_jmp_tb(s, 1, base + offset); + gen_set_label(l1); + gen_jmp_tb(s, 0, s->pc); +} + DISAS_INSN(undef_mac) { gen_exception(s, s->pc - 2, EXCP_LINEA); @@ -2994,6 +3019,7 @@ void register_m68k_insns (CPUM68KState *env) INSN(scc, 50c0, f0f8, CF_ISA_A); INSN(scc_mem, 50c0, f0c0, M68000); INSN(scc, 50c0, f0f8, M68000); + INSN(dbcc, 50c8, f0f8, M68000); INSN(tpf, 51f8, fff8, CF_ISA_A); /* Branch instructions. */ -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 08/17] m68k: modify movem instruction to manage word 2009-05-29 22:41 ` [Qemu-devel] [PATCH 07/17] m68k: add DBcc instruction Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 09/17] m68k: add 64bit divide Laurent Vivier 2009-05-30 22:00 ` [Qemu-devel] Re: [PATCH 07/17] m68k: add DBcc instruction Andreas Schwab 1 sibling, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier This patch modifies "movem" to manage "word" and "long" register size instead of only "word". Attach it to M68000 feature. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/translate.c | 52 +++++++++++++++++++++++++++++++++------------- 1 files changed, 37 insertions(+), 15 deletions(-) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index f2a0c92..c869cf9 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -1176,6 +1176,8 @@ DISAS_INSN(movem) TCGv reg; TCGv tmp; int is_load; + int opsize; + int32_t incr; mask = lduw_code(s->pc); s->pc += 2; @@ -1187,21 +1189,40 @@ DISAS_INSN(movem) addr = tcg_temp_new(); tcg_gen_mov_i32(addr, tmp); is_load = ((insn & 0x0400) != 0); - for (i = 0; i < 16; i++, mask >>= 1) { - if (mask & 1) { - if (i < 8) - reg = DREG(i, 0); - else - reg = AREG(i, 0); - if (is_load) { - tmp = gen_load(s, OS_LONG, addr, 0); - tcg_gen_mov_i32(reg, tmp); - } else { - gen_store(s, OS_LONG, addr, reg); - } - if (mask != 1) - tcg_gen_addi_i32(addr, addr, 4); - } + opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD; + incr = opsize_bytes(opsize); + if (!is_load && (insn & 070) == 040) { + for (i = 15; i >= 0; i--, mask >>= 1) { + if (mask & 1) { + if (i < 8) + reg = DREG(i, 0); + else + reg = AREG(i, 0); + gen_store(s, opsize, addr, reg); + if (mask != 1) + tcg_gen_subi_i32(addr, addr, incr); + } + } + tcg_gen_mov_i32(AREG(insn, 0), addr); + } else { + for (i = 0; i < 16; i++, mask >>= 1) { + if (mask & 1) { + if (i < 8) + reg = DREG(i, 0); + else + reg = AREG(i, 0); + if (is_load) { + tmp = gen_load(s, opsize, addr, 1); + tcg_gen_mov_i32(reg, tmp); + } else { + gen_store(s, opsize, addr, reg); + } + if (mask != 1 || (insn & 070) == 030) + tcg_gen_addi_i32(addr, addr, incr); + } + } + if ((insn & 070) == 030) + tcg_gen_mov_i32(AREG(insn, 0), addr); } } @@ -2975,6 +2996,7 @@ void register_m68k_insns (CPUM68KState *env) INSN(swap, 4840, fff8, CF_ISA_A); INSN(swap, 4840, fff8, M68000); INSN(movem, 48c0, fbc0, CF_ISA_A); + INSN(movem, 48c0, fbc0, M68000); INSN(ext, 4880, fff8, CF_ISA_A); INSN(ext, 4880, fff8, M68000); INSN(ext, 48c0, fff8, CF_ISA_A); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 09/17] m68k: add 64bit divide. 2009-05-29 22:41 ` [Qemu-devel] [PATCH 08/17] m68k: modify movem instruction to manage word Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 10/17] m68k: add 32bit and 64bit multiply Laurent Vivier 0 siblings, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier This patch modifies "divl" to support 64bit operands (QUAD_MULDIV feature). Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/cpu.h | 3 ++ target-m68k/helpers.h | 2 + target-m68k/op_helper.c | 77 ++++++++++++++++++++++++++++++++++++++++++++-- target-m68k/qregs.def | 1 + target-m68k/translate.c | 29 +++++++++++++++-- 5 files changed, 104 insertions(+), 8 deletions(-) diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index 240d75f..fa0b055 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -91,6 +91,9 @@ typedef struct CPUM68KState { uint32_t div1; uint32_t div2; + /* Upper 32 bits of a 64bit operand for quad MUL/DIV. */ + uint32_t quadh; + /* MMU status. */ struct { uint32_t ar; diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h index cb8a0c7..a158aee 100644 --- a/target-m68k/helpers.h +++ b/target-m68k/helpers.h @@ -5,6 +5,8 @@ DEF_HELPER_1(ff1, i32, i32) DEF_HELPER_2(sats, i32, i32, i32) DEF_HELPER_2(divu, void, env, i32) DEF_HELPER_2(divs, void, env, i32) +DEF_HELPER_1(divu64, void, env) +DEF_HELPER_1(divs64, void, env) DEF_HELPER_3(addx_cc, i32, env, i32, i32) DEF_HELPER_3(subx_cc, i32, env, i32, i32) DEF_HELPER_3(shl_cc, i32, env, i32, i32) diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c index a339a17..2d75b50 100644 --- a/target-m68k/op_helper.c +++ b/target-m68k/op_helper.c @@ -194,8 +194,11 @@ void HELPER(divu)(CPUState *env, uint32_t word) flags |= CCF_Z; else if ((int32_t)quot < 0) flags |= CCF_N; - env->div1 = quot; - env->div2 = rem; + /* Don't modify destination if overflow occured. */ + if ((flags & CCF_V) == 0) { + env->div1 = quot; + env->div2 = rem; + } env->cc_dest = flags; } @@ -220,7 +223,73 @@ void HELPER(divs)(CPUState *env, uint32_t word) flags |= CCF_Z; else if (quot < 0) flags |= CCF_N; - env->div1 = quot; - env->div2 = rem; + /* Don't modify destination if overflow occured. */ + if ((flags & CCF_V) == 0) { + env->div1 = quot; + env->div2 = rem; + } + env->cc_dest = flags; +} + +void HELPER(divu64)(CPUState *env) +{ + uint32_t num; + uint32_t den; + uint32_t quot; + uint32_t rem; + uint32_t flags; + + num = env->div1; + den = env->div2; + /* ??? This needs to make sure the throwing location is accurate. */ + if (den == 0) + raise_exception(EXCP_DIV0); + quot = (num | ((uint64_t)env->quadh << 32)) / den; + rem = (num | ((uint64_t)env->quadh << 32)) % den; + flags = 0; + /* Avoid using a PARAM1 of zero. This breaks dyngen because it uses + the address of a symbol, and gcc knows symbols can't have address + zero. */ + if (quot > 0xffffffff) + flags |= CCF_V; + if (quot == 0) + flags |= CCF_Z; + else if ((int64_t)quot < 0) + flags |= CCF_N; + /* Don't modify destination if overflow occured. */ + if ((flags & CCF_V) == 0) { + env->div1 = quot; + env->div2 = rem; + } + env->cc_dest = flags; +} + +void HELPER(divs64)(CPUState *env) +{ + int32_t num; + int32_t den; + int32_t quot; + int32_t rem; + int32_t flags; + + num = env->div1; + den = env->div2; + if (den == 0) + raise_exception(EXCP_DIV0); + quot = (num | ((int64_t)env->quadh << 32)) / den; + rem = (num | ((int64_t)env->quadh << 32)) % den; + rem = num % den; + flags = 0; + if (quot != (int32_t)quot) + flags |= CCF_V; + if (quot == 0) + flags |= CCF_Z; + else if (quot < 0) + flags |= CCF_N; + /* Don't modify destination if overflow occured. */ + if ((flags & CCF_V) == 0) { + env->div1 = quot; + env->div2 = rem; + } env->cc_dest = flags; } diff --git a/target-m68k/qregs.def b/target-m68k/qregs.def index 49400c4..76e0236 100644 --- a/target-m68k/qregs.def +++ b/target-m68k/qregs.def @@ -7,6 +7,7 @@ DEFO32(CC_SRC, cc_src) DEFO32(CC_X, cc_x) DEFO32(DIV1, div1) DEFO32(DIV2, div2) +DEFO32(QUADH, quadh) DEFO32(EXCEPTION, exception_index) DEFO32(HALTED, halted) DEFO32(MACSR, macsr) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index c869cf9..d0e223c 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -1025,8 +1025,26 @@ DISAS_INSN(divl) ext = lduw_code(s->pc); s->pc += 2; - if (ext & 0x87f8) { - gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); + if (ext & 0x400) { + if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) { + gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); + return; + } + num = DREG(ext, 12); + reg = DREG(ext, 0); + tcg_gen_mov_i32(QREG_DIV1, num); + tcg_gen_mov_i32(QREG_QUADH, reg); + SRC_EA(den, OS_LONG, 0, NULL); + tcg_gen_mov_i32(QREG_DIV2, den); + if (ext & 0x0800) { + gen_helper_divs64(cpu_env); + } else { + gen_helper_divu64(cpu_env); + } + tcg_gen_mov_i32(num, QREG_DIV1); + if (!TCGV_EQUAL(num, reg)) + tcg_gen_mov_i32(reg, QREG_DIV2); + s->cc_op = CC_OP_FLAGS; return; } num = DREG(ext, 12); @@ -1039,10 +1057,12 @@ DISAS_INSN(divl) } else { gen_helper_divu(cpu_env, tcg_const_i32(0)); } - if ((ext & 7) == ((ext >> 12) & 7)) { + if (((ext & 7) == ((ext >> 12) & 7)) || + m68k_feature(s->env, M68K_FEATURE_LONG_MULDIV)) { /* div */ tcg_gen_mov_i32 (reg, QREG_DIV1); - } else { + } + if ((ext & 7) != ((ext >> 12) & 7)) { /* rem */ tcg_gen_mov_i32 (reg, QREG_DIV2); } @@ -3013,6 +3033,7 @@ void register_m68k_insns (CPUM68KState *env) INSN(illegal, 4afc, ffff, M68000); INSN(mull, 4c00, ffc0, CF_ISA_A); INSN(divl, 4c40, ffc0, CF_ISA_A); + INSN(divl, 4c40, ffc0, LONG_MULDIV); INSN(sats, 4c80, fff8, CF_ISA_B); INSN(trap, 4e40, fff0, CF_ISA_A); INSN(trap, 4e40, fff0, M68000); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 10/17] m68k: add 32bit and 64bit multiply 2009-05-29 22:41 ` [Qemu-devel] [PATCH 09/17] m68k: add 64bit divide Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 11/17] m68k: add word data size for suba/adda Laurent Vivier 0 siblings, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier This patch modify "mull" to support 64bit result, and to update CC on 32bit operands. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/helpers.h | 4 +++ target-m68k/op_helper.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++ target-m68k/translate.c | 36 +++++++++++++++++++++---- 3 files changed, 100 insertions(+), 6 deletions(-) diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h index a158aee..ca2bf82 100644 --- a/target-m68k/helpers.h +++ b/target-m68k/helpers.h @@ -7,6 +7,10 @@ DEF_HELPER_2(divu, void, env, i32) DEF_HELPER_2(divs, void, env, i32) DEF_HELPER_1(divu64, void, env) DEF_HELPER_1(divs64, void, env) +DEF_HELPER_3(mulu32_cc, i32, env, i32, i32) +DEF_HELPER_3(muls32_cc, i32, env, i32, i32) +DEF_HELPER_3(mulu64, i32, env, i32, i32) +DEF_HELPER_3(muls64, i32, env, i32, i32) DEF_HELPER_3(addx_cc, i32, env, i32, i32) DEF_HELPER_3(subx_cc, i32, env, i32, i32) DEF_HELPER_3(shl_cc, i32, env, i32, i32) diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c index 2d75b50..76176f8 100644 --- a/target-m68k/op_helper.c +++ b/target-m68k/op_helper.c @@ -293,3 +293,69 @@ void HELPER(divs64)(CPUState *env) } env->cc_dest = flags; } + +uint32_t HELPER(mulu32_cc)(CPUState *env, uint32_t op1, uint32_t op2) +{ + uint64_t res = (uint32_t)op1 * op2; + uint32_t flags; + + flags = 0; + if (res >> 32) + flags |= CCF_V; + if ((uint32_t)res == 0) + flags |= CCF_Z; + if ((int32_t)res < 0) + flags |= CCF_N; + env->cc_dest = flags; + + return res; +} + +uint32_t HELPER(muls32_cc)(CPUState *env, uint32_t op1, uint32_t op2) +{ + int64_t res = (int32_t)op1 * (int32_t)op2; + uint32_t flags; + + flags = 0; + if (res != (int64_t)(int32_t)res) + flags |= CCF_V; + if ((uint32_t)res == 0) + flags |= CCF_Z; + if ((int32_t)res < 0) + flags |= CCF_N; + env->cc_dest = flags; + + return res; +} + +uint32_t HELPER(mulu64)(CPUState *env, uint32_t op1, uint32_t op2) +{ + uint64_t res = (uint64_t)op1 * op2; + uint32_t flags; + + env->quadh = res >> 32; + flags = 0; + if (res == 0) + flags |= CCF_Z; + if ((int64_t)res < 0) + flags |= CCF_N; + env->cc_dest = flags; + + return res; +} + +uint32_t HELPER(muls64)(CPUState *env, uint32_t op1, uint32_t op2) +{ + int64_t res = (uint64_t)(int32_t)op1 * (int32_t)op2; + uint32_t flags; + + env->quadh = res >> 32; + flags = 0; + if (res == 0) + flags |= CCF_Z; + if (res < 0) + flags |= CCF_N; + env->cc_dest = flags; + + return res; +} diff --git a/target-m68k/translate.c b/target-m68k/translate.c index d0e223c..eed804e 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -1635,22 +1635,45 @@ DISAS_INSN(mull) TCGv reg; TCGv src1; TCGv dest; + TCGv regh; /* The upper 32 bits of the product are discarded, so muls.l and mulu.l are functionally equivalent. */ ext = lduw_code(s->pc); s->pc += 2; - if (ext & 0x87ff) { - gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); - return; + if (ext & 0x400) { + if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) { + gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); + return; + } + reg = DREG(ext, 12); + regh = DREG(ext, 0); + SRC_EA(src1, OS_LONG, 0, NULL); + dest = tcg_temp_new(); + if (ext & 0x800) + gen_helper_muls64(dest, cpu_env, src1, reg); + else + gen_helper_mulu64(dest, cpu_env, src1, reg); + tcg_gen_mov_i32(reg, dest); + tcg_gen_mov_i32(regh, QREG_QUADH); + s->cc_op = CC_OP_FLAGS; + return; } reg = DREG(ext, 12); SRC_EA(src1, OS_LONG, 0, NULL); dest = tcg_temp_new(); - tcg_gen_mul_i32(dest, src1, reg); + if (m68k_feature(s->env, M68K_FEATURE_M68000)) { + if (ext & 0x800) + gen_helper_muls32_cc(dest, cpu_env, src1, reg); + else + gen_helper_mulu32_cc(dest, cpu_env, src1, reg); + s->cc_op = CC_OP_FLAGS; + } else { + tcg_gen_mul_i32(dest, src1, reg); + /* Unlike m68k, coldfire always clears the overflow bit. */ + gen_logic_cc(s, dest); + } tcg_gen_mov_i32(reg, dest); - /* Unlike m68k, coldfire always clears the overflow bit. */ - gen_logic_cc(s, dest); } DISAS_INSN(link) @@ -3032,6 +3055,7 @@ void register_m68k_insns (CPUM68KState *env) INSN(illegal, 4afc, ffff, CF_ISA_A); INSN(illegal, 4afc, ffff, M68000); INSN(mull, 4c00, ffc0, CF_ISA_A); + INSN(mull, 4c00, ffc0, LONG_MULDIV); INSN(divl, 4c40, ffc0, CF_ISA_A); INSN(divl, 4c40, ffc0, LONG_MULDIV); INSN(sats, 4c80, fff8, CF_ISA_B); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 11/17] m68k: add word data size for suba/adda 2009-05-29 22:41 ` [Qemu-devel] [PATCH 10/17] m68k: add 32bit and 64bit multiply Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 12/17] m68k: add fpu Laurent Vivier 0 siblings, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier Allows suba and adda to manage word sized effective address, and attach them to M68000 feature. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/translate.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index eed804e..89e5d5e 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -1885,7 +1885,7 @@ DISAS_INSN(suba) TCGv src; TCGv reg; - SRC_EA(src, OS_LONG, 0, NULL); + SRC_EA(src, (insn & 0x100) ? OS_LONG : OS_WORD, -1, NULL); reg = AREG(insn, 9); tcg_gen_sub_i32(reg, reg, src); } @@ -1995,7 +1995,7 @@ DISAS_INSN(adda) TCGv src; TCGv reg; - SRC_EA(src, OS_LONG, 0, NULL); + SRC_EA(src, (insn & 0x100) ? OS_LONG : OS_WORD, -1, NULL); reg = AREG(insn, 9); tcg_gen_add_i32(reg, reg, src); } @@ -3113,6 +3113,7 @@ void register_m68k_insns (CPUM68KState *env) INSN(subx, 9180, f1f8, CF_ISA_A); INSN(subx, 9100, f138, M68000); INSN(suba, 91c0, f1c0, CF_ISA_A); + INSN(suba, 90c0, f0c0, M68000); INSN(undef_mac, a000, f000, CF_ISA_A); INSN(undef_mac, a000, f000, M68000); @@ -3148,6 +3149,7 @@ void register_m68k_insns (CPUM68KState *env) INSN(addx, d180, f1f8, CF_ISA_A); INSN(addx, d100, f138, M68000); INSN(adda, d1c0, f1c0, CF_ISA_A); + INSN(adda, d0c0, f0c0, M68000); INSN(shift_im, e080, f0f0, CF_ISA_A); INSN(shift_reg, e0a0, f0f0, CF_ISA_A); INSN(shift_im, e080, f0f0, M68000); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 12/17] m68k: add fpu 2009-05-29 22:41 ` [Qemu-devel] [PATCH 11/17] m68k: add word data size for suba/adda Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 13/17] m68k: add "byte", "word" and memory shift Laurent Vivier 0 siblings, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier Modify "fpu" instruction to be compatible with 680x0 family and attach it to FPU feature (in addition to CF_FPU). Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/translate.c | 49 ++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 42 insertions(+), 7 deletions(-) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 89e5d5e..d00bde3 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2346,18 +2346,43 @@ DISAS_INSN(fpu) case 7: { TCGv addr; + int incr; uint16_t mask; int i; - if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0) + if ((ext & 0xf00) != 0 || (ext & 0xff) == 0) goto undef; - tmp32 = gen_lea(s, insn, OS_LONG); - if (IS_NULL_QREG(tmp32)) { - gen_addr_fault(s); - return; + if ((ext & 0x1000) == 0 && !m68k_feature(s->env, M68K_FEATURE_FPU)) + goto undef; + if ((insn & 070) == 040) + tmp32 = AREG(insn, 0); + else { + tmp32 = gen_lea(s, insn, OS_LONG); + if (IS_NULL_QREG(tmp32)) { + gen_addr_fault(s); + return; + } } addr = tcg_temp_new_i32(); tcg_gen_mov_i32(addr, tmp32); mask = 0x80; + if (m68k_feature(s->env, M68K_FEATURE_FPU)) + incr = 12; + else + incr = 8; + if ((ext & (1 << 13)) && (insn & 070) == 040) { + for (i = 0; i < 8; i++) { + if (ext & mask) { + s->is_mem = 1; + dest = FREG(i, 7); + tcg_gen_subi_i32(addr, addr, incr); + tcg_gen_mov_i32(AREG(insn, 0), addr); + tcg_gen_qemu_stf64(dest, addr, IS_USER(s)); + } + mask >>= 1; + } + tcg_temp_free_i32(addr); + return; + } for (i = 0; i < 8; i++) { if (ext & mask) { s->is_mem = 1; @@ -2369,8 +2394,11 @@ DISAS_INSN(fpu) /* load */ tcg_gen_qemu_ldf64(dest, addr, IS_USER(s)); } - if (ext & (mask - 1)) - tcg_gen_addi_i32(addr, addr, 8); + if (ext & (mask - 1) || (insn & 070) == 030) { + tcg_gen_addi_i32(addr, addr, incr); + if ((insn & 070) == 030) + tcg_gen_mov_i32(AREG(insn, 0), addr); + } } mask >>= 1; } @@ -2478,6 +2506,12 @@ DISAS_INSN(fpu) case 0x23: case 0x63: case 0x67: /* fmul */ gen_helper_mul_f64(res, cpu_env, res, src); break; + case 0x24: /* fsgldiv */ + gen_helper_div_f64(res, cpu_env, res, src); + break; + case 0x27: /* fsglmul */ + gen_helper_mul_f64(res, cpu_env, res, src); + break; case 0x28: case 0x68: case 0x6c: /* fsub */ gen_helper_sub_f64(res, cpu_env, res, src); break; @@ -3160,6 +3194,7 @@ void register_m68k_insns (CPUM68KState *env) INSN(fbcc, f280, ffc0, CF_FPU); INSN(frestore, f340, ffc0, CF_FPU); INSN(fsave, f340, ffc0, CF_FPU); + INSN(fpu, f200, ffc0, FPU); INSN(fbcc, f280, ffc0, FPU); INSN(frestore, f340, ffc0, FPU); INSN(fsave, f340, ffc0, FPU); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 13/17] m68k: add "byte", "word" and memory shift 2009-05-29 22:41 ` [Qemu-devel] [PATCH 12/17] m68k: add fpu Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 14/17] m68k: add "byte", "word" and memory rotate Laurent Vivier 0 siblings, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier This patch defines shift8_im, shift16_im, shift8_reg, shift16_reg, shift_mem and attach them to M68000 feature. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/cpu.h | 2 + target-m68k/helper.c | 160 +++++++++++++++++++++++++++-------------------- target-m68k/helpers.h | 12 +++- target-m68k/translate.c | 155 +++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 249 insertions(+), 80 deletions(-) diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index fa0b055..727a0b1 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -146,6 +146,8 @@ enum { CC_OP_SUBXB, /* CC_DEST = result, CC_SRC = source */ CC_OP_SUBXW, /* CC_DEST = result, CC_SRC = source */ CC_OP_SUBX, /* CC_DEST = result, CC_SRC = source */ + CC_OP_SHIFTB, /* CC_DEST = result, CC_SRC = carry */ + CC_OP_SHIFTW, /* CC_DEST = result, CC_SRC = carry */ CC_OP_SHIFT, /* CC_DEST = result, CC_SRC = carry */ }; diff --git a/target-m68k/helper.c b/target-m68k/helper.c index bcd73d5..f15902a 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -283,6 +283,12 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) flags |= CCF_V; \ } while (0) +#define SET_FLAGS_SHIFT(type) do { \ + SET_NZ((type)dest); \ + if (src) \ + flags |= CCF_C; \ + } while(0) + flags = 0; src = env->cc_src; dest = env->cc_dest; @@ -329,10 +335,14 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) case CC_OP_SUBX: SET_FLAGS_SUBX(int32_t, uint32_t); break; + case CC_OP_SHIFTB: + SET_FLAGS_SHIFT(int8_t); + break; + case CC_OP_SHIFTW: + SET_FLAGS_SHIFT(int16_t); + break; case CC_OP_SHIFT: - SET_NZ(dest); - if (src) - flags |= CCF_C; + SET_FLAGS_SHIFT(int32_t); break; default: cpu_abort(env, "Bad CC_OP %d", cc_op); @@ -533,77 +543,89 @@ void HELPER(set_sr)(CPUState *env, uint32_t val) m68k_switch_sp(env); } -uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift) -{ - uint32_t result; - uint32_t cf; - - shift &= 63; - if (shift == 0) { - result = val; - cf = env->cc_src & CCF_C; - } else if (shift < 32) { - result = val << shift; - cf = (val >> (32 - shift)) & 1; - } else if (shift == 32) { - result = 0; - cf = val & 1; - } else /* shift > 32 */ { - result = 0; - cf = 0; - } - env->cc_src = cf; - env->cc_x = (cf != 0); - env->cc_dest = result; - return result; -} - -uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift) -{ - uint32_t result; - uint32_t cf; - - shift &= 63; - if (shift == 0) { - result = val; - cf = env->cc_src & CCF_C; - } else if (shift < 32) { - result = val >> shift; - cf = (val >> (shift - 1)) & 1; - } else if (shift == 32) { - result = 0; - cf = val >> 31; - } else /* shift > 32 */ { - result = 0; - cf = 0; - } - env->cc_src = cf; - env->cc_x = (cf != 0); - env->cc_dest = result; - return result; -} - -uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift) -{ - uint32_t result; - uint32_t cf; - - shift &= 63; - if (shift == 0) { - result = val; - cf = (env->cc_src & CCF_C) != 0; - } else if (shift < 32) { - result = (int32_t)val >> shift; - cf = (val >> (shift - 1)) & 1; - } else /* shift >= 32 */ { - result = (int32_t)val >> 31; - cf = val >> 31; - } - env->cc_src = cf; - env->cc_x = cf; - env->cc_dest = result; - return result; -} +#define HELPER_SHL(type, bits) \ +uint32_t HELPER(glue(glue(shl, bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t cf; \ + shift &= 63; \ + if (shift == 0) { \ + result = (type)val; \ + cf = env->cc_src & CCF_C; \ + } else if (shift < bits) { \ + result = (type)val << shift; \ + cf = ((type)val >> (bits - shift)) & 1; \ + } else if (shift == bits) { \ + result = 0; \ + cf = val & 1; \ + } else /* shift > bits */ { \ + result = 0; \ + cf = 0; \ + } \ + env->cc_src = cf; \ + env->cc_x = (cf != 0); \ + env->cc_dest = result; \ + return result; \ +} + +HELPER_SHL(uint8_t, 8) +HELPER_SHL(uint16_t, 16) +HELPER_SHL(uint32_t, 32) + +#define HELPER_SHR(type, bits) \ +uint32_t HELPER(glue(glue(shr, bits), _cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t cf; \ + shift &= 63; \ + if (shift == 0) { \ + result = (type)val; \ + cf = env->cc_src & CCF_C; \ + } else if (shift < bits) { \ + result = (type)val >> shift; \ + cf = ((type)val >> (shift - 1)) & 1; \ + } else if (shift == bits) { \ + result = 0; \ + cf = (type)val >> (bits - 1); \ + } else /* shift > bits */ { \ + result = 0; \ + cf = 0; \ + } \ + env->cc_src = cf; \ + env->cc_x = (cf != 0); \ + env->cc_dest = result; \ + return result; \ +} + +HELPER_SHR(uint8_t, 8) +HELPER_SHR(uint16_t, 16) +HELPER_SHR(uint32_t, 32) + +#define HELPER_SAR(type, bits) \ +uint32_t HELPER(glue(glue(sar, bits), _cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t cf; \ + shift &= 63; \ + if (shift == 0) { \ + result = (type)val; \ + cf = (env->cc_src & CCF_C) != 0; \ + } else if (shift < bits) { \ + result = (type)val >> shift; \ + cf = (val >> (shift - 1)) & 1; \ + } else /* shift >= bits */ { \ + result = (type)val >> (bits - 1); \ + cf = val >> (bits - 1); \ + } \ + env->cc_src = cf; \ + env->cc_x = cf; \ + env->cc_dest = result; \ + return result; \ +} + +HELPER_SAR(int8_t, 8) +HELPER_SAR(int16_t, 16) +HELPER_SAR(int32_t, 32) /* FPU helpers. */ uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val) diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h index ca2bf82..d1993ab 100644 --- a/target-m68k/helpers.h +++ b/target-m68k/helpers.h @@ -13,9 +13,15 @@ DEF_HELPER_3(mulu64, i32, env, i32, i32) DEF_HELPER_3(muls64, i32, env, i32, i32) DEF_HELPER_3(addx_cc, i32, env, i32, i32) DEF_HELPER_3(subx_cc, i32, env, i32, i32) -DEF_HELPER_3(shl_cc, i32, env, i32, i32) -DEF_HELPER_3(shr_cc, i32, env, i32, i32) -DEF_HELPER_3(sar_cc, i32, env, i32, i32) +DEF_HELPER_3(shl8_cc, i32, env, i32, i32) +DEF_HELPER_3(shl16_cc, i32, env, i32, i32) +DEF_HELPER_3(shl32_cc, i32, env, i32, i32) +DEF_HELPER_3(shr8_cc, i32, env, i32, i32) +DEF_HELPER_3(shr16_cc, i32, env, i32, i32) +DEF_HELPER_3(shr32_cc, i32, env, i32, i32) +DEF_HELPER_3(sar8_cc, i32, env, i32, i32) +DEF_HELPER_3(sar16_cc, i32, env, i32, i32) +DEF_HELPER_3(sar32_cc, i32, env, i32, i32) DEF_HELPER_2(xflag_lt, i32, i32, i32) DEF_HELPER_2(set_sr, void, env, i32) DEF_HELPER_3(movec, void, env, i32, i32) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index d00bde3..10b67e5 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2013,6 +2013,63 @@ DISAS_INSN(addx) } /* TODO: This could be implemented without helper functions. */ +DISAS_INSN(shift8_im) +{ + TCGv reg; + int tmp; + TCGv shift; + TCGv dest; + + reg = DREG(insn, 0); + tmp = (insn >> 9) & 7; + if (tmp == 0) + tmp = 8; + shift = tcg_const_i32(tmp); + dest = tcg_temp_new_i32(); + /* No need to flush flags becuse we know we will set C flag. */ + if (insn & 0x100) { + gen_helper_shl8_cc(dest, cpu_env, reg, shift); + } else { + if (insn & 8) { + gen_helper_shr8_cc(dest, cpu_env, reg, shift); + } else { + gen_helper_sar8_cc(dest, cpu_env, reg, shift); + } + } + s->cc_op = CC_OP_SHIFTB; + gen_partset_reg(OS_BYTE, reg, dest); +} + +/* TODO: This could be implemented without helper functions. */ +DISAS_INSN(shift16_im) +{ + TCGv reg; + int tmp; + TCGv shift; + TCGv dest; + + reg = DREG(insn, 0); + tmp = (insn >> 9) & 7; + if (tmp == 0) + tmp = 8; + shift = tcg_const_i32(tmp); + dest = tcg_temp_new_i32(); + /* No need to flush flags becuse we know we will set C flag. */ + if (insn & 0x100) { + gen_helper_shl16_cc(dest, cpu_env, reg, shift); + } else { + if (insn & 8) { + gen_helper_shr16_cc(dest, cpu_env, reg, shift); + } else { + gen_helper_sar16_cc(dest, cpu_env, reg, shift); + } + } + s->cc_op = CC_OP_SHIFTW; + gen_partset_reg(OS_WORD, reg, dest); +} + + +/* TODO: This could be implemented without helper functions. */ DISAS_INSN(shift_im) { TCGv reg; @@ -2026,17 +2083,71 @@ DISAS_INSN(shift_im) shift = tcg_const_i32(tmp); /* No need to flush flags becuse we know we will set C flag. */ if (insn & 0x100) { - gen_helper_shl_cc(reg, cpu_env, reg, shift); + gen_helper_shl32_cc(reg, cpu_env, reg, shift); } else { if (insn & 8) { - gen_helper_shr_cc(reg, cpu_env, reg, shift); + gen_helper_shr32_cc(reg, cpu_env, reg, shift); } else { - gen_helper_sar_cc(reg, cpu_env, reg, shift); + gen_helper_sar32_cc(reg, cpu_env, reg, shift); } } s->cc_op = CC_OP_SHIFT; } +DISAS_INSN(shift8_reg) +{ + TCGv reg; + TCGv shift; + TCGv dest; + TCGv tmp; + + reg = DREG(insn, 0); + shift = DREG(insn, 9); + tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, shift, 63); + dest = tcg_temp_new_i32(); + /* Shift by zero leaves C flag unmodified. */ + gen_flush_flags(s); + if (insn & 0x100) { + gen_helper_shl8_cc(dest, cpu_env, reg, tmp); + } else { + if (insn & 8) { + gen_helper_shr8_cc(dest, cpu_env, reg, tmp); + } else { + gen_helper_sar8_cc(dest, cpu_env, reg, tmp); + } + } + s->cc_op = CC_OP_SHIFTB; + gen_partset_reg(OS_BYTE, reg, dest); +} + +DISAS_INSN(shift16_reg) +{ + TCGv reg; + TCGv shift; + TCGv dest; + TCGv tmp; + + reg = DREG(insn, 0); + shift = DREG(insn, 9); + tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, shift, 63); + dest = tcg_temp_new_i32(); + /* Shift by zero leaves C flag unmodified. */ + gen_flush_flags(s); + if (insn & 0x100) { + gen_helper_shl16_cc(dest, cpu_env, reg, tmp); + } else { + if (insn & 8) { + gen_helper_shr16_cc(dest, cpu_env, reg, tmp); + } else { + gen_helper_sar16_cc(dest, cpu_env, reg, tmp); + } + } + s->cc_op = CC_OP_SHIFTB; + gen_partset_reg(OS_WORD, reg, dest); +} + DISAS_INSN(shift_reg) { TCGv reg; @@ -2047,17 +2158,40 @@ DISAS_INSN(shift_reg) /* Shift by zero leaves C flag unmodified. */ gen_flush_flags(s); if (insn & 0x100) { - gen_helper_shl_cc(reg, cpu_env, reg, shift); + gen_helper_shl32_cc(reg, cpu_env, reg, shift); } else { if (insn & 8) { - gen_helper_shr_cc(reg, cpu_env, reg, shift); + gen_helper_shr32_cc(reg, cpu_env, reg, shift); } else { - gen_helper_sar_cc(reg, cpu_env, reg, shift); + gen_helper_sar32_cc(reg, cpu_env, reg, shift); } } s->cc_op = CC_OP_SHIFT; } +DISAS_INSN(shift_mem) +{ + TCGv src; + TCGv dest; + TCGv addr; + TCGv shift; + + SRC_EA(src, OS_WORD, 0, &addr); + dest = tcg_temp_new_i32(); + shift = tcg_const_i32(1); + if (insn & 0x100) { + gen_helper_shl16_cc(dest, cpu_env, src, shift); + } else { + if (insn & 8) { + gen_helper_shr16_cc(dest, cpu_env, src, shift); + } else { + gen_helper_sar16_cc(dest, cpu_env, src, shift); + } + } + s->cc_op = CC_OP_SHIFTW; + DEST_EA(insn, OS_WORD, dest, &addr); +} + DISAS_INSN(ff1) { TCGv reg; @@ -3186,8 +3320,13 @@ void register_m68k_insns (CPUM68KState *env) INSN(adda, d0c0, f0c0, M68000); INSN(shift_im, e080, f0f0, CF_ISA_A); INSN(shift_reg, e0a0, f0f0, CF_ISA_A); - INSN(shift_im, e080, f0f0, M68000); - INSN(shift_reg, e0a0, f0f0, M68000); + INSN(shift8_im, e000, f0f0, M68000); + INSN(shift16_im, e040, f0f0, M68000); + INSN(shift_im, e080, f0f0, M68000); + INSN(shift8_reg, e020, f0f0, M68000); + INSN(shift16_reg, e060, f0f0, M68000); + INSN(shift_reg, e0a0, f0f0, M68000); + INSN(shift_mem, e0c0, fcc0, M68000); INSN(undef_fpu, f000, f000, CF_ISA_A); INSN(undef_fpu, f000, f000, M68000); INSN(fpu, f200, ffc0, CF_FPU); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 14/17] m68k: add "byte", "word" and memory rotate. 2009-05-29 22:41 ` [Qemu-devel] [PATCH 13/17] m68k: add "byte", "word" and memory shift Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 15/17] m68k: add bitfield_mem, bitfield_reg Laurent Vivier 0 siblings, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier Add rotate_im, rotate8_im, rotate16_im, rotate_reg, rotate8_reg, rotate16_reg, rotate_mem and attach them to M68000 feature. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/exec.h | 4 + target-m68k/helper.c | 149 ++++++++++++++++++++++++++++++++++ target-m68k/helpers.h | 12 +++ target-m68k/translate.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 370 insertions(+), 0 deletions(-) diff --git a/target-m68k/exec.h b/target-m68k/exec.h index 3a86b1f..6f63cd8 100644 --- a/target-m68k/exec.h +++ b/target-m68k/exec.h @@ -29,6 +29,10 @@ register uint32_t T0 asm(AREG1); #include "cpu.h" #include "exec-all.h" +extern const uint8_t rox8_table[64]; +extern const uint8_t rox16_table[64]; +extern const uint8_t rox32_table[64]; + static inline void env_to_regs(void) { } diff --git a/target-m68k/helper.c b/target-m68k/helper.c index f15902a..92c7621 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -62,6 +62,42 @@ static m68k_def_t m68k_cpu_defs[] = { {NULL, 0}, }; +/* modulo 33 table */ +const uint8_t rox32_table[64] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9,10,11,12,13,14,15, + 16,17,18,19,20,21,22,23, + 24,25,26,27,28,29,30,31, + 32, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9,10,11,12,13,14, + 15,16,17,18,19,20,21,22, + 23,24,25,26,27,28,29,30, +}; + +/* modulo 17 table */ +const uint8_t rox16_table[64] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9,10,11,12,13,14,15, + 16, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9,10,11,12,13,14, + 15,16, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9,10,11,12,13, + 14,15,16, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9,10,11,12, +}; + +/* modulo 9 table */ +const uint8_t rox8_table[64] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 0, 1, 2, + 3, 4, 5, 6, 7, 8, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 0, +}; + void m68k_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) { unsigned int i; @@ -627,6 +663,119 @@ HELPER_SAR(int8_t, 8) HELPER_SAR(int16_t, 16) HELPER_SAR(int32_t, 32) +#define HELPER_ROL(type, bits) \ +uint32_t HELPER(glue(glue(rol,bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t flags; \ + int count = shift & (bits - 1); \ + if (count) \ + result = ((type)val << count) | ((type)val >> (bits - count)); \ + else \ + result = (type)val; \ + flags = 0; \ + if (result == 0) \ + flags |= CCF_Z; \ + if (result & (1 << (bits - 1))) \ + flags |= CCF_N; \ + if (shift && result & 1) \ + flags |= CCF_C; \ + env->cc_dest = flags; \ + return result; \ +} + +HELPER_ROL(uint8_t, 8) +HELPER_ROL(uint16_t, 16) +HELPER_ROL(uint32_t, 32) + +#define HELPER_ROR(type, bits) \ +uint32_t HELPER(glue(glue(ror,bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t flags; \ + int count = shift & (bits - 1); \ + if (count) \ + result = ((type)val >> count) | ((type)val << (bits - count)); \ + else \ + result = (type)val; \ + flags = 0; \ + if (result == 0) \ + flags |= CCF_Z; \ + if (result & (1 << (bits - 1))) \ + flags |= CCF_N; \ + if (shift && result & (1 << (bits - 1))) \ + flags |= CCF_C; \ + env->cc_dest = flags; \ + return result; \ +} + +HELPER_ROR(uint8_t, 8) +HELPER_ROR(uint16_t, 16) +HELPER_ROR(uint32_t, 32) + +#define HELPER_ROXR(type, bits) \ +uint32_t HELPER(glue(glue(roxr,bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t flags; \ + int count = shift; \ + if (bits == 8) count = rox8_table[count]; \ + if (bits == 16) count = rox16_table[count]; \ + if (bits == 32) count = rox32_table[count]; \ + if (count) { \ + result = ((type)val >> count) | ((type)env->cc_x << (bits - count)); \ + if (count > 1) \ + result |= (type)val << (bits + 1 - count); \ + env->cc_x = ((type)val >> (count - 1)) & 1; \ + } else \ + result = (type)val; \ + flags = 0; \ + if (result == 0) \ + flags |= CCF_Z; \ + if (result & (1 << (bits - 1))) \ + flags |= CCF_N; \ + if (env->cc_x) \ + flags |= CCF_C; \ + env->cc_dest = flags; \ + return result; \ +} + +HELPER_ROXR(uint8_t, 8) +HELPER_ROXR(uint16_t, 16) +HELPER_ROXR(uint32_t, 32) + +#define HELPER_ROXL(type, bits) \ +uint32_t HELPER(glue(glue(roxl,bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t flags; \ + int count; \ + count = shift; \ + if (bits == 8) count = rox8_table[count]; \ + if (bits == 16) count = rox16_table[count]; \ + if (bits == 32) count = rox32_table[count]; \ + if (count) { \ + result = ((type)val << count) | ((type)env->cc_x << (count - 1)); \ + if (count > 1) \ + result |= (type)val >> (bits + 1 - count); \ + env->cc_x = ((type)val >> (bits - count)) & 1; \ + } else \ + result = (type)val; \ + flags = 0; \ + if (result == 0) \ + flags |= CCF_Z; \ + if (result & (1 << (bits - 1))) \ + flags |= CCF_N; \ + if (env->cc_x) \ + flags |= CCF_C; \ + env->cc_dest = flags; \ + return result; \ +} + +HELPER_ROXL(uint8_t, 8) +HELPER_ROXL(uint16_t, 16) +HELPER_ROXL(uint32_t, 32) + /* FPU helpers. */ uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val) { diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h index d1993ab..07d1f82 100644 --- a/target-m68k/helpers.h +++ b/target-m68k/helpers.h @@ -22,6 +22,18 @@ DEF_HELPER_3(shr32_cc, i32, env, i32, i32) DEF_HELPER_3(sar8_cc, i32, env, i32, i32) DEF_HELPER_3(sar16_cc, i32, env, i32, i32) DEF_HELPER_3(sar32_cc, i32, env, i32, i32) +DEF_HELPER_3(rol8_cc, i32, env, i32, i32) +DEF_HELPER_3(rol16_cc, i32, env, i32, i32) +DEF_HELPER_3(rol32_cc, i32, env, i32, i32) +DEF_HELPER_3(ror8_cc, i32, env, i32, i32) +DEF_HELPER_3(ror16_cc, i32, env, i32, i32) +DEF_HELPER_3(ror32_cc, i32, env, i32, i32) +DEF_HELPER_3(roxr8_cc, i32, env, i32, i32) +DEF_HELPER_3(roxr16_cc, i32, env, i32, i32) +DEF_HELPER_3(roxr32_cc, i32, env, i32, i32) +DEF_HELPER_3(roxl8_cc, i32, env, i32, i32) +DEF_HELPER_3(roxl16_cc, i32, env, i32, i32) +DEF_HELPER_3(roxl32_cc, i32, env, i32, i32) DEF_HELPER_2(xflag_lt, i32, i32, i32) DEF_HELPER_2(set_sr, void, env, i32) DEF_HELPER_3(movec, void, env, i32, i32) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 10b67e5..17ab88c 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2192,6 +2192,204 @@ DISAS_INSN(shift_mem) DEST_EA(insn, OS_WORD, dest, &addr); } +DISAS_INSN(rotate_im) +{ + TCGv reg; + TCGv shift; + int tmp; + + reg = DREG(insn, 0); + tmp = (insn >> 9) & 7; + if (tmp == 0) + tmp = 8; + shift = tcg_const_i32(tmp); + if (insn & 8) { + if (insn & 0x100) { + gen_helper_rol32_cc(reg, cpu_env, reg, shift); + } else { + gen_helper_ror32_cc(reg, cpu_env, reg, shift); + } + } else { + if (insn & 0x100) { + gen_helper_roxl32_cc(reg, cpu_env, reg, shift); + } else { + gen_helper_roxr32_cc(reg, cpu_env, reg, shift); + } + } + s->cc_op = CC_OP_FLAGS; +} + +DISAS_INSN(rotate8_im) +{ + TCGv reg; + TCGv dest; + TCGv shift; + int tmp; + + reg = DREG(insn, 0); + tmp = (insn >> 9) & 7; + if (tmp == 0) + tmp = 8; + dest = tcg_temp_new_i32(); + shift = tcg_const_i32(tmp); + if (insn & 8) { + if (insn & 0x100) { + gen_helper_rol8_cc(dest, cpu_env, reg, shift); + } else { + gen_helper_ror8_cc(dest, cpu_env, reg, shift); + } + } else { + if (insn & 0x100) { + gen_helper_roxl8_cc(dest, cpu_env, reg, shift); + } else { + gen_helper_roxr8_cc(dest, cpu_env, reg, shift); + } + } + s->cc_op = CC_OP_FLAGS; + gen_partset_reg(OS_BYTE, reg, dest); +} + +DISAS_INSN(rotate16_im) +{ + TCGv reg; + TCGv dest; + TCGv shift; + int tmp; + + reg = DREG(insn, 0); + tmp = (insn >> 9) & 7; + if (tmp == 0) + tmp = 8; + dest = tcg_temp_new_i32(); + shift = tcg_const_i32(tmp); + if (insn & 8) { + if (insn & 0x100) { + gen_helper_rol16_cc(dest, cpu_env, reg, shift); + } else { + gen_helper_ror16_cc(dest, cpu_env, reg, shift); + } + } else { + if (insn & 0x100) { + gen_helper_roxl16_cc(dest, cpu_env, reg, shift); + } else { + gen_helper_roxr16_cc(dest, cpu_env, reg, shift); + } + } + s->cc_op = CC_OP_FLAGS; + gen_partset_reg(OS_WORD, reg, dest); +} + +DISAS_INSN(rotate_reg) +{ + TCGv reg; + TCGv src; + TCGv tmp; + + reg = DREG(insn, 0); + src = DREG(insn, 9); + tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, src, 63); + if (insn & 8) { + if (insn & 0x100) { + gen_helper_rol32_cc(reg, cpu_env, reg, tmp); + } else { + gen_helper_ror32_cc(reg, cpu_env, reg, tmp); + } + } else { + if (insn & 0x100) { + gen_helper_roxl32_cc(reg, cpu_env, reg, tmp); + } else { + gen_helper_roxr32_cc(reg, cpu_env, reg, tmp); + } + } + s->cc_op = CC_OP_FLAGS; +} + +DISAS_INSN(rotate8_reg) +{ + TCGv reg; + TCGv src; + TCGv dest; + TCGv tmp; + + reg = DREG(insn, 0); + src = DREG(insn, 9); + tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, src, 63); + dest = tcg_temp_new_i32(); + if (insn & 8) { + if (insn & 0x100) { + gen_helper_rol8_cc(dest, cpu_env, reg, tmp); + } else { + gen_helper_ror8_cc(dest, cpu_env, reg, tmp); + } + } else { + if (insn & 0x100) { + gen_helper_roxl8_cc(dest, cpu_env, reg, tmp); + } else { + gen_helper_roxr8_cc(dest, cpu_env, reg, tmp); + } + } + s->cc_op = CC_OP_FLAGS; + gen_partset_reg(OS_BYTE, reg, dest); +} + +DISAS_INSN(rotate16_reg) +{ + TCGv reg; + TCGv src; + TCGv dest; + TCGv tmp; + + reg = DREG(insn, 0); + src = DREG(insn, 9); + tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, src, 63); + dest = tcg_temp_new_i32(); + if (insn & 8) { + if (insn & 0x100) { + gen_helper_rol16_cc(dest, cpu_env, reg, tmp); + } else { + gen_helper_ror16_cc(dest, cpu_env, reg, tmp); + } + } else { + if (insn & 0x100) { + gen_helper_roxl16_cc(dest, cpu_env, reg, tmp); + } else { + gen_helper_roxr16_cc(dest, cpu_env, reg, tmp); + } + } + s->cc_op = CC_OP_FLAGS; + gen_partset_reg(OS_WORD, reg, dest); +} + +DISAS_INSN(rotate_mem) +{ + TCGv src; + TCGv dest; + TCGv addr; + TCGv shift; + + SRC_EA(src, OS_WORD, 0, &addr); + dest = tcg_temp_new_i32(); + shift = tcg_const_i32(1); + if (insn & 8) { + if (insn & 0x100) { + gen_helper_rol16_cc(dest, cpu_env, src, shift); + } else { + gen_helper_ror16_cc(dest, cpu_env, src, shift); + } + } else { + if (insn & 0x100) { + gen_helper_roxl16_cc(dest, cpu_env, src, shift); + } else { + gen_helper_roxr16_cc(dest, cpu_env, src, shift); + } + } + s->cc_op = CC_OP_FLAGS; + DEST_EA(insn, OS_WORD, dest, &addr); +} + DISAS_INSN(ff1) { TCGv reg; @@ -3327,6 +3525,13 @@ void register_m68k_insns (CPUM68KState *env) INSN(shift16_reg, e060, f0f0, M68000); INSN(shift_reg, e0a0, f0f0, M68000); INSN(shift_mem, e0c0, fcc0, M68000); + INSN(rotate_im, e090, f0f0, M68000); + INSN(rotate8_im, e010, f0f0, M68000); + INSN(rotate16_im, e050, f0f0, M68000); + INSN(rotate_reg, e0b0, f0f0, M68000); + INSN(rotate8_reg, e030, f0f0, M68000); + INSN(rotate16_reg,e070, f0f0, M68000); + INSN(rotate_mem, e4c0, fcc0, M68000); INSN(undef_fpu, f000, f000, CF_ISA_A); INSN(undef_fpu, f000, f000, M68000); INSN(fpu, f200, ffc0, CF_FPU); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 15/17] m68k: add bitfield_mem, bitfield_reg 2009-05-29 22:41 ` [Qemu-devel] [PATCH 14/17] m68k: add "byte", "word" and memory rotate Laurent Vivier @ 2009-05-29 22:41 ` Laurent Vivier 2009-05-29 22:42 ` [Qemu-devel] [PATCH 16/17] m68k: add variable offset/width to bitfield_reg/bitfield_mem Laurent Vivier 0 siblings, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:41 UTC (permalink / raw) To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier This patch implements bitfields instructions: bftst, bfextu, bfexts, bfffo, bfchg, bfclr, bfset, bfins and attach them to BITFIELD feature. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/helper.c | 27 ++++ target-m68k/helpers.h | 3 + target-m68k/translate.c | 323 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 353 insertions(+), 0 deletions(-) diff --git a/target-m68k/helper.c b/target-m68k/helper.c index 92c7621..32ff8ca 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -514,6 +514,33 @@ uint32_t HELPER(ff1)(uint32_t x) return n; } +uint32_t HELPER(bfffo)(uint32_t arg, uint32_t width) +{ + int n; + uint32_t mask; + mask = 0x80000000; + for (n = 0; n < width; n++) { + if (arg & mask) + break; + mask >>= 1; + } + return n; +} + +uint32_t HELPER(rol32)(uint32_t val, uint32_t shift) +{ + uint32_t result; + result = (val << shift) | (val >> (32 - shift)); + return result; +} + +uint32_t HELPER(ror32)(uint32_t val, uint32_t shift) +{ + uint32_t result; + result = (val >> shift) | (val << (32 - shift)); + return result; +} + uint32_t HELPER(sats)(uint32_t val, uint32_t ccr) { /* The result has the opposite sign to the original value. */ diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h index 07d1f82..949d5d5 100644 --- a/target-m68k/helpers.h +++ b/target-m68k/helpers.h @@ -2,6 +2,9 @@ DEF_HELPER_1(bitrev, i32, i32) DEF_HELPER_1(ff1, i32, i32) +DEF_HELPER_2(bfffo, i32, i32, i32) +DEF_HELPER_2(rol32, i32, i32, i32) +DEF_HELPER_2(ror32, i32, i32, i32) DEF_HELPER_2(sats, i32, i32, i32) DEF_HELPER_2(divu, void, env, i32) DEF_HELPER_2(divs, void, env, i32) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 17ab88c..289e3bb 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2390,6 +2390,327 @@ DISAS_INSN(rotate_mem) DEST_EA(insn, OS_WORD, dest, &addr); } +DISAS_INSN(bitfield_reg) +{ + uint16_t ext; + TCGv tmp; + TCGv tmp1; + TCGv reg; + int offset; + int width; + int op; + TCGv reg2; + uint32_t mask; + + reg = DREG(insn, 0); + op = (insn >> 8) & 7; + ext = lduw_code(s->pc); + s->pc += 2; + if ((ext & 0x820) == 0) { + /* constant offset and width */ + offset = (ext >> 6) & 31; + width = (ext & 31); + if (width == 0) + width = 32; + reg2 = DREG(ext, 12); + mask = 0xffffffff << (32 - width); + if (offset > 0) + mask = (mask >> offset) | (mask << (32 - offset)); + tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, reg, mask); + if (offset > 0) { + tmp1 = tcg_temp_new_i32(); + gen_helper_rol32(tmp1, tmp, tcg_const_i32(offset)); + } else + tmp1 = tmp; + gen_logic_cc(s, tmp1); + switch (op) { + case 0: /* bftst */ + break; + case 1: /* bfextu */ + if (offset + width != 32) + gen_helper_rol32(reg2, tmp, tcg_const_i32((offset + width) & 31)); + else + tcg_gen_mov_i32(reg2, tmp); + break; + case 2: /* bfchg */ + tcg_gen_xor_i32(reg, reg, tcg_const_i32(mask)); + break; + case 3: /* bfexts */ + if (offset > 0) + gen_helper_rol32(reg2, tmp, tcg_const_i32(offset)); + if (width < 32) + tcg_gen_sari_i32(reg2, reg2, 32 - width); + break; + case 4: /* bfclr */ + tcg_gen_and_i32(reg, reg, tcg_const_i32(mask)); + break; + case 5: /* bfffo */ + if (offset > 0) + gen_helper_rol32(reg2, tmp, tcg_const_i32(offset)); + gen_helper_bfffo(tmp, tmp, tcg_const_i32(width)); + tcg_gen_addi_i32(reg2, tmp, offset); + break; + case 6: /* bfset */ + tcg_gen_ori_i32(reg, reg, mask); + break; + case 7: /* bfins */ + if (width == 32) { + if (offset > 0) + gen_helper_ror32(reg, reg2, tcg_const_i32(offset)); + else + tcg_gen_mov_i32(reg, reg2); + } else { + tcg_gen_andi_i32(tmp, reg2, (1u << width) - 1); + if (offset + width != 32) + gen_helper_ror32(tmp, tmp, tcg_const_i32((offset + width) & 31)); + tcg_gen_andi_i32(reg, reg, ~mask); + tcg_gen_or_i32(reg, reg, tmp); + } + break; + } + return; + } + /* Not yet implemented */ + gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); +} + +/* Generate a load from a bitfield. */ +static void gen_bitfield_load(DisasContext *s, TCGv addr, int endpos, + TCGv *val1, TCGv *val2) +{ + TCGv tmp; + + if (endpos <= 8) + *val1 = gen_load(s, OS_BYTE, addr, 0); + else if (endpos <= 24) { + *val1 = gen_load(s, OS_WORD, addr, 0); + if (endpos > 16) { + tmp = tcg_temp_new_i32(); + tcg_gen_addi_i32(tmp, addr, 2); + *val2 = gen_load(s, OS_BYTE, tmp, 0); + } + } else { + *val1 = gen_load(s, OS_LONG, addr, 0); + if (endpos > 32) { + tmp = tcg_temp_new_i32(); + tcg_gen_addi_i32(tmp, addr, 4); + *val2 = gen_load(s, OS_BYTE, tmp, 0); + } + } +} + +/* Generate a store to a bitfield. */ +static void gen_bitfield_store(DisasContext *s, TCGv addr, int endpos, + TCGv val1, TCGv val2) +{ + TCGv tmp; + + if (endpos <= 8) + gen_store(s, OS_BYTE, addr, val1); + else if (endpos <= 24) { + gen_store(s, OS_WORD, addr, val1); + if (endpos > 16) { + tmp = tcg_temp_new_i32(); + tcg_gen_addi_i32(tmp, addr, 2); + gen_store(s, OS_BYTE, tmp, val2); + } + } else { + gen_store(s, OS_LONG, addr, val1); + if (endpos > 32) { + tmp = tcg_temp_new_i32(); + tcg_gen_addi_i32(tmp, addr, 4); + gen_store(s, OS_BYTE, tmp, val2); + } + } +} + +static TCGv gen_bitfield_cc(DisasContext *s, int offset, int width, + TCGv val1, TCGv val2) +{ + TCGv dest; + TCGv tmp; + + dest = tcg_temp_new_i32(); + + if (offset + width <= 8) + tcg_gen_shli_i32(dest, val1, 24 + offset); + else if (offset + width <= 24) { + tcg_gen_shli_i32(dest, val1, 16 + offset); + if (offset + width > 16) { + tmp = tcg_temp_new_i32(); + tcg_gen_shli_i32(tmp, val2, 8 + offset); + tcg_gen_or_i32(dest, dest, tmp); + } + } else { + tcg_gen_shli_i32(dest, val1, offset); + if (offset + width > 32) { + tmp = tcg_temp_new_i32(); + tcg_gen_shri_i32(tmp, val2, offset); + tcg_gen_or_i32(dest, dest, tmp); + } + } + tcg_gen_andi_i32(dest, dest, 0xffffffff << (32 - width)); + gen_logic_cc(s, dest); + return dest; +} + +static void gen_bitfield_op(int offset, int width, int op, TCGv val1, TCGv val2) +{ + uint32_t mask1; + uint32_t mask2; + int endpos = offset + width; + + if (endpos <= 8) { + mask1 = (0xff >> offset) & (0xff << (8 - endpos)); + mask2 = 0; + } else if (endpos <= 16) { + mask1 = (0xffff >> offset) & (0xffff << (16 - endpos)); + mask2 = 0; + } else if (endpos <= 24) { + mask1 = 0xffffff >> offset; + mask2 = 0xff & (0xff << (24 - endpos)); + } else if (endpos <= 32) { + mask1 = (0xffffffff >> offset) & (0xffffffff << (32 - endpos)); + mask2 = 0; + } else { + mask1 = 0xffffffff >> offset; + mask2 = 0xff & (0xff << (40 - endpos)); + } + switch (op) { + case 2: /* bfchg */ + tcg_gen_xori_i32(val1, val1, mask1); + if (mask2) + tcg_gen_xori_i32(val2, val2, mask2); + break; + case 4: /* bfclr */ + tcg_gen_andi_i32(val1, val1, ~mask1); + if (mask2) + tcg_gen_andi_i32(val2, val2, ~mask2); + break; + case 6: /* bfset */ + tcg_gen_ori_i32(val1, val1, mask1); + if (mask2) + tcg_gen_ori_i32(val2, val2, mask2); + break; + } +} + +static void gen_bitfield_ins(int offset, int width, TCGv src, + TCGv val1, TCGv val2) +{ + TCGv tmp; + int endpos = offset + width; + + tmp = tcg_temp_new_i32(); + if (width < 32) { + tcg_gen_andi_i32(tmp, src, (1u << width) - 1); + } else + tcg_gen_mov_i32(tmp, src); + if (endpos <= 8) { + if (endpos < 8) + tcg_gen_shli_i32(tmp, tmp, 8 - endpos); + tcg_gen_or_i32(val1, val1, tmp); + } else if (endpos <= 16) { + if (endpos < 16) + tcg_gen_shli_i32(tmp, tmp, 16 - endpos); + tcg_gen_or_i32(val1, val1, tmp); + } else if (endpos <= 24) { + tcg_gen_shri_i32(tmp, tmp, endpos - 16); + tcg_gen_or_i32(val1, val1, tmp); + tcg_gen_andi_i32(tmp, src, (1u << (endpos - 16)) - 1); + if (endpos < 24) + tcg_gen_shli_i32(tmp, tmp, 24 - endpos); + tcg_gen_or_i32(val2, val2, tmp); + } else if (endpos <= 32) { + if (endpos < 32) + tcg_gen_shli_i32(tmp, tmp, 32 - endpos); + tcg_gen_or_i32(val1, val1, tmp); + } else { + tcg_gen_shri_i32(tmp, tmp, endpos - 32); + tcg_gen_or_i32(val1, val1, tmp); + tcg_gen_andi_i32(tmp, src, (1u << (endpos - 32)) - 1); + tcg_gen_shri_i32(tmp, tmp, 32 - endpos); + tcg_gen_or_i32(val2, val2, tmp); + } +} + +DISAS_INSN(bitfield_mem) +{ + uint16_t ext; + TCGv val; + TCGv val1, val2; + TCGv src; + int offset; + int width; + int op; + TCGv reg; + TCGv addr; + uint32_t mask; + + op = (insn >> 8) & 7; + ext = lduw_code(s->pc); + s->pc += 2; + src = gen_lea(s, insn, OS_LONG); + if (IS_NULL_QREG(src)) { + gen_addr_fault(s); + return; + } + if ((ext & 0x820) == 0) { + /* constant offset and width */ + offset = (ext >> 6) & 31; + width = (ext & 31); + if (width == 0) + width = 32; + reg = DREG(ext, 12); + mask = 0xffffffff << (32 - width); + addr = tcg_temp_new_i32(); + if (offset > 7) { + tcg_gen_addi_i32(addr, src, offset >> 3); + offset &= 7; + } else + tcg_gen_mov_i32(addr, src); + if (offset > 0) + mask <<= 32 - offset; + gen_bitfield_load(s, addr, offset + width, &val1, &val2); + val = gen_bitfield_cc(s, offset, width, val1, val2); + switch (op) { + case 0: /* bftst */ + break; + case 1: /* bfextu */ + if (width < 32) + tcg_gen_shri_i32(reg, val, 32 - width); + else + tcg_gen_mov_i32(reg, val); + break; + case 3: /* bfexts */ + if (width < 32) + tcg_gen_sari_i32(reg, val, 32 - width); + else + tcg_gen_mov_i32(reg, val); + break; + case 5: /* bfffo */ + gen_helper_bfffo(val, val, tcg_const_i32(width)); + tcg_gen_addi_i32(reg, val, offset); + break; + case 2: /* bfchg */ + case 4: /* bfclr */ + case 6: /* bfset */ + gen_bitfield_op(offset, width, op, val1, val2); + gen_bitfield_store(s, addr, offset + width, val1, val2); + break; + case 7: /* bfins */ + gen_bitfield_op(offset, width, 4, val1, val2); + gen_bitfield_ins(offset, width, reg, val1, val2); + gen_bitfield_store(s, addr, offset + width, val1, val2); + break; + } + return; + } + /* Not yet implemented */ + gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); +} + DISAS_INSN(ff1) { TCGv reg; @@ -3532,6 +3853,8 @@ void register_m68k_insns (CPUM68KState *env) INSN(rotate8_reg, e030, f0f0, M68000); INSN(rotate16_reg,e070, f0f0, M68000); INSN(rotate_mem, e4c0, fcc0, M68000); + INSN(bitfield_mem,e8c0, f8c0, BITFIELD); + INSN(bitfield_reg,e8c0, f8f8, BITFIELD); INSN(undef_fpu, f000, f000, CF_ISA_A); INSN(undef_fpu, f000, f000, M68000); INSN(fpu, f200, ffc0, CF_FPU); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 16/17] m68k: add variable offset/width to bitfield_reg/bitfield_mem 2009-05-29 22:41 ` [Qemu-devel] [PATCH 15/17] m68k: add bitfield_mem, bitfield_reg Laurent Vivier @ 2009-05-29 22:42 ` Laurent Vivier 2009-05-29 22:42 ` [Qemu-devel] [PATCH 17/17] m68k: add cas Laurent Vivier 0 siblings, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:42 UTC (permalink / raw) To: qemu-devel; +Cc: Laurent Vivier This patch allows bitfield instructions to read bit offset and field size from a register instead of an immediat value. Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/helper.c | 42 ++++ target-m68k/helpers.h | 2 + target-m68k/translate.c | 517 +++++++++++++++++++++++------------------------ 3 files changed, 292 insertions(+), 269 deletions(-) diff --git a/target-m68k/helper.c b/target-m68k/helper.c index 32ff8ca..3ae0366 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -530,6 +530,8 @@ uint32_t HELPER(bfffo)(uint32_t arg, uint32_t width) uint32_t HELPER(rol32)(uint32_t val, uint32_t shift) { uint32_t result; + if (shift == 0 || shift == 32) + return val; result = (val << shift) | (val >> (32 - shift)); return result; } @@ -537,6 +539,8 @@ uint32_t HELPER(rol32)(uint32_t val, uint32_t shift) uint32_t HELPER(ror32)(uint32_t val, uint32_t shift) { uint32_t result; + if (shift == 0 || shift == 32) + return val; result = (val >> shift) | (val << (32 - shift)); return result; } @@ -1182,3 +1186,41 @@ void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc) res |= (uint64_t)(val & 0xffff0000) << 16; env->macc[acc + 1] = res; } + +/* load from a bitfield */ + +uint64_t HELPER(bitfield_load)(uint32_t addr, uint32_t offset, uint32_t width) +{ + uint8_t data[8]; + uint64_t bitfield; + int size; + int i; + + size = (offset + width + 7) >> 3; + cpu_physical_memory_rw(addr, data, size, 0); + + bitfield = data[0]; + for (i = 1; i < 8; i++) + bitfield = (bitfield << 8) | data[i]; + + return bitfield; +} + +/* store to a bitfield */ + +void HELPER(bitfield_store)(uint32_t addr, uint32_t offset, uint32_t width, + uint64_t bitfield) +{ + uint8_t data[8]; + int size; + int i; + + size = (offset + width + 7) >> 3; + + for (i = 0; i < 8; i++) { + data[7 - i] = bitfield; + bitfield >>= 8; + } + + cpu_physical_memory_rw(addr, data, size, 1); +} diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h index 949d5d5..d71ed26 100644 --- a/target-m68k/helpers.h +++ b/target-m68k/helpers.h @@ -78,4 +78,6 @@ DEF_HELPER_3(set_mac_extu, void, env, i32, i32) DEF_HELPER_2(flush_flags, void, env, i32) DEF_HELPER_1(raise_exception, void, i32) +DEF_HELPER_3(bitfield_load, i64, i32, i32, i32); +DEF_HELPER_4(bitfield_store, void, i32, i32, i32, i64); #include "def-helper.h" diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 289e3bb..4c36b6a 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2390,263 +2390,225 @@ DISAS_INSN(rotate_mem) DEST_EA(insn, OS_WORD, dest, &addr); } +static void bitfield_param(uint16_t ext, TCGv *offset, TCGv *width, TCGv *mask) +{ + TCGv tmp; + + /* offset */ + + if (ext & 0x0800) { + *offset = DREG(ext, 6); + } else { + *offset = tcg_temp_new_i32(); + tcg_gen_movi_i32(*offset, (ext >> 6) & 31); + } + + /* width */ + + if (ext & 0x0020) { + *width = DREG(ext, 0); + tcg_gen_subi_i32(*width, *width, 1); + tcg_gen_andi_i32(*width, *width, 31); + tcg_gen_addi_i32(*width, *width, 1); + } else { + *width = tcg_temp_new_i32(); + tcg_gen_movi_i32(*width, ((ext - 1) & 31) + 1); + } + + /* mask */ + + tmp = tcg_temp_new_i32(); + tcg_gen_sub_i32(tmp, tcg_const_i32(32), *width); + *mask = tcg_temp_new_i32(); + tcg_gen_shl_i32(*mask, tcg_const_i32(0xffffffff), tmp); +} + DISAS_INSN(bitfield_reg) { uint16_t ext; TCGv tmp; TCGv tmp1; TCGv reg; - int offset; - int width; + TCGv offset; + TCGv width; int op; TCGv reg2; - uint32_t mask; + TCGv mask; reg = DREG(insn, 0); op = (insn >> 8) & 7; ext = lduw_code(s->pc); s->pc += 2; - if ((ext & 0x820) == 0) { - /* constant offset and width */ - offset = (ext >> 6) & 31; - width = (ext & 31); - if (width == 0) - width = 32; - reg2 = DREG(ext, 12); - mask = 0xffffffff << (32 - width); - if (offset > 0) - mask = (mask >> offset) | (mask << (32 - offset)); - tmp = tcg_temp_new_i32(); - tcg_gen_andi_i32(tmp, reg, mask); - if (offset > 0) { - tmp1 = tcg_temp_new_i32(); - gen_helper_rol32(tmp1, tmp, tcg_const_i32(offset)); - } else - tmp1 = tmp; - gen_logic_cc(s, tmp1); - switch (op) { - case 0: /* bftst */ - break; - case 1: /* bfextu */ - if (offset + width != 32) - gen_helper_rol32(reg2, tmp, tcg_const_i32((offset + width) & 31)); - else - tcg_gen_mov_i32(reg2, tmp); - break; - case 2: /* bfchg */ - tcg_gen_xor_i32(reg, reg, tcg_const_i32(mask)); - break; - case 3: /* bfexts */ - if (offset > 0) - gen_helper_rol32(reg2, tmp, tcg_const_i32(offset)); - if (width < 32) - tcg_gen_sari_i32(reg2, reg2, 32 - width); - break; - case 4: /* bfclr */ - tcg_gen_and_i32(reg, reg, tcg_const_i32(mask)); - break; - case 5: /* bfffo */ - if (offset > 0) - gen_helper_rol32(reg2, tmp, tcg_const_i32(offset)); - gen_helper_bfffo(tmp, tmp, tcg_const_i32(width)); - tcg_gen_addi_i32(reg2, tmp, offset); - break; - case 6: /* bfset */ - tcg_gen_ori_i32(reg, reg, mask); - break; - case 7: /* bfins */ - if (width == 32) { - if (offset > 0) - gen_helper_ror32(reg, reg2, tcg_const_i32(offset)); - else - tcg_gen_mov_i32(reg, reg2); - } else { - tcg_gen_andi_i32(tmp, reg2, (1u << width) - 1); - if (offset + width != 32) - gen_helper_ror32(tmp, tmp, tcg_const_i32((offset + width) & 31)); - tcg_gen_andi_i32(reg, reg, ~mask); - tcg_gen_or_i32(reg, reg, tmp); - } - break; - } - return; - } - /* Not yet implemented */ - gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); -} -/* Generate a load from a bitfield. */ -static void gen_bitfield_load(DisasContext *s, TCGv addr, int endpos, - TCGv *val1, TCGv *val2) -{ - TCGv tmp; - - if (endpos <= 8) - *val1 = gen_load(s, OS_BYTE, addr, 0); - else if (endpos <= 24) { - *val1 = gen_load(s, OS_WORD, addr, 0); - if (endpos > 16) { - tmp = tcg_temp_new_i32(); - tcg_gen_addi_i32(tmp, addr, 2); - *val2 = gen_load(s, OS_BYTE, tmp, 0); - } - } else { - *val1 = gen_load(s, OS_LONG, addr, 0); - if (endpos > 32) { - tmp = tcg_temp_new_i32(); - tcg_gen_addi_i32(tmp, addr, 4); - *val2 = gen_load(s, OS_BYTE, tmp, 0); - } - } -} + bitfield_param(ext, &offset, &width, &mask); -/* Generate a store to a bitfield. */ -static void gen_bitfield_store(DisasContext *s, TCGv addr, int endpos, - TCGv val1, TCGv val2) -{ - TCGv tmp; + if (ext & 0x0800) + tcg_gen_andi_i32(offset, offset, 31); + gen_helper_ror32(mask, mask, offset); - if (endpos <= 8) - gen_store(s, OS_BYTE, addr, val1); - else if (endpos <= 24) { - gen_store(s, OS_WORD, addr, val1); - if (endpos > 16) { - tmp = tcg_temp_new_i32(); - tcg_gen_addi_i32(tmp, addr, 2); - gen_store(s, OS_BYTE, tmp, val2); - } - } else { - gen_store(s, OS_LONG, addr, val1); - if (endpos > 32) { - tmp = tcg_temp_new_i32(); - tcg_gen_addi_i32(tmp, addr, 4); - gen_store(s, OS_BYTE, tmp, val2); - } + /* reg & mask */ + + tmp = tcg_temp_new_i32(); + tcg_gen_and_i32(tmp, reg, mask); + + tmp1 = tcg_temp_new_i32(); + gen_helper_rol32(tmp1, tmp, offset); + gen_logic_cc(s, tmp1); + + reg2 = DREG(ext, 12); + switch (op) { + case 0: /* bftst */ + break; + case 1: /* bfextu */ + tcg_gen_add_i32(tmp1, offset, width); + tcg_gen_andi_i32(tmp1, tmp1, 31); + gen_helper_rol32(reg2, tmp, tmp1); + break; + case 2: /* bfchg */ + tcg_gen_xor_i32(reg, reg, mask); + break; + case 3: /* bfexts */ + gen_helper_rol32(reg2, tmp, offset); + tcg_gen_sub_i32(width, tcg_const_i32(32), width); + tcg_gen_sar_i32(reg2, reg2, width); + break; + case 4: /* bfclr */ + tcg_gen_and_i32(reg, reg, mask); + break; + case 5: /* bfffo */ + gen_helper_rol32(reg2, tmp, offset); + gen_helper_bfffo(tmp, tmp, width); + tcg_gen_add_i32(reg2, tmp, offset); + break; + case 6: /* bfset */ + tcg_gen_or_i32(reg, reg, mask); + break; + case 7: /* bfins */ + tcg_gen_shl_i32(tmp1, tcg_const_i32(1), width); + tcg_gen_subi_i32(tmp1, tmp1, 1); + tcg_gen_and_i32(tmp, reg2, tmp1); + tcg_gen_add_i32(tmp1, offset, width); + tcg_gen_andi_i32(tmp1, tmp1, 31); + gen_helper_ror32(tmp, tmp, tmp1); + tcg_gen_not_i32(mask, mask); + tcg_gen_and_i32(reg, reg, mask); + tcg_gen_or_i32(reg, reg, tmp); + break; } } -static TCGv gen_bitfield_cc(DisasContext *s, int offset, int width, - TCGv val1, TCGv val2) +static TCGv gen_bitfield_cc(DisasContext *s, + TCGv offset, TCGv mask_cc, TCGv_i64 bitfield) { TCGv dest; - TCGv tmp; + TCGv_i64 tmp64; + /* move bitfield to a 32bit */ + + tmp64 = tcg_temp_new_i64(); + + tcg_gen_extu_i32_i64(tmp64, offset); + + /* tmp64 = bitfield << offset */ + + tcg_gen_shl_i64(tmp64, bitfield, tmp64); + + /* tmp = (bitfield << offset) >> 32 */ + + tcg_gen_shri_i64(tmp64, bitfield, 32ULL); dest = tcg_temp_new_i32(); + tcg_gen_trunc_i64_i32(dest, tmp64); - if (offset + width <= 8) - tcg_gen_shli_i32(dest, val1, 24 + offset); - else if (offset + width <= 24) { - tcg_gen_shli_i32(dest, val1, 16 + offset); - if (offset + width > 16) { - tmp = tcg_temp_new_i32(); - tcg_gen_shli_i32(tmp, val2, 8 + offset); - tcg_gen_or_i32(dest, dest, tmp); - } - } else { - tcg_gen_shli_i32(dest, val1, offset); - if (offset + width > 32) { - tmp = tcg_temp_new_i32(); - tcg_gen_shri_i32(tmp, val2, offset); - tcg_gen_or_i32(dest, dest, tmp); - } - } - tcg_gen_andi_i32(dest, dest, 0xffffffff << (32 - width)); + /* compute cc */ + + tcg_gen_and_i32(dest, dest, mask_cc); gen_logic_cc(s, dest); + return dest; } -static void gen_bitfield_op(int offset, int width, int op, TCGv val1, TCGv val2) -{ - uint32_t mask1; - uint32_t mask2; - int endpos = offset + width; - - if (endpos <= 8) { - mask1 = (0xff >> offset) & (0xff << (8 - endpos)); - mask2 = 0; - } else if (endpos <= 16) { - mask1 = (0xffff >> offset) & (0xffff << (16 - endpos)); - mask2 = 0; - } else if (endpos <= 24) { - mask1 = 0xffffff >> offset; - mask2 = 0xff & (0xff << (24 - endpos)); - } else if (endpos <= 32) { - mask1 = (0xffffffff >> offset) & (0xffffffff << (32 - endpos)); - mask2 = 0; - } else { - mask1 = 0xffffffff >> offset; - mask2 = 0xff & (0xff << (40 - endpos)); - } - switch (op) { - case 2: /* bfchg */ - tcg_gen_xori_i32(val1, val1, mask1); - if (mask2) - tcg_gen_xori_i32(val2, val2, mask2); - break; - case 4: /* bfclr */ - tcg_gen_andi_i32(val1, val1, ~mask1); - if (mask2) - tcg_gen_andi_i32(val2, val2, ~mask2); - break; - case 6: /* bfset */ - tcg_gen_ori_i32(val1, val1, mask1); - if (mask2) - tcg_gen_ori_i32(val2, val2, mask2); - break; - } -} - -static void gen_bitfield_ins(int offset, int width, TCGv src, - TCGv val1, TCGv val2) +static TCGv_i64 gen_bitfield_mask(TCGv offset, TCGv width) { TCGv tmp; - int endpos = offset + width; + TCGv_i64 mask; + TCGv_i64 shift; + + mask = tcg_temp_new_i64(); + + /* mask = (1u << width) - 1; */ + + tcg_gen_extu_i32_i64(mask, width); + tcg_gen_shl_i64(mask, tcg_const_i64(1), mask); + tcg_gen_subi_i64(mask, mask, 1); + + /* shift = 64 - (width + offset); */ tmp = tcg_temp_new_i32(); - if (width < 32) { - tcg_gen_andi_i32(tmp, src, (1u << width) - 1); - } else - tcg_gen_mov_i32(tmp, src); - if (endpos <= 8) { - if (endpos < 8) - tcg_gen_shli_i32(tmp, tmp, 8 - endpos); - tcg_gen_or_i32(val1, val1, tmp); - } else if (endpos <= 16) { - if (endpos < 16) - tcg_gen_shli_i32(tmp, tmp, 16 - endpos); - tcg_gen_or_i32(val1, val1, tmp); - } else if (endpos <= 24) { - tcg_gen_shri_i32(tmp, tmp, endpos - 16); - tcg_gen_or_i32(val1, val1, tmp); - tcg_gen_andi_i32(tmp, src, (1u << (endpos - 16)) - 1); - if (endpos < 24) - tcg_gen_shli_i32(tmp, tmp, 24 - endpos); - tcg_gen_or_i32(val2, val2, tmp); - } else if (endpos <= 32) { - if (endpos < 32) - tcg_gen_shli_i32(tmp, tmp, 32 - endpos); - tcg_gen_or_i32(val1, val1, tmp); - } else { - tcg_gen_shri_i32(tmp, tmp, endpos - 32); - tcg_gen_or_i32(val1, val1, tmp); - tcg_gen_andi_i32(tmp, src, (1u << (endpos - 32)) - 1); - tcg_gen_shri_i32(tmp, tmp, 32 - endpos); - tcg_gen_or_i32(val2, val2, tmp); - } + tcg_gen_add_i32(tmp, offset, width); + tcg_gen_sub_i32(tmp, tcg_const_i32(64), tmp); + shift = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(shift, tmp); + + /* mask <<= shift */ + + tcg_gen_shl_i64(mask, mask, shift); + + return mask; +} + +static void gen_bitfield_ins(TCGv offset, TCGv width, TCGv src, + TCGv_i64 val) +{ + TCGv_i64 insert; + TCGv_i64 shift; + TCGv tmp; + + tmp = tcg_temp_new_i32(); + + /* tmp = (1u << width) - 1; */ + + tcg_gen_shl_i32(tmp, tcg_const_i32(1), width); + tcg_gen_subi_i32(tmp, tmp, 1); + + /* tmp = tmp & src; */ + + tcg_gen_and_i32(tmp, tmp, src); + + /* insert = (i64)tmp; */ + + insert = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(insert, tmp); + + /* tmp = 64 - (width + offset); */ + + tcg_gen_add_i32(tmp, offset, width); + tcg_gen_sub_i32(tmp, tcg_const_i32(64), tmp); + shift = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(shift, tmp); + + /* insert <<= shift */ + + tcg_gen_shl_i64(insert, insert, shift); + + /* val |= select */ + + tcg_gen_or_i64(val, val, insert); } DISAS_INSN(bitfield_mem) { uint16_t ext; + int op; + TCGv_i64 bitfield; + TCGv_i64 mask_bitfield; + TCGv mask_cc; + TCGv shift; TCGv val; - TCGv val1, val2; TCGv src; - int offset; - int width; - int op; + TCGv offset; + TCGv width; TCGv reg; - TCGv addr; - uint32_t mask; + TCGv tmp; op = (insn >> 8) & 7; ext = lduw_code(s->pc); @@ -2656,59 +2618,76 @@ DISAS_INSN(bitfield_mem) gen_addr_fault(s); return; } - if ((ext & 0x820) == 0) { - /* constant offset and width */ - offset = (ext >> 6) & 31; - width = (ext & 31); - if (width == 0) - width = 32; - reg = DREG(ext, 12); - mask = 0xffffffff << (32 - width); - addr = tcg_temp_new_i32(); - if (offset > 7) { - tcg_gen_addi_i32(addr, src, offset >> 3); - offset &= 7; - } else - tcg_gen_mov_i32(addr, src); - if (offset > 0) - mask <<= 32 - offset; - gen_bitfield_load(s, addr, offset + width, &val1, &val2); - val = gen_bitfield_cc(s, offset, width, val1, val2); - switch (op) { - case 0: /* bftst */ - break; - case 1: /* bfextu */ - if (width < 32) - tcg_gen_shri_i32(reg, val, 32 - width); - else - tcg_gen_mov_i32(reg, val); - break; - case 3: /* bfexts */ - if (width < 32) - tcg_gen_sari_i32(reg, val, 32 - width); - else - tcg_gen_mov_i32(reg, val); - break; - case 5: /* bfffo */ - gen_helper_bfffo(val, val, tcg_const_i32(width)); - tcg_gen_addi_i32(reg, val, offset); - break; - case 2: /* bfchg */ - case 4: /* bfclr */ - case 6: /* bfset */ - gen_bitfield_op(offset, width, op, val1, val2); - gen_bitfield_store(s, addr, offset + width, val1, val2); - break; - case 7: /* bfins */ - gen_bitfield_op(offset, width, 4, val1, val2); - gen_bitfield_ins(offset, width, reg, val1, val2); - gen_bitfield_store(s, addr, offset + width, val1, val2); - break; - } - return; + + bitfield_param(ext, &offset, &width, &mask_cc); + + /* adjust src and offset */ + + /* src += offset >> 3; */ + + tmp = tcg_temp_new_i32(); + tcg_gen_shri_i32(tmp, offset, 3); + tcg_gen_add_i32(src, src, tmp); + + /* offset &= 7; */ + + tcg_gen_andi_i32(offset, offset, 7); + + /* load */ + + bitfield = tcg_temp_new_i64(); + gen_helper_bitfield_load(bitfield, src, offset, width); + + /* compute CC and move bitfield into a 32bit */ + + val = gen_bitfield_cc(s, offset, mask_cc, bitfield); + + /* execute operation */ + + reg = DREG(ext, 12); + switch (op) { + case 0: /* bftst */ + break; + case 1: /* bfextu */ + shift = tcg_temp_new_i32(); + tcg_gen_sub_i32(shift, tcg_const_i32(32), width); + tcg_gen_shr_i32(reg, val, shift); + break; + case 2: /* bfchg */ + mask_bitfield = gen_bitfield_mask(offset, width); + tcg_gen_xor_i64(bitfield, bitfield, mask_bitfield); + gen_helper_bitfield_store(src, offset, width, bitfield); + break; + case 3: /* bfexts */ + shift = tcg_temp_new_i32(); + tcg_gen_sub_i32(shift, tcg_const_i32(32), width); + tcg_gen_sar_i32(reg, val, shift); + break; + case 4: /* bfclr */ + mask_bitfield = gen_bitfield_mask(offset, width); + tcg_gen_not_i64(mask_bitfield, mask_bitfield); + tcg_gen_and_i64(bitfield, bitfield, mask_bitfield); + gen_helper_bitfield_store(src, offset, width, bitfield); + break; + case 5: /* bfffo */ + gen_helper_bfffo(val, val, width); + tcg_gen_add_i32(reg, val, offset); + break; + case 6: /* bfset */ + mask_bitfield = gen_bitfield_mask(offset, width); + tcg_gen_or_i64(bitfield, bitfield, mask_bitfield); + gen_helper_bitfield_store(src, offset, width, bitfield); + break; + case 7: /* bfins */ + /* clear */ + mask_bitfield = gen_bitfield_mask(offset, width); + tcg_gen_not_i64(mask_bitfield, mask_bitfield); + tcg_gen_and_i64(bitfield, bitfield, mask_bitfield); + /* insert */ + gen_bitfield_ins(offset, width, reg, bitfield); + gen_helper_bitfield_store(src, offset, width, bitfield); + break; } - /* Not yet implemented */ - gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); } DISAS_INSN(ff1) -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] [PATCH 17/17] m68k: add cas 2009-05-29 22:42 ` [Qemu-devel] [PATCH 16/17] m68k: add variable offset/width to bitfield_reg/bitfield_mem Laurent Vivier @ 2009-05-29 22:42 ` Laurent Vivier 2009-05-30 13:53 ` [Qemu-devel] " Andreas Schwab 0 siblings, 1 reply; 26+ messages in thread From: Laurent Vivier @ 2009-05-29 22:42 UTC (permalink / raw) To: qemu-devel; +Cc: Laurent Vivier This instruction is needed to execute commands like "ls" or "date" (from a debian lenny m68k). It define a new feaure, CAS, and attach this new instruction to it. Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- target-m68k/cpu.h | 3 +- target-m68k/helper.c | 2 + target-m68k/translate.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletions(-) diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index 727a0b1..93956c3 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -209,7 +209,8 @@ enum m68k_features { M68K_FEATURE_QUAD_MULDIV, /* 64 bit multiply/divide. */ M68K_FEATURE_BCCL, /* Long conditional branches. */ M68K_FEATURE_BITFIELD, /* Bit field insns. */ - M68K_FEATURE_FPU + M68K_FEATURE_FPU, + M68K_FEATURE_CAS }; static inline int m68k_feature(CPUM68KState *env, int feature) diff --git a/target-m68k/helper.c b/target-m68k/helper.c index 3ae0366..67e823a 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -162,6 +162,7 @@ static int cpu_m68k_set_model(CPUM68KState *env, const char *name) m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX); m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV); m68k_set_feature(env, M68K_FEATURE_FPU); + m68k_set_feature(env, M68K_FEATURE_CAS); case M68K_CPUID_M68000: m68k_set_feature(env, M68K_FEATURE_M68000); m68k_set_feature(env, M68K_FEATURE_USP); @@ -207,6 +208,7 @@ static int cpu_m68k_set_model(CPUM68KState *env, const char *name) m68k_set_feature(env, M68K_FEATURE_BITFIELD); m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV); m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV); + m68k_set_feature(env, M68K_FEATURE_CAS); break; } diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 4c36b6a..4372975 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -1375,6 +1375,67 @@ DISAS_INSN(arith_im) } } +DISAS_INSN(cas) +{ + int opsize; + TCGv dest; + TCGv tmp; + TCGv cmp; + TCGv update; + TCGv addr; + TCGv res; + uint16_t ext; + int l1, l2; + + if ((insn & 0x3f) == 0x3c) { + /* CAS2: Not yet implemented */ + gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); + } + + switch((insn >> 9) & 3) { + case 1: + opsize = OS_BYTE; + break; + case 2: + opsize = OS_WORD; + break; + case 3: + opsize = OS_LONG; + break; + default: + abort(); + } + + ext = lduw_code(s->pc); + s->pc += 2; + addr = gen_lea(s, insn, opsize); + if (IS_NULL_QREG(addr)) { + gen_addr_fault(s); + return; + } + + cmp = DREG(ext, 0); + update = DREG(ext, 6); + tmp = gen_load(s, opsize, addr, 0); + dest = tcg_temp_local_new(); + tcg_gen_mov_i32(dest, tmp); + + res = tcg_temp_new(); + tcg_gen_sub_i32(res, dest, cmp); + gen_logic_cc(s, res); + + l1 = gen_new_label(); + l2 = gen_new_label(); + + gen_jmpcc(s, 6 /* !Z */, l1); + gen_store(s, opsize, addr, update); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_mov_i32(cmp, dest); + gen_set_label(l2); + tcg_temp_free(dest); +} + DISAS_INSN(byterev) { TCGv reg; @@ -3664,6 +3725,7 @@ void register_m68k_insns (CPUM68KState *env) INSN(bitop_im, 0840, ffc0, M68000); INSN(bitop_im, 0880, ffc0, CF_ISA_A); INSN(bitop_im, 0880, ffc0, M68000); + INSN(cas, 08c0, f9c0, CAS); INSN(bitop_im, 08c0, ffc0, CF_ISA_A); INSN(bitop_im, 08c0, ffc0, M68000); INSN(arith_im, 0a80, fff8, CF_ISA_A); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] Re: [PATCH 17/17] m68k: add cas 2009-05-29 22:42 ` [Qemu-devel] [PATCH 17/17] m68k: add cas Laurent Vivier @ 2009-05-30 13:53 ` Andreas Schwab 2009-05-30 16:53 ` Laurent Vivier 0 siblings, 1 reply; 26+ messages in thread From: Andreas Schwab @ 2009-05-30 13:53 UTC (permalink / raw) To: Laurent Vivier; +Cc: qemu-devel Laurent Vivier <laurent@vivier.eu> writes: > + cmp = DREG(ext, 0); > + update = DREG(ext, 6); > + tmp = gen_load(s, opsize, addr, 0); > + dest = tcg_temp_local_new(); > + tcg_gen_mov_i32(dest, tmp); > + > + res = tcg_temp_new(); > + tcg_gen_sub_i32(res, dest, cmp); > + gen_logic_cc(s, res); > + > + l1 = gen_new_label(); > + l2 = gen_new_label(); > + > + gen_jmpcc(s, 6 /* !Z */, l1); > + gen_store(s, opsize, addr, update); This has a bug: addr is used around a jump. Andreas. --- >From b87bc72daf28f519017c79615b962c47a1e0492d Mon Sep 17 00:00:00 2001 From: Andreas Schwab <schwab@linux-m68k.org> Date: Sat, 30 May 2009 15:32:20 +0200 Subject: [PATCH] m68k: fix use of temporary around jump Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> --- target-m68k/translate.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 4372975..9d68b02 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -1382,6 +1382,7 @@ DISAS_INSN(cas) TCGv tmp; TCGv cmp; TCGv update; + TCGv taddr; TCGv addr; TCGv res; uint16_t ext; @@ -1408,17 +1409,19 @@ DISAS_INSN(cas) ext = lduw_code(s->pc); s->pc += 2; - addr = gen_lea(s, insn, opsize); - if (IS_NULL_QREG(addr)) { + taddr = gen_lea(s, insn, opsize); + if (IS_NULL_QREG(taddr)) { gen_addr_fault(s); return; } cmp = DREG(ext, 0); update = DREG(ext, 6); - tmp = gen_load(s, opsize, addr, 0); + tmp = gen_load(s, opsize, taddr, 0); dest = tcg_temp_local_new(); tcg_gen_mov_i32(dest, tmp); + addr = tcg_temp_local_new (); + tcg_gen_mov_i32(addr, taddr); res = tcg_temp_new(); tcg_gen_sub_i32(res, dest, cmp); @@ -1434,6 +1437,7 @@ DISAS_INSN(cas) tcg_gen_mov_i32(cmp, dest); gen_set_label(l2); tcg_temp_free(dest); + tcg_temp_free(addr); } DISAS_INSN(byterev) -- 1.6.3.1 -- Andreas Schwab, schwab@linux-m68k.org GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different." ^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] Re: [PATCH 17/17] m68k: add cas 2009-05-30 13:53 ` [Qemu-devel] " Andreas Schwab @ 2009-05-30 16:53 ` Laurent Vivier 0 siblings, 0 replies; 26+ messages in thread From: Laurent Vivier @ 2009-05-30 16:53 UTC (permalink / raw) To: Andreas Schwab; +Cc: qemu-devel Le samedi 30 mai 2009 à 15:53 +0200, Andreas Schwab a écrit : > Laurent Vivier <laurent@vivier.eu> writes: > > > + cmp = DREG(ext, 0); > > + update = DREG(ext, 6); > > + tmp = gen_load(s, opsize, addr, 0); > > + dest = tcg_temp_local_new(); > > + tcg_gen_mov_i32(dest, tmp); > > + > > + res = tcg_temp_new(); > > + tcg_gen_sub_i32(res, dest, cmp); > > + gen_logic_cc(s, res); > > + > > + l1 = gen_new_label(); > > + l2 = gen_new_label(); > > + > > + gen_jmpcc(s, 6 /* !Z */, l1); > > + gen_store(s, opsize, addr, update); > > This has a bug: addr is used around a jump. > I agree, thank you. (I didn't read tcg/README correctly...) Laurent ^ permalink raw reply [flat|nested] 26+ messages in thread
* [Qemu-devel] Re: [PATCH 07/17] m68k: add DBcc instruction. 2009-05-29 22:41 ` [Qemu-devel] [PATCH 07/17] m68k: add DBcc instruction Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 08/17] m68k: modify movem instruction to manage word Laurent Vivier @ 2009-05-30 22:00 ` Andreas Schwab 2009-05-30 22:05 ` Laurent Vivier 1 sibling, 1 reply; 26+ messages in thread From: Andreas Schwab @ 2009-05-30 22:00 UTC (permalink / raw) To: Laurent Vivier; +Cc: qemu-devel Laurent Vivier <laurent@vivier.eu> writes: > + tmp = tcg_temp_new(); > + tcg_gen_ext16s_i32(tmp, reg); > + tcg_gen_addi_i32(tmp, tmp, -1); > + gen_partset_reg(OS_WORD, reg, tmp); > + tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); The counter needs to be compared with -1, not 0. Andreas. --- >From 07f10a1b4a4aa4a54468e1106a4bbc28c5ada45e Mon Sep 17 00:00:00 2001 From: Andreas Schwab <schwab@linux-m68k.org> Date: Sat, 30 May 2009 23:52:11 +0200 Subject: [PATCH] m68k: fix decoding of dbcc The counter needs to be compared with -1, not 0. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> --- target-m68k/translate.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 9d68b02..ea6b34b 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -942,7 +942,7 @@ DISAS_INSN(dbcc) tcg_gen_ext16s_i32(tmp, reg); tcg_gen_addi_i32(tmp, tmp, -1); gen_partset_reg(OS_WORD, reg, tmp); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); + tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, -1, l1); gen_jmp_tb(s, 1, base + offset); gen_set_label(l1); gen_jmp_tb(s, 0, s->pc); -- 1.6.3.1 -- Andreas Schwab, schwab@linux-m68k.org GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different." ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Qemu-devel] Re: [PATCH 07/17] m68k: add DBcc instruction. 2009-05-30 22:00 ` [Qemu-devel] Re: [PATCH 07/17] m68k: add DBcc instruction Andreas Schwab @ 2009-05-30 22:05 ` Laurent Vivier 0 siblings, 0 replies; 26+ messages in thread From: Laurent Vivier @ 2009-05-30 22:05 UTC (permalink / raw) To: Andreas Schwab; +Cc: qemu-devel Le dimanche 31 mai 2009 à 00:00 +0200, Andreas Schwab a écrit : > Laurent Vivier <laurent@vivier.eu> writes: > > > + tmp = tcg_temp_new(); > > + tcg_gen_ext16s_i32(tmp, reg); > > + tcg_gen_addi_i32(tmp, tmp, -1); > > + gen_partset_reg(OS_WORD, reg, tmp); > > + tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); > > The counter needs to be compared with -1, not 0. Yes, "ls -l" works better, now. Laurent > Andreas. > --- > From 07f10a1b4a4aa4a54468e1106a4bbc28c5ada45e Mon Sep 17 00:00:00 2001 > From: Andreas Schwab <schwab@linux-m68k.org> > Date: Sat, 30 May 2009 23:52:11 +0200 > Subject: [PATCH] m68k: fix decoding of dbcc > > The counter needs to be compared with -1, not 0. > > Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> > --- > target-m68k/translate.c | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/target-m68k/translate.c b/target-m68k/translate.c > index 9d68b02..ea6b34b 100644 > --- a/target-m68k/translate.c > +++ b/target-m68k/translate.c > @@ -942,7 +942,7 @@ DISAS_INSN(dbcc) > tcg_gen_ext16s_i32(tmp, reg); > tcg_gen_addi_i32(tmp, tmp, -1); > gen_partset_reg(OS_WORD, reg, tmp); > - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); > + tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, -1, l1); > gen_jmp_tb(s, 1, base + offset); > gen_set_label(l1); > gen_jmp_tb(s, 0, s->pc); > -- > 1.6.3.1 > ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions. 2009-05-29 22:41 ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 05/17] m68k: add Motorola 680x0 family common instructions Laurent Vivier @ 2009-05-31 2:06 ` Stuart Brady 2009-05-31 9:03 ` Laurent Vivier 1 sibling, 1 reply; 26+ messages in thread From: Stuart Brady @ 2009-05-31 2:06 UTC (permalink / raw) To: qemu-devel I just happened to notice these: On Sat, May 30, 2009 at 12:41:48AM +0200, Laurent Vivier wrote: > +/* Read a 8-bit immediat constant */ Should be: /* Read an 8-bit immediate constant */ ^ ^ > +/* Read a 16-bit immediat constant */ Should be: /* Read a 16-bit immediate constant */ ^ If I knew more about the M68K, perhaps I'd be of more help... :/ Cheers, -- Stuart Brady ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions. 2009-05-31 2:06 ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Stuart Brady @ 2009-05-31 9:03 ` Laurent Vivier 0 siblings, 0 replies; 26+ messages in thread From: Laurent Vivier @ 2009-05-31 9:03 UTC (permalink / raw) To: Stuart Brady; +Cc: qemu-devel Le dimanche 31 mai 2009 à 03:06 +0100, Stuart Brady a écrit : > I just happened to notice these: > > On Sat, May 30, 2009 at 12:41:48AM +0200, Laurent Vivier wrote: > > +/* Read a 8-bit immediat constant */ > > Should be: > /* Read an 8-bit immediate constant */ > ^ ^ > > > +/* Read a 16-bit immediat constant */ > > Should be: > /* Read a 16-bit immediate constant */ > ^ > > If I knew more about the M68K, perhaps I'd be of more help... :/ Corrected, thank you. Regards, Laurent ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support 2009-05-29 22:41 [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32() Laurent Vivier @ 2009-05-30 17:31 ` François Revol 2009-09-21 2:56 ` Rob Landley 2 siblings, 0 replies; 26+ messages in thread From: François Revol @ 2009-05-30 17:31 UTC (permalink / raw) To: Laurent Vivier; +Cc: qemu-devel > This series of patches is a port to Qemu 0.10 of Andreas Schwab M68K > patch > to support Motorola 680x0 CPU family. Ohh cool, now I just need to add a real system target to test my Haiku port :) François. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support 2009-05-29 22:41 [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32() Laurent Vivier 2009-05-30 17:31 ` [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support François Revol @ 2009-09-21 2:56 ` Rob Landley 2 siblings, 0 replies; 26+ messages in thread From: Rob Landley @ 2009-09-21 2:56 UTC (permalink / raw) To: qemu-devel; +Cc: Till Straumann, Charles Stevens, schwab, Laurent Vivier On Friday 29 May 2009 17:41:44 Laurent Vivier wrote: > This series of patches is a port to Qemu 0.10 of Andreas Schwab M68K patch > to support Motorola 680x0 CPU family. > > It has been tested with some commands from a debian m68k lenny disk. Has there been any progress on this? (Or current versions I can test?) I have a cross compiler, root filesystem, and kernel built for m68k, but no test environment. Charles Stevens got a system image running under aranym, but that has several limitations (such as no serial I/O, which makes a serial console problematic), and I'm testing all my other targets on qemu. All the current system images are coldfire, which I haven't played with because I haven't done any nommu targets yet. Presumably I could shoehorn a real m68k into a coldfire system emulation, assuming I could beat a relevant .config out of the kernel... Rob -- Latency is more important than throughput. It's that simple. - Linus Torvalds ^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2009-09-21 2:56 UTC | newest] Thread overview: 26+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-05-29 22:41 [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32() Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 02/17] m68k: add tcg_gen_debug_insn_start() Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 03/17] m68k: define m680x0 CPUs and features Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 05/17] m68k: add Motorola 680x0 family common instructions Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 06/17] m68k: add Scc instruction with memory operand Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 07/17] m68k: add DBcc instruction Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 08/17] m68k: modify movem instruction to manage word Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 09/17] m68k: add 64bit divide Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 10/17] m68k: add 32bit and 64bit multiply Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 11/17] m68k: add word data size for suba/adda Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 12/17] m68k: add fpu Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 13/17] m68k: add "byte", "word" and memory shift Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 14/17] m68k: add "byte", "word" and memory rotate Laurent Vivier 2009-05-29 22:41 ` [Qemu-devel] [PATCH 15/17] m68k: add bitfield_mem, bitfield_reg Laurent Vivier 2009-05-29 22:42 ` [Qemu-devel] [PATCH 16/17] m68k: add variable offset/width to bitfield_reg/bitfield_mem Laurent Vivier 2009-05-29 22:42 ` [Qemu-devel] [PATCH 17/17] m68k: add cas Laurent Vivier 2009-05-30 13:53 ` [Qemu-devel] " Andreas Schwab 2009-05-30 16:53 ` Laurent Vivier 2009-05-30 22:00 ` [Qemu-devel] Re: [PATCH 07/17] m68k: add DBcc instruction Andreas Schwab 2009-05-30 22:05 ` Laurent Vivier 2009-05-31 2:06 ` [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions Stuart Brady 2009-05-31 9:03 ` Laurent Vivier 2009-05-30 17:31 ` [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support François Revol 2009-09-21 2:56 ` Rob Landley
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).