diff options
author | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-05-29 14:57:59 +0000 |
---|---|---|
committer | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-05-29 14:57:59 +0000 |
commit | acf930aaa3763be08a41f2478b3e0b252f545cd0 (patch) | |
tree | 087d303e39cc7e186a20bfef4842131edef3a1ad | |
parent | 2b8bdefc3a35473e1d43c22e6201aad900dccad2 (diff) |
ColdFire EMAC support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2895 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | cpu-exec.c | 4 | ||||
-rw-r--r-- | target-m68k/cpu.h | 19 | ||||
-rw-r--r-- | target-m68k/helper.c | 38 | ||||
-rw-r--r-- | target-m68k/op.c | 417 | ||||
-rw-r--r-- | target-m68k/qregs.def | 2 | ||||
-rw-r--r-- | target-m68k/translate.c | 286 |
6 files changed, 763 insertions, 3 deletions
diff --git a/cpu-exec.c b/cpu-exec.c index ea18b73ff0..c3d99d4181 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -196,7 +196,9 @@ static inline TranslationBlock *tb_find_fast(void) cs_base = 0; pc = env->PC; #elif defined(TARGET_M68K) - flags = (env->fpcr & M68K_FPCR_PREC) | (env->sr & SR_S); + flags = (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */ + | (env->sr & SR_S) /* Bit 13 */ + | ((env->macsr >> 4) & 0xf); /* Bits 0-3 */ cs_base = 0; pc = env->pc; #elif defined(TARGET_SH4) diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index a81b91dffd..acbb51690d 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -71,6 +71,14 @@ typedef struct CPUM68KState { uint32_t fpsr; float_status fp_status; + uint64_t mactmp; + /* EMAC Hardware deals with 48-bit values composed of one 32-bit and + two 8-bit parts. We store a single 64-bit value and + rearrange/extend this when changing modes. */ + uint64_t macc[4]; + uint32_t macsr; + uint32_t mac_mask; + /* Temporary storage for DIV helpers. */ uint32_t div1; uint32_t div2; @@ -143,11 +151,22 @@ enum { #define SR_S 0x2000 #define SR_T 0x8000 +#define MACSR_PAV0 0x100 +#define MACSR_OMC 0x080 +#define MACSR_SU 0x040 +#define MACSR_FI 0x020 +#define MACSR_RT 0x010 +#define MACSR_N 0x008 +#define MACSR_Z 0x004 +#define MACSR_V 0x002 +#define MACSR_EV 0x001 + typedef struct m68k_def_t m68k_def_t; int cpu_m68k_set_model(CPUM68KState *env, const char * name); void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector); +void m68k_set_macsr(CPUM68KState *env, uint32_t val); #define M68K_FPCR_PREC (1 << 6) diff --git a/target-m68k/helper.c b/target-m68k/helper.c index 12e3f78676..bdbc1de396 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -69,7 +69,6 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name) m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); m68k_set_feature(env, M68K_FEATURE_CF_ISA_C); m68k_set_feature(env, M68K_FEATURE_CF_FPU); - m68k_set_feature(env, M68K_FEATURE_CF_MAC); m68k_set_feature(env, M68K_FEATURE_CF_EMAC); break; case M68K_CPUID_ANY: @@ -77,7 +76,8 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name) m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); m68k_set_feature(env, M68K_FEATURE_CF_ISA_C); m68k_set_feature(env, M68K_FEATURE_CF_FPU); - m68k_set_feature(env, M68K_FEATURE_CF_MAC); + /* MAC and EMAC are mututally exclusive, so pick EMAC. + It's mostly backwards compatible. */ m68k_set_feature(env, M68K_FEATURE_CF_EMAC); m68k_set_feature(env, M68K_FEATURE_EXT_FULL); break; @@ -227,6 +227,40 @@ void helper_movec(CPUM68KState *env, int reg, uint32_t val) } } +void m68k_set_macsr(CPUM68KState *env, uint32_t val) +{ + uint32_t acc; + int8_t exthigh; + uint8_t extlow; + uint64_t regval; + int i; + if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) { + for (i = 0; i < 4; i++) { + regval = env->macc[i]; + exthigh = regval >> 40; + if (env->macsr & MACSR_FI) { + acc = regval >> 8; + extlow = regval; + } else { + acc = regval; + extlow = regval >> 32; + } + if (env->macsr & MACSR_FI) { + regval = (((uint64_t)acc) << 8) | extlow; + regval |= ((int64_t)exthigh) << 40; + } else if (env->macsr & MACSR_SU) { + regval = acc | (((int64_t)extlow) << 32); + regval |= ((int64_t)exthigh) << 40; + } else { + regval = acc | (((uint64_t)extlow) << 32); + regval |= ((uint64_t)(uint8_t)exthigh) << 40; + } + env->macc[i] = regval; + } + } + env->macsr = val; +} + /* MMU */ /* TODO: This will need fixing once the MMU is implemented. */ diff --git a/target-m68k/op.c b/target-m68k/op.c index d483488be8..febfe034c1 100644 --- a/target-m68k/op.c +++ b/target-m68k/op.c @@ -285,6 +285,16 @@ OP(shr_cc) FORCE_RET(); } +OP(sar32) +{ + int32_t op2 = get_op(PARAM2); + uint32_t op3 = get_op(PARAM3); + uint32_t result; + result = op2 >> op3; + set_op(PARAM1, result); + FORCE_RET(); +} + OP(sar_cc) { int32_t op1 = get_op(PARAM1); @@ -651,3 +661,410 @@ OP(movec) #define MEMSUFFIX _kernel #include "op_mem.h" #endif + +/* MAC unit. */ +/* TODO: The MAC instructions use 64-bit arithmetic fairly extensively. + This results in fairly large ops (and sometimes other issues) on 32-bit + hosts. Maybe move most of them into helpers. */ +OP(macmuls) +{ + uint32_t op1 = get_op(PARAM1); + uint32_t op2 = get_op(PARAM2); + int64_t product; + int64_t res; + + product = (uint64_t)op1 * op2; + res = (product << 24) >> 24; + if (res != product) { + env->macsr |= MACSR_V; + if (env->macsr & MACSR_OMC) { + /* Make sure the accumulate operation overflows. */ + if (product < 0) + res = ~(1ll << 50); + else + res = 1ll << 50; + } + } + env->mactmp = res; + FORCE_RET(); +} + +OP(macmulu) +{ + uint32_t op1 = get_op(PARAM1); + uint32_t op2 = get_op(PARAM2); + uint64_t product; + + product = (uint64_t)op1 * op2; + if (product & (0xffffffull << 40)) { + env->macsr |= MACSR_V; + if (env->macsr & MACSR_OMC) { + /* Make sure the accumulate operation overflows. */ + product = 1ll << 50; + } else { + product &= ((1ull << 40) - 1); + } + } + env->mactmp = product; + FORCE_RET(); +} + +OP(macmulf) +{ + int32_t op1 = get_op(PARAM1); + int32_t op2 = get_op(PARAM2); + uint64_t product; + uint32_t remainder; + + product = (uint64_t)op1 * op2; + if (env->macsr & MACSR_RT) { + remainder = product & 0xffffff; + product >>= 24; + if (remainder > 0x800000) + product++; + else if (remainder == 0x800000) + product += (product & 1); + } else { + product >>= 24; + } + env->mactmp = product; + FORCE_RET(); +} + +OP(macshl) +{ + env->mactmp <<= 1; +} + +OP(macshr) +{ + env->mactmp >>= 1; +} + +OP(macadd) +{ + int acc = PARAM1; + env->macc[acc] += env->mactmp; + FORCE_RET(); +} + +OP(macsub) +{ + int acc = PARAM1; + env->macc[acc] -= env->mactmp; + FORCE_RET(); +} + +OP(macsats) +{ + int acc = PARAM1; + int64_t sum; + int64_t result; + + sum = env->macc[acc]; + result = (sum << 16) >> 16; + if (result != sum) { + env->macsr |= MACSR_V; + } + if (env->macsr & MACSR_V) { + env->macsr |= MACSR_PAV0 << acc; + if (env->macsr & MACSR_OMC) { + /* The result is saturated to 32 bits, despite overflow occuring + at 48 bits. Seems weird, but that's what the hardware docs + say. */ + result = (result >> 63) ^ 0x7fffffff; + } + } + env->macc[acc] = result; + FORCE_RET(); +} + +OP(macsatu) +{ + int acc = PARAM1; + uint64_t sum; + + sum = env->macc[acc]; + if (sum & (0xffffull << 48)) { + env->macsr |= MACSR_V; + } + if (env->macsr & MACSR_V) { + env->macsr |= MACSR_PAV0 << acc; + if (env->macsr & MACSR_OMC) { + if (sum > (1ull << 53)) + sum = 0; + else + sum = (1ull << 48) - 1; + } else { + sum &= ((1ull << 48) - 1); + } + } + FORCE_RET(); +} + +OP(macsatf) +{ + int acc = PARAM1; + int64_t sum; + int64_t result; + + sum = env->macc[acc]; + result = (sum << 16) >> 16; + if (result != sum) { + env->macsr |= MACSR_V; + } + if (env->macsr & MACSR_V) { + env->macsr |= MACSR_PAV0 << acc; + if (env->macsr & MACSR_OMC) { + result = (result >> 63) ^ 0x7fffffffffffll; + } + } + env->macc[acc] = result; + FORCE_RET(); +} + +OP(mac_clear_flags) +{ + env->macsr &= ~(MACSR_V | MACSR_Z | MACSR_N | MACSR_EV); +} + +OP(mac_set_flags) +{ + int acc = PARAM1; + uint64_t val; + val = env->macc[acc]; + if (val == 0) + env->macsr |= MACSR_Z; + else if (val & (1ull << 47)); + env->macsr |= MACSR_N; + if (env->macsr & (MACSR_PAV0 << acc)) { + env->macsr |= MACSR_V; + } + if (env->macsr & MACSR_FI) { + val = ((int64_t)val) >> 40; + if (val != 0 && val != -1) + env->macsr |= MACSR_EV; + } else if (env->macsr & MACSR_SU) { + val = ((int64_t)val) >> 32; + if (val != 0 && val != -1) + env->macsr |= MACSR_EV; + } else { + if ((val >> 32) != 0) + env->macsr |= MACSR_EV; + } + FORCE_RET(); +} + +OP(get_macf) +{ + int acc = PARAM2; + int64_t val; + int rem; + uint32_t result; + + val = env->macc[acc]; + if (env->macsr & MACSR_SU) { + /* 16-bit rounding. */ + rem = val & 0xffffff; + val = (val >> 24) & 0xffffu; + if (rem > 0x800000) + val++; + else if (rem == 0x800000) + val += (val & 1); + } else if (env->macsr & MACSR_RT) { + /* 32-bit rounding. */ + rem = val & 0xff; + val >>= 8; + if (rem > 0x80) + val++; + else if (rem == 0x80) + val += (val & 1); + } else { + /* No rounding. */ + val >>= 8; + } + if (env->macsr & MACSR_OMC) { + /* Saturate. */ + if (env->macsr & MACSR_SU) { + if (val != (uint16_t) val) { + result = ((val >> 63) ^ 0x7fff) & 0xffff; + } else { + result = val & 0xffff; + } + } else { + if (val != (uint32_t)val) { + result = ((uint32_t)(val >> 63) & 0x7fffffff); + } else { + result = (uint32_t)val; + } + } + } else { + /* No saturation. */ + if (env->macsr & MACSR_SU) { + result = val & 0xffff; + } else { + result = (uint32_t)val; + } + } + set_op(PARAM1, result); + FORCE_RET(); +} + +OP(get_maci) +{ + int acc = PARAM2; + set_op(PARAM1, (uint32_t)env->macc[acc]); + FORCE_RET(); +} + +OP(get_macs) +{ + int acc = PARAM2; + int64_t val = env->macc[acc]; + uint32_t result; + if (val == (int32_t)val) { + result = (int32_t)val; + } else { + result = (val >> 61) ^ 0x7fffffff; + } + set_op(PARAM1, result); + FORCE_RET(); +} + +OP(get_macu) +{ + int acc = PARAM2; + uint64_t val = env->macc[acc]; + uint32_t result; + if ((val >> 32) == 0) { + result = (uint32_t)val; + } else { + result = 0xffffffffu; + } + set_op(PARAM1, result); + FORCE_RET(); +} + +OP(clear_mac) +{ + int acc = PARAM1; + + env->macc[acc] = 0; + env->macsr &= ~(MACSR_PAV0 << acc); + FORCE_RET(); +} + +OP(move_mac) +{ + int dest = PARAM1; + int src = PARAM2; + uint32_t mask; + env->macc[dest] = env->macc[src]; + mask = MACSR_PAV0 << dest; + if (env->macsr & (MACSR_PAV0 << src)) + env->macsr |= mask; + else + env->macsr &= ~mask; + FORCE_RET(); +} + +OP(get_mac_extf) +{ + uint32_t val; + int acc = PARAM2; + val = env->macc[acc] & 0x00ff; + val = (env->macc[acc] >> 32) & 0xff00; + val |= (env->macc[acc + 1] << 16) & 0x00ff0000; + val |= (env->macc[acc + 1] >> 16) & 0xff000000; + set_op(PARAM1, val); + FORCE_RET(); +} + +OP(get_mac_exti) +{ + uint32_t val; + int acc = PARAM2; + val = (env->macc[acc] >> 32) & 0xffff; + val |= (env->macc[acc + 1] >> 16) & 0xffff0000; + set_op(PARAM1, val); + FORCE_RET(); +} + +OP(set_macf) +{ + int acc = PARAM2; + int32_t val = get_op(PARAM1); + env->macc[acc] = ((int64_t)val) << 8; + env->macsr &= ~(MACSR_PAV0 << acc); + FORCE_RET(); +} + +OP(set_macs) +{ + int acc = PARAM2; + int32_t val = get_op(PARAM1); + env->macc[acc] = val; + env->macsr &= ~(MACSR_PAV0 << acc); + FORCE_RET(); +} + +OP(set_macu) +{ + int acc = PARAM2; + uint32_t val = get_op(PARAM1); + env->macc[acc] = val; + env->macsr &= ~(MACSR_PAV0 << acc); + FORCE_RET(); +} + +OP(set_mac_extf) +{ + int acc = PARAM2; + int32_t val = get_op(PARAM1); + int64_t res; + int32_t tmp; + res = env->macc[acc] & 0xffffffff00ull; + tmp = (int16_t)(val & 0xff00); + res |= ((int64_t)tmp) << 32; + res |= val & 0xff; + env->macc[acc] = res; + res = env->macc[acc + 1] & 0xffffffff00ull; + tmp = (val & 0xff000000); + res |= ((int64_t)tmp) << 16; + res |= (val >> 16) & 0xff; + env->macc[acc + 1] = res; +} + +OP(set_mac_exts) +{ + int acc = PARAM2; + int32_t val = get_op(PARAM1); + int64_t res; + int32_t tmp; + res = (uint32_t)env->macc[acc]; + tmp = (int16_t)val; + res |= ((int64_t)tmp) << 32; + env->macc[acc] = res; + res = (uint32_t)env->macc[acc + 1]; + tmp = val & 0xffff0000; + res |= (int64_t)tmp << 16; + env->macc[acc + 1] = res; +} + +OP(set_mac_extu) +{ + int acc = PARAM2; + int32_t val = get_op(PARAM1); + uint64_t res; + res = (uint32_t)env->macc[acc]; + res |= ((uint64_t)(val & 0xffff)) << 32; + env->macc[acc] = res; + res = (uint32_t)env->macc[acc + 1]; + res |= (uint64_t)(val & 0xffff0000) << 16; + env->macc[acc + 1] = res; +} + +OP(set_macsr) +{ + m68k_set_macsr(env, get_op(PARAM1)); +} diff --git a/target-m68k/qregs.def b/target-m68k/qregs.def index 08e7e85156..bf568a5147 100644 --- a/target-m68k/qregs.def +++ b/target-m68k/qregs.def @@ -33,3 +33,5 @@ DEFO32(CC_X, cc_x) DEFO32(DIV1, div1) DEFO32(DIV2, div2) DEFO32(EXCEPTION, exception_index) +DEFO32(MACSR, macsr) +DEFO32(MAC_MASK, mac_mask) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 7c91760278..1d32e8f0f7 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2433,6 +2433,279 @@ DISAS_INSN(fsave) qemu_assert(0, "FSAVE not implemented"); } +static inline int gen_mac_extract_word(DisasContext *s, int val, int upper) +{ + int tmp = gen_new_qreg(QMODE_I32); + if (s->env->macsr & MACSR_FI) { + if (upper) + gen_op_and32(tmp, val, gen_im32(0xffff0000)); + else + gen_op_shl32(tmp, val, gen_im32(16)); + } else if (s->env->macsr & MACSR_SU) { + if (upper) + gen_op_sar32(tmp, val, gen_im32(16)); + else + gen_op_ext16s32(tmp, val); + } else { + if (upper) + gen_op_shr32(tmp, val, gen_im32(16)); + else + gen_op_ext16u32(tmp, val); + } + return tmp; +} + +DISAS_INSN(mac) +{ + int rx; + int ry; + uint16_t ext; + int acc; + int l1; + int tmp; + int addr; + int loadval; + int dual; + int saved_flags = -1; + + ext = lduw_code(s->pc); + s->pc += 2; + + acc = ((insn >> 7) & 1) | ((ext >> 3) & 2); + dual = ((insn & 0x30) != 0 && (ext & 3) != 0); + if (insn & 0x30) { + /* MAC with load. */ + tmp = gen_lea(s, insn, OS_LONG); + addr = gen_new_qreg(QMODE_I32); + gen_op_and32(addr, tmp, QREG_MAC_MASK); + /* Load the value now to ensure correct exception behavior. + Perform writeback after reading the MAC inputs. */ + loadval = gen_load(s, OS_LONG, addr, 0); + + acc ^= 1; + rx = (ext & 0x8000) ? AREG(ext, 12) : DREG(insn, 12); + ry = (ext & 8) ? AREG(ext, 0) : DREG(ext, 0); + } else { + loadval = addr = -1; + rx = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9); + ry = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0); + } + + gen_op_mac_clear_flags(); + l1 = -1; + if ((s->env->macsr & MACSR_OMC) != 0 && !dual) { + /* Skip the multiply if we know we will ignore it. */ + l1 = gen_new_label(); + tmp = gen_new_qreg(QMODE_I32); + gen_op_and32(tmp, QREG_MACSR, gen_im32(1 << (acc + 8))); + gen_op_jmp_nz32(tmp, l1); + } + + if ((ext & 0x0800) == 0) { + /* Word. */ + rx = gen_mac_extract_word(s, rx, (ext & 0x80) != 0); + ry = gen_mac_extract_word(s, ry, (ext & 0x40) != 0); + } + if (s->env->macsr & MACSR_FI) { + gen_op_macmulf(rx, ry); + } else { + if (s->env->macsr & MACSR_SU) + gen_op_macmuls(rx, ry); + else + gen_op_macmulu(rx, ry); + switch ((ext >> 9) & 3) { + case 1: + gen_op_macshl(); + break; + case 3: + gen_op_macshr(); + break; + } + } + + if (dual) { + /* Save the overflow flag from the multiply. */ + saved_flags = gen_new_qreg(QMODE_I32); + gen_op_mov32(saved_flags, QREG_MACSR); + } + + if ((s->env->macsr & MACSR_OMC) != 0 && dual) { + /* Skip the accumulate if the value is already saturated. */ + l1 = gen_new_label(); + tmp = gen_new_qreg(QMODE_I32); + gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc)); + gen_op_jmp_nz32(tmp, l1); + } + + if (insn & 0x100) + gen_op_macsub(acc); + else + gen_op_macadd(acc); + + if (s->env->macsr & MACSR_FI) + gen_op_macsatf(acc); + else if (s->env->macsr & MACSR_SU) + gen_op_macsats(acc); + else + gen_op_macsatu(acc); + + if (l1 != -1) + gen_set_label(l1); + + if (dual) { + /* Dual accumulate variant. */ + acc = (ext >> 2) & 3; + /* Restore the overflow flag from the multiplier. */ + gen_op_mov32(QREG_MACSR, saved_flags); + if ((s->env->macsr & MACSR_OMC) != 0) { + /* Skip the accumulate if the value is already saturated. */ + l1 = gen_new_label(); + tmp = gen_new_qreg(QMODE_I32); + gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc)); + gen_op_jmp_nz32(tmp, l1); + } + if (ext & 2) + gen_op_macsub(acc); + else + gen_op_macadd(acc); + if (s->env->macsr & MACSR_FI) + gen_op_macsatf(acc); + else if (s->env->macsr & MACSR_SU) + gen_op_macsats(acc); + else + gen_op_macsatu(acc); + if (l1 != -1) + gen_set_label(l1); + } + gen_op_mac_set_flags(acc); + + if (insn & 0x30) { + int rw; + rw = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9); + gen_op_mov32(rw, loadval); + /* FIXME: Should address writeback happen with the masked or + unmasked value? */ + switch ((insn >> 3) & 7) { + case 3: /* Post-increment. */ + gen_op_add32(AREG(insn, 0), addr, gen_im32(4)); + break; + case 4: /* Pre-decrement. */ + gen_op_mov32(AREG(insn, 0), addr); + } + } +} + +DISAS_INSN(from_mac) +{ + int rx; + int acc; + + rx = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0); + acc = (insn >> 9) & 3; + if (s->env->macsr & MACSR_FI) { + gen_op_get_macf(rx, acc); + } else if ((s->env->macsr & MACSR_OMC) == 0) { + gen_op_get_maci(rx, acc); + } else if (s->env->macsr & MACSR_SU) { + gen_op_get_macs(rx, acc); + } else { + gen_op_get_macu(rx, acc); + } + if (insn & 0x40) + gen_op_clear_mac(acc); +} + +DISAS_INSN(move_mac) +{ + int src; + int dest; + src = insn & 3; + dest = (insn >> 9) & 3; + gen_op_move_mac(dest, src); + gen_op_mac_clear_flags(); + gen_op_mac_set_flags(dest); +} + +DISAS_INSN(from_macsr) +{ + int reg; + + reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0); + gen_op_mov32(reg, QREG_MACSR); +} + +DISAS_INSN(from_mask) +{ + int reg; + reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0); + gen_op_mov32(reg, QREG_MAC_MASK); +} + +DISAS_INSN(from_mext) +{ + int reg; + int acc; + reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0); + acc = (insn & 0x400) ? 2 : 0; + if (s->env->macsr & MACSR_FI) + gen_op_get_mac_extf(reg, acc); + else + gen_op_get_mac_exti(reg, acc); +} + +DISAS_INSN(macsr_to_ccr) +{ + gen_op_mov32(QREG_CC_X, gen_im32(0)); + gen_op_and32(QREG_CC_DEST, QREG_MACSR, gen_im32(0xf)); + s->cc_op = CC_OP_FLAGS; +} + +DISAS_INSN(to_mac) +{ + int acc; + int val; + acc = (insn >>9) & 3; + SRC_EA(val, OS_LONG, 0, NULL); + if (s->env->macsr & MACSR_FI) { + gen_op_set_macf(val, acc); + } else if (s->env->macsr & MACSR_SU) { + gen_op_set_macs(val, acc); + } else { + gen_op_set_macu(val, acc); + } + gen_op_mac_clear_flags(); + gen_op_mac_set_flags(acc); +} + +DISAS_INSN(to_macsr) +{ + int val; + SRC_EA(val, OS_LONG, 0, NULL); + gen_op_set_macsr(val); + gen_lookup_tb(s); +} + +DISAS_INSN(to_mask) +{ + int val; + SRC_EA(val, OS_LONG, 0, NULL); + gen_op_or32(QREG_MAC_MASK, val, gen_im32(0xffff0000)); +} + +DISAS_INSN(to_mext) +{ + int val; + int acc; + SRC_EA(val, OS_LONG, 0, NULL); + acc = (insn & 0x400) ? 2 : 0; + if (s->env->macsr & MACSR_FI) + gen_op_set_mac_extf(val, acc); + else if (s->env->macsr & MACSR_SU) + gen_op_set_mac_exts(val, acc); + else + gen_op_set_mac_extu(val, acc); +} + static disas_proc opcode_table[65536]; static void @@ -2545,7 +2818,20 @@ void register_m68k_insns (CPUM68KState *env) INSN(addsub, 9000, f000, CF_ISA_A); INSN(subx, 9180, f1f8, CF_ISA_A); INSN(suba, 91c0, f1c0, CF_ISA_A); + INSN(undef_mac, a000, f000, CF_ISA_A); + INSN(mac, a000, f100, CF_EMAC); + INSN(from_mac, a180, f9b0, CF_EMAC); + INSN(move_mac, a110, f9fc, CF_EMAC); + INSN(from_macsr,a980, f9f0, CF_EMAC); + INSN(from_mask, ad80, fff0, CF_EMAC); + INSN(from_mext, ab80, fbf0, CF_EMAC); + INSN(macsr_to_ccr, a9c0, ffff, CF_EMAC); + INSN(to_mac, a100, f9c0, CF_EMAC); + INSN(to_macsr, a900, ffc0, CF_EMAC); + INSN(to_mext, ab00, fbc0, CF_EMAC); + INSN(to_mask, ad00, ffc0, CF_EMAC); + INSN(mov3q, a140, f1c0, CF_ISA_B); INSN(cmp, b000, f1c0, CF_ISA_B); /* cmp.b */ INSN(cmp, b040, f1c0, CF_ISA_B); /* cmp.w */ |