* [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support @ 2009-11-23 20:49 Nathan Froyd 2009-11-23 20:49 ` [Qemu-devel] [PATCH 01/11] target-mips: add ISAMode bits for mips16 execution Nathan Froyd ` (11 more replies) 0 siblings, 12 replies; 18+ messages in thread From: Nathan Froyd @ 2009-11-23 20:49 UTC (permalink / raw) To: qemu-devel This patchset adds MIPS16 support to the MIPS backend. MIPS16 is a compact encoding of a subset of the MIPS integer instructions, similar to ARM's Thumb mode. The processor enters MIPS16 mode by executing a special jump instruction; execution continus at the jump target in MIPS16 mode until the processor returns to MIPS32/64 mode by executing a special jump instruction. The patches have been tested with GCC's testsuite and GDB's testsuite. -Nathan ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH 01/11] target-mips: add ISAMode bits for mips16 execution 2009-11-23 20:49 [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Nathan Froyd @ 2009-11-23 20:49 ` Nathan Froyd 2009-11-28 10:17 ` Aurelien Jarno 2009-11-23 20:50 ` [Qemu-devel] [PATCH 02/11] target-mips: add new HFLAGs for JALX and 16/32-bit delay slots Nathan Froyd ` (10 subsequent siblings) 11 siblings, 1 reply; 18+ messages in thread From: Nathan Froyd @ 2009-11-23 20:49 UTC (permalink / raw) To: qemu-devel Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/cpu.h | 1 + target-mips/translate.c | 2 ++ 2 files changed, 3 insertions(+), 0 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 82f9a38..e8febe6 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -167,6 +167,7 @@ struct TCState { target_ulong CP0_TCContext; target_ulong CP0_TCSchedule; target_ulong CP0_TCScheFBack; + uint32_t ISAMode; /* MIPS32 or MIPS16 mode */ int32_t CP0_Debug_tcstatus; }; diff --git a/target-mips/translate.c b/target-mips/translate.c index e9d9224..b0a1b29 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -463,6 +463,7 @@ typedef struct DisasContext { struct TranslationBlock *tb; target_ulong pc, saved_pc; uint32_t opcode; + int isa_mode; int singlestep_enabled; /* Routine used to access memory */ int mem_idx; @@ -8306,6 +8307,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, ctx.pc = pc_start; ctx.saved_pc = -1; ctx.singlestep_enabled = env->singlestep_enabled; + ctx.isa_mode = env->active_tc.ISAMode; ctx.tb = tb; ctx.bstate = BS_NONE; /* Restore delay slot state from the tb context. */ -- 1.6.3.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 01/11] target-mips: add ISAMode bits for mips16 execution 2009-11-23 20:49 ` [Qemu-devel] [PATCH 01/11] target-mips: add ISAMode bits for mips16 execution Nathan Froyd @ 2009-11-28 10:17 ` Aurelien Jarno 2009-11-30 17:45 ` Aurelien Jarno 0 siblings, 1 reply; 18+ messages in thread From: Aurelien Jarno @ 2009-11-28 10:17 UTC (permalink / raw) To: Nathan Froyd; +Cc: qemu-devel On Mon, Nov 23, 2009 at 12:49:59PM -0800, Nathan Froyd wrote: > > Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> > --- > target-mips/cpu.h | 1 + > target-mips/translate.c | 2 ++ > 2 files changed, 3 insertions(+), 0 deletions(-) > > diff --git a/target-mips/cpu.h b/target-mips/cpu.h > index 82f9a38..e8febe6 100644 > --- a/target-mips/cpu.h > +++ b/target-mips/cpu.h > @@ -167,6 +167,7 @@ struct TCState { > target_ulong CP0_TCContext; > target_ulong CP0_TCSchedule; > target_ulong CP0_TCScheFBack; > + uint32_t ISAMode; /* MIPS32 or MIPS16 mode */ > int32_t CP0_Debug_tcstatus; > }; I am fine with this. > diff --git a/target-mips/translate.c b/target-mips/translate.c > index e9d9224..b0a1b29 100644 > --- a/target-mips/translate.c > +++ b/target-mips/translate.c > @@ -463,6 +463,7 @@ typedef struct DisasContext { > struct TranslationBlock *tb; > target_ulong pc, saved_pc; > uint32_t opcode; > + int isa_mode; > int singlestep_enabled; > /* Routine used to access memory */ > int mem_idx; > @@ -8306,6 +8307,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, > ctx.pc = pc_start; > ctx.saved_pc = -1; > ctx.singlestep_enabled = env->singlestep_enabled; > + ctx.isa_mode = env->active_tc.ISAMode; > ctx.tb = tb; > ctx.bstate = BS_NONE; > /* Restore delay slot state from the tb context. */ Instead of a new ctx value, it's probably better to use a new bit in hflags. It is also necessary to change MIPS_HFLAG_TMASK accordingly, to ensure a MIPS16 translation block is not later executed while ISAMode is 0 (while it should generate an exception) and vice-versa. This also mean that hflags should be recomputed each time ISAMode is changed. -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurelien@aurel32.net http://www.aurel32.net ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 01/11] target-mips: add ISAMode bits for mips16 execution 2009-11-28 10:17 ` Aurelien Jarno @ 2009-11-30 17:45 ` Aurelien Jarno 0 siblings, 0 replies; 18+ messages in thread From: Aurelien Jarno @ 2009-11-30 17:45 UTC (permalink / raw) To: Nathan Froyd; +Cc: qemu-devel On Sat, Nov 28, 2009 at 11:17:20AM +0100, Aurelien Jarno wrote: > On Mon, Nov 23, 2009 at 12:49:59PM -0800, Nathan Froyd wrote: > > > > Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> > > --- > > target-mips/cpu.h | 1 + > > target-mips/translate.c | 2 ++ > > 2 files changed, 3 insertions(+), 0 deletions(-) > > > > diff --git a/target-mips/cpu.h b/target-mips/cpu.h > > index 82f9a38..e8febe6 100644 > > --- a/target-mips/cpu.h > > +++ b/target-mips/cpu.h > > @@ -167,6 +167,7 @@ struct TCState { > > target_ulong CP0_TCContext; > > target_ulong CP0_TCSchedule; > > target_ulong CP0_TCScheFBack; > > + uint32_t ISAMode; /* MIPS32 or MIPS16 mode */ > > int32_t CP0_Debug_tcstatus; > > }; > > I am fine with this. > > > diff --git a/target-mips/translate.c b/target-mips/translate.c > > index e9d9224..b0a1b29 100644 > > --- a/target-mips/translate.c > > +++ b/target-mips/translate.c > > @@ -463,6 +463,7 @@ typedef struct DisasContext { > > struct TranslationBlock *tb; > > target_ulong pc, saved_pc; > > uint32_t opcode; > > + int isa_mode; > > int singlestep_enabled; > > /* Routine used to access memory */ > > int mem_idx; > > @@ -8306,6 +8307,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, > > ctx.pc = pc_start; > > ctx.saved_pc = -1; > > ctx.singlestep_enabled = env->singlestep_enabled; > > + ctx.isa_mode = env->active_tc.ISAMode; > > ctx.tb = tb; > > ctx.bstate = BS_NONE; > > /* Restore delay slot state from the tb context. */ > > Instead of a new ctx value, it's probably better to use a new bit in > hflags. It is also necessary to change MIPS_HFLAG_TMASK accordingly, to > ensure a MIPS16 translation block is not later executed while ISAMode is > 0 (while it should generate an exception) and vice-versa. > > This also mean that hflags should be recomputed each time ISAMode is > changed. > Actually just changing ctx.hflags is enough, as it is automatically saved to env->hflags at the end of the TB or if an exception can occur. -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurelien@aurel32.net http://www.aurel32.net ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH 02/11] target-mips: add new HFLAGs for JALX and 16/32-bit delay slots 2009-11-23 20:49 [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Nathan Froyd 2009-11-23 20:49 ` [Qemu-devel] [PATCH 01/11] target-mips: add ISAMode bits for mips16 execution Nathan Froyd @ 2009-11-23 20:50 ` Nathan Froyd 2009-11-23 20:50 ` [Qemu-devel] [PATCH 03/11] target-mips: change interrupt bits to be mips16-aware Nathan Froyd ` (9 subsequent siblings) 11 siblings, 0 replies; 18+ messages in thread From: Nathan Froyd @ 2009-11-23 20:50 UTC (permalink / raw) To: qemu-devel We create separate masks for the "basic" branch hflags and the "extended" branch hflags and define MIPS_HFLAG_BMASK as the logical or of those two. This is done to avoid churning the codebase in lots of different places. Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/cpu.h | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index e8febe6..9413be0 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -441,11 +441,17 @@ struct CPUMIPSState { * the delay slot, record what type of branch it is so that we can * resume translation properly. It might be possible to reduce * this from three bits to two. */ -#define MIPS_HFLAG_BMASK 0x1C00 +#define MIPS_HFLAG_BMASK_BASE 0x1C00 #define MIPS_HFLAG_B 0x0400 /* Unconditional branch */ #define MIPS_HFLAG_BC 0x0800 /* Conditional branch */ #define MIPS_HFLAG_BL 0x0C00 /* Likely branch */ #define MIPS_HFLAG_BR 0x1000 /* branch to register (can't link TB) */ + /* Extra flags about the current pending branch. */ +#define MIPS_HFLAG_BMASK_EXT 0xE000 +#define MIPS_HFLAG_BDS16 0x2000 /* branch requires 16-bit delay slot */ +#define MIPS_HFLAG_BDS32 0x4000 /* branch requires 32-bit delay slot */ +#define MIPS_HFLAG_BX 0x8000 /* branch exchange execution mode */ +#define MIPS_HFLAG_BMASK (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT) target_ulong btarget; /* Jump / branch target */ target_ulong bcond; /* Branch condition (if needed) */ -- 1.6.3.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH 03/11] target-mips: change interrupt bits to be mips16-aware 2009-11-23 20:49 [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Nathan Froyd 2009-11-23 20:49 ` [Qemu-devel] [PATCH 01/11] target-mips: add ISAMode bits for mips16 execution Nathan Froyd 2009-11-23 20:50 ` [Qemu-devel] [PATCH 02/11] target-mips: add new HFLAGs for JALX and 16/32-bit delay slots Nathan Froyd @ 2009-11-23 20:50 ` Nathan Froyd 2009-11-28 10:17 ` Aurelien Jarno 2009-11-23 20:50 ` [Qemu-devel] [PATCH 04/11] target-mips: move ROTR and ROTRV inside gen_shift_{imm, } Nathan Froyd ` (8 subsequent siblings) 11 siblings, 1 reply; 18+ messages in thread From: Nathan Froyd @ 2009-11-23 20:50 UTC (permalink / raw) To: qemu-devel Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/helper.c | 47 ++++++++++++++++++++++++++--------------------- target-mips/op_helper.c | 10 +++++++--- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index 4a37277..e54a31a 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -339,6 +339,20 @@ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_CACHE] = "cache error", }; +static target_ulong exception_resume_pc (CPUState *env) +{ + target_ulong bad_pc; + + bad_pc = env->active_tc.PC | env->active_tc.ISAMode; + if (env->hflags & MIPS_HFLAG_BMASK) { + /* If the exception was raised from a delay slot, come back to + the jump. */ + bad_pc -= (env->hflags & MIPS_HFLAG_BDS16 ? 2 : 4); + } + + return bad_pc; +} + void do_interrupt (CPUState *env) { #if !defined(CONFIG_USER_ONLY) @@ -366,7 +380,7 @@ void do_interrupt (CPUState *env) resume will always occur on the next instruction (but we assume the pc has always been updated during code translation). */ - env->CP0_DEPC = env->active_tc.PC; + env->CP0_DEPC = env->active_tc.PC | env->active_tc.ISAMode; goto enter_debug_mode; case EXCP_DINT: env->CP0_Debug |= 1 << CP0DB_DINT; @@ -383,14 +397,8 @@ void do_interrupt (CPUState *env) case EXCP_DDBL: env->CP0_Debug |= 1 << CP0DB_DDBL; set_DEPC: - if (env->hflags & MIPS_HFLAG_BMASK) { - /* If the exception was raised from a delay slot, - come back to the jump. */ - env->CP0_DEPC = env->active_tc.PC - 4; - env->hflags &= ~MIPS_HFLAG_BMASK; - } else { - env->CP0_DEPC = env->active_tc.PC; - } + env->CP0_DEPC = exception_resume_pc(env); + env->hflags &= ~MIPS_HFLAG_BMASK; enter_debug_mode: env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0; env->hflags &= ~(MIPS_HFLAG_KSU); @@ -398,6 +406,8 @@ void do_interrupt (CPUState *env) if (!(env->CP0_Status & (1 << CP0St_EXL))) env->CP0_Cause &= ~(1 << CP0Ca_BD); env->active_tc.PC = (int32_t)0xBFC00480; + /* Exception handlers are entered in 32-bit mode. */ + env->active_tc.ISAMode = 0; break; case EXCP_RESET: cpu_reset(env); @@ -409,20 +419,16 @@ void do_interrupt (CPUState *env) case EXCP_NMI: env->CP0_Status |= (1 << CP0St_NMI); set_error_EPC: - if (env->hflags & MIPS_HFLAG_BMASK) { - /* If the exception was raised from a delay slot, - come back to the jump. */ - env->CP0_ErrorEPC = env->active_tc.PC - 4; - env->hflags &= ~MIPS_HFLAG_BMASK; - } else { - env->CP0_ErrorEPC = env->active_tc.PC; - } + env->CP0_ErrorEPC = exception_resume_pc(env); + env->hflags &= ~MIPS_HFLAG_BMASK; env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; env->hflags &= ~(MIPS_HFLAG_KSU); if (!(env->CP0_Status & (1 << CP0St_EXL))) env->CP0_Cause &= ~(1 << CP0Ca_BD); env->active_tc.PC = (int32_t)0xBFC00000; + /* Exception handlers are entered in 32-bit mode. */ + env->active_tc.ISAMode = 0; break; case EXCP_EXT_INTERRUPT: cause = 0; @@ -524,13 +530,10 @@ void do_interrupt (CPUState *env) } set_EPC: if (!(env->CP0_Status & (1 << CP0St_EXL))) { + env->CP0_EPC = exception_resume_pc(env); if (env->hflags & MIPS_HFLAG_BMASK) { - /* If the exception was raised from a delay slot, - come back to the jump. */ - env->CP0_EPC = env->active_tc.PC - 4; env->CP0_Cause |= (1 << CP0Ca_BD); } else { - env->CP0_EPC = env->active_tc.PC; env->CP0_Cause &= ~(1 << CP0Ca_BD); } env->CP0_Status |= (1 << CP0St_EXL); @@ -544,6 +547,8 @@ void do_interrupt (CPUState *env) env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff); } env->active_tc.PC += offset; + /* Exception handlers are entered in 32-bit mode. */ + env->active_tc.ISAMode = 0; env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC); break; default: diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 52d687d..d585d65 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1701,10 +1701,12 @@ void helper_eret (void) { debug_pre_eret(); if (env->CP0_Status & (1 << CP0St_ERL)) { - env->active_tc.PC = env->CP0_ErrorEPC; + env->active_tc.PC = env->CP0_ErrorEPC & ~(target_ulong)1; + env->active_tc.ISAMode = env->CP0_ErrorEPC & 1; env->CP0_Status &= ~(1 << CP0St_ERL); } else { - env->active_tc.PC = env->CP0_EPC; + env->active_tc.PC = env->CP0_EPC & ~(target_ulong)1; + env->active_tc.ISAMode = env->CP0_EPC & 1; env->CP0_Status &= ~(1 << CP0St_EXL); } compute_hflags(env); @@ -1715,7 +1717,9 @@ void helper_eret (void) void helper_deret (void) { debug_pre_eret(); - env->active_tc.PC = env->CP0_DEPC; + env->active_tc.PC = env->CP0_DEPC & ~(target_ulong)1; + env->active_tc.ISAMode = env->CP0_DEPC & 1; + env->hflags &= MIPS_HFLAG_DM; compute_hflags(env); debug_post_eret(); -- 1.6.3.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 03/11] target-mips: change interrupt bits to be mips16-aware 2009-11-23 20:50 ` [Qemu-devel] [PATCH 03/11] target-mips: change interrupt bits to be mips16-aware Nathan Froyd @ 2009-11-28 10:17 ` Aurelien Jarno 0 siblings, 0 replies; 18+ messages in thread From: Aurelien Jarno @ 2009-11-28 10:17 UTC (permalink / raw) To: Nathan Froyd; +Cc: qemu-devel On Mon, Nov 23, 2009 at 12:50:01PM -0800, Nathan Froyd wrote: > > Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> > --- > target-mips/helper.c | 47 ++++++++++++++++++++++++++--------------------- > target-mips/op_helper.c | 10 +++++++--- > 2 files changed, 33 insertions(+), 24 deletions(-) > > diff --git a/target-mips/helper.c b/target-mips/helper.c > index 4a37277..e54a31a 100644 > --- a/target-mips/helper.c > +++ b/target-mips/helper.c > @@ -339,6 +339,20 @@ static const char * const excp_names[EXCP_LAST + 1] = { > [EXCP_CACHE] = "cache error", > }; > > +static target_ulong exception_resume_pc (CPUState *env) > +{ > + target_ulong bad_pc; > + > + bad_pc = env->active_tc.PC | env->active_tc.ISAMode; > + if (env->hflags & MIPS_HFLAG_BMASK) { > + /* If the exception was raised from a delay slot, come back to > + the jump. */ > + bad_pc -= (env->hflags & MIPS_HFLAG_BDS16 ? 2 : 4); > + } > + > + return bad_pc; > +} This function is only used on softmmu target. This breaks compilation of linux-user targets, it should be protected with: #if !defined(CONFIG_USER_ONLY) #endif > void do_interrupt (CPUState *env) > { > #if !defined(CONFIG_USER_ONLY) > @@ -366,7 +380,7 @@ void do_interrupt (CPUState *env) > resume will always occur on the next instruction > (but we assume the pc has always been updated during > code translation). */ > - env->CP0_DEPC = env->active_tc.PC; > + env->CP0_DEPC = env->active_tc.PC | env->active_tc.ISAMode; > goto enter_debug_mode; > case EXCP_DINT: > env->CP0_Debug |= 1 << CP0DB_DINT; > @@ -383,14 +397,8 @@ void do_interrupt (CPUState *env) > case EXCP_DDBL: > env->CP0_Debug |= 1 << CP0DB_DDBL; > set_DEPC: > - if (env->hflags & MIPS_HFLAG_BMASK) { > - /* If the exception was raised from a delay slot, > - come back to the jump. */ > - env->CP0_DEPC = env->active_tc.PC - 4; > - env->hflags &= ~MIPS_HFLAG_BMASK; > - } else { > - env->CP0_DEPC = env->active_tc.PC; > - } > + env->CP0_DEPC = exception_resume_pc(env); > + env->hflags &= ~MIPS_HFLAG_BMASK; > enter_debug_mode: > env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0; > env->hflags &= ~(MIPS_HFLAG_KSU); > @@ -398,6 +406,8 @@ void do_interrupt (CPUState *env) > if (!(env->CP0_Status & (1 << CP0St_EXL))) > env->CP0_Cause &= ~(1 << CP0Ca_BD); > env->active_tc.PC = (int32_t)0xBFC00480; > + /* Exception handlers are entered in 32-bit mode. */ > + env->active_tc.ISAMode = 0; > break; > case EXCP_RESET: > cpu_reset(env); > @@ -409,20 +419,16 @@ void do_interrupt (CPUState *env) > case EXCP_NMI: > env->CP0_Status |= (1 << CP0St_NMI); > set_error_EPC: > - if (env->hflags & MIPS_HFLAG_BMASK) { > - /* If the exception was raised from a delay slot, > - come back to the jump. */ > - env->CP0_ErrorEPC = env->active_tc.PC - 4; > - env->hflags &= ~MIPS_HFLAG_BMASK; > - } else { > - env->CP0_ErrorEPC = env->active_tc.PC; > - } > + env->CP0_ErrorEPC = exception_resume_pc(env); > + env->hflags &= ~MIPS_HFLAG_BMASK; > env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); > env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; > env->hflags &= ~(MIPS_HFLAG_KSU); > if (!(env->CP0_Status & (1 << CP0St_EXL))) > env->CP0_Cause &= ~(1 << CP0Ca_BD); > env->active_tc.PC = (int32_t)0xBFC00000; > + /* Exception handlers are entered in 32-bit mode. */ > + env->active_tc.ISAMode = 0; > break; > case EXCP_EXT_INTERRUPT: > cause = 0; > @@ -524,13 +530,10 @@ void do_interrupt (CPUState *env) > } > set_EPC: > if (!(env->CP0_Status & (1 << CP0St_EXL))) { > + env->CP0_EPC = exception_resume_pc(env); > if (env->hflags & MIPS_HFLAG_BMASK) { > - /* If the exception was raised from a delay slot, > - come back to the jump. */ > - env->CP0_EPC = env->active_tc.PC - 4; > env->CP0_Cause |= (1 << CP0Ca_BD); > } else { > - env->CP0_EPC = env->active_tc.PC; > env->CP0_Cause &= ~(1 << CP0Ca_BD); > } > env->CP0_Status |= (1 << CP0St_EXL); > @@ -544,6 +547,8 @@ void do_interrupt (CPUState *env) > env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff); > } > env->active_tc.PC += offset; > + /* Exception handlers are entered in 32-bit mode. */ > + env->active_tc.ISAMode = 0; > env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC); > break; > default: > diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c > index 52d687d..d585d65 100644 > --- a/target-mips/op_helper.c > +++ b/target-mips/op_helper.c > @@ -1701,10 +1701,12 @@ void helper_eret (void) > { > debug_pre_eret(); > if (env->CP0_Status & (1 << CP0St_ERL)) { > - env->active_tc.PC = env->CP0_ErrorEPC; > + env->active_tc.PC = env->CP0_ErrorEPC & ~(target_ulong)1; > + env->active_tc.ISAMode = env->CP0_ErrorEPC & 1; > env->CP0_Status &= ~(1 << CP0St_ERL); > } else { > - env->active_tc.PC = env->CP0_EPC; > + env->active_tc.PC = env->CP0_EPC & ~(target_ulong)1; > + env->active_tc.ISAMode = env->CP0_EPC & 1; > env->CP0_Status &= ~(1 << CP0St_EXL); > } > compute_hflags(env); > @@ -1715,7 +1717,9 @@ void helper_eret (void) > void helper_deret (void) > { > debug_pre_eret(); > - env->active_tc.PC = env->CP0_DEPC; > + env->active_tc.PC = env->CP0_DEPC & ~(target_ulong)1; > + env->active_tc.ISAMode = env->CP0_DEPC & 1; > + > env->hflags &= MIPS_HFLAG_DM; > compute_hflags(env); > debug_post_eret(); > -- > 1.6.3.2 > > > > -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurelien@aurel32.net http://www.aurel32.net ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH 04/11] target-mips: move ROTR and ROTRV inside gen_shift_{imm, } 2009-11-23 20:49 [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Nathan Froyd ` (2 preceding siblings ...) 2009-11-23 20:50 ` [Qemu-devel] [PATCH 03/11] target-mips: change interrupt bits to be mips16-aware Nathan Froyd @ 2009-11-23 20:50 ` Nathan Froyd 2009-11-23 20:50 ` [Qemu-devel] [PATCH 05/11] target-mips: make gen_compute_branch 16/32-bit-aware Nathan Froyd ` (7 subsequent siblings) 11 siblings, 0 replies; 18+ messages in thread From: Nathan Froyd @ 2009-11-23 20:50 UTC (permalink / raw) To: qemu-devel It's easier to implement mips16 shift instructions if we're not examining the opcode inside gen_shift_{imm,}. So move ROTR and ROTRV and do the special-case handling of SRL and SRLV inside decode_opc. Likewise for their 64-bit counterparts. Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/translate.c | 287 ++++++++++++++++++++++++----------------------- 1 files changed, 148 insertions(+), 139 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index b0a1b29..c03d1bf 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -128,18 +128,23 @@ enum { /* SSNOP is SLL r0, r0, 1 */ /* EHB is SLL r0, r0, 3 */ OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */ + OPC_ROTR = OPC_SRL | (1 << 21), OPC_SRA = 0x03 | OPC_SPECIAL, OPC_SLLV = 0x04 | OPC_SPECIAL, OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */ + OPC_ROTRV = OPC_SRLV | (1 << 6), OPC_SRAV = 0x07 | OPC_SPECIAL, OPC_DSLLV = 0x14 | OPC_SPECIAL, OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */ + OPC_DROTRV = OPC_DSRLV | (1 << 6), OPC_DSRAV = 0x17 | OPC_SPECIAL, OPC_DSLL = 0x38 | OPC_SPECIAL, OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */ + OPC_DROTR = OPC_DSRL | (1 << 21), OPC_DSRA = 0x3B | OPC_SPECIAL, OPC_DSLL32 = 0x3C | OPC_SPECIAL, OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */ + OPC_DROTR32 = OPC_DSRL32 | (1 << 21), OPC_DSRA32 = 0x3F | OPC_SPECIAL, /* Multiplication / division */ OPC_MULT = 0x18 | OPC_SPECIAL, @@ -1447,43 +1452,24 @@ static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc, opn = "sra"; break; case OPC_SRL: - switch ((ctx->opcode >> 21) & 0x1f) { - case 0: - if (uimm != 0) { - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm); - } else { - tcg_gen_ext32s_tl(cpu_gpr[rt], t0); - } - opn = "srl"; - break; - case 1: - /* rotr is decoded as srl on non-R2 CPUs */ - if (env->insn_flags & ISA_MIPS32R2) { - if (uimm != 0) { - TCGv_i32 t1 = tcg_temp_new_i32(); - - tcg_gen_trunc_tl_i32(t1, t0); - tcg_gen_rotri_i32(t1, t1, uimm); - tcg_gen_ext_i32_tl(cpu_gpr[rt], t1); - tcg_temp_free_i32(t1); - } - opn = "rotr"; - } else { - if (uimm != 0) { - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm); - } else { - tcg_gen_ext32s_tl(cpu_gpr[rt], t0); - } - opn = "srl"; - } - break; - default: - MIPS_INVAL("invalid srl flag"); - generate_exception(ctx, EXCP_RI); - break; + if (uimm != 0) { + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm); + } else { + tcg_gen_ext32s_tl(cpu_gpr[rt], t0); } + opn = "srl"; + break; + case OPC_ROTR: + if (uimm != 0) { + TCGv_i32 t1 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(t1, t0); + tcg_gen_rotri_i32(t1, t1, uimm); + tcg_gen_ext_i32_tl(cpu_gpr[rt], t1); + tcg_temp_free_i32(t1); + } + opn = "rotr"; break; #if defined(TARGET_MIPS64) case OPC_DSLL: @@ -1495,28 +1481,14 @@ static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc, opn = "dsra"; break; case OPC_DSRL: - switch ((ctx->opcode >> 21) & 0x1f) { - case 0: - tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm); - opn = "dsrl"; - break; - case 1: - /* drotr is decoded as dsrl on non-R2 CPUs */ - if (env->insn_flags & ISA_MIPS32R2) { - if (uimm != 0) { - tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm); - } - opn = "drotr"; - } else { - tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm); - opn = "dsrl"; - } - break; - default: - MIPS_INVAL("invalid dsrl flag"); - generate_exception(ctx, EXCP_RI); - break; + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm); + opn = "dsrl"; + break; + case OPC_DROTR: + if (uimm != 0) { + tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm); } + opn = "drotr"; break; case OPC_DSLL32: tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32); @@ -1527,26 +1499,12 @@ static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc, opn = "dsra32"; break; case OPC_DSRL32: - switch ((ctx->opcode >> 21) & 0x1f) { - case 0: - tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32); - opn = "dsrl32"; - break; - case 1: - /* drotr32 is decoded as dsrl32 on non-R2 CPUs */ - if (env->insn_flags & ISA_MIPS32R2) { - tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32); - opn = "drotr32"; - } else { - tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32); - opn = "dsrl32"; - } - break; - default: - MIPS_INVAL("invalid dsrl32 flag"); - generate_exception(ctx, EXCP_RI); - break; - } + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32); + opn = "dsrl32"; + break; + case OPC_DROTR32: + tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32); + opn = "drotr32"; break; #endif } @@ -1895,40 +1853,25 @@ static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc, opn = "srav"; break; case OPC_SRLV: - switch ((ctx->opcode >> 6) & 0x1f) { - case 0: - tcg_gen_ext32u_tl(t1, t1); - tcg_gen_andi_tl(t0, t0, 0x1f); - tcg_gen_shr_tl(t0, t1, t0); - tcg_gen_ext32s_tl(cpu_gpr[rd], t0); - opn = "srlv"; - break; - case 1: - /* rotrv is decoded as srlv on non-R2 CPUs */ - if (env->insn_flags & ISA_MIPS32R2) { - TCGv_i32 t2 = tcg_temp_new_i32(); - TCGv_i32 t3 = tcg_temp_new_i32(); - - tcg_gen_trunc_tl_i32(t2, t0); - tcg_gen_trunc_tl_i32(t3, t1); - tcg_gen_andi_i32(t2, t2, 0x1f); - tcg_gen_rotr_i32(t2, t3, t2); - tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); - tcg_temp_free_i32(t2); - tcg_temp_free_i32(t3); - opn = "rotrv"; - } else { - tcg_gen_ext32u_tl(t1, t1); - tcg_gen_andi_tl(t0, t0, 0x1f); - tcg_gen_shr_tl(t0, t1, t0); - tcg_gen_ext32s_tl(cpu_gpr[rd], t0); - opn = "srlv"; - } - break; - default: - MIPS_INVAL("invalid srlv flag"); - generate_exception(ctx, EXCP_RI); - break; + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_andi_tl(t0, t0, 0x1f); + tcg_gen_shr_tl(t0, t1, t0); + tcg_gen_ext32s_tl(cpu_gpr[rd], t0); + opn = "srlv"; + break; + case OPC_ROTRV: + { + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_andi_i32(t2, t2, 0x1f); + tcg_gen_rotr_i32(t2, t3, t2); + tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + opn = "rotrv"; } break; #if defined(TARGET_MIPS64) @@ -1943,29 +1886,14 @@ static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc, opn = "dsrav"; break; case OPC_DSRLV: - switch ((ctx->opcode >> 6) & 0x1f) { - case 0: - tcg_gen_andi_tl(t0, t0, 0x3f); - tcg_gen_shr_tl(cpu_gpr[rd], t1, t0); - opn = "dsrlv"; - break; - case 1: - /* drotrv is decoded as dsrlv on non-R2 CPUs */ - if (env->insn_flags & ISA_MIPS32R2) { - tcg_gen_andi_tl(t0, t0, 0x3f); - tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0); - opn = "drotrv"; - } else { - tcg_gen_andi_tl(t0, t0, 0x3f); - tcg_gen_shr_tl(t0, t1, t0); - opn = "dsrlv"; - } - break; - default: - MIPS_INVAL("invalid dsrlv flag"); - generate_exception(ctx, EXCP_RI); - break; - } + tcg_gen_andi_tl(t0, t0, 0x3f); + tcg_gen_shr_tl(cpu_gpr[rd], t1, t0); + opn = "dsrlv"; + break; + case OPC_DROTRV: + tcg_gen_andi_tl(t0, t0, 0x3f); + tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0); + opn = "drotrv"; break; #endif } @@ -7677,9 +7605,24 @@ static void decode_opc (CPUState *env, DisasContext *ctx) switch (op1) { case OPC_SLL: /* Shift with immediate */ case OPC_SRA: - case OPC_SRL: gen_shift_imm(env, ctx, op1, rd, rt, sa); break; + case OPC_SRL: + switch ((ctx->opcode >> 21) & 0x1f) { + case 1: + /* rotr is decoded as srl on non-R2 CPUs */ + if (env->insn_flags & ISA_MIPS32R2) { + op1 = OPC_ROTR; + } + /* Fallthrough */ + case 0: + gen_shift_imm(env, ctx, op1, rd, rt, sa); + break; + default: + generate_exception(ctx, EXCP_RI); + break; + } + break; case OPC_MOVN: /* Conditional move */ case OPC_MOVZ: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32); @@ -7689,10 +7632,25 @@ static void decode_opc (CPUState *env, DisasContext *ctx) gen_arith(env, ctx, op1, rd, rs, rt); break; case OPC_SLLV: /* Shifts */ - case OPC_SRLV: case OPC_SRAV: gen_shift(env, ctx, op1, rd, rs, rt); break; + case OPC_SRLV: + switch ((ctx->opcode >> 6) & 0x1f) { + case 1: + /* rotrv is decoded as srlv on non-R2 CPUs */ + if (env->insn_flags & ISA_MIPS32R2) { + op1 = OPC_ROTRV; + } + /* Fallthrough */ + case 0: + gen_shift(env, ctx, op1, rd, rs, rt); + break; + default: + generate_exception(ctx, EXCP_RI); + break; + } + break; case OPC_SLT: /* Set on less than */ case OPC_SLTU: gen_slt(env, op1, rd, rs, rt); @@ -7770,14 +7728,48 @@ static void decode_opc (CPUState *env, DisasContext *ctx) /* MIPS64 specific opcodes */ case OPC_DSLL: case OPC_DSRA: - case OPC_DSRL: case OPC_DSLL32: case OPC_DSRA32: - case OPC_DSRL32: check_insn(env, ctx, ISA_MIPS3); check_mips_64(ctx); gen_shift_imm(env, ctx, op1, rd, rt, sa); break; + case OPC_DSRL: + switch ((ctx->opcode >> 21) & 0x1f) { + case 1: + /* drotr is decoded as dsrl on non-R2 CPUs */ + if (env->insn_flags & ISA_MIPS32R2) { + op1 = OPC_DROTR; + } + /* Fallthrough */ + case 0: + check_insn(env, ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift_imm(env, ctx, op1, rd, rt, sa); + break; + default: + generate_exception(ctx, EXCP_RI); + break; + } + break; + case OPC_DSRL32: + switch ((ctx->opcode >> 21) & 0x1f) { + case 1: + /* drotr32 is decoded as dsrl32 on non-R2 CPUs */ + if (env->insn_flags & ISA_MIPS32R2) { + op1 = OPC_DROTR32; + } + /* Fallthrough */ + case 0: + check_insn(env, ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift_imm(env, ctx, op1, rd, rt, sa); + break; + default: + generate_exception(ctx, EXCP_RI); + break; + } + break; case OPC_DADD ... OPC_DSUBU: check_insn(env, ctx, ISA_MIPS3); check_mips_64(ctx); @@ -7785,11 +7777,28 @@ static void decode_opc (CPUState *env, DisasContext *ctx) break; case OPC_DSLLV: case OPC_DSRAV: - case OPC_DSRLV: check_insn(env, ctx, ISA_MIPS3); check_mips_64(ctx); gen_shift(env, ctx, op1, rd, rs, rt); break; + case OPC_DSRLV: + switch ((ctx->opcode >> 6) & 0x1f) { + case 1: + /* drotrv is decoded as dsrlv on non-R2 CPUs */ + if (env->insn_flags & ISA_MIPS32R2) { + op1 = OPC_DROTRV; + } + /* Fallthrough */ + case 0: + check_insn(env, ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift(env, ctx, op1, rd, rs, rt); + break; + default: + generate_exception(ctx, EXCP_RI); + break; + } + break; case OPC_DMULT ... OPC_DDIVU: check_insn(env, ctx, ISA_MIPS3); check_mips_64(ctx); -- 1.6.3.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH 05/11] target-mips: make gen_compute_branch 16/32-bit-aware 2009-11-23 20:49 [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Nathan Froyd ` (3 preceding siblings ...) 2009-11-23 20:50 ` [Qemu-devel] [PATCH 04/11] target-mips: move ROTR and ROTRV inside gen_shift_{imm, } Nathan Froyd @ 2009-11-23 20:50 ` Nathan Froyd 2009-11-23 20:50 ` [Qemu-devel] [PATCH 06/11] target-mips: add gen_base_offset_addr Nathan Froyd ` (6 subsequent siblings) 11 siblings, 0 replies; 18+ messages in thread From: Nathan Froyd @ 2009-11-23 20:50 UTC (permalink / raw) To: qemu-devel Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/translate.c | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index c03d1bf..1157e97 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -2406,6 +2406,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) /* Branches (before delay slot) */ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, + int insn_bytes, int rs, int rt, int32_t offset) { target_ulong btgt = -1; @@ -2434,7 +2435,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, gen_load_gpr(t1, rt); bcond_compute = 1; } - btgt = ctx->pc + 4 + offset; + btgt = ctx->pc + insn_bytes + offset; break; case OPC_BGEZ: case OPC_BGEZAL: @@ -2453,12 +2454,12 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, gen_load_gpr(t0, rs); bcond_compute = 1; } - btgt = ctx->pc + 4 + offset; + btgt = ctx->pc + insn_bytes + offset; break; case OPC_J: case OPC_JAL: /* Jump to immediate */ - btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset; + btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset; break; case OPC_JR: case OPC_JALR: @@ -7670,7 +7671,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) gen_muldiv(ctx, op1, rs, rt); break; case OPC_JR ... OPC_JALR: - gen_compute_branch(ctx, op1, rs, rd, sa); + gen_compute_branch(ctx, op1, 4, rs, rd, sa); return; case OPC_TGE ... OPC_TEQ: /* Traps */ case OPC_TNE: @@ -7959,7 +7960,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) switch (op1) { case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */ case OPC_BLTZAL ... OPC_BGEZALL: - gen_compute_branch(ctx, op1, rs, -1, imm << 2); + gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2); return; case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */ case OPC_TNEI: @@ -8078,11 +8079,11 @@ static void decode_opc (CPUState *env, DisasContext *ctx) break; case OPC_J ... OPC_JAL: /* Jump */ offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; - gen_compute_branch(ctx, op, rs, rt, offset); + gen_compute_branch(ctx, op, 4, rs, rt, offset); return; case OPC_BEQ ... OPC_BGTZ: /* Branch */ case OPC_BEQL ... OPC_BGTZL: - gen_compute_branch(ctx, op, rs, rt, imm << 2); + gen_compute_branch(ctx, op, 4, rs, rt, imm << 2); return; case OPC_LB ... OPC_LWR: /* Load and stores */ case OPC_SB ... OPC_SW: -- 1.6.3.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH 06/11] target-mips: add gen_base_offset_addr 2009-11-23 20:49 [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Nathan Froyd ` (4 preceding siblings ...) 2009-11-23 20:50 ` [Qemu-devel] [PATCH 05/11] target-mips: make gen_compute_branch 16/32-bit-aware Nathan Froyd @ 2009-11-23 20:50 ` Nathan Froyd 2009-11-28 10:17 ` Aurelien Jarno 2009-11-23 20:50 ` [Qemu-devel] [PATCH 07/11] target-mips: split out delay slot handling Nathan Froyd ` (5 subsequent siblings) 11 siblings, 1 reply; 18+ messages in thread From: Nathan Froyd @ 2009-11-23 20:50 UTC (permalink / raw) To: qemu-devel This is a common pattern in existing code. We'll also use it to implement the mips16 SAVE/RESTORE instructions. Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/translate.c | 40 ++++++++++++++++------------------------ 1 files changed, 16 insertions(+), 24 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 1157e97..fece3c1 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -997,6 +997,19 @@ OP_ST_ATOMIC(scd,st64,ld64,0x7); #endif #undef OP_ST_ATOMIC +static void gen_base_offset_addr (DisasContext *ctx, TCGv addr, + int base, int16_t offset) +{ + if (base == 0) { + tcg_gen_movi_tl(addr, offset); + } else if (offset == 0) { + gen_load_gpr(addr, base); + } else { + tcg_gen_movi_tl(addr, offset); + gen_op_addr_add(ctx, addr, addr, cpu_gpr[base]); + } +} + /* Load and store */ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, int base, int16_t offset) @@ -1005,14 +1018,7 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - if (base == 0) { - tcg_gen_movi_tl(t0, offset); - } else if (offset == 0) { - gen_load_gpr(t0, base); - } else { - tcg_gen_movi_tl(t0, offset); - gen_op_addr_add(ctx, t0, cpu_gpr[base], t0); - } + gen_base_offset_addr(ctx, t0, base, offset); /* Don't do NOP if destination is zero: we must perform the actual memory access. */ switch (opc) { @@ -1163,14 +1169,7 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt, t0 = tcg_temp_local_new(); - if (base == 0) { - tcg_gen_movi_tl(t0, offset); - } else if (offset == 0) { - gen_load_gpr(t0, base); - } else { - tcg_gen_movi_tl(t0, offset); - gen_op_addr_add(ctx, t0, cpu_gpr[base], t0); - } + gen_base_offset_addr(ctx, t0, base, offset); /* Don't do NOP if destination is zero: we must perform the actual memory access. */ @@ -1202,14 +1201,7 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, const char *opn = "flt_ldst"; TCGv t0 = tcg_temp_new(); - if (base == 0) { - tcg_gen_movi_tl(t0, offset); - } else if (offset == 0) { - gen_load_gpr(t0, base); - } else { - tcg_gen_movi_tl(t0, offset); - gen_op_addr_add(ctx, t0, cpu_gpr[base], t0); - } + gen_base_offset_addr(ctx, t0, base, offset); /* Don't do NOP if destination is zero: we must perform the actual memory access. */ switch (opc) { -- 1.6.3.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 06/11] target-mips: add gen_base_offset_addr 2009-11-23 20:50 ` [Qemu-devel] [PATCH 06/11] target-mips: add gen_base_offset_addr Nathan Froyd @ 2009-11-28 10:17 ` Aurelien Jarno 0 siblings, 0 replies; 18+ messages in thread From: Aurelien Jarno @ 2009-11-28 10:17 UTC (permalink / raw) To: Nathan Froyd; +Cc: qemu-devel On Mon, Nov 23, 2009 at 12:50:04PM -0800, Nathan Froyd wrote: > This is a common pattern in existing code. We'll also use it to > implement the mips16 SAVE/RESTORE instructions. > > Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> > --- > target-mips/translate.c | 40 ++++++++++++++++------------------------ > 1 files changed, 16 insertions(+), 24 deletions(-) > > diff --git a/target-mips/translate.c b/target-mips/translate.c > index 1157e97..fece3c1 100644 > --- a/target-mips/translate.c > +++ b/target-mips/translate.c > @@ -997,6 +997,19 @@ OP_ST_ATOMIC(scd,st64,ld64,0x7); > #endif > #undef OP_ST_ATOMIC > > +static void gen_base_offset_addr (DisasContext *ctx, TCGv addr, > + int base, int16_t offset) > +{ > + if (base == 0) { > + tcg_gen_movi_tl(addr, offset); > + } else if (offset == 0) { > + gen_load_gpr(addr, base); > + } else { > + tcg_gen_movi_tl(addr, offset); > + gen_op_addr_add(ctx, addr, addr, cpu_gpr[base]); I am nitpicking a bit, but it's better to keep the two last argument as in the original version to keep the immediate value in the last position. This saves one instruction on non-RISC hosts. > + } > +} > + > /* Load and store */ > static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, > int base, int16_t offset) > @@ -1005,14 +1018,7 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, > TCGv t0 = tcg_temp_new(); > TCGv t1 = tcg_temp_new(); > > - if (base == 0) { > - tcg_gen_movi_tl(t0, offset); > - } else if (offset == 0) { > - gen_load_gpr(t0, base); > - } else { > - tcg_gen_movi_tl(t0, offset); > - gen_op_addr_add(ctx, t0, cpu_gpr[base], t0); > - } > + gen_base_offset_addr(ctx, t0, base, offset); > /* Don't do NOP if destination is zero: we must perform the actual > memory access. */ > switch (opc) { > @@ -1163,14 +1169,7 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt, > > t0 = tcg_temp_local_new(); > > - if (base == 0) { > - tcg_gen_movi_tl(t0, offset); > - } else if (offset == 0) { > - gen_load_gpr(t0, base); > - } else { > - tcg_gen_movi_tl(t0, offset); > - gen_op_addr_add(ctx, t0, cpu_gpr[base], t0); > - } > + gen_base_offset_addr(ctx, t0, base, offset); > /* Don't do NOP if destination is zero: we must perform the actual > memory access. */ > > @@ -1202,14 +1201,7 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, > const char *opn = "flt_ldst"; > TCGv t0 = tcg_temp_new(); > > - if (base == 0) { > - tcg_gen_movi_tl(t0, offset); > - } else if (offset == 0) { > - gen_load_gpr(t0, base); > - } else { > - tcg_gen_movi_tl(t0, offset); > - gen_op_addr_add(ctx, t0, cpu_gpr[base], t0); > - } > + gen_base_offset_addr(ctx, t0, base, offset); > /* Don't do NOP if destination is zero: we must perform the actual > memory access. */ > switch (opc) { > -- > 1.6.3.2 > > > > -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurelien@aurel32.net http://www.aurel32.net ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH 07/11] target-mips: split out delay slot handling 2009-11-23 20:49 [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Nathan Froyd ` (5 preceding siblings ...) 2009-11-23 20:50 ` [Qemu-devel] [PATCH 06/11] target-mips: add gen_base_offset_addr Nathan Froyd @ 2009-11-23 20:50 ` Nathan Froyd 2009-11-23 20:50 ` [Qemu-devel] [PATCH 08/11] target-mips: add enums for MIPS16 opcodes Nathan Froyd ` (4 subsequent siblings) 11 siblings, 0 replies; 18+ messages in thread From: Nathan Froyd @ 2009-11-23 20:50 UTC (permalink / raw) To: qemu-devel Move delay slot handling to common code whose invocation can be controlled from gen_intermediate_code_internal. Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/translate.c | 134 +++++++++++++++++++++++++++------------------- 1 files changed, 79 insertions(+), 55 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index fece3c1..e7aee33 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -7548,6 +7548,56 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, fregnames[fs], fregnames[ft]); } +static void handle_delay_slot (CPUState *env, DisasContext *ctx, + int insn_bytes) +{ + if (ctx->hflags & MIPS_HFLAG_BMASK) { + int hflags = ctx->hflags & MIPS_HFLAG_BMASK; + /* Branches completion */ + ctx->hflags &= ~MIPS_HFLAG_BMASK; + ctx->bstate = BS_BRANCH; + save_cpu_state(ctx, 0); + /* FIXME: Need to clear can_do_io. */ + switch (hflags) { + case MIPS_HFLAG_B: + /* unconditional branch */ + MIPS_DEBUG("unconditional branch"); + gen_goto_tb(ctx, 0, ctx->btarget); + break; + case MIPS_HFLAG_BL: + /* blikely taken case */ + MIPS_DEBUG("blikely branch taken"); + gen_goto_tb(ctx, 0, ctx->btarget); + break; + case MIPS_HFLAG_BC: + /* Conditional branch */ + MIPS_DEBUG("conditional branch"); + { + int l1 = gen_new_label(); + + tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1); + gen_goto_tb(ctx, 1, ctx->pc + insn_bytes); + gen_set_label(l1); + gen_goto_tb(ctx, 0, ctx->btarget); + } + break; + case MIPS_HFLAG_BR: + /* unconditional branch to register */ + MIPS_DEBUG("branch to register"); + tcg_gen_mov_tl(cpu_PC, btarget); + if (ctx->singlestep_enabled) { + save_cpu_state(ctx, 0); + gen_helper_0i(raise_exception, EXCP_DEBUG); + } + tcg_gen_exit_tb(0); + break; + default: + MIPS_DEBUG("unknown branch"); + break; + } + } +} + /* ISA extensions (ASEs) */ /* MIPS16 extension to MIPS32 */ /* SmartMIPS extension to MIPS32 */ @@ -7558,7 +7608,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, #endif -static void decode_opc (CPUState *env, DisasContext *ctx) +static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch) { int32_t offset; int rs, rt, rd, sa; @@ -7573,7 +7623,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) } /* Handle blikely not taken case */ - if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) { + if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) { int l1 = gen_new_label(); MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4); @@ -7664,7 +7714,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx) break; case OPC_JR ... OPC_JALR: gen_compute_branch(ctx, op1, 4, rs, rd, sa); - return; + *is_branch = 1; + break; case OPC_TGE ... OPC_TEQ: /* Traps */ case OPC_TNE: gen_trap(ctx, op1, rs, rt, -1); @@ -7953,7 +8004,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx) case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */ case OPC_BLTZAL ... OPC_BGEZALL: gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2); - return; + *is_branch = 1; + break; case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */ case OPC_TNEI: gen_trap(ctx, op1, rs, -1, imm); @@ -8072,11 +8124,13 @@ static void decode_opc (CPUState *env, DisasContext *ctx) case OPC_J ... OPC_JAL: /* Jump */ offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; gen_compute_branch(ctx, op, 4, rs, rt, offset); - return; + *is_branch = 1; + break; case OPC_BEQ ... OPC_BGTZ: /* Branch */ case OPC_BEQL ... OPC_BGTZL: gen_compute_branch(ctx, op, 4, rs, rt, imm << 2); - return; + *is_branch = 1; + break; case OPC_LB ... OPC_LWR: /* Load and stores */ case OPC_SB ... OPC_SW: case OPC_SWR: @@ -8137,7 +8191,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx) case OPC_BC1: gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode), (rt >> 2) & 0x7, imm << 2); - return; + *is_branch = 1; + break; case OPC_S_FMT: case OPC_D_FMT: case OPC_W_FMT: @@ -8242,51 +8297,6 @@ static void decode_opc (CPUState *env, DisasContext *ctx) generate_exception(ctx, EXCP_RI); break; } - if (ctx->hflags & MIPS_HFLAG_BMASK) { - int hflags = ctx->hflags & MIPS_HFLAG_BMASK; - /* Branches completion */ - ctx->hflags &= ~MIPS_HFLAG_BMASK; - ctx->bstate = BS_BRANCH; - save_cpu_state(ctx, 0); - /* FIXME: Need to clear can_do_io. */ - switch (hflags) { - case MIPS_HFLAG_B: - /* unconditional branch */ - MIPS_DEBUG("unconditional branch"); - gen_goto_tb(ctx, 0, ctx->btarget); - break; - case MIPS_HFLAG_BL: - /* blikely taken case */ - MIPS_DEBUG("blikely branch taken"); - gen_goto_tb(ctx, 0, ctx->btarget); - break; - case MIPS_HFLAG_BC: - /* Conditional branch */ - MIPS_DEBUG("conditional branch"); - { - int l1 = gen_new_label(); - - tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1); - gen_goto_tb(ctx, 1, ctx->pc + 4); - gen_set_label(l1); - gen_goto_tb(ctx, 0, ctx->btarget); - } - break; - case MIPS_HFLAG_BR: - /* unconditional branch to register */ - MIPS_DEBUG("branch to register"); - tcg_gen_mov_tl(cpu_PC, btarget); - if (ctx->singlestep_enabled) { - save_cpu_state(ctx, 0); - gen_helper_0i(raise_exception, EXCP_DEBUG); - } - tcg_gen_exit_tb(0); - break; - default: - MIPS_DEBUG("unknown branch"); - break; - } - } } static inline void @@ -8300,6 +8310,8 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, int j, lj = -1; int num_insns; int max_insns; + int insn_bytes; + int is_branch; if (search_pc) qemu_log("search pc %d\n", search_pc); @@ -8360,9 +8372,21 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, } if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) gen_io_start(); - ctx.opcode = ldl_code(ctx.pc); - decode_opc(env, &ctx); - ctx.pc += 4; + + is_branch = 0; + if (ctx.isa_mode == 0) { + ctx.opcode = ldl_code(ctx.pc); + insn_bytes = 4; + decode_opc(env, &ctx, &is_branch); + } else { + generate_exception(&ctx, EXCP_RI); + break; + } + if (!is_branch) { + handle_delay_slot(env, &ctx, insn_bytes); + } + ctx.pc += insn_bytes; + num_insns++; /* Execute a branch and its delay slot as a single instruction. -- 1.6.3.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH 08/11] target-mips: add enums for MIPS16 opcodes 2009-11-23 20:49 [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Nathan Froyd ` (6 preceding siblings ...) 2009-11-23 20:50 ` [Qemu-devel] [PATCH 07/11] target-mips: split out delay slot handling Nathan Froyd @ 2009-11-23 20:50 ` Nathan Froyd 2009-11-23 20:50 ` [Qemu-devel] [PATCH 09/11] target-mips: add mips16 instruction decoding Nathan Froyd ` (3 subsequent siblings) 11 siblings, 0 replies; 18+ messages in thread From: Nathan Froyd @ 2009-11-23 20:50 UTC (permalink / raw) To: qemu-devel Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/translate.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 112 insertions(+), 0 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index e7aee33..611774b 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -7600,6 +7600,118 @@ static void handle_delay_slot (CPUState *env, DisasContext *ctx, /* ISA extensions (ASEs) */ /* MIPS16 extension to MIPS32 */ + +/* MIPS16 major opcodes */ +enum { + M16_OPC_ADDIUSP = 0x00, + M16_OPC_ADDIUPC = 0x01, + M16_OPC_B = 0x02, + M16_OPC_JAL = 0x03, + M16_OPC_BEQZ = 0x04, + M16_OPC_BNEQZ = 0x05, + M16_OPC_SHIFT = 0x06, + M16_OPC_LD = 0x07, + M16_OPC_RRIA = 0x08, + M16_OPC_ADDIU8 = 0x09, + M16_OPC_SLTI = 0x0a, + M16_OPC_SLTIU = 0x0b, + M16_OPC_I8 = 0x0c, + M16_OPC_LI = 0x0d, + M16_OPC_CMPI = 0x0e, + M16_OPC_SD = 0x0f, + M16_OPC_LB = 0x10, + M16_OPC_LH = 0x11, + M16_OPC_LWSP = 0x12, + M16_OPC_LW = 0x13, + M16_OPC_LBU = 0x14, + M16_OPC_LHU = 0x15, + M16_OPC_LWPC = 0x16, + M16_OPC_LWU = 0x17, + M16_OPC_SB = 0x18, + M16_OPC_SH = 0x19, + M16_OPC_SWSP = 0x1a, + M16_OPC_SW = 0x1b, + M16_OPC_RRR = 0x1c, + M16_OPC_RR = 0x1d, + M16_OPC_EXTEND = 0x1e, + M16_OPC_I64 = 0x1f +}; + +/* I8 funct field */ +enum { + I8_BTEQZ = 0x0, + I8_BTNEZ = 0x1, + I8_SWRASP = 0x2, + I8_ADJSP = 0x3, + I8_SVRS = 0x4, + I8_MOV32R = 0x5, + I8_MOVR32 = 0x7 +}; + +/* RRR f field */ +enum { + RRR_DADDU = 0x0, + RRR_ADDU = 0x1, + RRR_DSUBU = 0x2, + RRR_SUBU = 0x3 +}; + +/* RR funct field */ +enum { + RR_JR = 0x00, + RR_SDBBP = 0x01, + RR_SLT = 0x02, + RR_SLTU = 0x03, + RR_SLLV = 0x04, + RR_BREAK = 0x05, + RR_SRLV = 0x06, + RR_SRAV = 0x07, + RR_DSRL = 0x08, + RR_CMP = 0x0a, + RR_NEG = 0x0b, + RR_AND = 0x0c, + RR_OR = 0x0d, + RR_XOR = 0x0e, + RR_NOT = 0x0f, + RR_MFHI = 0x10, + RR_CNVT = 0x11, + RR_MFLO = 0x12, + RR_DSRA = 0x13, + RR_DSLLV = 0x14, + RR_DSRLV = 0x16, + RR_DSRAV = 0x17, + RR_MULT = 0x18, + RR_MULTU = 0x19, + RR_DIV = 0x1a, + RR_DIVU = 0x1b, + RR_DMULT = 0x1c, + RR_DMULTU = 0x1d, + RR_DDIV = 0x1e, + RR_DDIVU = 0x1f +}; + +/* I64 funct field */ +enum { + I64_LDSP = 0x0, + I64_SDSP = 0x1, + I64_SDRASP = 0x2, + I64_DADJSP = 0x3, + I64_LDPC = 0x4, + I64_DADDIU = 0x5, + I64_DADDIUPC = 0x6, + I64_DADDIUSP = 0x7 +}; + +/* RR ry field for CNVT */ +enum { + RR_RY_CNVT_ZEB = 0x0, + RR_RY_CNVT_ZEH = 0x1, + RR_RY_CNVT_ZEW = 0x2, + RR_RY_CNVT_SEB = 0x4, + RR_RY_CNVT_SEH = 0x5, + RR_RY_CNVT_SEW = 0x6, +}; + /* SmartMIPS extension to MIPS32 */ #if defined(TARGET_MIPS64) -- 1.6.3.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH 09/11] target-mips: add mips16 instruction decoding 2009-11-23 20:49 [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Nathan Froyd ` (7 preceding siblings ...) 2009-11-23 20:50 ` [Qemu-devel] [PATCH 08/11] target-mips: add enums for MIPS16 opcodes Nathan Froyd @ 2009-11-23 20:50 ` Nathan Froyd 2009-11-28 10:17 ` Aurelien Jarno 2009-11-23 20:50 ` [Qemu-devel] [PATCH 10/11] gdbstub: add MIPS16 support Nathan Froyd ` (2 subsequent siblings) 11 siblings, 1 reply; 18+ messages in thread From: Nathan Froyd @ 2009-11-23 20:50 UTC (permalink / raw) To: qemu-devel There's no good way to add this incrementally, so we do it all at once. The only changes to shared code are in handle_delay_slot. We need to flip ISAMode when doing a jump-and-exchange. We also need to set ISAMode the low bit of the target address for jump-to-register. Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/translate.c | 980 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 976 insertions(+), 4 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 611774b..49d2264 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -83,6 +83,7 @@ enum { OPC_LH = (0x21 << 26), OPC_LWL = (0x22 << 26), OPC_LW = (0x23 << 26), + OPC_LWPC = OPC_LW | 0x5, OPC_LBU = (0x24 << 26), OPC_LHU = (0x25 << 26), OPC_LWR = (0x26 << 26), @@ -173,6 +174,7 @@ enum { /* Jumps */ OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */ OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */ + OPC_JALRC = OPC_JALR | (0x5 << 6), /* Traps */ OPC_TGE = 0x30 | OPC_SPECIAL, OPC_TGEU = 0x31 | OPC_SPECIAL, @@ -1074,6 +1076,19 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, opn = "sdr"; break; #endif + case OPC_LWPC: + save_cpu_state(ctx, 1); + if (ctx->hflags & MIPS_HFLAG_BMASK) { + int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4; + + tcg_gen_movi_tl(t1, (ctx->pc - branch_bytes) & ~(target_ulong)3); + } else { + tcg_gen_movi_tl(t1, ctx->pc & ~(target_ulong)3); + } + gen_op_addr_add(ctx, t0, t0, t1); + op_ldst_lw(t0, t0, ctx); + gen_store_gpr(t0, rt); + break; case OPC_LW: save_cpu_state(ctx, 0); op_ldst_lw(t0, t0, ctx); @@ -2450,11 +2465,13 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, break; case OPC_J: case OPC_JAL: + case OPC_JALX: /* Jump to immediate */ btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset; break; case OPC_JR: case OPC_JALR: + case OPC_JALRC: /* Jump to register */ if (offset != 0 && offset != 16) { /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the @@ -2517,18 +2534,29 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, ctx->hflags |= MIPS_HFLAG_B; MIPS_DEBUG("j " TARGET_FMT_lx, btgt); break; + case OPC_JALX: + ctx->hflags |= MIPS_HFLAG_BX; + /* Fallthrough */ case OPC_JAL: blink = 31; ctx->hflags |= MIPS_HFLAG_B; + ctx->hflags |= (ctx->isa_mode + ? MIPS_HFLAG_BDS16 + : MIPS_HFLAG_BDS32); MIPS_DEBUG("jal " TARGET_FMT_lx, btgt); break; case OPC_JR: ctx->hflags |= MIPS_HFLAG_BR; + if (ctx->isa_mode) + ctx->hflags |= MIPS_HFLAG_BDS16; MIPS_DEBUG("jr %s", regnames[rs]); break; case OPC_JALR: + case OPC_JALRC: blink = rt; ctx->hflags |= MIPS_HFLAG_BR; + if (ctx->isa_mode) + ctx->hflags |= MIPS_HFLAG_BDS16; MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]); break; default: @@ -2625,7 +2653,13 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, ctx->btarget = btgt; if (blink > 0) { - tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + 8); + int post_delay = insn_bytes; + int lowbit = ctx->isa_mode; + + if (opc != OPC_JALRC) + post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4); + + tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit); } out: @@ -7558,10 +7592,17 @@ static void handle_delay_slot (CPUState *env, DisasContext *ctx, ctx->bstate = BS_BRANCH; save_cpu_state(ctx, 0); /* FIXME: Need to clear can_do_io. */ - switch (hflags) { + switch (hflags & MIPS_HFLAG_BMASK_BASE) { case MIPS_HFLAG_B: /* unconditional branch */ MIPS_DEBUG("unconditional branch"); + if (hflags & MIPS_HFLAG_BX) { + TCGv_i32 t0 = tcg_temp_new_i32(); + + tcg_gen_movi_i32(t0, 1 - ctx->isa_mode); + tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, active_tc.ISAMode)); + tcg_temp_free_i32(t0); + } gen_goto_tb(ctx, 0, ctx->btarget); break; case MIPS_HFLAG_BL: @@ -7584,7 +7625,20 @@ static void handle_delay_slot (CPUState *env, DisasContext *ctx, case MIPS_HFLAG_BR: /* unconditional branch to register */ MIPS_DEBUG("branch to register"); - tcg_gen_mov_tl(cpu_PC, btarget); + if (env->insn_flags & ASE_MIPS16) { + TCGv t0 = tcg_temp_new(); + TCGv_i32 t1 = tcg_temp_new_i32(); + + tcg_gen_andi_tl(t0, btarget, 0x1); + tcg_gen_trunc_tl_i32(t1, t0); + tcg_temp_free(t0); + tcg_gen_st_i32(t1, cpu_env, offsetof(CPUState, active_tc.ISAMode)); + tcg_temp_free_i32(t1); + + tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1); + } else { + tcg_gen_mov_tl(cpu_PC, btarget); + } if (ctx->singlestep_enabled) { save_cpu_state(ctx, 0); gen_helper_0i(raise_exception, EXCP_DEBUG); @@ -7712,6 +7766,918 @@ enum { RR_RY_CNVT_SEW = 0x6, }; +static int xlat (int r) +{ + static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 }; + + return map[r]; +} + +static void gen_mips16_save (DisasContext *ctx, + int xsregs, int aregs, + int do_ra, int do_s0, int do_s1, + int framesize) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int args, astatic; + + switch (aregs) { + case 0: + case 1: + case 2: + case 3: + case 11: + args = 0; + break; + case 4: + case 5: + case 6: + case 7: + args = 1; + break; + case 8: + case 9: + case 10: + args = 2; + break; + case 12: + case 13: + args = 3; + break; + case 14: + args = 4; + break; + default: + generate_exception(ctx, EXCP_RI); + return; + } + + switch (args) { + case 4: + gen_base_offset_addr(ctx, t0, 29, 12); + gen_load_gpr(t1, 7); + op_ldst_sw(t1, t0, ctx); + /* Fall through */ + case 3: + gen_base_offset_addr(ctx, t0, 29, 8); + gen_load_gpr(t1, 6); + op_ldst_sw(t1, t0, ctx); + /* Fall through */ + case 2: + gen_base_offset_addr(ctx, t0, 29, 4); + gen_load_gpr(t1, 5); + op_ldst_sw(t1, t0, ctx); + /* Fall through */ + case 1: + gen_base_offset_addr(ctx, t0, 29, 0); + gen_load_gpr(t1, 4); + op_ldst_sw(t1, t0, ctx); + } + + gen_load_gpr(t0, 29); + +#define DECR_AND_STORE(reg) do { \ + tcg_gen_subi_tl(t0, t0, 4); \ + gen_load_gpr(t1, reg); \ + op_ldst_sw(t1, t0, ctx); \ + } while (0) + + if (do_ra) { + DECR_AND_STORE(31); + } + + switch (xsregs) { + case 7: + DECR_AND_STORE(30); + /* Fall through */ + case 6: + DECR_AND_STORE(23); + /* Fall through */ + case 5: + DECR_AND_STORE(22); + /* Fall through */ + case 4: + DECR_AND_STORE(21); + /* Fall through */ + case 3: + DECR_AND_STORE(20); + /* Fall through */ + case 2: + DECR_AND_STORE(19); + /* Fall through */ + case 1: + DECR_AND_STORE(18); + } + + if (do_s1) { + DECR_AND_STORE(17); + } + if (do_s0) { + DECR_AND_STORE(16); + } + + switch (aregs) { + case 0: + case 4: + case 8: + case 12: + case 14: + astatic = 0; + break; + case 1: + case 5: + case 9: + case 13: + astatic = 1; + break; + case 2: + case 6: + case 10: + astatic = 2; + break; + case 3: + case 7: + astatic = 3; + break; + case 11: + astatic = 4; + break; + default: + generate_exception(ctx, EXCP_RI); + return; + } + + if (astatic > 0) { + DECR_AND_STORE(7); + if (astatic > 1) { + DECR_AND_STORE(6); + if (astatic > 2) { + DECR_AND_STORE(5); + if (astatic > 3) { + DECR_AND_STORE(4); + } + } + } + } +#undef DECR_AND_STORE + + tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize); + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_mips16_restore (DisasContext *ctx, + int xsregs, int aregs, + int do_ra, int do_s0, int do_s1, + int framesize) +{ + int astatic; + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + tcg_gen_addi_tl(t0, cpu_gpr[29], framesize); + +#define DECR_AND_LOAD(reg) do { \ + tcg_gen_subi_tl(t0, t0, 4); \ + op_ldst_lw(t1, t0, ctx); \ + gen_store_gpr(t1, reg); \ + } while (0) + + if (do_ra) { + DECR_AND_LOAD(31); + } + + switch (xsregs) { + case 7: + DECR_AND_LOAD(30); + /* Fall through */ + case 6: + DECR_AND_LOAD(23); + /* Fall through */ + case 5: + DECR_AND_LOAD(22); + /* Fall through */ + case 4: + DECR_AND_LOAD(21); + /* Fall through */ + case 3: + DECR_AND_LOAD(20); + /* Fall through */ + case 2: + DECR_AND_LOAD(19); + /* Fall through */ + case 1: + DECR_AND_LOAD(18); + } + + if (do_s1) { + DECR_AND_LOAD(17); + } + if (do_s0) { + DECR_AND_LOAD(16); + } + + switch (aregs) { + case 0: + case 4: + case 8: + case 12: + case 14: + astatic = 0; + break; + case 1: + case 5: + case 9: + case 13: + astatic = 1; + break; + case 2: + case 6: + case 10: + astatic = 2; + break; + case 3: + case 7: + astatic = 3; + break; + case 11: + astatic = 4; + break; + default: + generate_exception(ctx, EXCP_RI); + return; + } + + if (astatic > 0) { + DECR_AND_LOAD(7); + if (astatic > 1) { + DECR_AND_LOAD(6); + if (astatic > 2) { + DECR_AND_LOAD(5); + if (astatic > 3) { + DECR_AND_LOAD(4); + } + } + } + } +#undef DECR_AND_LOAD + + tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize); + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_addiupc (DisasContext *ctx, int rx, int imm) +{ + TCGv t0 = tcg_temp_new(); + + tcg_gen_movi_tl(t0, ctx->pc & ~(target_ulong)3); + tcg_gen_addi_tl(cpu_gpr[rx], t0, imm); + + tcg_temp_free(t0); +} + +static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx, + int *is_branch) +{ + int extend = lduw_code(ctx->pc + 2); + int op, rx, ry, funct, sa; + int16_t imm, offset; + + ctx->opcode = (ctx->opcode << 16) | extend; + op = (ctx->opcode >> 11) & 0x1f; + sa = (ctx->opcode >> 22) & 0x1f; + funct = (ctx->opcode >> 8) & 0x7; + rx = xlat((ctx->opcode >> 8) & 0x7); + ry = xlat((ctx->opcode >> 5) & 0x7); + offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11 + | ((ctx->opcode >> 21) & 0x3f) << 5 + | (ctx->opcode & 0x1f)); + + /* The extended opcodes cleverly reuse the opcodes from their 16-bit + counterparts. */ + switch (op) { + case M16_OPC_ADDIUSP: + gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm); + break; + case M16_OPC_ADDIUPC: + gen_addiupc(ctx, rx, imm); + break; + case M16_OPC_B: + gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_BEQZ: + gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_BNEQZ: + gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_SHIFT: + switch (ctx->opcode & 0x3) { + case 0x0: + gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa); + break; + case 0x1: +#if defined(TARGET_MIPS64) + gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa); +#else + generate_exception(ctx, EXCP_RI); +#endif + break; + case 0x2: + gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa); + break; + case 0x3: + gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa); + break; + } + break; +#if defined(TARGET_MIPS64) + case M16_OPC_LD: + gen_ldst(ctx, OPC_LD, ry, rx, offset); + break; +#endif + case M16_OPC_RRIA: + imm = ctx->opcode & 0xf; + imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4; + imm = imm | ((ctx->opcode >> 16) & 0xf) << 11; + imm = (int16_t) (imm << 1) >> 1; + if ((ctx->opcode >> 4) & 0x1) { +#if defined(TARGET_MIPS64) + gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm); +#else + generate_exception(ctx, EXCP_RI); +#endif + } else { + gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm); + } + break; + case M16_OPC_ADDIU8: + gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm); + break; + case M16_OPC_SLTI: + gen_slt_imm(env, OPC_SLTI, 24, rx, imm); + break; + case M16_OPC_SLTIU: + gen_slt_imm(env, OPC_SLTIU, 24, rx, imm); + break; + case M16_OPC_I8: + switch (funct) { + case I8_BTEQZ: + gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1); + break; + case I8_BTNEZ: + gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1); + break; + case I8_SWRASP: + gen_ldst(ctx, OPC_SW, 31, 29, imm); + break; + case I8_ADJSP: + gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm); + break; + case I8_SVRS: + { + int xsregs = (ctx->opcode >> 24) & 0x7; + int aregs = (ctx->opcode >> 16) & 0xf; + int do_ra = (ctx->opcode >> 6) & 0x1; + int do_s0 = (ctx->opcode >> 5) & 0x1; + int do_s1 = (ctx->opcode >> 4) & 0x1; + int framesize = (((ctx->opcode >> 20) & 0xf) << 4 + | (ctx->opcode & 0xf)) << 3; + + if (ctx->opcode & (1 << 7)) { + gen_mips16_save(ctx, xsregs, aregs, + do_ra, do_s0, do_s1, + framesize); + } else { + gen_mips16_restore(ctx, xsregs, aregs, + do_ra, do_s0, do_s1, + framesize); + } + } + break; + default: + generate_exception(ctx, EXCP_RI); + break; + } + break; + case M16_OPC_LI: + tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm); + break; + case M16_OPC_CMPI: + tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm); + break; +#if defined(TARGET_MIPS64) + case M16_OPC_SD: + gen_ldst(ctx, OPC_SD, ry, rx, offset); + break; +#endif + case M16_OPC_LB: + gen_ldst(ctx, OPC_LB, ry, rx, offset); + break; + case M16_OPC_LH: + gen_ldst(ctx, OPC_LH, ry, rx, offset); + break; + case M16_OPC_LWSP: + gen_ldst(ctx, OPC_LW, rx, 29, offset); + break; + case M16_OPC_LW: + gen_ldst(ctx, OPC_LW, ry, rx, offset); + break; + case M16_OPC_LBU: + gen_ldst(ctx, OPC_LBU, ry, rx, offset); + break; + case M16_OPC_LHU: + gen_ldst(ctx, OPC_LHU, ry, rx, offset); + break; + case M16_OPC_LWPC: + gen_ldst(ctx, OPC_LWPC, rx, 0, offset); + break; +#if defined(TARGET_MIPS64) + case M16_OPC_LWU: + gen_ldst(ctx, OPC_LWU, ry, rx, offset); + break; +#endif + case M16_OPC_SB: + gen_ldst(ctx, OPC_SB, ry, rx, offset); + break; + case M16_OPC_SH: + gen_ldst(ctx, OPC_SH, ry, rx, offset); + break; + case M16_OPC_SWSP: + gen_ldst(ctx, OPC_SW, rx, 29, offset); + break; + case M16_OPC_SW: + gen_ldst(ctx, OPC_SW, ry, rx, offset); + break; + default: + generate_exception(ctx, EXCP_RI); + break; + } + + return 4; +} + +static int decode_mips16_opc (CPUState *env, DisasContext *ctx, + int *is_branch) +{ + int rx, ry; + int sa; + int op, cnvt_op, op1, offset; + int funct; + int n_bytes; + + op = (ctx->opcode >> 11) & 0x1f; + sa = (ctx->opcode >> 2) & 0x7; + sa = sa == 0 ? 8 : sa; + rx = xlat((ctx->opcode >> 8) & 0x7); + cnvt_op = (ctx->opcode >> 5) & 0x7; + ry = xlat((ctx->opcode >> 5) & 0x7); + op1 = offset = ctx->opcode & 0x1f; + + n_bytes = 2; + + switch (op) { + case M16_OPC_ADDIUSP: + { + int16_t imm = ((uint8_t) ctx->opcode) << 2; + + gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm); + } + break; + case M16_OPC_ADDIUPC: + gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2); + break; + case M16_OPC_B: + offset = (ctx->opcode & 0x7ff) << 1; + offset = (int16_t)(offset << 4) >> 4; + gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_JAL: + offset = lduw_code(ctx->pc + 2); + offset = (((ctx->opcode & 0x1f) << 21) + | ((ctx->opcode >> 5) & 0x1f) << 16 + | offset) << 2; + op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL; + gen_compute_branch(ctx, op, 4, rx, ry, offset); + n_bytes = 4; + *is_branch = 1; + break; + case M16_OPC_BEQZ: + gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_BNEQZ: + gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_SHIFT: + switch (ctx->opcode & 0x3) { + case 0x0: + gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa); + break; + case 0x1: +#if defined(TARGET_MIPS64) + gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa); +#else + generate_exception(ctx, EXCP_RI); +#endif + break; + case 0x2: + gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa); + break; + case 0x3: + gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa); + break; + } + break; +#if defined(TARGET_MIPS64) + case M16_OPC_LD: + gen_ldst(ctx, OPC_LD, ry, rx, offset << 3); + break; +#endif + case M16_OPC_RRIA: + { + int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4; + + if ((ctx->opcode >> 4) & 1) { +#if defined(TARGET_MIPS64) + gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm); +#else + generate_exception(ctx, EXCP_RI); +#endif + } else { + gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm); + } + } + break; + case M16_OPC_ADDIU8: + { + int16_t imm = (int8_t) ctx->opcode; + + gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm); + } + break; + case M16_OPC_SLTI: + { + int16_t imm = (uint8_t) ctx->opcode; + + gen_slt_imm(env, OPC_SLTI, 24, rx, imm); + } + break; + case M16_OPC_SLTIU: + { + int16_t imm = (uint8_t) ctx->opcode; + + gen_slt_imm(env, OPC_SLTIU, 24, rx, imm); + } + break; + case M16_OPC_I8: + { + int reg32; + + funct = (ctx->opcode >> 8) & 0x7; + switch (funct) { + case I8_BTEQZ: + gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0, + ((int8_t)ctx->opcode) << 1); + break; + case I8_BTNEZ: + gen_compute_branch(ctx, OPC_BNE, 2, 24, 0, + ((int8_t)ctx->opcode) << 1); + break; + case I8_SWRASP: + gen_ldst(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2); + break; + case I8_ADJSP: + gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, + ((int8_t)ctx->opcode) << 3); + break; + case I8_SVRS: + { + int do_ra = ctx->opcode & (1 << 6); + int do_s0 = ctx->opcode & (1 << 5); + int do_s1 = ctx->opcode & (1 << 4); + int framesize = ctx->opcode & 0xf; + + if (framesize == 0) { + framesize = 128; + } else { + framesize = framesize << 3; + } + + if (ctx->opcode & (1 << 7)) { + gen_mips16_save(ctx, 0, 0, + do_ra, do_s0, do_s1, framesize); + } else { + gen_mips16_restore(ctx, 0, 0, + do_ra, do_s0, do_s1, framesize); + } + } + break; + case I8_MOV32R: + { + int rz = xlat(ctx->opcode & 0x7); + + reg32 = (((ctx->opcode >> 3) & 0x3) << 3) | + ((ctx->opcode >> 5) & 0x7); + gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0); + } + break; + case I8_MOVR32: + reg32 = ctx->opcode & 0x1f; + gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0); + break; + default: + generate_exception(ctx, EXCP_RI); + break; + } + } + break; + case M16_OPC_LI: + { + int16_t imm = (uint8_t) ctx->opcode; + + gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm); + } + break; + case M16_OPC_CMPI: + { + int16_t imm = (uint8_t) ctx->opcode; + + gen_logic_imm(env, OPC_XORI, 24, rx, imm); + } + break; +#if defined(TARGET_MIPS64) + case M16_OPC_SD: + gen_ldst(ctx, OPC_SD, ry, rx, offset << 3); + break; +#endif + case M16_OPC_LB: + gen_ldst(ctx, OPC_LB, ry, rx, offset); + break; + case M16_OPC_LH: + gen_ldst(ctx, OPC_LH, ry, rx, offset << 1); + break; + case M16_OPC_LWSP: + gen_ldst(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2); + break; + case M16_OPC_LW: + gen_ldst(ctx, OPC_LW, ry, rx, offset << 2); + break; + case M16_OPC_LBU: + gen_ldst(ctx, OPC_LBU, ry, rx, offset); + break; + case M16_OPC_LHU: + gen_ldst(ctx, OPC_LHU, ry, rx, offset << 1); + break; + case M16_OPC_LWPC: + gen_ldst(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2); + break; +#if defined (TARGET_MIPS64) + case M16_OPC_LWU: + gen_ldst(ctx, OPC_LWU, ry, rx, offset << 2); + break; +#endif + case M16_OPC_SB: + gen_ldst(ctx, OPC_SB, ry, rx, offset); + break; + case M16_OPC_SH: + gen_ldst(ctx, OPC_SH, ry, rx, offset << 1); + break; + case M16_OPC_SWSP: + gen_ldst(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2); + break; + case M16_OPC_SW: + gen_ldst(ctx, OPC_SW, ry, rx, offset << 2); + break; + case M16_OPC_RRR: + { + int rz = xlat((ctx->opcode >> 2) & 0x7); + int mips32_op; + + switch (ctx->opcode & 0x3) { + case RRR_ADDU: + mips32_op = OPC_ADDU; + break; + case RRR_SUBU: + mips32_op = OPC_SUBU; + break; +#if defined(TARGET_MIPS64) + case RRR_DADDU: + mips32_op = OPC_DADDU; + break; + case RRR_DSUBU: + mips32_op = OPC_DSUBU; + break; +#endif + default: + generate_exception(ctx, EXCP_RI); + goto done; + } + + gen_arith(env, ctx, mips32_op, rz, rx, ry); + done: + ; + } + break; + case M16_OPC_RR: + switch (op1) { + case RR_JR: + { + int nd = (ctx->opcode >> 7) & 0x1; + int link = (ctx->opcode >> 6) & 0x1; + int ra = (ctx->opcode >> 5) & 0x1; + + if (link) { + op = nd ? OPC_JALRC : OPC_JALR; + } else { + op = OPC_JR; + } + + gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0); + if (!nd) { + *is_branch = 1; + } + } + break; + case RR_SDBBP: + /* XXX: not clear which exception should be raised + * when in debug mode... + */ + check_insn(env, ctx, ISA_MIPS32); + if (!(ctx->hflags & MIPS_HFLAG_DM)) { + generate_exception(ctx, EXCP_DBp); + } else { + generate_exception(ctx, EXCP_DBp); + } + break; + case RR_SLT: + gen_slt(env, OPC_SLT, 24, rx, ry); + break; + case RR_SLTU: + gen_slt(env, OPC_SLTU, 24, rx, ry); + break; + case RR_BREAK: + generate_exception(ctx, EXCP_BREAK); + break; + case RR_SLLV: + gen_shift(env, ctx, OPC_SLLV, ry, rx, ry); + break; + case RR_SRLV: + gen_shift(env, ctx, OPC_SRLV, ry, rx, ry); + break; + case RR_SRAV: + gen_shift(env, ctx, OPC_SRAV, ry, rx, ry); + break; +#if defined (TARGET_MIPS64) + case RR_DSRL: + gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa); + break; +#endif + case RR_CMP: + gen_logic(env, OPC_XOR, 24, rx, ry); + break; + case RR_NEG: + gen_arith(env, ctx, OPC_SUBU, rx, 0, ry); + break; + case RR_AND: + gen_logic(env, OPC_AND, rx, rx, ry); + break; + case RR_OR: + gen_logic(env, OPC_OR, rx, rx, ry); + break; + case RR_XOR: + gen_logic(env, OPC_XOR, rx, rx, ry); + break; + case RR_NOT: + gen_logic(env, OPC_NOR, rx, ry, 0); + break; + case RR_MFHI: + gen_HILO(ctx, OPC_MFHI, rx); + break; + case RR_CNVT: + switch (cnvt_op) { + case RR_RY_CNVT_ZEB: + tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; + case RR_RY_CNVT_ZEH: + tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; + case RR_RY_CNVT_SEB: + tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; + case RR_RY_CNVT_SEH: + tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; +#if defined (TARGET_MIPS64) + case RR_RY_CNVT_ZEW: + tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; + case RR_RY_CNVT_SEW: + tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; +#endif + default: + generate_exception(ctx, EXCP_RI); + break; + } + break; + case RR_MFLO: + gen_HILO(ctx, OPC_MFLO, rx); + break; +#if defined (TARGET_MIPS64) + case RR_DSRA: + gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa); + break; + case RR_DSLLV: + gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry); + case RR_DSRLV: + gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry); + break; + case RR_DSRAV: + gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry); + break; +#endif + case RR_MULT: + gen_muldiv(ctx, OPC_MULT, rx, ry); + break; + case RR_MULTU: + gen_muldiv(ctx, OPC_MULTU, rx, ry); + break; + case RR_DIV: + gen_muldiv(ctx, OPC_DIV, rx, ry); + break; + case RR_DIVU: + gen_muldiv(ctx, OPC_DIVU, rx, ry); + break; +#if defined (TARGET_MIPS64) + case RR_DMULT: + gen_muldiv(ctx, OPC_DMULT, rx, ry); + break; + case RR_DMULTU: + gen_muldiv(ctx, OPC_DMULTU, rx, ry); + break; + case RR_DDIV: + gen_muldiv(ctx, OPC_DDIV, rx, ry); + break; + case RR_DDIVU: + gen_muldiv(ctx, OPC_DDIVU, rx, ry); + break; +#endif + default: + generate_exception(ctx, EXCP_RI); + break; + } + break; + case M16_OPC_EXTEND: + decode_extended_mips16_opc(env, ctx, is_branch); + n_bytes = 4; + break; +#if defined(TARGET_MIPS64) + case M16_OPC_I64: + funct = (ctx->opcode >> 8) & 0x7; + switch (funct) { + case I64_LDSP: + gen_ldst(ctx, OPC_LD, ry, 29, offset << 3); + break; + case I64_SDSP: + gen_ldst(ctx, OPC_SD, ry, 29, offset << 3); + break; + case I64_SDRASP: + gen_ldst(ctx, OPC_SD, 31, 29, (ctx->opcode & 0xff) << 3); + break; + case I64_DADJSP: + gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, + ((int8_t)ctx->opcode) << 3); + break; + case I64_LDPC: + break; + case I64_DADDIU: + gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, + ((int8_t)(offset << 3)) >> 3); + break; + case I64_DADDIUPC: + break; + case I64_DADDIUSP: + gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, + ((int8_t)(offset << 3)) >> 1); + break; + } +#endif + default: + generate_exception(ctx, EXCP_RI); + break; + } + + return n_bytes; +} + /* SmartMIPS extension to MIPS32 */ #if defined(TARGET_MIPS64) @@ -8400,7 +9366,10 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch) #endif case OPC_JALX: check_insn(env, ctx, ASE_MIPS16); - /* MIPS16: Not implemented. */ + offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; + gen_compute_branch(ctx, op, 4, rs, rt, offset); + *is_branch = 1; + break; case OPC_MDMX: check_insn(env, ctx, ASE_MDMX); /* MDMX: Not implemented. */ @@ -8490,6 +9459,9 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, ctx.opcode = ldl_code(ctx.pc); insn_bytes = 4; decode_opc(env, &ctx, &is_branch); + } else if (env->insn_flags & ASE_MIPS16) { + ctx.opcode = lduw_code(ctx.pc); + insn_bytes = decode_mips16_opc(env, &ctx, &is_branch); } else { generate_exception(&ctx, EXCP_RI); break; -- 1.6.3.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 09/11] target-mips: add mips16 instruction decoding 2009-11-23 20:50 ` [Qemu-devel] [PATCH 09/11] target-mips: add mips16 instruction decoding Nathan Froyd @ 2009-11-28 10:17 ` Aurelien Jarno 0 siblings, 0 replies; 18+ messages in thread From: Aurelien Jarno @ 2009-11-28 10:17 UTC (permalink / raw) To: Nathan Froyd; +Cc: qemu-devel On Mon, Nov 23, 2009 at 12:50:07PM -0800, Nathan Froyd wrote: > There's no good way to add this incrementally, so we do it all at once. > The only changes to shared code are in handle_delay_slot. We need to > flip ISAMode when doing a jump-and-exchange. We also need to set > ISAMode the low bit of the target address for jump-to-register. This patch breaks the boot of both MIPS kernel. On little endian, the kernel crashes with the following message: CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == 00000000, ra == 80120004 On big endian, it fails before printing a single message on the console. See also my other comments inline. > Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> > --- > target-mips/translate.c | 980 ++++++++++++++++++++++++++++++++++++++++++++++- > 1 files changed, 976 insertions(+), 4 deletions(-) > > diff --git a/target-mips/translate.c b/target-mips/translate.c > index 611774b..49d2264 100644 > --- a/target-mips/translate.c > +++ b/target-mips/translate.c > @@ -83,6 +83,7 @@ enum { > OPC_LH = (0x21 << 26), > OPC_LWL = (0x22 << 26), > OPC_LW = (0x23 << 26), > + OPC_LWPC = OPC_LW | 0x5, > OPC_LBU = (0x24 << 26), > OPC_LHU = (0x25 << 26), > OPC_LWR = (0x26 << 26), > @@ -173,6 +174,7 @@ enum { > /* Jumps */ > OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */ > OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */ > + OPC_JALRC = OPC_JALR | (0x5 << 6), > /* Traps */ > OPC_TGE = 0x30 | OPC_SPECIAL, > OPC_TGEU = 0x31 | OPC_SPECIAL, > @@ -1074,6 +1076,19 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, > opn = "sdr"; > break; > #endif > + case OPC_LWPC: > + save_cpu_state(ctx, 1); > + if (ctx->hflags & MIPS_HFLAG_BMASK) { > + int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4; > + > + tcg_gen_movi_tl(t1, (ctx->pc - branch_bytes) & ~(target_ulong)3); > + } else { > + tcg_gen_movi_tl(t1, ctx->pc & ~(target_ulong)3); > + } > + gen_op_addr_add(ctx, t0, t0, t1); > + op_ldst_lw(t0, t0, ctx); > + gen_store_gpr(t0, rt); > + break; > case OPC_LW: > save_cpu_state(ctx, 0); > op_ldst_lw(t0, t0, ctx); > @@ -2450,11 +2465,13 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, > break; > case OPC_J: > case OPC_JAL: > + case OPC_JALX: > /* Jump to immediate */ > btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset; > break; > case OPC_JR: > case OPC_JALR: > + case OPC_JALRC: > /* Jump to register */ > if (offset != 0 && offset != 16) { > /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the > @@ -2517,18 +2534,29 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, > ctx->hflags |= MIPS_HFLAG_B; > MIPS_DEBUG("j " TARGET_FMT_lx, btgt); > break; > + case OPC_JALX: > + ctx->hflags |= MIPS_HFLAG_BX; > + /* Fallthrough */ > case OPC_JAL: > blink = 31; > ctx->hflags |= MIPS_HFLAG_B; > + ctx->hflags |= (ctx->isa_mode > + ? MIPS_HFLAG_BDS16 > + : MIPS_HFLAG_BDS32); > MIPS_DEBUG("jal " TARGET_FMT_lx, btgt); > break; > case OPC_JR: > ctx->hflags |= MIPS_HFLAG_BR; > + if (ctx->isa_mode) > + ctx->hflags |= MIPS_HFLAG_BDS16; > MIPS_DEBUG("jr %s", regnames[rs]); > break; > case OPC_JALR: > + case OPC_JALRC: > blink = rt; > ctx->hflags |= MIPS_HFLAG_BR; > + if (ctx->isa_mode) > + ctx->hflags |= MIPS_HFLAG_BDS16; > MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]); > break; > default: > @@ -2625,7 +2653,13 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, > > ctx->btarget = btgt; > if (blink > 0) { > - tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + 8); > + int post_delay = insn_bytes; > + int lowbit = ctx->isa_mode; > + > + if (opc != OPC_JALRC) > + post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4); > + > + tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit); > } > > out: > @@ -7558,10 +7592,17 @@ static void handle_delay_slot (CPUState *env, DisasContext *ctx, > ctx->bstate = BS_BRANCH; > save_cpu_state(ctx, 0); > /* FIXME: Need to clear can_do_io. */ > - switch (hflags) { > + switch (hflags & MIPS_HFLAG_BMASK_BASE) { > case MIPS_HFLAG_B: > /* unconditional branch */ > MIPS_DEBUG("unconditional branch"); > + if (hflags & MIPS_HFLAG_BX) { > + TCGv_i32 t0 = tcg_temp_new_i32(); > + > + tcg_gen_movi_i32(t0, 1 - ctx->isa_mode); > + tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, active_tc.ISAMode)); > + tcg_temp_free_i32(t0); > + } > gen_goto_tb(ctx, 0, ctx->btarget); > break; > case MIPS_HFLAG_BL: > @@ -7584,7 +7625,20 @@ static void handle_delay_slot (CPUState *env, DisasContext *ctx, > case MIPS_HFLAG_BR: > /* unconditional branch to register */ > MIPS_DEBUG("branch to register"); > - tcg_gen_mov_tl(cpu_PC, btarget); > + if (env->insn_flags & ASE_MIPS16) { > + TCGv t0 = tcg_temp_new(); > + TCGv_i32 t1 = tcg_temp_new_i32(); > + > + tcg_gen_andi_tl(t0, btarget, 0x1); > + tcg_gen_trunc_tl_i32(t1, t0); > + tcg_temp_free(t0); > + tcg_gen_st_i32(t1, cpu_env, offsetof(CPUState, active_tc.ISAMode)); > + tcg_temp_free_i32(t1); > + > + tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1); > + } else { > + tcg_gen_mov_tl(cpu_PC, btarget); > + } > if (ctx->singlestep_enabled) { > save_cpu_state(ctx, 0); > gen_helper_0i(raise_exception, EXCP_DEBUG); > @@ -7712,6 +7766,918 @@ enum { > RR_RY_CNVT_SEW = 0x6, > }; > > +static int xlat (int r) > +{ > + static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 }; > + > + return map[r]; > +} > + > +static void gen_mips16_save (DisasContext *ctx, > + int xsregs, int aregs, > + int do_ra, int do_s0, int do_s1, > + int framesize) > +{ > + TCGv t0 = tcg_temp_new(); > + TCGv t1 = tcg_temp_new(); > + int args, astatic; > + > + switch (aregs) { > + case 0: > + case 1: > + case 2: > + case 3: > + case 11: > + args = 0; > + break; > + case 4: > + case 5: > + case 6: > + case 7: > + args = 1; > + break; > + case 8: > + case 9: > + case 10: > + args = 2; > + break; > + case 12: > + case 13: > + args = 3; > + break; > + case 14: > + args = 4; > + break; > + default: > + generate_exception(ctx, EXCP_RI); > + return; > + } > + > + switch (args) { > + case 4: > + gen_base_offset_addr(ctx, t0, 29, 12); > + gen_load_gpr(t1, 7); > + op_ldst_sw(t1, t0, ctx); > + /* Fall through */ > + case 3: > + gen_base_offset_addr(ctx, t0, 29, 8); > + gen_load_gpr(t1, 6); > + op_ldst_sw(t1, t0, ctx); > + /* Fall through */ > + case 2: > + gen_base_offset_addr(ctx, t0, 29, 4); > + gen_load_gpr(t1, 5); > + op_ldst_sw(t1, t0, ctx); > + /* Fall through */ > + case 1: > + gen_base_offset_addr(ctx, t0, 29, 0); > + gen_load_gpr(t1, 4); > + op_ldst_sw(t1, t0, ctx); > + } > + > + gen_load_gpr(t0, 29); > + > +#define DECR_AND_STORE(reg) do { \ > + tcg_gen_subi_tl(t0, t0, 4); \ > + gen_load_gpr(t1, reg); \ > + op_ldst_sw(t1, t0, ctx); \ > + } while (0) > + > + if (do_ra) { > + DECR_AND_STORE(31); > + } > + > + switch (xsregs) { > + case 7: > + DECR_AND_STORE(30); > + /* Fall through */ > + case 6: > + DECR_AND_STORE(23); > + /* Fall through */ > + case 5: > + DECR_AND_STORE(22); > + /* Fall through */ > + case 4: > + DECR_AND_STORE(21); > + /* Fall through */ > + case 3: > + DECR_AND_STORE(20); > + /* Fall through */ > + case 2: > + DECR_AND_STORE(19); > + /* Fall through */ > + case 1: > + DECR_AND_STORE(18); > + } > + > + if (do_s1) { > + DECR_AND_STORE(17); > + } > + if (do_s0) { > + DECR_AND_STORE(16); > + } > + > + switch (aregs) { > + case 0: > + case 4: > + case 8: > + case 12: > + case 14: > + astatic = 0; > + break; > + case 1: > + case 5: > + case 9: > + case 13: > + astatic = 1; > + break; > + case 2: > + case 6: > + case 10: > + astatic = 2; > + break; > + case 3: > + case 7: > + astatic = 3; > + break; > + case 11: > + astatic = 4; > + break; > + default: > + generate_exception(ctx, EXCP_RI); > + return; > + } > + > + if (astatic > 0) { > + DECR_AND_STORE(7); > + if (astatic > 1) { > + DECR_AND_STORE(6); > + if (astatic > 2) { > + DECR_AND_STORE(5); > + if (astatic > 3) { > + DECR_AND_STORE(4); > + } > + } > + } > + } > +#undef DECR_AND_STORE > + > + tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize); > + tcg_temp_free(t0); > + tcg_temp_free(t1); > +} > + > +static void gen_mips16_restore (DisasContext *ctx, > + int xsregs, int aregs, > + int do_ra, int do_s0, int do_s1, > + int framesize) > +{ > + int astatic; > + TCGv t0 = tcg_temp_new(); > + TCGv t1 = tcg_temp_new(); > + > + tcg_gen_addi_tl(t0, cpu_gpr[29], framesize); > + > +#define DECR_AND_LOAD(reg) do { \ > + tcg_gen_subi_tl(t0, t0, 4); \ > + op_ldst_lw(t1, t0, ctx); \ > + gen_store_gpr(t1, reg); \ > + } while (0) > + > + if (do_ra) { > + DECR_AND_LOAD(31); > + } > + > + switch (xsregs) { > + case 7: > + DECR_AND_LOAD(30); > + /* Fall through */ > + case 6: > + DECR_AND_LOAD(23); > + /* Fall through */ > + case 5: > + DECR_AND_LOAD(22); > + /* Fall through */ > + case 4: > + DECR_AND_LOAD(21); > + /* Fall through */ > + case 3: > + DECR_AND_LOAD(20); > + /* Fall through */ > + case 2: > + DECR_AND_LOAD(19); > + /* Fall through */ > + case 1: > + DECR_AND_LOAD(18); > + } > + > + if (do_s1) { > + DECR_AND_LOAD(17); > + } > + if (do_s0) { > + DECR_AND_LOAD(16); > + } > + > + switch (aregs) { > + case 0: > + case 4: > + case 8: > + case 12: > + case 14: > + astatic = 0; > + break; > + case 1: > + case 5: > + case 9: > + case 13: > + astatic = 1; > + break; > + case 2: > + case 6: > + case 10: > + astatic = 2; > + break; > + case 3: > + case 7: > + astatic = 3; > + break; > + case 11: > + astatic = 4; > + break; > + default: > + generate_exception(ctx, EXCP_RI); > + return; > + } > + > + if (astatic > 0) { > + DECR_AND_LOAD(7); > + if (astatic > 1) { > + DECR_AND_LOAD(6); > + if (astatic > 2) { > + DECR_AND_LOAD(5); > + if (astatic > 3) { > + DECR_AND_LOAD(4); > + } > + } > + } > + } > +#undef DECR_AND_LOAD > + > + tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize); > + tcg_temp_free(t0); > + tcg_temp_free(t1); > +} > + > +static void gen_addiupc (DisasContext *ctx, int rx, int imm) > +{ > + TCGv t0 = tcg_temp_new(); > + > + tcg_gen_movi_tl(t0, ctx->pc & ~(target_ulong)3); > + tcg_gen_addi_tl(cpu_gpr[rx], t0, imm); > + > + tcg_temp_free(t0); > +} > + > +static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx, > + int *is_branch) > +{ > + int extend = lduw_code(ctx->pc + 2); > + int op, rx, ry, funct, sa; > + int16_t imm, offset; > + > + ctx->opcode = (ctx->opcode << 16) | extend; > + op = (ctx->opcode >> 11) & 0x1f; > + sa = (ctx->opcode >> 22) & 0x1f; > + funct = (ctx->opcode >> 8) & 0x7; > + rx = xlat((ctx->opcode >> 8) & 0x7); > + ry = xlat((ctx->opcode >> 5) & 0x7); > + offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11 > + | ((ctx->opcode >> 21) & 0x3f) << 5 > + | (ctx->opcode & 0x1f)); > + > + /* The extended opcodes cleverly reuse the opcodes from their 16-bit > + counterparts. */ > + switch (op) { > + case M16_OPC_ADDIUSP: > + gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm); > + break; > + case M16_OPC_ADDIUPC: > + gen_addiupc(ctx, rx, imm); > + break; > + case M16_OPC_B: > + gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1); > + /* No delay slot, so just process as a normal instruction */ > + break; > + case M16_OPC_BEQZ: > + gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1); > + /* No delay slot, so just process as a normal instruction */ > + break; > + case M16_OPC_BNEQZ: > + gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1); > + /* No delay slot, so just process as a normal instruction */ > + break; > + case M16_OPC_SHIFT: > + switch (ctx->opcode & 0x3) { > + case 0x0: > + gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa); > + break; > + case 0x1: > +#if defined(TARGET_MIPS64) > + gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa); Shouldn't this generate an exception on 64-bit CPU, but with 64-bit instructions not enabled? The MIPS16e manual is not really clear about that. Same for other instructions below. > +#else > + generate_exception(ctx, EXCP_RI); > +#endif > + break; > + case 0x2: > + gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa); > + break; > + case 0x3: > + gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa); > + break; > + } > + break; > +#if defined(TARGET_MIPS64) > + case M16_OPC_LD: > + gen_ldst(ctx, OPC_LD, ry, rx, offset); > + break; > +#endif > + case M16_OPC_RRIA: > + imm = ctx->opcode & 0xf; > + imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4; > + imm = imm | ((ctx->opcode >> 16) & 0xf) << 11; > + imm = (int16_t) (imm << 1) >> 1; > + if ((ctx->opcode >> 4) & 0x1) { > +#if defined(TARGET_MIPS64) > + gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm); > +#else > + generate_exception(ctx, EXCP_RI); > +#endif > + } else { > + gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm); > + } > + break; > + case M16_OPC_ADDIU8: > + gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm); > + break; > + case M16_OPC_SLTI: > + gen_slt_imm(env, OPC_SLTI, 24, rx, imm); > + break; > + case M16_OPC_SLTIU: > + gen_slt_imm(env, OPC_SLTIU, 24, rx, imm); > + break; > + case M16_OPC_I8: > + switch (funct) { > + case I8_BTEQZ: > + gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1); > + break; > + case I8_BTNEZ: > + gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1); > + break; > + case I8_SWRASP: > + gen_ldst(ctx, OPC_SW, 31, 29, imm); > + break; > + case I8_ADJSP: > + gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm); > + break; > + case I8_SVRS: > + { > + int xsregs = (ctx->opcode >> 24) & 0x7; > + int aregs = (ctx->opcode >> 16) & 0xf; > + int do_ra = (ctx->opcode >> 6) & 0x1; > + int do_s0 = (ctx->opcode >> 5) & 0x1; > + int do_s1 = (ctx->opcode >> 4) & 0x1; > + int framesize = (((ctx->opcode >> 20) & 0xf) << 4 > + | (ctx->opcode & 0xf)) << 3; > + > + if (ctx->opcode & (1 << 7)) { > + gen_mips16_save(ctx, xsregs, aregs, > + do_ra, do_s0, do_s1, > + framesize); > + } else { > + gen_mips16_restore(ctx, xsregs, aregs, > + do_ra, do_s0, do_s1, > + framesize); > + } > + } > + break; > + default: > + generate_exception(ctx, EXCP_RI); > + break; > + } > + break; > + case M16_OPC_LI: > + tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm); > + break; > + case M16_OPC_CMPI: > + tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm); > + break; > +#if defined(TARGET_MIPS64) > + case M16_OPC_SD: > + gen_ldst(ctx, OPC_SD, ry, rx, offset); > + break; > +#endif > + case M16_OPC_LB: > + gen_ldst(ctx, OPC_LB, ry, rx, offset); > + break; > + case M16_OPC_LH: > + gen_ldst(ctx, OPC_LH, ry, rx, offset); > + break; > + case M16_OPC_LWSP: > + gen_ldst(ctx, OPC_LW, rx, 29, offset); > + break; > + case M16_OPC_LW: > + gen_ldst(ctx, OPC_LW, ry, rx, offset); > + break; > + case M16_OPC_LBU: > + gen_ldst(ctx, OPC_LBU, ry, rx, offset); > + break; > + case M16_OPC_LHU: > + gen_ldst(ctx, OPC_LHU, ry, rx, offset); > + break; > + case M16_OPC_LWPC: > + gen_ldst(ctx, OPC_LWPC, rx, 0, offset); > + break; > +#if defined(TARGET_MIPS64) > + case M16_OPC_LWU: > + gen_ldst(ctx, OPC_LWU, ry, rx, offset); > + break; > +#endif > + case M16_OPC_SB: > + gen_ldst(ctx, OPC_SB, ry, rx, offset); > + break; > + case M16_OPC_SH: > + gen_ldst(ctx, OPC_SH, ry, rx, offset); > + break; > + case M16_OPC_SWSP: > + gen_ldst(ctx, OPC_SW, rx, 29, offset); > + break; > + case M16_OPC_SW: > + gen_ldst(ctx, OPC_SW, ry, rx, offset); > + break; > + default: > + generate_exception(ctx, EXCP_RI); > + break; > + } > + > + return 4; > +} > + > +static int decode_mips16_opc (CPUState *env, DisasContext *ctx, > + int *is_branch) > +{ > + int rx, ry; > + int sa; > + int op, cnvt_op, op1, offset; > + int funct; > + int n_bytes; > + > + op = (ctx->opcode >> 11) & 0x1f; > + sa = (ctx->opcode >> 2) & 0x7; > + sa = sa == 0 ? 8 : sa; > + rx = xlat((ctx->opcode >> 8) & 0x7); > + cnvt_op = (ctx->opcode >> 5) & 0x7; > + ry = xlat((ctx->opcode >> 5) & 0x7); > + op1 = offset = ctx->opcode & 0x1f; > + > + n_bytes = 2; > + > + switch (op) { > + case M16_OPC_ADDIUSP: > + { > + int16_t imm = ((uint8_t) ctx->opcode) << 2; > + > + gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm); > + } > + break; > + case M16_OPC_ADDIUPC: > + gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2); > + break; > + case M16_OPC_B: > + offset = (ctx->opcode & 0x7ff) << 1; > + offset = (int16_t)(offset << 4) >> 4; > + gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset); > + /* No delay slot, so just process as a normal instruction */ > + break; > + case M16_OPC_JAL: > + offset = lduw_code(ctx->pc + 2); > + offset = (((ctx->opcode & 0x1f) << 21) > + | ((ctx->opcode >> 5) & 0x1f) << 16 > + | offset) << 2; > + op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL; > + gen_compute_branch(ctx, op, 4, rx, ry, offset); > + n_bytes = 4; > + *is_branch = 1; > + break; > + case M16_OPC_BEQZ: > + gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1); > + /* No delay slot, so just process as a normal instruction */ > + break; > + case M16_OPC_BNEQZ: > + gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1); > + /* No delay slot, so just process as a normal instruction */ > + break; > + case M16_OPC_SHIFT: > + switch (ctx->opcode & 0x3) { > + case 0x0: > + gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa); > + break; > + case 0x1: > +#if defined(TARGET_MIPS64) > + gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa); > +#else > + generate_exception(ctx, EXCP_RI); > +#endif > + break; > + case 0x2: > + gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa); > + break; > + case 0x3: > + gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa); > + break; > + } > + break; > +#if defined(TARGET_MIPS64) > + case M16_OPC_LD: > + gen_ldst(ctx, OPC_LD, ry, rx, offset << 3); > + break; > +#endif > + case M16_OPC_RRIA: > + { > + int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4; > + > + if ((ctx->opcode >> 4) & 1) { > +#if defined(TARGET_MIPS64) > + gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm); > +#else > + generate_exception(ctx, EXCP_RI); > +#endif > + } else { > + gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm); > + } > + } > + break; > + case M16_OPC_ADDIU8: > + { > + int16_t imm = (int8_t) ctx->opcode; > + > + gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm); > + } > + break; > + case M16_OPC_SLTI: > + { > + int16_t imm = (uint8_t) ctx->opcode; > + > + gen_slt_imm(env, OPC_SLTI, 24, rx, imm); > + } > + break; > + case M16_OPC_SLTIU: > + { > + int16_t imm = (uint8_t) ctx->opcode; > + > + gen_slt_imm(env, OPC_SLTIU, 24, rx, imm); > + } > + break; > + case M16_OPC_I8: > + { > + int reg32; > + > + funct = (ctx->opcode >> 8) & 0x7; > + switch (funct) { > + case I8_BTEQZ: > + gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0, > + ((int8_t)ctx->opcode) << 1); > + break; > + case I8_BTNEZ: > + gen_compute_branch(ctx, OPC_BNE, 2, 24, 0, > + ((int8_t)ctx->opcode) << 1); > + break; > + case I8_SWRASP: > + gen_ldst(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2); > + break; > + case I8_ADJSP: > + gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, > + ((int8_t)ctx->opcode) << 3); > + break; > + case I8_SVRS: > + { > + int do_ra = ctx->opcode & (1 << 6); > + int do_s0 = ctx->opcode & (1 << 5); > + int do_s1 = ctx->opcode & (1 << 4); > + int framesize = ctx->opcode & 0xf; > + > + if (framesize == 0) { > + framesize = 128; > + } else { > + framesize = framesize << 3; > + } > + > + if (ctx->opcode & (1 << 7)) { > + gen_mips16_save(ctx, 0, 0, > + do_ra, do_s0, do_s1, framesize); > + } else { > + gen_mips16_restore(ctx, 0, 0, > + do_ra, do_s0, do_s1, framesize); > + } > + } > + break; > + case I8_MOV32R: > + { > + int rz = xlat(ctx->opcode & 0x7); > + > + reg32 = (((ctx->opcode >> 3) & 0x3) << 3) | > + ((ctx->opcode >> 5) & 0x7); > + gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0); > + } > + break; > + case I8_MOVR32: > + reg32 = ctx->opcode & 0x1f; > + gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0); > + break; > + default: > + generate_exception(ctx, EXCP_RI); > + break; > + } > + } > + break; > + case M16_OPC_LI: > + { > + int16_t imm = (uint8_t) ctx->opcode; > + > + gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm); > + } > + break; > + case M16_OPC_CMPI: > + { > + int16_t imm = (uint8_t) ctx->opcode; > + > + gen_logic_imm(env, OPC_XORI, 24, rx, imm); > + } > + break; > +#if defined(TARGET_MIPS64) > + case M16_OPC_SD: > + gen_ldst(ctx, OPC_SD, ry, rx, offset << 3); > + break; > +#endif > + case M16_OPC_LB: > + gen_ldst(ctx, OPC_LB, ry, rx, offset); > + break; > + case M16_OPC_LH: > + gen_ldst(ctx, OPC_LH, ry, rx, offset << 1); > + break; > + case M16_OPC_LWSP: > + gen_ldst(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2); > + break; > + case M16_OPC_LW: > + gen_ldst(ctx, OPC_LW, ry, rx, offset << 2); > + break; > + case M16_OPC_LBU: > + gen_ldst(ctx, OPC_LBU, ry, rx, offset); > + break; > + case M16_OPC_LHU: > + gen_ldst(ctx, OPC_LHU, ry, rx, offset << 1); > + break; > + case M16_OPC_LWPC: > + gen_ldst(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2); > + break; > +#if defined (TARGET_MIPS64) > + case M16_OPC_LWU: > + gen_ldst(ctx, OPC_LWU, ry, rx, offset << 2); > + break; > +#endif > + case M16_OPC_SB: > + gen_ldst(ctx, OPC_SB, ry, rx, offset); > + break; > + case M16_OPC_SH: > + gen_ldst(ctx, OPC_SH, ry, rx, offset << 1); > + break; > + case M16_OPC_SWSP: > + gen_ldst(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2); > + break; > + case M16_OPC_SW: > + gen_ldst(ctx, OPC_SW, ry, rx, offset << 2); > + break; > + case M16_OPC_RRR: > + { > + int rz = xlat((ctx->opcode >> 2) & 0x7); > + int mips32_op; > + > + switch (ctx->opcode & 0x3) { > + case RRR_ADDU: > + mips32_op = OPC_ADDU; > + break; > + case RRR_SUBU: > + mips32_op = OPC_SUBU; > + break; > +#if defined(TARGET_MIPS64) > + case RRR_DADDU: > + mips32_op = OPC_DADDU; > + break; > + case RRR_DSUBU: > + mips32_op = OPC_DSUBU; > + break; > +#endif > + default: > + generate_exception(ctx, EXCP_RI); > + goto done; > + } > + > + gen_arith(env, ctx, mips32_op, rz, rx, ry); > + done: > + ; > + } > + break; > + case M16_OPC_RR: > + switch (op1) { > + case RR_JR: > + { > + int nd = (ctx->opcode >> 7) & 0x1; > + int link = (ctx->opcode >> 6) & 0x1; > + int ra = (ctx->opcode >> 5) & 0x1; > + > + if (link) { > + op = nd ? OPC_JALRC : OPC_JALR; > + } else { > + op = OPC_JR; > + } > + > + gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0); > + if (!nd) { > + *is_branch = 1; > + } > + } > + break; > + case RR_SDBBP: > + /* XXX: not clear which exception should be raised > + * when in debug mode... > + */ > + check_insn(env, ctx, ISA_MIPS32); > + if (!(ctx->hflags & MIPS_HFLAG_DM)) { > + generate_exception(ctx, EXCP_DBp); > + } else { > + generate_exception(ctx, EXCP_DBp); > + } > + break; > + case RR_SLT: > + gen_slt(env, OPC_SLT, 24, rx, ry); > + break; > + case RR_SLTU: > + gen_slt(env, OPC_SLTU, 24, rx, ry); > + break; > + case RR_BREAK: > + generate_exception(ctx, EXCP_BREAK); > + break; > + case RR_SLLV: > + gen_shift(env, ctx, OPC_SLLV, ry, rx, ry); > + break; > + case RR_SRLV: > + gen_shift(env, ctx, OPC_SRLV, ry, rx, ry); > + break; > + case RR_SRAV: > + gen_shift(env, ctx, OPC_SRAV, ry, rx, ry); > + break; > +#if defined (TARGET_MIPS64) > + case RR_DSRL: > + gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa); > + break; > +#endif > + case RR_CMP: > + gen_logic(env, OPC_XOR, 24, rx, ry); > + break; > + case RR_NEG: > + gen_arith(env, ctx, OPC_SUBU, rx, 0, ry); > + break; > + case RR_AND: > + gen_logic(env, OPC_AND, rx, rx, ry); > + break; > + case RR_OR: > + gen_logic(env, OPC_OR, rx, rx, ry); > + break; > + case RR_XOR: > + gen_logic(env, OPC_XOR, rx, rx, ry); > + break; > + case RR_NOT: > + gen_logic(env, OPC_NOR, rx, ry, 0); > + break; > + case RR_MFHI: > + gen_HILO(ctx, OPC_MFHI, rx); > + break; > + case RR_CNVT: > + switch (cnvt_op) { > + case RR_RY_CNVT_ZEB: > + tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]); > + break; > + case RR_RY_CNVT_ZEH: > + tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]); > + break; > + case RR_RY_CNVT_SEB: > + tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]); > + break; > + case RR_RY_CNVT_SEH: > + tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]); > + break; > +#if defined (TARGET_MIPS64) > + case RR_RY_CNVT_ZEW: > + tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]); > + break; > + case RR_RY_CNVT_SEW: > + tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]); > + break; > +#endif > + default: > + generate_exception(ctx, EXCP_RI); > + break; > + } > + break; > + case RR_MFLO: > + gen_HILO(ctx, OPC_MFLO, rx); > + break; > +#if defined (TARGET_MIPS64) > + case RR_DSRA: > + gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa); > + break; > + case RR_DSLLV: > + gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry); > + case RR_DSRLV: > + gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry); > + break; > + case RR_DSRAV: > + gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry); > + break; > +#endif > + case RR_MULT: > + gen_muldiv(ctx, OPC_MULT, rx, ry); > + break; > + case RR_MULTU: > + gen_muldiv(ctx, OPC_MULTU, rx, ry); > + break; > + case RR_DIV: > + gen_muldiv(ctx, OPC_DIV, rx, ry); > + break; > + case RR_DIVU: > + gen_muldiv(ctx, OPC_DIVU, rx, ry); > + break; > +#if defined (TARGET_MIPS64) > + case RR_DMULT: > + gen_muldiv(ctx, OPC_DMULT, rx, ry); > + break; > + case RR_DMULTU: > + gen_muldiv(ctx, OPC_DMULTU, rx, ry); > + break; > + case RR_DDIV: > + gen_muldiv(ctx, OPC_DDIV, rx, ry); > + break; > + case RR_DDIVU: > + gen_muldiv(ctx, OPC_DDIVU, rx, ry); > + break; > +#endif > + default: > + generate_exception(ctx, EXCP_RI); > + break; > + } > + break; > + case M16_OPC_EXTEND: > + decode_extended_mips16_opc(env, ctx, is_branch); > + n_bytes = 4; > + break; > +#if defined(TARGET_MIPS64) > + case M16_OPC_I64: > + funct = (ctx->opcode >> 8) & 0x7; > + switch (funct) { > + case I64_LDSP: > + gen_ldst(ctx, OPC_LD, ry, 29, offset << 3); > + break; > + case I64_SDSP: > + gen_ldst(ctx, OPC_SD, ry, 29, offset << 3); > + break; > + case I64_SDRASP: > + gen_ldst(ctx, OPC_SD, 31, 29, (ctx->opcode & 0xff) << 3); > + break; > + case I64_DADJSP: > + gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, > + ((int8_t)ctx->opcode) << 3); > + break; > + case I64_LDPC: > + break; > + case I64_DADDIU: > + gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, > + ((int8_t)(offset << 3)) >> 3); > + break; > + case I64_DADDIUPC: > + break; > + case I64_DADDIUSP: > + gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, > + ((int8_t)(offset << 3)) >> 1); > + break; > + } > +#endif > + default: > + generate_exception(ctx, EXCP_RI); > + break; > + } > + > + return n_bytes; > +} > + > /* SmartMIPS extension to MIPS32 */ > > #if defined(TARGET_MIPS64) > @@ -8400,7 +9366,10 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch) > #endif > case OPC_JALX: > check_insn(env, ctx, ASE_MIPS16); > - /* MIPS16: Not implemented. */ > + offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; > + gen_compute_branch(ctx, op, 4, rs, rt, offset); > + *is_branch = 1; > + break; > case OPC_MDMX: > check_insn(env, ctx, ASE_MDMX); > /* MDMX: Not implemented. */ > @@ -8490,6 +9459,9 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, > ctx.opcode = ldl_code(ctx.pc); > insn_bytes = 4; > decode_opc(env, &ctx, &is_branch); > + } else if (env->insn_flags & ASE_MIPS16) { > + ctx.opcode = lduw_code(ctx.pc); > + insn_bytes = decode_mips16_opc(env, &ctx, &is_branch); > } else { > generate_exception(&ctx, EXCP_RI); > break; > -- > 1.6.3.2 > > > > -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurelien@aurel32.net http://www.aurel32.net ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH 10/11] gdbstub: add MIPS16 support 2009-11-23 20:49 [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Nathan Froyd ` (8 preceding siblings ...) 2009-11-23 20:50 ` [Qemu-devel] [PATCH 09/11] target-mips: add mips16 instruction decoding Nathan Froyd @ 2009-11-23 20:50 ` Nathan Froyd 2009-11-23 20:50 ` [Qemu-devel] [PATCH 11/11] target-mips: add copyright notice for mips16 work Nathan Froyd 2009-11-28 10:17 ` [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Aurelien Jarno 11 siblings, 0 replies; 18+ messages in thread From: Nathan Froyd @ 2009-11-23 20:50 UTC (permalink / raw) To: qemu-devel The only thing to do here is to expose ISAMode to GDB and to set ISAMode properly when we change the PC. Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- gdbstub.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index 055093f..58a701b 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -1053,7 +1053,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n) case 34: GET_REGL(env->active_tc.HI[0]); case 35: GET_REGL(env->CP0_BadVAddr); case 36: GET_REGL((int32_t)env->CP0_Cause); - case 37: GET_REGL(env->active_tc.PC); + case 37: GET_REGL(env->active_tc.PC | env->active_tc.ISAMode); case 72: GET_REGL(0); /* fp */ case 89: GET_REGL((int32_t)env->CP0_PRid); } @@ -1114,7 +1114,10 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n) case 34: env->active_tc.HI[0] = tmp; break; case 35: env->CP0_BadVAddr = tmp; break; case 36: env->CP0_Cause = tmp; break; - case 37: env->active_tc.PC = tmp; break; + case 37: + env->active_tc.PC = tmp & ~(target_ulong)1; + env->active_tc.ISAMode = tmp & 1; + break; case 72: /* fp, ignored */ break; default: if (n > 89) @@ -1609,7 +1612,8 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc) #elif defined (TARGET_SH4) s->c_cpu->pc = pc; #elif defined (TARGET_MIPS) - s->c_cpu->active_tc.PC = pc; + s->c_cpu->active_tc.PC = pc & ~(target_ulong)1; + s->c_cpu->active_tc.ISAMode = pc & 1; #elif defined (TARGET_MICROBLAZE) s->c_cpu->sregs[SR_PC] = pc; #elif defined (TARGET_CRIS) -- 1.6.3.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH 11/11] target-mips: add copyright notice for mips16 work 2009-11-23 20:49 [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Nathan Froyd ` (9 preceding siblings ...) 2009-11-23 20:50 ` [Qemu-devel] [PATCH 10/11] gdbstub: add MIPS16 support Nathan Froyd @ 2009-11-23 20:50 ` Nathan Froyd 2009-11-28 10:17 ` [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Aurelien Jarno 11 siblings, 0 replies; 18+ messages in thread From: Nathan Froyd @ 2009-11-23 20:50 UTC (permalink / raw) To: qemu-devel Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/translate.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 49d2264..ef5e726 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -4,6 +4,7 @@ * Copyright (c) 2004-2005 Jocelyn Mayer * Copyright (c) 2006 Marius Groeger (FPU operations) * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 support) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public -- 1.6.3.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support 2009-11-23 20:49 [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Nathan Froyd ` (10 preceding siblings ...) 2009-11-23 20:50 ` [Qemu-devel] [PATCH 11/11] target-mips: add copyright notice for mips16 work Nathan Froyd @ 2009-11-28 10:17 ` Aurelien Jarno 11 siblings, 0 replies; 18+ messages in thread From: Aurelien Jarno @ 2009-11-28 10:17 UTC (permalink / raw) To: Nathan Froyd; +Cc: qemu-devel Hi, On Mon, Nov 23, 2009 at 12:49:58PM -0800, Nathan Froyd wrote: > This patchset adds MIPS16 support to the MIPS backend. MIPS16 is a > compact encoding of a subset of the MIPS integer instructions, similar > to ARM's Thumb mode. The processor enters MIPS16 mode by executing a > special jump instruction; execution continus at the jump target in > MIPS16 mode until the processor returns to MIPS32/64 mode by executing a > special jump instruction. > > The patches have been tested with GCC's testsuite and GDB's testsuite. It's nice there is someone working on items from target-mips/TODO. By the way, this patchset misses one patch to remove the entry from this file ;-) More seriously, this patchset still has a few problems, but I don't expect them difficult to solve. Please see the comments on different patches. -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurelien@aurel32.net http://www.aurel32.net ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2009-11-30 19:27 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-11-23 20:49 [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Nathan Froyd 2009-11-23 20:49 ` [Qemu-devel] [PATCH 01/11] target-mips: add ISAMode bits for mips16 execution Nathan Froyd 2009-11-28 10:17 ` Aurelien Jarno 2009-11-30 17:45 ` Aurelien Jarno 2009-11-23 20:50 ` [Qemu-devel] [PATCH 02/11] target-mips: add new HFLAGs for JALX and 16/32-bit delay slots Nathan Froyd 2009-11-23 20:50 ` [Qemu-devel] [PATCH 03/11] target-mips: change interrupt bits to be mips16-aware Nathan Froyd 2009-11-28 10:17 ` Aurelien Jarno 2009-11-23 20:50 ` [Qemu-devel] [PATCH 04/11] target-mips: move ROTR and ROTRV inside gen_shift_{imm, } Nathan Froyd 2009-11-23 20:50 ` [Qemu-devel] [PATCH 05/11] target-mips: make gen_compute_branch 16/32-bit-aware Nathan Froyd 2009-11-23 20:50 ` [Qemu-devel] [PATCH 06/11] target-mips: add gen_base_offset_addr Nathan Froyd 2009-11-28 10:17 ` Aurelien Jarno 2009-11-23 20:50 ` [Qemu-devel] [PATCH 07/11] target-mips: split out delay slot handling Nathan Froyd 2009-11-23 20:50 ` [Qemu-devel] [PATCH 08/11] target-mips: add enums for MIPS16 opcodes Nathan Froyd 2009-11-23 20:50 ` [Qemu-devel] [PATCH 09/11] target-mips: add mips16 instruction decoding Nathan Froyd 2009-11-28 10:17 ` Aurelien Jarno 2009-11-23 20:50 ` [Qemu-devel] [PATCH 10/11] gdbstub: add MIPS16 support Nathan Froyd 2009-11-23 20:50 ` [Qemu-devel] [PATCH 11/11] target-mips: add copyright notice for mips16 work Nathan Froyd 2009-11-28 10:17 ` [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support Aurelien Jarno
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).