-----BEGIN PGP SIGNATURE-----
iQIcBAABAgAGBQJaTlhMAAoJEPMMOL0/L748xsMQAIcRxsab41rsDuTVE3LU9OlW DKVO8O8gqG/l2QlFVAHphg5/w1d1CqTVQE5pFu6qf+/O1V2mcO95g9ZaIRQ2Rt/C blstw+D6xxxqaBe3EFnbuWUGrfdp6Mc8rfR/HtG8J5quNucMX/IpnKVSYxDqql6m gCDwT/N9hGMfEIW+QdcTh3tSpT4D1fWyJSbWWpM02necmAvg+mSvcJ8qQ8uYVyA5 Yc0OjSMZix9SFTn/QSKeh2+ofv+0HpauOLIGBcZ44xw0N40NiRhMFDITwyuv/rY6 tA8cQFw2OhwX7J9tbW4h4Jq8zyFjlarZfHFAij+X0mC2Id58KZaCcsCLlOhbR3x9 EA6Rtd9UKLHlrQfSLuB/bcJ3LgjxkiEjoooBHeFYofqhcW5A3Uk5FxxnMO5kYodZ yWOLZ3r7i9mzDHPECfNvKRIyC0IWp+hsZqC9UQt51/vupwAMq1EGYOJ2HBBpa0PS QSIAQX2XhKj/0yCAXM4nTKqAE9h6UKHNNmYoxJvPUsF7/Bobahr3sDZAepuuGADP b4l95pZ/Gjqm5d8S9I/A6zIm5vV8Fp0BMozhigNQ4e9yGpKapyOYZPiIgNb8wj0L /6Pqq9zoD8jbszg2H9/0kPTt57NjSMgqgHNRWfvvY8zL2LkvGxzpLmOe80BQcjYe CxWyb6Y53IWR6F3CXpnj =42iq -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/vivier/tags/m68k-for-2.12-pull-request' into staging # gpg: Signature made Thu 04 Jan 2018 16:37:32 GMT # gpg: using RSA key 0xF30C38BD3F2FBE3C # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" # gpg: aka "Laurent Vivier <laurent@vivier.eu>" # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier/tags/m68k-for-2.12-pull-request: target/m68k: fix m68k_cpu_dump_state() target/m68k: add the Interrupt Stack Pointer target/m68k: add andi/ori/eori to SR/CCR target/m68k: add 680x0 "move to SR" instruction target/m68k: move CCR/SR functions target/m68k: implement fsave/frestore target/m68k: add reset target/m68k: add cpush/cinv target/m68k: softmmu cleanup target/m68k: add move16 target/m68k: add chk and chk2 target/m68k: manage 680x0 stack frames target/m68k: add CPU_LOG_INT trace target/m68k: use insn_pc to generate instruction fault address linux-user, m68k: correctly manage SR in context target/m68k: fix gen_get_ccr() target-m68k: sync CC_OP before gen_jmp_tb() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
232e5537e4
@ -2985,6 +2985,13 @@ void cpu_loop(CPUM68KState *env)
|
||||
info._sifields._sigfault._addr = env->pc;
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
break;
|
||||
case EXCP_CHK:
|
||||
info.si_signo = TARGET_SIGFPE;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_FPE_INTOVF;
|
||||
info._sifields._sigfault._addr = env->pc;
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
break;
|
||||
case EXCP_DIV0:
|
||||
info.si_signo = TARGET_SIGFPE;
|
||||
info.si_errno = 0;
|
||||
|
@ -5612,13 +5612,14 @@ struct target_rt_sigframe
|
||||
static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
|
||||
abi_ulong mask)
|
||||
{
|
||||
uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
|
||||
__put_user(mask, &sc->sc_mask);
|
||||
__put_user(env->aregs[7], &sc->sc_usp);
|
||||
__put_user(env->dregs[0], &sc->sc_d0);
|
||||
__put_user(env->dregs[1], &sc->sc_d1);
|
||||
__put_user(env->aregs[0], &sc->sc_a0);
|
||||
__put_user(env->aregs[1], &sc->sc_a1);
|
||||
__put_user(env->sr, &sc->sc_sr);
|
||||
__put_user(sr, &sc->sc_sr);
|
||||
__put_user(env->pc, &sc->sc_pc);
|
||||
}
|
||||
|
||||
@ -5634,7 +5635,7 @@ restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
|
||||
__get_user(env->aregs[1], &sc->sc_a1);
|
||||
__get_user(env->pc, &sc->sc_pc);
|
||||
__get_user(temp, &sc->sc_sr);
|
||||
env->sr = (env->sr & 0xff00) | (temp & 0xff);
|
||||
cpu_m68k_set_ccr(env, temp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5726,7 +5727,7 @@ static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
|
||||
CPUM68KState *env)
|
||||
{
|
||||
target_greg_t *gregs = uc->tuc_mcontext.gregs;
|
||||
uint32_t sr = cpu_m68k_get_ccr(env);
|
||||
uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
|
||||
|
||||
__put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
|
||||
__put_user(env->dregs[0], &gregs[0]);
|
||||
|
@ -55,17 +55,17 @@ static void m68k_cpu_reset(CPUState *s)
|
||||
mcc->parent_reset(s);
|
||||
|
||||
memset(env, 0, offsetof(CPUM68KState, end_reset_fields));
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
env->sr = 0x2700;
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
cpu_m68k_set_sr(env, SR_S | SR_I);
|
||||
#else
|
||||
cpu_m68k_set_sr(env, 0);
|
||||
#endif
|
||||
m68k_switch_sp(env);
|
||||
for (i = 0; i < 8; i++) {
|
||||
env->fregs[i].d = nan;
|
||||
}
|
||||
cpu_m68k_set_fpcr(env, 0);
|
||||
env->fpsr = 0;
|
||||
|
||||
cpu_m68k_set_ccr(env, 0);
|
||||
/* TODO: We should set PC from the interrupt vector. */
|
||||
env->pc = 0;
|
||||
}
|
||||
@ -134,9 +134,18 @@ static void m68020_cpu_initfn(Object *obj)
|
||||
m68k_set_feature(env, M68K_FEATURE_CAS);
|
||||
m68k_set_feature(env, M68K_FEATURE_BKPT);
|
||||
m68k_set_feature(env, M68K_FEATURE_RTD);
|
||||
m68k_set_feature(env, M68K_FEATURE_CHK2);
|
||||
}
|
||||
#define m68030_cpu_initfn m68020_cpu_initfn
|
||||
#define m68040_cpu_initfn m68020_cpu_initfn
|
||||
|
||||
static void m68040_cpu_initfn(Object *obj)
|
||||
{
|
||||
M68kCPU *cpu = M68K_CPU(obj);
|
||||
CPUM68KState *env = &cpu->env;
|
||||
|
||||
m68020_cpu_initfn(obj);
|
||||
m68k_set_feature(env, M68K_FEATURE_M68040);
|
||||
}
|
||||
|
||||
static void m68060_cpu_initfn(Object *obj)
|
||||
{
|
||||
@ -156,6 +165,7 @@ static void m68060_cpu_initfn(Object *obj)
|
||||
m68k_set_feature(env, M68K_FEATURE_CAS);
|
||||
m68k_set_feature(env, M68K_FEATURE_BKPT);
|
||||
m68k_set_feature(env, M68K_FEATURE_RTD);
|
||||
m68k_set_feature(env, M68K_FEATURE_CHK2);
|
||||
}
|
||||
|
||||
static void m5208_cpu_initfn(Object *obj)
|
||||
|
@ -45,6 +45,8 @@
|
||||
#define EXCP_ADDRESS 3 /* Address error. */
|
||||
#define EXCP_ILLEGAL 4 /* Illegal instruction. */
|
||||
#define EXCP_DIV0 5 /* Divide by zero */
|
||||
#define EXCP_CHK 6 /* CHK, CHK2 Instructions */
|
||||
#define EXCP_TRAPCC 7 /* FTRAPcc, TRAPcc, TRAPV Instructions */
|
||||
#define EXCP_PRIVILEGE 8 /* Privilege violation. */
|
||||
#define EXCP_TRACE 9
|
||||
#define EXCP_LINEA 10 /* Unimplemented line-A (MAC) opcode. */
|
||||
@ -53,6 +55,9 @@
|
||||
#define EXCP_DEBEGBP 13 /* Breakpoint debug interrupt. */
|
||||
#define EXCP_FORMAT 14 /* RTE format error. */
|
||||
#define EXCP_UNINITIALIZED 15
|
||||
#define EXCP_SPURIOUS 24 /* Spurious interrupt */
|
||||
#define EXCP_INT_LEVEL_1 25 /* Level 1 Interrupt autovector */
|
||||
#define EXCP_INT_LEVEL_7 31 /* Level 7 Interrupt autovector */
|
||||
#define EXCP_TRAP0 32 /* User trap #0. */
|
||||
#define EXCP_TRAP15 47 /* User trap #15. */
|
||||
#define EXCP_FP_BSUN 48 /* Branch Set on Unordered */
|
||||
@ -63,6 +68,9 @@
|
||||
#define EXCP_FP_OVFL 53 /* Overflow */
|
||||
#define EXCP_FP_SNAN 54 /* Signaling Not-A-Number */
|
||||
#define EXCP_FP_UNIMP 55 /* Unimplemented Data type */
|
||||
#define EXCP_MMU_CONF 56 /* MMU Configuration Error */
|
||||
#define EXCP_MMU_ILLEGAL 57 /* MMU Illegal Operation Error */
|
||||
#define EXCP_MMU_ACCESS 58 /* MMU Access Level Violation Error */
|
||||
#define EXCP_UNSUPPORTED 61
|
||||
|
||||
#define EXCP_RTE 0x100
|
||||
@ -81,7 +89,7 @@ typedef struct CPUM68KState {
|
||||
|
||||
/* SSP and USP. The current_sp is stored in aregs[7], the other here. */
|
||||
int current_sp;
|
||||
uint32_t sp[2];
|
||||
uint32_t sp[3];
|
||||
|
||||
/* Condition flags. */
|
||||
uint32_t cc_op;
|
||||
@ -170,6 +178,7 @@ int cpu_m68k_signal_handler(int host_signum, void *pinfo,
|
||||
void *puc);
|
||||
uint32_t cpu_m68k_get_ccr(CPUM68KState *env);
|
||||
void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t);
|
||||
void cpu_m68k_set_sr(CPUM68KState *env, uint32_t);
|
||||
void cpu_m68k_set_fpcr(CPUM68KState *env, uint32_t val);
|
||||
|
||||
|
||||
@ -210,10 +219,79 @@ typedef enum {
|
||||
#define SR_I 0x0700
|
||||
#define SR_M 0x1000
|
||||
#define SR_S 0x2000
|
||||
#define SR_T 0x8000
|
||||
#define SR_T_SHIFT 14
|
||||
#define SR_T 0xc000
|
||||
|
||||
#define M68K_SSP 0
|
||||
#define M68K_USP 1
|
||||
#define M68K_ISP 2
|
||||
|
||||
/* m68k Control Registers */
|
||||
|
||||
/* ColdFire */
|
||||
/* Memory Management Control Registers */
|
||||
#define M68K_CR_ASID 0x003
|
||||
#define M68K_CR_ACR0 0x004
|
||||
#define M68K_CR_ACR1 0x005
|
||||
#define M68K_CR_ACR2 0x006
|
||||
#define M68K_CR_ACR3 0x007
|
||||
#define M68K_CR_MMUBAR 0x008
|
||||
|
||||
/* Processor Miscellaneous Registers */
|
||||
#define M68K_CR_PC 0x80F
|
||||
|
||||
/* Local Memory and Module Control Registers */
|
||||
#define M68K_CR_ROMBAR0 0xC00
|
||||
#define M68K_CR_ROMBAR1 0xC01
|
||||
#define M68K_CR_RAMBAR0 0xC04
|
||||
#define M68K_CR_RAMBAR1 0xC05
|
||||
#define M68K_CR_MPCR 0xC0C
|
||||
#define M68K_CR_EDRAMBAR 0xC0D
|
||||
#define M68K_CR_SECMBAR 0xC0E
|
||||
#define M68K_CR_MBAR 0xC0F
|
||||
|
||||
/* Local Memory Address Permutation Control Registers */
|
||||
#define M68K_CR_PCR1U0 0xD02
|
||||
#define M68K_CR_PCR1L0 0xD03
|
||||
#define M68K_CR_PCR2U0 0xD04
|
||||
#define M68K_CR_PCR2L0 0xD05
|
||||
#define M68K_CR_PCR3U0 0xD06
|
||||
#define M68K_CR_PCR3L0 0xD07
|
||||
#define M68K_CR_PCR1U1 0xD0A
|
||||
#define M68K_CR_PCR1L1 0xD0B
|
||||
#define M68K_CR_PCR2U1 0xD0C
|
||||
#define M68K_CR_PCR2L1 0xD0D
|
||||
#define M68K_CR_PCR3U1 0xD0E
|
||||
#define M68K_CR_PCR3L1 0xD0F
|
||||
|
||||
/* MC680x0 */
|
||||
/* MC680[1234]0/CPU32 */
|
||||
#define M68K_CR_SFC 0x000
|
||||
#define M68K_CR_DFC 0x001
|
||||
#define M68K_CR_USP 0x800
|
||||
#define M68K_CR_VBR 0x801 /* + Coldfire */
|
||||
|
||||
/* MC680[234]0 */
|
||||
#define M68K_CR_CACR 0x002 /* + Coldfire */
|
||||
#define M68K_CR_CAAR 0x802 /* MC68020 and MC68030 only */
|
||||
#define M68K_CR_MSP 0x803
|
||||
#define M68K_CR_ISP 0x804
|
||||
|
||||
/* MC68040/MC68LC040 */
|
||||
#define M68K_CR_TC 0x003
|
||||
#define M68K_CR_ITT0 0x004
|
||||
#define M68K_CR_ITT1 0x005
|
||||
#define M68K_CR_DTT0 0x006
|
||||
#define M68K_CR_DTT1 0x007
|
||||
#define M68K_CR_MMUSR 0x805
|
||||
#define M68K_CR_URP 0x806
|
||||
#define M68K_CR_SRP 0x807
|
||||
|
||||
/* MC68EC040 */
|
||||
#define M68K_CR_IACR0 0x004
|
||||
#define M68K_CR_IACR1 0x005
|
||||
#define M68K_CR_DACR0 0x006
|
||||
#define M68K_CR_DACR1 0x007
|
||||
|
||||
#define M68K_FPIAR_SHIFT 0
|
||||
#define M68K_FPIAR (1 << M68K_FPIAR_SHIFT)
|
||||
@ -296,6 +374,8 @@ enum m68k_features {
|
||||
M68K_FEATURE_CAS,
|
||||
M68K_FEATURE_BKPT,
|
||||
M68K_FEATURE_RTD,
|
||||
M68K_FEATURE_CHK2,
|
||||
M68K_FEATURE_M68040, /* instructions specific to MC68040 */
|
||||
};
|
||||
|
||||
static inline int m68k_feature(CPUM68KState *env, int feature)
|
||||
|
@ -63,7 +63,7 @@ int m68k_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
} else {
|
||||
switch (n) {
|
||||
case 16:
|
||||
env->sr = tmp;
|
||||
cpu_m68k_set_sr(env, tmp);
|
||||
break;
|
||||
case 17:
|
||||
env->pc = tmp;
|
||||
|
@ -171,28 +171,84 @@ void m68k_cpu_init_gdb(M68kCPU *cpu)
|
||||
/* TODO: Add [E]MAC registers. */
|
||||
}
|
||||
|
||||
void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
|
||||
void HELPER(cf_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
|
||||
{
|
||||
M68kCPU *cpu = m68k_env_get_cpu(env);
|
||||
|
||||
switch (reg) {
|
||||
case 0x02: /* CACR */
|
||||
case M68K_CR_CACR:
|
||||
env->cacr = val;
|
||||
m68k_switch_sp(env);
|
||||
break;
|
||||
case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
|
||||
case M68K_CR_ACR0:
|
||||
case M68K_CR_ACR1:
|
||||
case M68K_CR_ACR2:
|
||||
case M68K_CR_ACR3:
|
||||
/* TODO: Implement Access Control Registers. */
|
||||
break;
|
||||
case 0x801: /* VBR */
|
||||
case M68K_CR_VBR:
|
||||
env->vbr = val;
|
||||
break;
|
||||
/* TODO: Implement control registers. */
|
||||
default:
|
||||
cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
|
||||
cpu_abort(CPU(cpu),
|
||||
"Unimplemented control register write 0x%x = 0x%x\n",
|
||||
reg, val);
|
||||
}
|
||||
}
|
||||
|
||||
void HELPER(m68k_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
|
||||
{
|
||||
M68kCPU *cpu = m68k_env_get_cpu(env);
|
||||
|
||||
switch (reg) {
|
||||
/* MC680[1234]0 */
|
||||
case M68K_CR_VBR:
|
||||
env->vbr = val;
|
||||
return;
|
||||
/* MC680[234]0 */
|
||||
case M68K_CR_CACR:
|
||||
env->cacr = val;
|
||||
m68k_switch_sp(env);
|
||||
return;
|
||||
/* MC680[34]0 */
|
||||
case M68K_CR_USP:
|
||||
env->sp[M68K_USP] = val;
|
||||
return;
|
||||
case M68K_CR_MSP:
|
||||
env->sp[M68K_SSP] = val;
|
||||
return;
|
||||
case M68K_CR_ISP:
|
||||
env->sp[M68K_ISP] = val;
|
||||
return;
|
||||
}
|
||||
cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
|
||||
reg, val);
|
||||
}
|
||||
|
||||
uint32_t HELPER(m68k_movec_from)(CPUM68KState *env, uint32_t reg)
|
||||
{
|
||||
M68kCPU *cpu = m68k_env_get_cpu(env);
|
||||
|
||||
switch (reg) {
|
||||
/* MC680[1234]0 */
|
||||
case M68K_CR_VBR:
|
||||
return env->vbr;
|
||||
/* MC680[234]0 */
|
||||
case M68K_CR_CACR:
|
||||
return env->cacr;
|
||||
/* MC680[34]0 */
|
||||
case M68K_CR_USP:
|
||||
return env->sp[M68K_USP];
|
||||
case M68K_CR_MSP:
|
||||
return env->sp[M68K_SSP];
|
||||
case M68K_CR_ISP:
|
||||
return env->sp[M68K_ISP];
|
||||
}
|
||||
cpu_abort(CPU(cpu), "Unimplemented control register read 0x%x\n",
|
||||
reg);
|
||||
}
|
||||
|
||||
void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
|
||||
{
|
||||
uint32_t acc;
|
||||
@ -232,8 +288,20 @@ void m68k_switch_sp(CPUM68KState *env)
|
||||
int new_sp;
|
||||
|
||||
env->sp[env->current_sp] = env->aregs[7];
|
||||
new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
|
||||
? M68K_SSP : M68K_USP;
|
||||
if (m68k_feature(env, M68K_FEATURE_M68000)) {
|
||||
if (env->sr & SR_S) {
|
||||
if (env->sr & SR_M) {
|
||||
new_sp = M68K_SSP;
|
||||
} else {
|
||||
new_sp = M68K_ISP;
|
||||
}
|
||||
} else {
|
||||
new_sp = M68K_USP;
|
||||
}
|
||||
} else {
|
||||
new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
|
||||
? M68K_SSP : M68K_USP;
|
||||
}
|
||||
env->aregs[7] = env->sp[new_sp];
|
||||
env->current_sp = new_sp;
|
||||
}
|
||||
@ -316,13 +384,17 @@ uint32_t HELPER(sats)(uint32_t val, uint32_t v)
|
||||
return val;
|
||||
}
|
||||
|
||||
void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
|
||||
void cpu_m68k_set_sr(CPUM68KState *env, uint32_t sr)
|
||||
{
|
||||
env->sr = val & 0xffe0;
|
||||
cpu_m68k_set_ccr(env, val);
|
||||
env->sr = sr & 0xffe0;
|
||||
cpu_m68k_set_ccr(env, sr);
|
||||
m68k_switch_sp(env);
|
||||
}
|
||||
|
||||
void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
|
||||
{
|
||||
cpu_m68k_set_sr(env, val);
|
||||
}
|
||||
|
||||
/* MAC unit. */
|
||||
/* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
|
||||
@ -707,3 +779,10 @@ void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
|
||||
res |= (uint64_t)(val & 0xffff0000) << 16;
|
||||
env->macc[acc + 1] = res;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
void HELPER(reset)(CPUM68KState *env)
|
||||
{
|
||||
/* FIXME: reset all except CPU */
|
||||
}
|
||||
#endif
|
||||
|
@ -8,7 +8,9 @@ DEF_HELPER_4(divsl, void, env, int, int, s32)
|
||||
DEF_HELPER_4(divull, void, env, int, int, i32)
|
||||
DEF_HELPER_4(divsll, void, env, int, int, s32)
|
||||
DEF_HELPER_2(set_sr, void, env, i32)
|
||||
DEF_HELPER_3(movec, void, env, i32, i32)
|
||||
DEF_HELPER_3(cf_movec_to, void, env, i32, i32)
|
||||
DEF_HELPER_3(m68k_movec_to, void, env, i32, i32)
|
||||
DEF_HELPER_2(m68k_movec_from, i32, env, i32)
|
||||
DEF_HELPER_4(cas2w, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(cas2l, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(cas2l_parallel, void, env, i32, i32, i32)
|
||||
@ -94,3 +96,10 @@ DEF_HELPER_FLAGS_4(bfchg_mem, TCG_CALL_NO_WG, i32, env, i32, s32, i32)
|
||||
DEF_HELPER_FLAGS_4(bfclr_mem, TCG_CALL_NO_WG, i32, env, i32, s32, i32)
|
||||
DEF_HELPER_FLAGS_4(bfset_mem, TCG_CALL_NO_WG, i32, env, i32, s32, i32)
|
||||
DEF_HELPER_FLAGS_4(bfffo_mem, TCG_CALL_NO_WG, i64, env, i32, s32, i32)
|
||||
|
||||
DEF_HELPER_3(chk, void, env, s32, s32)
|
||||
DEF_HELPER_4(chk2, void, env, s32, s32, s32)
|
||||
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
DEF_HELPER_FLAGS_1(reset, TCG_CALL_NO_RWG, void, env)
|
||||
#endif
|
||||
|
@ -30,6 +30,7 @@ static const MonitorDef monitor_defs[] = {
|
||||
{ "sr", offsetof(CPUM68KState, sr) },
|
||||
{ "ssp", offsetof(CPUM68KState, sp[0]) },
|
||||
{ "usp", offsetof(CPUM68KState, sp[1]) },
|
||||
{ "isp", offsetof(CPUM68KState, sp[2]) },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
@ -51,7 +51,7 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
|
||||
}
|
||||
}
|
||||
|
||||
static void do_rte(CPUM68KState *env)
|
||||
static void cf_rte(CPUM68KState *env)
|
||||
{
|
||||
uint32_t sp;
|
||||
uint32_t fmt;
|
||||
@ -62,13 +62,158 @@ static void do_rte(CPUM68KState *env)
|
||||
sp |= (fmt >> 28) & 3;
|
||||
env->aregs[7] = sp + 8;
|
||||
|
||||
helper_set_sr(env, fmt);
|
||||
cpu_m68k_set_sr(env, fmt);
|
||||
}
|
||||
|
||||
static void do_interrupt_all(CPUM68KState *env, int is_hw)
|
||||
static void m68k_rte(CPUM68KState *env)
|
||||
{
|
||||
uint32_t sp;
|
||||
uint16_t fmt;
|
||||
uint16_t sr;
|
||||
|
||||
sp = env->aregs[7];
|
||||
throwaway:
|
||||
sr = cpu_lduw_kernel(env, sp);
|
||||
sp += 2;
|
||||
env->pc = cpu_ldl_kernel(env, sp);
|
||||
sp += 4;
|
||||
if (m68k_feature(env, M68K_FEATURE_QUAD_MULDIV)) {
|
||||
/* all except 68000 */
|
||||
fmt = cpu_lduw_kernel(env, sp);
|
||||
sp += 2;
|
||||
switch (fmt >> 12) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
env->aregs[7] = sp;
|
||||
cpu_m68k_set_sr(env, sr);
|
||||
goto throwaway;
|
||||
case 2:
|
||||
case 3:
|
||||
sp += 4;
|
||||
break;
|
||||
case 4:
|
||||
sp += 8;
|
||||
break;
|
||||
case 7:
|
||||
sp += 52;
|
||||
break;
|
||||
}
|
||||
}
|
||||
env->aregs[7] = sp;
|
||||
cpu_m68k_set_sr(env, sr);
|
||||
}
|
||||
|
||||
static const char *m68k_exception_name(int index)
|
||||
{
|
||||
switch (index) {
|
||||
case EXCP_ACCESS:
|
||||
return "Access Fault";
|
||||
case EXCP_ADDRESS:
|
||||
return "Address Error";
|
||||
case EXCP_ILLEGAL:
|
||||
return "Illegal Instruction";
|
||||
case EXCP_DIV0:
|
||||
return "Divide by Zero";
|
||||
case EXCP_CHK:
|
||||
return "CHK/CHK2";
|
||||
case EXCP_TRAPCC:
|
||||
return "FTRAPcc, TRAPcc, TRAPV";
|
||||
case EXCP_PRIVILEGE:
|
||||
return "Privilege Violation";
|
||||
case EXCP_TRACE:
|
||||
return "Trace";
|
||||
case EXCP_LINEA:
|
||||
return "A-Line";
|
||||
case EXCP_LINEF:
|
||||
return "F-Line";
|
||||
case EXCP_DEBEGBP: /* 68020/030 only */
|
||||
return "Copro Protocol Violation";
|
||||
case EXCP_FORMAT:
|
||||
return "Format Error";
|
||||
case EXCP_UNINITIALIZED:
|
||||
return "Unitialized Interruot";
|
||||
case EXCP_SPURIOUS:
|
||||
return "Spurious Interrupt";
|
||||
case EXCP_INT_LEVEL_1:
|
||||
return "Level 1 Interrupt";
|
||||
case EXCP_INT_LEVEL_1 + 1:
|
||||
return "Level 2 Interrupt";
|
||||
case EXCP_INT_LEVEL_1 + 2:
|
||||
return "Level 3 Interrupt";
|
||||
case EXCP_INT_LEVEL_1 + 3:
|
||||
return "Level 4 Interrupt";
|
||||
case EXCP_INT_LEVEL_1 + 4:
|
||||
return "Level 5 Interrupt";
|
||||
case EXCP_INT_LEVEL_1 + 5:
|
||||
return "Level 6 Interrupt";
|
||||
case EXCP_INT_LEVEL_1 + 6:
|
||||
return "Level 7 Interrupt";
|
||||
case EXCP_TRAP0:
|
||||
return "TRAP #0";
|
||||
case EXCP_TRAP0 + 1:
|
||||
return "TRAP #1";
|
||||
case EXCP_TRAP0 + 2:
|
||||
return "TRAP #2";
|
||||
case EXCP_TRAP0 + 3:
|
||||
return "TRAP #3";
|
||||
case EXCP_TRAP0 + 4:
|
||||
return "TRAP #4";
|
||||
case EXCP_TRAP0 + 5:
|
||||
return "TRAP #5";
|
||||
case EXCP_TRAP0 + 6:
|
||||
return "TRAP #6";
|
||||
case EXCP_TRAP0 + 7:
|
||||
return "TRAP #7";
|
||||
case EXCP_TRAP0 + 8:
|
||||
return "TRAP #8";
|
||||
case EXCP_TRAP0 + 9:
|
||||
return "TRAP #9";
|
||||
case EXCP_TRAP0 + 10:
|
||||
return "TRAP #10";
|
||||
case EXCP_TRAP0 + 11:
|
||||
return "TRAP #11";
|
||||
case EXCP_TRAP0 + 12:
|
||||
return "TRAP #12";
|
||||
case EXCP_TRAP0 + 13:
|
||||
return "TRAP #13";
|
||||
case EXCP_TRAP0 + 14:
|
||||
return "TRAP #14";
|
||||
case EXCP_TRAP0 + 15:
|
||||
return "TRAP #15";
|
||||
case EXCP_FP_BSUN:
|
||||
return "FP Branch/Set on unordered condition";
|
||||
case EXCP_FP_INEX:
|
||||
return "FP Inexact Result";
|
||||
case EXCP_FP_DZ:
|
||||
return "FP Divide by Zero";
|
||||
case EXCP_FP_UNFL:
|
||||
return "FP Underflow";
|
||||
case EXCP_FP_OPERR:
|
||||
return "FP Operand Error";
|
||||
case EXCP_FP_OVFL:
|
||||
return "FP Overflow";
|
||||
case EXCP_FP_SNAN:
|
||||
return "FP Signaling NAN";
|
||||
case EXCP_FP_UNIMP:
|
||||
return "FP Unimplemented Data Type";
|
||||
case EXCP_MMU_CONF: /* 68030/68851 only */
|
||||
return "MMU Configuration Error";
|
||||
case EXCP_MMU_ILLEGAL: /* 68851 only */
|
||||
return "MMU Illegal Operation";
|
||||
case EXCP_MMU_ACCESS: /* 68851 only */
|
||||
return "MMU Access Level Violation";
|
||||
case 64 ... 255:
|
||||
return "User Defined Vector";
|
||||
}
|
||||
return "Unassigned";
|
||||
}
|
||||
|
||||
static void cf_interrupt_all(CPUM68KState *env, int is_hw)
|
||||
{
|
||||
CPUState *cs = CPU(m68k_env_get_cpu(env));
|
||||
uint32_t sp;
|
||||
uint32_t sr;
|
||||
uint32_t fmt;
|
||||
uint32_t retaddr;
|
||||
uint32_t vector;
|
||||
@ -80,7 +225,7 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
|
||||
switch (cs->exception_index) {
|
||||
case EXCP_RTE:
|
||||
/* Return from an exception. */
|
||||
do_rte(env);
|
||||
cf_rte(env);
|
||||
return;
|
||||
case EXCP_HALT_INSN:
|
||||
if (semihosting_enabled()
|
||||
@ -106,10 +251,17 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
|
||||
|
||||
vector = cs->exception_index << 2;
|
||||
|
||||
sr = env->sr | cpu_m68k_get_ccr(env);
|
||||
if (qemu_loglevel_mask(CPU_LOG_INT)) {
|
||||
static int count;
|
||||
qemu_log("INT %6d: %s(%#x) pc=%08x sp=%08x sr=%04x\n",
|
||||
++count, m68k_exception_name(cs->exception_index),
|
||||
vector, env->pc, env->aregs[7], sr);
|
||||
}
|
||||
|
||||
fmt |= 0x40000000;
|
||||
fmt |= vector << 16;
|
||||
fmt |= env->sr;
|
||||
fmt |= cpu_m68k_get_ccr(env);
|
||||
fmt |= sr;
|
||||
|
||||
env->sr |= SR_S;
|
||||
if (is_hw) {
|
||||
@ -131,6 +283,119 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
|
||||
env->pc = cpu_ldl_kernel(env, env->vbr + vector);
|
||||
}
|
||||
|
||||
static inline void do_stack_frame(CPUM68KState *env, uint32_t *sp,
|
||||
uint16_t format, uint16_t sr,
|
||||
uint32_t addr, uint32_t retaddr)
|
||||
{
|
||||
CPUState *cs = CPU(m68k_env_get_cpu(env));
|
||||
switch (format) {
|
||||
case 4:
|
||||
*sp -= 4;
|
||||
cpu_stl_kernel(env, *sp, env->pc);
|
||||
*sp -= 4;
|
||||
cpu_stl_kernel(env, *sp, addr);
|
||||
break;
|
||||
case 3:
|
||||
case 2:
|
||||
*sp -= 4;
|
||||
cpu_stl_kernel(env, *sp, addr);
|
||||
break;
|
||||
}
|
||||
*sp -= 2;
|
||||
cpu_stw_kernel(env, *sp, (format << 12) + (cs->exception_index << 2));
|
||||
*sp -= 4;
|
||||
cpu_stl_kernel(env, *sp, retaddr);
|
||||
*sp -= 2;
|
||||
cpu_stw_kernel(env, *sp, sr);
|
||||
}
|
||||
|
||||
static void m68k_interrupt_all(CPUM68KState *env, int is_hw)
|
||||
{
|
||||
CPUState *cs = CPU(m68k_env_get_cpu(env));
|
||||
uint32_t sp;
|
||||
uint32_t retaddr;
|
||||
uint32_t vector;
|
||||
uint16_t sr, oldsr;
|
||||
|
||||
retaddr = env->pc;
|
||||
|
||||
if (!is_hw) {
|
||||
switch (cs->exception_index) {
|
||||
case EXCP_RTE:
|
||||
/* Return from an exception. */
|
||||
m68k_rte(env);
|
||||
return;
|
||||
case EXCP_TRAP0 ... EXCP_TRAP15:
|
||||
/* Move the PC after the trap instruction. */
|
||||
retaddr += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vector = cs->exception_index << 2;
|
||||
|
||||
sr = env->sr | cpu_m68k_get_ccr(env);
|
||||
if (qemu_loglevel_mask(CPU_LOG_INT)) {
|
||||
static int count;
|
||||
qemu_log("INT %6d: %s(%#x) pc=%08x sp=%08x sr=%04x\n",
|
||||
++count, m68k_exception_name(cs->exception_index),
|
||||
vector, env->pc, env->aregs[7], sr);
|
||||
}
|
||||
|
||||
/*
|
||||
* MC68040UM/AD, chapter 9.3.10
|
||||
*/
|
||||
|
||||
/* "the processor first make an internal copy" */
|
||||
oldsr = sr;
|
||||
/* "set the mode to supervisor" */
|
||||
sr |= SR_S;
|
||||
/* "suppress tracing" */
|
||||
sr &= ~SR_T;
|
||||
/* "sets the processor interrupt mask" */
|
||||
if (is_hw) {
|
||||
sr |= (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT);
|
||||
}
|
||||
cpu_m68k_set_sr(env, sr);
|
||||
sp = env->aregs[7];
|
||||
|
||||
sp &= ~1;
|
||||
if (cs->exception_index == EXCP_ADDRESS) {
|
||||
do_stack_frame(env, &sp, 2, oldsr, 0, retaddr);
|
||||
} else if (cs->exception_index == EXCP_ILLEGAL ||
|
||||
cs->exception_index == EXCP_DIV0 ||
|
||||
cs->exception_index == EXCP_CHK ||
|
||||
cs->exception_index == EXCP_TRAPCC ||
|
||||
cs->exception_index == EXCP_TRACE) {
|
||||
/* FIXME: addr is not only env->pc */
|
||||
do_stack_frame(env, &sp, 2, oldsr, env->pc, retaddr);
|
||||
} else if (is_hw && oldsr & SR_M &&
|
||||
cs->exception_index >= EXCP_SPURIOUS &&
|
||||
cs->exception_index <= EXCP_INT_LEVEL_7) {
|
||||
do_stack_frame(env, &sp, 0, oldsr, 0, retaddr);
|
||||
oldsr = sr;
|
||||
env->aregs[7] = sp;
|
||||
cpu_m68k_set_sr(env, sr &= ~SR_M);
|
||||
sp = env->aregs[7] & ~1;
|
||||
do_stack_frame(env, &sp, 1, oldsr, 0, retaddr);
|
||||
} else {
|
||||
do_stack_frame(env, &sp, 0, oldsr, 0, retaddr);
|
||||
}
|
||||
|
||||
env->aregs[7] = sp;
|
||||
/* Jump to vector. */
|
||||
env->pc = cpu_ldl_kernel(env, env->vbr + vector);
|
||||
}
|
||||
|
||||
static void do_interrupt_all(CPUM68KState *env, int is_hw)
|
||||
{
|
||||
if (m68k_feature(env, M68K_FEATURE_M68000)) {
|
||||
m68k_interrupt_all(env, is_hw);
|
||||
return;
|
||||
}
|
||||
cf_interrupt_all(env, is_hw);
|
||||
}
|
||||
|
||||
void m68k_cpu_do_interrupt(CPUState *cs)
|
||||
{
|
||||
M68kCPU *cpu = M68K_CPU(cs);
|
||||
@ -679,3 +944,64 @@ uint64_t HELPER(bfffo_mem)(CPUM68KState *env, uint32_t addr,
|
||||
is already zero. */
|
||||
return n | ffo;
|
||||
}
|
||||
|
||||
void HELPER(chk)(CPUM68KState *env, int32_t val, int32_t ub)
|
||||
{
|
||||
/* From the specs:
|
||||
* X: Not affected, C,V,Z: Undefined,
|
||||
* N: Set if val < 0; cleared if val > ub, undefined otherwise
|
||||
* We implement here values found from a real MC68040:
|
||||
* X,V,Z: Not affected
|
||||
* N: Set if val < 0; cleared if val >= 0
|
||||
* C: if 0 <= ub: set if val < 0 or val > ub, cleared otherwise
|
||||
* if 0 > ub: set if val > ub and val < 0, cleared otherwise
|
||||
*/
|
||||
env->cc_n = val;
|
||||
env->cc_c = 0 <= ub ? val < 0 || val > ub : val > ub && val < 0;
|
||||
|
||||
if (val < 0 || val > ub) {
|
||||
CPUState *cs = CPU(m68k_env_get_cpu(env));
|
||||
|
||||
/* Recover PC and CC_OP for the beginning of the insn. */
|
||||
cpu_restore_state(cs, GETPC());
|
||||
|
||||
/* flags have been modified by gen_flush_flags() */
|
||||
env->cc_op = CC_OP_FLAGS;
|
||||
/* Adjust PC to end of the insn. */
|
||||
env->pc += 2;
|
||||
|
||||
cs->exception_index = EXCP_CHK;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
}
|
||||
|
||||
void HELPER(chk2)(CPUM68KState *env, int32_t val, int32_t lb, int32_t ub)
|
||||
{
|
||||
/* From the specs:
|
||||
* X: Not affected, N,V: Undefined,
|
||||
* Z: Set if val is equal to lb or ub
|
||||
* C: Set if val < lb or val > ub, cleared otherwise
|
||||
* We implement here values found from a real MC68040:
|
||||
* X,N,V: Not affected
|
||||
* Z: Set if val is equal to lb or ub
|
||||
* C: if lb <= ub: set if val < lb or val > ub, cleared otherwise
|
||||
* if lb > ub: set if val > ub and val < lb, cleared otherwise
|
||||
*/
|
||||
env->cc_z = val != lb && val != ub;
|
||||
env->cc_c = lb <= ub ? val < lb || val > ub : val > ub && val < lb;
|
||||
|
||||
if (env->cc_c) {
|
||||
CPUState *cs = CPU(m68k_env_get_cpu(env));
|
||||
|
||||
/* Recover PC and CC_OP for the beginning of the insn. */
|
||||
cpu_restore_state(cs, GETPC());
|
||||
|
||||
/* flags have been modified by gen_flush_flags() */
|
||||
env->cc_op = CC_OP_FLAGS;
|
||||
/* Adjust PC to end of the insn. */
|
||||
env->pc += 4;
|
||||
|
||||
cs->exception_index = EXCP_CHK;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
}
|
||||
|
@ -270,7 +270,6 @@ static void gen_raise_exception(int nr)
|
||||
|
||||
static void gen_exception(DisasContext *s, uint32_t where, int nr)
|
||||
{
|
||||
update_cc_op(s);
|
||||
gen_jmp_im(s, where);
|
||||
gen_raise_exception(nr);
|
||||
}
|
||||
@ -1510,12 +1509,12 @@ DISAS_INSN(dbcc)
|
||||
|
||||
DISAS_INSN(undef_mac)
|
||||
{
|
||||
gen_exception(s, s->pc - 2, EXCP_LINEA);
|
||||
gen_exception(s, s->insn_pc, EXCP_LINEA);
|
||||
}
|
||||
|
||||
DISAS_INSN(undef_fpu)
|
||||
{
|
||||
gen_exception(s, s->pc - 2, EXCP_LINEF);
|
||||
gen_exception(s, s->insn_pc, EXCP_LINEF);
|
||||
}
|
||||
|
||||
DISAS_INSN(undef)
|
||||
@ -1524,8 +1523,8 @@ DISAS_INSN(undef)
|
||||
for the 680x0 series, as well as those that are implemented
|
||||
but actually illegal for CPU32 or pre-68020. */
|
||||
qemu_log_mask(LOG_UNIMP, "Illegal instruction: %04x @ %08x",
|
||||
insn, s->pc - 2);
|
||||
gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED);
|
||||
insn, s->insn_pc);
|
||||
gen_exception(s, s->insn_pc, EXCP_UNSUPPORTED);
|
||||
}
|
||||
|
||||
DISAS_INSN(mulw)
|
||||
@ -2132,6 +2131,68 @@ DISAS_INSN(bitop_im)
|
||||
}
|
||||
}
|
||||
|
||||
static TCGv gen_get_ccr(DisasContext *s)
|
||||
{
|
||||
TCGv dest;
|
||||
|
||||
update_cc_op(s);
|
||||
dest = tcg_temp_new();
|
||||
gen_helper_get_ccr(dest, cpu_env);
|
||||
return dest;
|
||||
}
|
||||
|
||||
static TCGv gen_get_sr(DisasContext *s)
|
||||
{
|
||||
TCGv ccr;
|
||||
TCGv sr;
|
||||
|
||||
ccr = gen_get_ccr(s);
|
||||
sr = tcg_temp_new();
|
||||
tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
|
||||
tcg_gen_or_i32(sr, sr, ccr);
|
||||
return sr;
|
||||
}
|
||||
|
||||
static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
|
||||
{
|
||||
if (ccr_only) {
|
||||
tcg_gen_movi_i32(QREG_CC_C, val & CCF_C ? 1 : 0);
|
||||
tcg_gen_movi_i32(QREG_CC_V, val & CCF_V ? -1 : 0);
|
||||
tcg_gen_movi_i32(QREG_CC_Z, val & CCF_Z ? 0 : 1);
|
||||
tcg_gen_movi_i32(QREG_CC_N, val & CCF_N ? -1 : 0);
|
||||
tcg_gen_movi_i32(QREG_CC_X, val & CCF_X ? 1 : 0);
|
||||
} else {
|
||||
TCGv sr = tcg_const_i32(val);
|
||||
gen_helper_set_sr(cpu_env, sr);
|
||||
tcg_temp_free(sr);
|
||||
}
|
||||
set_cc_op(s, CC_OP_FLAGS);
|
||||
}
|
||||
|
||||
static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only)
|
||||
{
|
||||
if (ccr_only) {
|
||||
gen_helper_set_ccr(cpu_env, val);
|
||||
} else {
|
||||
gen_helper_set_sr(cpu_env, val);
|
||||
}
|
||||
set_cc_op(s, CC_OP_FLAGS);
|
||||
}
|
||||
|
||||
static void gen_move_to_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
||||
bool ccr_only)
|
||||
{
|
||||
if ((insn & 0x3f) == 0x3c) {
|
||||
uint16_t val;
|
||||
val = read_im16(env, s);
|
||||
gen_set_sr_im(s, val, ccr_only);
|
||||
} else {
|
||||
TCGv src;
|
||||
SRC_EA(env, src, OS_WORD, 0, NULL);
|
||||
gen_set_sr(s, src, ccr_only);
|
||||
}
|
||||
}
|
||||
|
||||
DISAS_INSN(arith_im)
|
||||
{
|
||||
int op;
|
||||
@ -2140,6 +2201,7 @@ DISAS_INSN(arith_im)
|
||||
TCGv dest;
|
||||
TCGv addr;
|
||||
int opsize;
|
||||
bool with_SR = ((insn & 0x3f) == 0x3c);
|
||||
|
||||
op = (insn >> 9) & 7;
|
||||
opsize = insn_opsize(insn);
|
||||
@ -2156,32 +2218,73 @@ DISAS_INSN(arith_im)
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
SRC_EA(env, src1, opsize, 1, (op == 6) ? NULL : &addr);
|
||||
|
||||
if (with_SR) {
|
||||
/* SR/CCR can only be used with andi/eori/ori */
|
||||
if (op == 2 || op == 3 || op == 6) {
|
||||
disas_undef(env, s, insn);
|
||||
return;
|
||||
}
|
||||
switch (opsize) {
|
||||
case OS_BYTE:
|
||||
src1 = gen_get_ccr(s);
|
||||
break;
|
||||
case OS_WORD:
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
src1 = gen_get_sr(s);
|
||||
break;
|
||||
case OS_LONG:
|
||||
disas_undef(env, s, insn);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
SRC_EA(env, src1, opsize, 1, (op == 6) ? NULL : &addr);
|
||||
}
|
||||
dest = tcg_temp_new();
|
||||
switch (op) {
|
||||
case 0: /* ori */
|
||||
tcg_gen_or_i32(dest, src1, im);
|
||||
gen_logic_cc(s, dest, opsize);
|
||||
if (with_SR) {
|
||||
gen_set_sr(s, dest, opsize == OS_BYTE);
|
||||
} else {
|
||||
DEST_EA(env, insn, opsize, dest, &addr);
|
||||
gen_logic_cc(s, dest, opsize);
|
||||
}
|
||||
break;
|
||||
case 1: /* andi */
|
||||
tcg_gen_and_i32(dest, src1, im);
|
||||
gen_logic_cc(s, dest, opsize);
|
||||
if (with_SR) {
|
||||
gen_set_sr(s, dest, opsize == OS_BYTE);
|
||||
} else {
|
||||
DEST_EA(env, insn, opsize, dest, &addr);
|
||||
gen_logic_cc(s, dest, opsize);
|
||||
}
|
||||
break;
|
||||
case 2: /* subi */
|
||||
tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, src1, im);
|
||||
tcg_gen_sub_i32(dest, src1, im);
|
||||
gen_update_cc_add(dest, im, opsize);
|
||||
set_cc_op(s, CC_OP_SUBB + opsize);
|
||||
DEST_EA(env, insn, opsize, dest, &addr);
|
||||
break;
|
||||
case 3: /* addi */
|
||||
tcg_gen_add_i32(dest, src1, im);
|
||||
gen_update_cc_add(dest, im, opsize);
|
||||
tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, im);
|
||||
set_cc_op(s, CC_OP_ADDB + opsize);
|
||||
DEST_EA(env, insn, opsize, dest, &addr);
|
||||
break;
|
||||
case 5: /* eori */
|
||||
tcg_gen_xor_i32(dest, src1, im);
|
||||
gen_logic_cc(s, dest, opsize);
|
||||
if (with_SR) {
|
||||
gen_set_sr(s, dest, opsize == OS_BYTE);
|
||||
} else {
|
||||
DEST_EA(env, insn, opsize, dest, &addr);
|
||||
gen_logic_cc(s, dest, opsize);
|
||||
}
|
||||
break;
|
||||
case 6: /* cmpi */
|
||||
gen_update_cc_cmp(s, src1, im, opsize);
|
||||
@ -2190,9 +2293,6 @@ DISAS_INSN(arith_im)
|
||||
abort();
|
||||
}
|
||||
tcg_temp_free(im);
|
||||
if (op != 6) {
|
||||
DEST_EA(env, insn, opsize, dest, &addr);
|
||||
}
|
||||
tcg_temp_free(dest);
|
||||
}
|
||||
|
||||
@ -2475,17 +2575,6 @@ DISAS_INSN(clr)
|
||||
tcg_temp_free(zero);
|
||||
}
|
||||
|
||||
static TCGv gen_get_ccr(DisasContext *s)
|
||||
{
|
||||
TCGv dest;
|
||||
|
||||
gen_flush_flags(s);
|
||||
update_cc_op(s);
|
||||
dest = tcg_temp_new();
|
||||
gen_helper_get_ccr(dest, cpu_env);
|
||||
return dest;
|
||||
}
|
||||
|
||||
DISAS_INSN(move_from_ccr)
|
||||
{
|
||||
TCGv ccr;
|
||||
@ -2512,43 +2601,9 @@ DISAS_INSN(neg)
|
||||
tcg_temp_free(dest);
|
||||
}
|
||||
|
||||
static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
|
||||
{
|
||||
if (ccr_only) {
|
||||
tcg_gen_movi_i32(QREG_CC_C, val & CCF_C ? 1 : 0);
|
||||
tcg_gen_movi_i32(QREG_CC_V, val & CCF_V ? -1 : 0);
|
||||
tcg_gen_movi_i32(QREG_CC_Z, val & CCF_Z ? 0 : 1);
|
||||
tcg_gen_movi_i32(QREG_CC_N, val & CCF_N ? -1 : 0);
|
||||
tcg_gen_movi_i32(QREG_CC_X, val & CCF_X ? 1 : 0);
|
||||
} else {
|
||||
gen_helper_set_sr(cpu_env, tcg_const_i32(val));
|
||||
}
|
||||
set_cc_op(s, CC_OP_FLAGS);
|
||||
}
|
||||
|
||||
static void gen_set_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
||||
int ccr_only)
|
||||
{
|
||||
if ((insn & 0x38) == 0) {
|
||||
if (ccr_only) {
|
||||
gen_helper_set_ccr(cpu_env, DREG(insn, 0));
|
||||
} else {
|
||||
gen_helper_set_sr(cpu_env, DREG(insn, 0));
|
||||
}
|
||||
set_cc_op(s, CC_OP_FLAGS);
|
||||
} else if ((insn & 0x3f) == 0x3c) {
|
||||
uint16_t val;
|
||||
val = read_im16(env, s);
|
||||
gen_set_sr_im(s, val, ccr_only);
|
||||
} else {
|
||||
disas_undef(env, s, insn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DISAS_INSN(move_to_ccr)
|
||||
{
|
||||
gen_set_sr(env, s, insn, 1);
|
||||
gen_move_to_sr(env, s, insn, true);
|
||||
}
|
||||
|
||||
DISAS_INSN(not)
|
||||
@ -2585,7 +2640,7 @@ DISAS_INSN(swap)
|
||||
|
||||
DISAS_INSN(bkpt)
|
||||
{
|
||||
gen_exception(s, s->pc - 2, EXCP_DEBUG);
|
||||
gen_exception(s, s->insn_pc, EXCP_DEBUG);
|
||||
}
|
||||
|
||||
DISAS_INSN(pea)
|
||||
@ -2638,7 +2693,7 @@ DISAS_INSN(pulse)
|
||||
|
||||
DISAS_INSN(illegal)
|
||||
{
|
||||
gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
|
||||
gen_exception(s, s->insn_pc, EXCP_ILLEGAL);
|
||||
}
|
||||
|
||||
/* ??? This should be atomic. */
|
||||
@ -2668,7 +2723,7 @@ DISAS_INSN(mull)
|
||||
|
||||
if (ext & 0x400) {
|
||||
if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
|
||||
gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
|
||||
gen_exception(s, s->insn_pc, EXCP_UNSUPPORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2764,6 +2819,18 @@ DISAS_INSN(unlk)
|
||||
tcg_temp_free(src);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
DISAS_INSN(reset)
|
||||
{
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
|
||||
gen_helper_reset(cpu_env);
|
||||
}
|
||||
#endif
|
||||
|
||||
DISAS_INSN(nop)
|
||||
{
|
||||
}
|
||||
@ -2897,6 +2964,7 @@ DISAS_INSN(branch)
|
||||
gen_jmp_tb(s, 0, s->pc);
|
||||
} else {
|
||||
/* Unconditional branch. */
|
||||
update_cc_op(s);
|
||||
gen_jmp_tb(s, 0, base + offset);
|
||||
}
|
||||
}
|
||||
@ -4204,16 +4272,148 @@ DISAS_INSN(ff1)
|
||||
gen_helper_ff1(reg, reg);
|
||||
}
|
||||
|
||||
static TCGv gen_get_sr(DisasContext *s)
|
||||
DISAS_INSN(chk)
|
||||
{
|
||||
TCGv ccr;
|
||||
TCGv sr;
|
||||
TCGv src, reg;
|
||||
int opsize;
|
||||
|
||||
ccr = gen_get_ccr(s);
|
||||
sr = tcg_temp_new();
|
||||
tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
|
||||
tcg_gen_or_i32(sr, sr, ccr);
|
||||
return sr;
|
||||
switch ((insn >> 7) & 3) {
|
||||
case 3:
|
||||
opsize = OS_WORD;
|
||||
break;
|
||||
case 2:
|
||||
if (m68k_feature(env, M68K_FEATURE_CHK2)) {
|
||||
opsize = OS_LONG;
|
||||
break;
|
||||
}
|
||||
/* fallthru */
|
||||
default:
|
||||
gen_exception(s, s->insn_pc, EXCP_ILLEGAL);
|
||||
return;
|
||||
}
|
||||
SRC_EA(env, src, opsize, 1, NULL);
|
||||
reg = gen_extend(DREG(insn, 9), opsize, 1);
|
||||
|
||||
gen_flush_flags(s);
|
||||
gen_helper_chk(cpu_env, reg, src);
|
||||
}
|
||||
|
||||
DISAS_INSN(chk2)
|
||||
{
|
||||
uint16_t ext;
|
||||
TCGv addr1, addr2, bound1, bound2, reg;
|
||||
int opsize;
|
||||
|
||||
switch ((insn >> 9) & 3) {
|
||||
case 0:
|
||||
opsize = OS_BYTE;
|
||||
break;
|
||||
case 1:
|
||||
opsize = OS_WORD;
|
||||
break;
|
||||
case 2:
|
||||
opsize = OS_LONG;
|
||||
break;
|
||||
default:
|
||||
gen_exception(s, s->insn_pc, EXCP_ILLEGAL);
|
||||
return;
|
||||
}
|
||||
|
||||
ext = read_im16(env, s);
|
||||
if ((ext & 0x0800) == 0) {
|
||||
gen_exception(s, s->insn_pc, EXCP_ILLEGAL);
|
||||
return;
|
||||
}
|
||||
|
||||
addr1 = gen_lea(env, s, insn, OS_UNSIZED);
|
||||
addr2 = tcg_temp_new();
|
||||
tcg_gen_addi_i32(addr2, addr1, opsize_bytes(opsize));
|
||||
|
||||
bound1 = gen_load(s, opsize, addr1, 1);
|
||||
tcg_temp_free(addr1);
|
||||
bound2 = gen_load(s, opsize, addr2, 1);
|
||||
tcg_temp_free(addr2);
|
||||
|
||||
reg = tcg_temp_new();
|
||||
if (ext & 0x8000) {
|
||||
tcg_gen_mov_i32(reg, AREG(ext, 12));
|
||||
} else {
|
||||
gen_ext(reg, DREG(ext, 12), opsize, 1);
|
||||
}
|
||||
|
||||
gen_flush_flags(s);
|
||||
gen_helper_chk2(cpu_env, reg, bound1, bound2);
|
||||
tcg_temp_free(reg);
|
||||
}
|
||||
|
||||
static void m68k_copy_line(TCGv dst, TCGv src, int index)
|
||||
{
|
||||
TCGv addr;
|
||||
TCGv_i64 t0, t1;
|
||||
|
||||
addr = tcg_temp_new();
|
||||
|
||||
t0 = tcg_temp_new_i64();
|
||||
t1 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_andi_i32(addr, src, ~15);
|
||||
tcg_gen_qemu_ld64(t0, addr, index);
|
||||
tcg_gen_addi_i32(addr, addr, 8);
|
||||
tcg_gen_qemu_ld64(t1, addr, index);
|
||||
|
||||
tcg_gen_andi_i32(addr, dst, ~15);
|
||||
tcg_gen_qemu_st64(t0, addr, index);
|
||||
tcg_gen_addi_i32(addr, addr, 8);
|
||||
tcg_gen_qemu_st64(t1, addr, index);
|
||||
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free(addr);
|
||||
}
|
||||
|
||||
DISAS_INSN(move16_reg)
|
||||
{
|
||||
int index = IS_USER(s);
|
||||
TCGv tmp;
|
||||
uint16_t ext;
|
||||
|
||||
ext = read_im16(env, s);
|
||||
if ((ext & (1 << 15)) == 0) {
|
||||
gen_exception(s, s->insn_pc, EXCP_ILLEGAL);
|
||||
}
|
||||
|
||||
m68k_copy_line(AREG(ext, 12), AREG(insn, 0), index);
|
||||
|
||||
/* Ax can be Ay, so save Ay before incrementing Ax */
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_mov_i32(tmp, AREG(ext, 12));
|
||||
tcg_gen_addi_i32(AREG(insn, 0), AREG(insn, 0), 16);
|
||||
tcg_gen_addi_i32(AREG(ext, 12), tmp, 16);
|
||||
tcg_temp_free(tmp);
|
||||
}
|
||||
|
||||
DISAS_INSN(move16_mem)
|
||||
{
|
||||
int index = IS_USER(s);
|
||||
TCGv reg, addr;
|
||||
|
||||
reg = AREG(insn, 0);
|
||||
addr = tcg_const_i32(read_im32(env, s));
|
||||
|
||||
if ((insn >> 3) & 1) {
|
||||
/* MOVE16 (xxx).L, (Ay) */
|
||||
m68k_copy_line(reg, addr, index);
|
||||
} else {
|
||||
/* MOVE16 (Ay), (xxx).L */
|
||||
m68k_copy_line(addr, reg, index);
|
||||
}
|
||||
|
||||
tcg_temp_free(addr);
|
||||
|
||||
if (((insn >> 3) & 2) == 0) {
|
||||
/* (Ay)+ */
|
||||
tcg_gen_addi_i32(reg, reg, 16);
|
||||
}
|
||||
}
|
||||
|
||||
DISAS_INSN(strldsr)
|
||||
@ -4241,27 +4441,28 @@ DISAS_INSN(move_from_sr)
|
||||
TCGv sr;
|
||||
|
||||
if (IS_USER(s) && !m68k_feature(env, M68K_FEATURE_M68000)) {
|
||||
gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
sr = gen_get_sr(s);
|
||||
DEST_EA(env, insn, OS_WORD, sr, NULL);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
DISAS_INSN(move_to_sr)
|
||||
{
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
gen_set_sr(env, s, insn, 0);
|
||||
gen_move_to_sr(env, s, insn, false);
|
||||
gen_lookup_tb(s);
|
||||
}
|
||||
|
||||
DISAS_INSN(move_from_usp)
|
||||
{
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
tcg_gen_ld_i32(AREG(insn, 0), cpu_env,
|
||||
@ -4271,7 +4472,7 @@ DISAS_INSN(move_from_usp)
|
||||
DISAS_INSN(move_to_usp)
|
||||
{
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
tcg_gen_st_i32(AREG(insn, 0), cpu_env,
|
||||
@ -4280,6 +4481,11 @@ DISAS_INSN(move_to_usp)
|
||||
|
||||
DISAS_INSN(halt)
|
||||
{
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
|
||||
gen_exception(s, s->pc, EXCP_HALT_INSN);
|
||||
}
|
||||
|
||||
@ -4288,7 +4494,7 @@ DISAS_INSN(stop)
|
||||
uint16_t ext;
|
||||
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4302,19 +4508,19 @@ DISAS_INSN(stop)
|
||||
DISAS_INSN(rte)
|
||||
{
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
gen_exception(s, s->pc - 2, EXCP_RTE);
|
||||
gen_exception(s, s->insn_pc, EXCP_RTE);
|
||||
}
|
||||
|
||||
DISAS_INSN(movec)
|
||||
DISAS_INSN(cf_movec)
|
||||
{
|
||||
uint16_t ext;
|
||||
TCGv reg;
|
||||
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4325,14 +4531,39 @@ DISAS_INSN(movec)
|
||||
} else {
|
||||
reg = DREG(ext, 12);
|
||||
}
|
||||
gen_helper_movec(cpu_env, tcg_const_i32(ext & 0xfff), reg);
|
||||
gen_helper_cf_movec_to(cpu_env, tcg_const_i32(ext & 0xfff), reg);
|
||||
gen_lookup_tb(s);
|
||||
}
|
||||
|
||||
DISAS_INSN(m68k_movec)
|
||||
{
|
||||
uint16_t ext;
|
||||
TCGv reg;
|
||||
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
|
||||
ext = read_im16(env, s);
|
||||
|
||||
if (ext & 0x8000) {
|
||||
reg = AREG(ext, 12);
|
||||
} else {
|
||||
reg = DREG(ext, 12);
|
||||
}
|
||||
if (insn & 1) {
|
||||
gen_helper_m68k_movec_to(cpu_env, tcg_const_i32(ext & 0xfff), reg);
|
||||
} else {
|
||||
gen_helper_m68k_movec_from(reg, cpu_env, tcg_const_i32(ext & 0xfff));
|
||||
}
|
||||
gen_lookup_tb(s);
|
||||
}
|
||||
|
||||
DISAS_INSN(intouch)
|
||||
{
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
/* ICache fetch. Implement as no-op. */
|
||||
@ -4341,15 +4572,33 @@ DISAS_INSN(intouch)
|
||||
DISAS_INSN(cpushl)
|
||||
{
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
/* Cache push/invalidate. Implement as no-op. */
|
||||
}
|
||||
|
||||
DISAS_INSN(cpush)
|
||||
{
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
/* Cache push/invalidate. Implement as no-op. */
|
||||
}
|
||||
|
||||
DISAS_INSN(cinv)
|
||||
{
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
/* Invalidate cache line. Implement as no-op. */
|
||||
}
|
||||
|
||||
DISAS_INSN(wddata)
|
||||
{
|
||||
gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
}
|
||||
|
||||
DISAS_INSN(wdebug)
|
||||
@ -4357,16 +4606,17 @@ DISAS_INSN(wdebug)
|
||||
M68kCPU *cpu = m68k_env_get_cpu(env);
|
||||
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
/* TODO: Implement wdebug. */
|
||||
cpu_abort(CPU(cpu), "WDEBUG not implemented");
|
||||
}
|
||||
#endif
|
||||
|
||||
DISAS_INSN(trap)
|
||||
{
|
||||
gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
|
||||
gen_exception(s, s->insn_pc, EXCP_TRAP0 + (insn & 0xf));
|
||||
}
|
||||
|
||||
static void gen_load_fcr(DisasContext *s, TCGv res, int reg)
|
||||
@ -4875,6 +5125,7 @@ static void gen_fjmpcc(DisasContext *s, int cond, TCGLabel *l1)
|
||||
DisasCompare c;
|
||||
|
||||
gen_fcc_cond(&c, s, cond);
|
||||
update_cc_op(s);
|
||||
tcg_gen_brcond_i32(c.tcond, c.v1, c.v2, l1);
|
||||
free_cond(&c);
|
||||
}
|
||||
@ -4919,21 +5170,40 @@ DISAS_INSN(fscc)
|
||||
tcg_temp_free(tmp);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
DISAS_INSN(frestore)
|
||||
{
|
||||
M68kCPU *cpu = m68k_env_get_cpu(env);
|
||||
TCGv addr;
|
||||
|
||||
/* TODO: Implement frestore. */
|
||||
cpu_abort(CPU(cpu), "FRESTORE not implemented");
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
if (m68k_feature(s->env, M68K_FEATURE_M68040)) {
|
||||
SRC_EA(env, addr, OS_LONG, 0, NULL);
|
||||
/* FIXME: check the state frame */
|
||||
} else {
|
||||
disas_undef(env, s, insn);
|
||||
}
|
||||
}
|
||||
|
||||
DISAS_INSN(fsave)
|
||||
{
|
||||
M68kCPU *cpu = m68k_env_get_cpu(env);
|
||||
if (IS_USER(s)) {
|
||||
gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: Implement fsave. */
|
||||
cpu_abort(CPU(cpu), "FSAVE not implemented");
|
||||
if (m68k_feature(s->env, M68K_FEATURE_M68040)) {
|
||||
/* always write IDLE */
|
||||
TCGv idle = tcg_const_i32(0x41000000);
|
||||
DEST_EA(env, insn, OS_LONG, idle, NULL);
|
||||
tcg_temp_free(idle);
|
||||
} else {
|
||||
disas_undef(env, s, insn);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline TCGv gen_mac_extract_word(DisasContext *s, TCGv val, int upper)
|
||||
{
|
||||
@ -5306,7 +5576,7 @@ void register_m68k_insns (CPUM68KState *env)
|
||||
BASE(undef, 0000, 0000);
|
||||
INSN(arith_im, 0080, fff8, CF_ISA_A);
|
||||
INSN(arith_im, 0000, ff00, M68000);
|
||||
INSN(undef, 00c0, ffc0, M68000);
|
||||
INSN(chk2, 00c0, f9c0, CHK2);
|
||||
INSN(bitrev, 00c0, fff8, CF_ISA_APLUSC);
|
||||
BASE(bitop_reg, 0100, f1c0);
|
||||
BASE(bitop_reg, 0140, f1c0);
|
||||
@ -5339,6 +5609,7 @@ void register_m68k_insns (CPUM68KState *env)
|
||||
BASE(move, 1000, f000);
|
||||
BASE(move, 2000, f000);
|
||||
BASE(move, 3000, f000);
|
||||
INSN(chk, 4000, f040, M68000);
|
||||
INSN(strldsr, 40e7, ffff, CF_ISA_APLUSC);
|
||||
INSN(negx, 4080, fff8, CF_ISA_A);
|
||||
INSN(negx, 4000, ff00, M68000);
|
||||
@ -5356,8 +5627,9 @@ void register_m68k_insns (CPUM68KState *env)
|
||||
BASE(move_to_ccr, 44c0, ffc0);
|
||||
INSN(not, 4680, fff8, CF_ISA_A);
|
||||
INSN(not, 4600, ff00, M68000);
|
||||
INSN(undef, 46c0, ffc0, M68000);
|
||||
INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
BASE(move_to_sr, 46c0, ffc0);
|
||||
#endif
|
||||
INSN(nbcd, 4800, ffc0, M68000);
|
||||
INSN(linkl, 4808, fff8, M68000);
|
||||
BASE(pea, 4840, ffc0);
|
||||
@ -5372,7 +5644,9 @@ void register_m68k_insns (CPUM68KState *env)
|
||||
BASE(tst, 4a00, ff00);
|
||||
INSN(tas, 4ac0, ffc0, CF_ISA_B);
|
||||
INSN(tas, 4ac0, ffc0, M68000);
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
INSN(halt, 4ac8, ffff, CF_ISA_A);
|
||||
#endif
|
||||
INSN(pulse, 4acc, ffff, CF_ISA_A);
|
||||
BASE(illegal, 4afc, ffff);
|
||||
INSN(mull, 4c00, ffc0, CF_ISA_A);
|
||||
@ -5383,14 +5657,18 @@ void register_m68k_insns (CPUM68KState *env)
|
||||
BASE(trap, 4e40, fff0);
|
||||
BASE(link, 4e50, fff8);
|
||||
BASE(unlk, 4e58, fff8);
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
INSN(move_to_usp, 4e60, fff8, USP);
|
||||
INSN(move_from_usp, 4e68, fff8, USP);
|
||||
BASE(nop, 4e71, ffff);
|
||||
INSN(reset, 4e70, ffff, M68000);
|
||||
BASE(stop, 4e72, ffff);
|
||||
BASE(rte, 4e73, ffff);
|
||||
INSN(cf_movec, 4e7b, ffff, CF_ISA_A);
|
||||
INSN(m68k_movec, 4e7a, fffe, M68000);
|
||||
#endif
|
||||
BASE(nop, 4e71, ffff);
|
||||
INSN(rtd, 4e74, ffff, RTD);
|
||||
BASE(rts, 4e75, ffff);
|
||||
INSN(movec, 4e7b, ffff, CF_ISA_A);
|
||||
BASE(jump, 4e80, ffc0);
|
||||
BASE(jump, 4ec0, ffc0);
|
||||
INSN(addsubq, 5000, f080, M68000);
|
||||
@ -5494,17 +5772,23 @@ void register_m68k_insns (CPUM68KState *env)
|
||||
BASE(undef_fpu, f000, f000);
|
||||
INSN(fpu, f200, ffc0, CF_FPU);
|
||||
INSN(fbcc, f280, ffc0, CF_FPU);
|
||||
INSN(frestore, f340, ffc0, CF_FPU);
|
||||
INSN(fsave, f300, ffc0, CF_FPU);
|
||||
INSN(fpu, f200, ffc0, FPU);
|
||||
INSN(fscc, f240, ffc0, FPU);
|
||||
INSN(fbcc, f280, ff80, FPU);
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
INSN(frestore, f340, ffc0, CF_FPU);
|
||||
INSN(fsave, f300, ffc0, CF_FPU);
|
||||
INSN(frestore, f340, ffc0, FPU);
|
||||
INSN(fsave, f300, ffc0, FPU);
|
||||
INSN(intouch, f340, ffc0, CF_ISA_A);
|
||||
INSN(cpushl, f428, ff38, CF_ISA_A);
|
||||
INSN(cpush, f420, ff20, M68040);
|
||||
INSN(cinv, f400, ff20, M68040);
|
||||
INSN(wddata, fb00, ff00, CF_ISA_A);
|
||||
INSN(wdebug, fbc0, ffc0, CF_ISA_A);
|
||||
#endif
|
||||
INSN(move16_mem, f600, ffe0, M68040);
|
||||
INSN(move16_reg, f620, fff8, M68040);
|
||||
#undef INSN
|
||||
}
|
||||
|
||||
@ -5652,9 +5936,12 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
|
||||
}
|
||||
cpu_fprintf (f, "PC = %08x ", env->pc);
|
||||
sr = env->sr | cpu_m68k_get_ccr(env);
|
||||
cpu_fprintf(f, "SR = %04x %c%c%c%c%c ", sr, (sr & CCF_X) ? 'X' : '-',
|
||||
(sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
|
||||
(sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
|
||||
cpu_fprintf(f, "SR = %04x T:%x I:%x %c%c %c%c%c%c%c\n",
|
||||
sr, (sr & SR_T) >> SR_T_SHIFT, (sr & SR_I) >> SR_I_SHIFT,
|
||||
(sr & SR_S) ? 'S' : 'U', (sr & SR_M) ? '%' : 'I',
|
||||
(sr & CCF_X) ? 'X' : '-', (sr & CCF_N) ? 'N' : '-',
|
||||
(sr & CCF_Z) ? 'Z' : '-', (sr & CCF_V) ? 'V' : '-',
|
||||
(sr & CCF_C) ? 'C' : '-');
|
||||
cpu_fprintf(f, "FPSR = %08x %c%c%c%c ", env->fpsr,
|
||||
(env->fpsr & FPSR_CC_A) ? 'A' : '-',
|
||||
(env->fpsr & FPSR_CC_I) ? 'I' : '-',
|
||||
@ -5687,6 +5974,14 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
|
||||
cpu_fprintf(f, "RP ");
|
||||
break;
|
||||
}
|
||||
cpu_fprintf(f, "\n");
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
cpu_fprintf(f, "%sA7(MSP) = %08x %sA7(USP) = %08x %sA7(ISP) = %08x\n",
|
||||
env->current_sp == M68K_SSP ? "->" : " ", env->sp[M68K_SSP],
|
||||
env->current_sp == M68K_USP ? "->" : " ", env->sp[M68K_USP],
|
||||
env->current_sp == M68K_ISP ? "->" : " ", env->sp[M68K_ISP]);
|
||||
cpu_fprintf(f, "VBR = 0x%08x\n", env->vbr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb,
|
||||
|
Loading…
Reference in New Issue
Block a user