mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 16:23:55 -06:00
Add MIPS32R2 instructions, and generally straighten out the instruction
decoding. This is also the first percent towards MIPS64 support. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2224 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
8c0fdd856c
commit
7a387fffce
7 changed files with 2233 additions and 589 deletions
360
target-mips/op.c
360
target-mips/op.c
|
@ -437,6 +437,18 @@ void op_srl (void)
|
|||
RETURN();
|
||||
}
|
||||
|
||||
void op_rotr (void)
|
||||
{
|
||||
target_ulong tmp;
|
||||
|
||||
if (T1) {
|
||||
tmp = T0 << (0x20 - T1);
|
||||
T0 = (T0 >> T1) | tmp;
|
||||
} else
|
||||
T0 = T1;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_sllv (void)
|
||||
{
|
||||
T0 = T1 << (T0 & 0x1F);
|
||||
|
@ -455,6 +467,19 @@ void op_srlv (void)
|
|||
RETURN();
|
||||
}
|
||||
|
||||
void op_rotrv (void)
|
||||
{
|
||||
target_ulong tmp;
|
||||
|
||||
T0 &= 0x1F;
|
||||
if (T0) {
|
||||
tmp = T1 << (0x20 - T0);
|
||||
T0 = (T1 >> T0) | tmp;
|
||||
} else
|
||||
T0 = T1;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_clo (void)
|
||||
{
|
||||
int n;
|
||||
|
@ -602,6 +627,20 @@ void op_movz (void)
|
|||
RETURN();
|
||||
}
|
||||
|
||||
void op_movf (void)
|
||||
{
|
||||
if (!(env->fcr31 & PARAM1))
|
||||
env->gpr[PARAM2] = env->gpr[PARAM3];
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_movt (void)
|
||||
{
|
||||
if (env->fcr31 & PARAM1)
|
||||
env->gpr[PARAM2] = env->gpr[PARAM3];
|
||||
RETURN();
|
||||
}
|
||||
|
||||
/* Tests */
|
||||
#define OP_COND(name, cond) \
|
||||
void glue(op_, name) (void) \
|
||||
|
@ -625,28 +664,32 @@ OP_COND(gtz, (int32_t)T0 > 0);
|
|||
OP_COND(lez, (int32_t)T0 <= 0);
|
||||
OP_COND(ltz, (int32_t)T0 < 0);
|
||||
|
||||
/* Branchs */
|
||||
/* Branches */
|
||||
//#undef USE_DIRECT_JUMP
|
||||
|
||||
void OPPROTO op_goto_tb0(void)
|
||||
{
|
||||
GOTO_TB(op_goto_tb0, PARAM1, 0);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void OPPROTO op_goto_tb1(void)
|
||||
{
|
||||
GOTO_TB(op_goto_tb1, PARAM1, 1);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
/* Branch to register */
|
||||
void op_save_breg_target (void)
|
||||
{
|
||||
env->btarget = T2;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_restore_breg_target (void)
|
||||
{
|
||||
T2 = env->btarget;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_breg (void)
|
||||
|
@ -724,12 +767,24 @@ void op_mfc0_pagemask (void)
|
|||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_pagegrain (void)
|
||||
{
|
||||
T0 = env->CP0_PageGrain;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_wired (void)
|
||||
{
|
||||
T0 = env->CP0_Wired;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_hwrena (void)
|
||||
{
|
||||
T0 = env->CP0_HWREna;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_badvaddr (void)
|
||||
{
|
||||
T0 = env->CP0_BadVAddr;
|
||||
|
@ -766,6 +821,18 @@ void op_mfc0_status (void)
|
|||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_intctl (void)
|
||||
{
|
||||
T0 = env->CP0_IntCtl;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_srsctl (void)
|
||||
{
|
||||
T0 = env->CP0_SRSCtl;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_cause (void)
|
||||
{
|
||||
T0 = env->CP0_Cause;
|
||||
|
@ -784,6 +851,12 @@ void op_mfc0_prid (void)
|
|||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_ebase (void)
|
||||
{
|
||||
T0 = env->CP0_EBase;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_config0 (void)
|
||||
{
|
||||
T0 = env->CP0_Config0;
|
||||
|
@ -796,24 +869,48 @@ void op_mfc0_config1 (void)
|
|||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_config2 (void)
|
||||
{
|
||||
T0 = env->CP0_Config2;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_config3 (void)
|
||||
{
|
||||
T0 = env->CP0_Config3;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_lladdr (void)
|
||||
{
|
||||
T0 = env->CP0_LLAddr >> 4;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_watchlo (void)
|
||||
void op_mfc0_watchlo0 (void)
|
||||
{
|
||||
T0 = env->CP0_WatchLo;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_watchhi (void)
|
||||
void op_mfc0_watchhi0 (void)
|
||||
{
|
||||
T0 = env->CP0_WatchHi;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_xcontext (void)
|
||||
{
|
||||
T0 = env->CP0_XContext;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_framemask (void)
|
||||
{
|
||||
T0 = env->CP0_Framemask;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_debug (void)
|
||||
{
|
||||
T0 = env->CP0_Debug;
|
||||
|
@ -828,6 +925,12 @@ void op_mfc0_depc (void)
|
|||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_performance0 (void)
|
||||
{
|
||||
T0 = env->CP0_Performance0;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_taglo (void)
|
||||
{
|
||||
T0 = env->CP0_TagLo;
|
||||
|
@ -840,6 +943,18 @@ void op_mfc0_datalo (void)
|
|||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_taghi (void)
|
||||
{
|
||||
T0 = env->CP0_TagHi;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_datahi (void)
|
||||
{
|
||||
T0 = env->CP0_DataHi;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mfc0_errorepc (void)
|
||||
{
|
||||
T0 = env->CP0_ErrorEPC;
|
||||
|
@ -854,37 +969,57 @@ void op_mfc0_desave (void)
|
|||
|
||||
void op_mtc0_index (void)
|
||||
{
|
||||
env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F);
|
||||
env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1));
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_entrylo0 (void)
|
||||
{
|
||||
env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
|
||||
/* Large physaddr not implemented */
|
||||
/* 1k pages not implemented */
|
||||
env->CP0_EntryLo0 = T0 & 0x3FFFFFFFUL;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_entrylo1 (void)
|
||||
{
|
||||
env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
|
||||
/* Large physaddr not implemented */
|
||||
/* 1k pages not implemented */
|
||||
env->CP0_EntryLo1 = T0 & 0x3FFFFFFFUL;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_context (void)
|
||||
{
|
||||
env->CP0_Context = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0);
|
||||
env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_pagemask (void)
|
||||
{
|
||||
env->CP0_PageMask = T0 & 0x01FFE000;
|
||||
/* 1k pages not implemented */
|
||||
env->CP0_PageMask = T0 & 0x1FFFE000;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_pagegrain (void)
|
||||
{
|
||||
/* SmartMIPS not implemented */
|
||||
/* Large physaddr not implemented */
|
||||
/* 1k pages not implemented */
|
||||
env->CP0_PageGrain = 0;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_wired (void)
|
||||
{
|
||||
env->CP0_Wired = T0 & 0x0000000F;
|
||||
env->CP0_Wired = T0 & (MIPS_TLB_NB - 1);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_hwrena (void)
|
||||
{
|
||||
env->CP0_HWREna = T0 & 0x0000000F;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
|
@ -898,6 +1033,8 @@ void op_mtc0_entryhi (void)
|
|||
{
|
||||
uint32_t old, val;
|
||||
|
||||
/* 1k pages not implemented */
|
||||
/* Ignore MIPS64 TLB for now */
|
||||
val = T0 & 0xFFFFE0FF;
|
||||
old = env->CP0_EntryHi;
|
||||
env->CP0_EntryHi = val;
|
||||
|
@ -950,6 +1087,20 @@ void op_mtc0_status (void)
|
|||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_intctl (void)
|
||||
{
|
||||
/* vectored interrupts not implemented */
|
||||
env->CP0_IntCtl = 0;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_srsctl (void)
|
||||
{
|
||||
/* shadow registers not implemented */
|
||||
env->CP0_SRSCtl = 0;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_cause (void)
|
||||
{
|
||||
uint32_t val, old;
|
||||
|
@ -960,7 +1111,6 @@ void op_mtc0_cause (void)
|
|||
#if 0
|
||||
{
|
||||
int i, mask;
|
||||
|
||||
/* Check if we ever asserted a software IRQ */
|
||||
for (i = 0; i < 2; i++) {
|
||||
mask = 0x100 << i;
|
||||
|
@ -978,28 +1128,56 @@ void op_mtc0_epc (void)
|
|||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_ebase (void)
|
||||
{
|
||||
/* vectored interrupts not implemented */
|
||||
/* Multi-CPU not implemented */
|
||||
env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_config0 (void)
|
||||
{
|
||||
#if defined(MIPS_USES_R4K_TLB)
|
||||
env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001);
|
||||
/* Fixed mapping MMU not implemented */
|
||||
env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF88) | (T0 & 0x00000001);
|
||||
#else
|
||||
env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001);
|
||||
env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF88) | (T0 & 0x00000001);
|
||||
#endif
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_watchlo (void)
|
||||
void op_mtc0_config2 (void)
|
||||
{
|
||||
/* tertiary/secondary caches not implemented */
|
||||
env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_watchlo0 (void)
|
||||
{
|
||||
env->CP0_WatchLo = T0;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_watchhi (void)
|
||||
void op_mtc0_watchhi0 (void)
|
||||
{
|
||||
env->CP0_WatchHi = T0 & 0x40FF0FF8;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_xcontext (void)
|
||||
{
|
||||
env->CP0_XContext = T0; /* XXX */
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_framemask (void)
|
||||
{
|
||||
env->CP0_Framemask = T0; /* XXX */
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_debug (void)
|
||||
{
|
||||
env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
|
||||
|
@ -1016,12 +1194,36 @@ void op_mtc0_depc (void)
|
|||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_performance0 (void)
|
||||
{
|
||||
env->CP0_Performance0 = T0; /* XXX */
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_taglo (void)
|
||||
{
|
||||
env->CP0_TagLo = T0 & 0xFFFFFCF6;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_datalo (void)
|
||||
{
|
||||
env->CP0_DataLo = T0; /* XXX */
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_taghi (void)
|
||||
{
|
||||
env->CP0_TagHi = T0; /* XXX */
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_datahi (void)
|
||||
{
|
||||
env->CP0_DataHi = T0; /* XXX */
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_mtc0_errorepc (void)
|
||||
{
|
||||
env->CP0_ErrorEPC = T0;
|
||||
|
@ -1422,6 +1624,42 @@ void op_tlbr (void)
|
|||
void op_pmon (void)
|
||||
{
|
||||
CALL_FROM_TB1(do_pmon, PARAM1);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_di (void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
T0 = env->CP0_Status;
|
||||
val = T0 & ~(1 << CP0St_IE);
|
||||
if (val != T0) {
|
||||
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
|
||||
env->CP0_Status = val;
|
||||
}
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_ei (void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
T0 = env->CP0_Status;
|
||||
val = T0 | (1 << CP0St_IE);
|
||||
if (val != T0) {
|
||||
const uint32_t mask = 0x0000FF00;
|
||||
|
||||
env->CP0_Status = val;
|
||||
if (!(env->hflags & MIPS_HFLAG_EXL) &&
|
||||
!(env->hflags & MIPS_HFLAG_ERL) &&
|
||||
!(env->hflags & MIPS_HFLAG_DM) &&
|
||||
(env->CP0_Status & env->CP0_Cause & mask)) {
|
||||
env->interrupt_request |= CPU_INTERRUPT_HARD;
|
||||
if (logfile)
|
||||
CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
|
||||
}
|
||||
}
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_trap (void)
|
||||
|
@ -1434,12 +1672,14 @@ void op_trap (void)
|
|||
|
||||
void op_debug (void)
|
||||
{
|
||||
CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
|
||||
CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_set_lladdr (void)
|
||||
{
|
||||
env->CP0_LLAddr = T2;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void debug_eret (void);
|
||||
|
@ -1456,12 +1696,50 @@ void op_eret (void)
|
|||
env->CP0_Status &= ~(1 << CP0St_EXL);
|
||||
}
|
||||
env->CP0_LLAddr = 1;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_deret (void)
|
||||
{
|
||||
CALL_FROM_TB0(debug_eret);
|
||||
env->PC = env->CP0_DEPC;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_rdhwr_cpunum(void)
|
||||
{
|
||||
if (env->CP0_HWREna & (1 << 0))
|
||||
T0 = env->CP0_EBase & 0x2ff;
|
||||
else
|
||||
CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_rdhwr_synci_step(void)
|
||||
{
|
||||
if (env->CP0_HWREna & (1 << 1))
|
||||
T0 = env->SYNCI_Step;
|
||||
else
|
||||
CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_rdhwr_cc(void)
|
||||
{
|
||||
if (env->CP0_HWREna & (1 << 2))
|
||||
T0 = env->CP0_Count;
|
||||
else
|
||||
CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_rdhwr_ccres(void)
|
||||
{
|
||||
if (env->CP0_HWREna & (1 << 3))
|
||||
T0 = env->CCRes;
|
||||
else
|
||||
CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_save_state (void)
|
||||
|
@ -1491,10 +1769,62 @@ void op_raise_exception_err (void)
|
|||
void op_exit_tb (void)
|
||||
{
|
||||
EXIT_TB();
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_wait (void)
|
||||
{
|
||||
env->halted = 1;
|
||||
CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
/* Bitfield operations. */
|
||||
void op_ext(void)
|
||||
{
|
||||
unsigned int pos = PARAM1;
|
||||
unsigned int size = PARAM2;
|
||||
|
||||
T0 = (T1 >> pos) & ((1 << size) - 1);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_ins(void)
|
||||
{
|
||||
unsigned int pos = PARAM1;
|
||||
unsigned int size = PARAM2;
|
||||
target_ulong mask = ((1 << size) - 1) << pos;
|
||||
|
||||
T0 = (T2 & ~mask) | ((T1 << pos) & mask);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_wsbh(void)
|
||||
{
|
||||
T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_dsbh(void)
|
||||
{
|
||||
T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_dshd(void)
|
||||
{
|
||||
T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_seb(void)
|
||||
{
|
||||
T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void op_seh(void)
|
||||
{
|
||||
T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
|
||||
RETURN();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue