mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 15:23:53 -06:00
MCF5208 emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2924 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
62ea5b0bd3
commit
20dcee9483
13 changed files with 833 additions and 296 deletions
|
@ -59,6 +59,10 @@ typedef struct CPUM68KState {
|
|||
uint32_t pc;
|
||||
uint32_t sr;
|
||||
|
||||
/* SSP and USP. The current_sp is stored in aregs[7], the other here. */
|
||||
int current_sp;
|
||||
uint32_t sp[2];
|
||||
|
||||
/* Condition flags. */
|
||||
uint32_t cc_op;
|
||||
uint32_t cc_dest;
|
||||
|
@ -92,6 +96,7 @@ typedef struct CPUM68KState {
|
|||
uint32_t vbr;
|
||||
uint32_t mbar;
|
||||
uint32_t rambar0;
|
||||
uint32_t cacr;
|
||||
|
||||
uint32_t features;
|
||||
|
||||
|
@ -151,6 +156,12 @@ enum {
|
|||
#define SR_S 0x2000
|
||||
#define SR_T 0x8000
|
||||
|
||||
#define M68K_SSP 0
|
||||
#define M68K_USP 1
|
||||
|
||||
/* CACR fields are implementation defined, but some bits are common. */
|
||||
#define M68K_CACR_EUSP 0x10
|
||||
|
||||
#define MACSR_PAV0 0x100
|
||||
#define MACSR_OMC 0x080
|
||||
#define MACSR_SU 0x040
|
||||
|
@ -167,6 +178,7 @@ 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);
|
||||
void m68k_switch_sp(CPUM68KState *env);
|
||||
|
||||
#define M68K_FPCR_PREC (1 << 6)
|
||||
|
||||
|
@ -179,6 +191,7 @@ enum m68k_features {
|
|||
M68K_FEATURE_CF_FPU,
|
||||
M68K_FEATURE_CF_MAC,
|
||||
M68K_FEATURE_CF_EMAC,
|
||||
M68K_FEATURE_USP,
|
||||
M68K_FEATURE_EXT_FULL, /* 68020+ full extension word. */
|
||||
M68K_FEATURE_WORD_INDEX /* word sized address index registers. */
|
||||
};
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
enum m68k_cpuid {
|
||||
M68K_CPUID_M5206,
|
||||
M68K_CPUID_M5208,
|
||||
M68K_CPUID_CFV4E,
|
||||
M68K_CPUID_ANY,
|
||||
};
|
||||
|
@ -39,6 +40,7 @@ struct m68k_def_t {
|
|||
|
||||
static m68k_def_t m68k_cpu_defs[] = {
|
||||
{"m5206", M68K_CPUID_M5206},
|
||||
{"m5208", M68K_CPUID_M5208},
|
||||
{"cfv4e", M68K_CPUID_CFV4E},
|
||||
{"any", M68K_CPUID_ANY},
|
||||
{NULL, 0},
|
||||
|
@ -64,12 +66,18 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name)
|
|||
case M68K_CPUID_M5206:
|
||||
m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
|
||||
break;
|
||||
case M68K_CPUID_M5208:
|
||||
m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
|
||||
m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
|
||||
m68k_set_feature(env, M68K_FEATURE_USP);
|
||||
break;
|
||||
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_CF_ISA_C);
|
||||
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_CF_ISA_A);
|
||||
|
@ -79,6 +87,7 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name)
|
|||
/* 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_USP);
|
||||
m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
|
||||
break;
|
||||
}
|
||||
|
@ -215,7 +224,11 @@ void helper_movec(CPUM68KState *env, int reg, uint32_t val)
|
|||
{
|
||||
switch (reg) {
|
||||
case 0x02: /* CACR */
|
||||
/* Ignored. */
|
||||
env->cacr = val;
|
||||
m68k_switch_sp(env);
|
||||
break;
|
||||
case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
|
||||
/* TODO: Implement Access Control Registers. */
|
||||
break;
|
||||
case 0x801: /* VBR */
|
||||
env->vbr = val;
|
||||
|
@ -261,6 +274,17 @@ void m68k_set_macsr(CPUM68KState *env, uint32_t val)
|
|||
env->macsr = val;
|
||||
}
|
||||
|
||||
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;
|
||||
env->aregs[7] = env->sp[new_sp];
|
||||
env->current_sp = new_sp;
|
||||
}
|
||||
|
||||
/* MMU */
|
||||
|
||||
/* TODO: This will need fixing once the MMU is implemented. */
|
||||
|
|
|
@ -478,6 +478,13 @@ OP(fp_result)
|
|||
FORCE_RET();
|
||||
}
|
||||
|
||||
OP(set_sr)
|
||||
{
|
||||
env->sr = get_op(PARAM1);
|
||||
m68k_switch_sp(env);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
OP(jmp)
|
||||
{
|
||||
GOTO_LABEL_PARAM(1);
|
||||
|
|
|
@ -87,6 +87,7 @@ static void do_rte(void)
|
|||
env->pc = ldl_kernel(sp + 4);
|
||||
sp |= (fmt >> 28) & 3;
|
||||
env->sr = fmt & 0xffff;
|
||||
m68k_switch_sp(env);
|
||||
env->aregs[7] = sp + 8;
|
||||
}
|
||||
|
||||
|
@ -128,9 +129,6 @@ void do_interrupt(int is_hw)
|
|||
}
|
||||
}
|
||||
|
||||
/* TODO: Implement USP. */
|
||||
sp = env->aregs[7];
|
||||
|
||||
vector = env->exception_index << 2;
|
||||
|
||||
fmt |= 0x40000000;
|
||||
|
@ -138,6 +136,15 @@ void do_interrupt(int is_hw)
|
|||
fmt |= vector << 16;
|
||||
fmt |= env->sr;
|
||||
|
||||
env->sr |= SR_S;
|
||||
if (is_hw) {
|
||||
env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT);
|
||||
env->sr &= ~SR_M;
|
||||
}
|
||||
m68k_switch_sp(env);
|
||||
|
||||
sp = env->aregs[7];
|
||||
|
||||
/* ??? This could cause MMU faults. */
|
||||
sp &= ~3;
|
||||
sp -= 4;
|
||||
|
@ -145,11 +152,6 @@ void do_interrupt(int is_hw)
|
|||
sp -= 4;
|
||||
stl_kernel(sp, fmt);
|
||||
env->aregs[7] = sp;
|
||||
env->sr |= SR_S;
|
||||
if (is_hw) {
|
||||
env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT);
|
||||
env->sr &= ~SR_M;
|
||||
}
|
||||
/* Jump to vector. */
|
||||
env->pc = ldl_kernel(env->vbr + vector);
|
||||
}
|
||||
|
|
|
@ -1345,7 +1345,7 @@ static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
|
|||
gen_op_logic_cc(gen_im32(val & 0xf));
|
||||
gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4));
|
||||
if (!ccr_only) {
|
||||
gen_op_mov32(QREG_SR, gen_im32(val & 0xff00));
|
||||
gen_op_set_sr(gen_im32(val & 0xff00));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1365,7 +1365,7 @@ static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only)
|
|||
gen_op_and32(src1, src1, gen_im32(1));
|
||||
gen_op_update_xflag_tst(src1);
|
||||
if (!ccr_only) {
|
||||
gen_op_and32(QREG_SR, reg, gen_im32(0xff00));
|
||||
gen_op_set_sr(reg);
|
||||
}
|
||||
}
|
||||
else if ((insn & 0x3f) == 0x3c)
|
||||
|
@ -2797,8 +2797,8 @@ void register_m68k_insns (CPUM68KState *env)
|
|||
INSN(trap, 4e40, fff0, CF_ISA_A);
|
||||
INSN(link, 4e50, fff8, CF_ISA_A);
|
||||
INSN(unlk, 4e58, fff8, CF_ISA_A);
|
||||
INSN(move_to_usp, 4e60, fff8, CF_ISA_B);
|
||||
INSN(move_from_usp, 4e68, fff8, CF_ISA_B);
|
||||
INSN(move_to_usp, 4e60, fff8, USP);
|
||||
INSN(move_from_usp, 4e68, fff8, USP);
|
||||
INSN(nop, 4e71, ffff, CF_ISA_A);
|
||||
INSN(stop, 4e72, ffff, CF_ISA_A);
|
||||
INSN(rte, 4e73, ffff, CF_ISA_A);
|
||||
|
@ -3261,6 +3261,7 @@ void cpu_reset(CPUM68KState *env)
|
|||
#if !defined (CONFIG_USER_ONLY)
|
||||
env->sr = 0x2700;
|
||||
#endif
|
||||
m68k_switch_sp(env);
|
||||
/* ??? FP regs should be initialized to NaN. */
|
||||
env->cc_op = CC_OP_FLAGS;
|
||||
/* TODO: We should set PC from the interrupt vector. */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue