* [Qemu-devel] [PATCH v2 00/11] target-mips: add mips16 support @ 2009-12-08 16:06 Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 01/11] target-mips: add new HFLAGs for JALX and 16/32-bit delay slots Nathan Froyd ` (10 more replies) 0 siblings, 11 replies; 13+ messages in thread From: Nathan Froyd @ 2009-12-08 16:06 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. Mode switching occurs when either a special instruction (JALX) is executed, or when a jump-to-register instruction is executed; the instruction mode for the target PC is indicated by the low bit of the register. The patches have been tested with GCC's testsuite and GDB's testsuite. Changes from v1: Fixed bug preventing Linux boot Fixed usermode compilation error Fixed confusion of delay slot size vs. branch size Fixed bugs in PC-relative loads and adds Moved mode bit from ISAMode field to hflags Implemented extended I64 opcodes Implemented LDPC instruction Implemented DADDIUPC 64-bit MIPS16 instructions cause RI exceptions when not running in 64-bit mode (This is required; see section 1.5 of MIPS16e 64-bit spec: MD00077.) Deleted MIPS16 ASE from TODO Flipped Config1.CA bit for appropriate CPUs -Nathan ^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 01/11] target-mips: add new HFLAGs for JALX and 16/32-bit delay slots 2009-12-08 16:06 [Qemu-devel] [PATCH v2 00/11] target-mips: add mips16 support Nathan Froyd @ 2009-12-08 16:06 ` Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 02/11] target-mips: change interrupt bits to be mips16-aware Nathan Froyd ` (9 subsequent siblings) 10 siblings, 0 replies; 13+ messages in thread From: Nathan Froyd @ 2009-12-08 16:06 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. We also make the execution mode an hflag under MIPS_HFLAG_TMASK Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/cpu.h | 47 ++++++++++++++++++++++++++++------------------- 1 files changed, 28 insertions(+), 19 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 97e106f..b78aec5 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -416,35 +416,44 @@ struct CPUMIPSState { int error_code; uint32_t hflags; /* CPU State */ /* TMASK defines different execution modes */ -#define MIPS_HFLAG_TMASK 0x03FF -#define MIPS_HFLAG_MODE 0x0007 /* execution modes */ +#define MIPS_HFLAG_TMASK 0x007FF +#define MIPS_HFLAG_MODE 0x00007 /* execution modes */ /* The KSU flags must be the lowest bits in hflags. The flag order must be the same as defined for CP0 Status. This allows to use the bits as the value of mmu_idx. */ -#define MIPS_HFLAG_KSU 0x0003 /* kernel/supervisor/user mode mask */ -#define MIPS_HFLAG_UM 0x0002 /* user mode flag */ -#define MIPS_HFLAG_SM 0x0001 /* supervisor mode flag */ -#define MIPS_HFLAG_KM 0x0000 /* kernel mode flag */ -#define MIPS_HFLAG_DM 0x0004 /* Debug mode */ -#define MIPS_HFLAG_64 0x0008 /* 64-bit instructions enabled */ -#define MIPS_HFLAG_CP0 0x0010 /* CP0 enabled */ -#define MIPS_HFLAG_FPU 0x0020 /* FPU enabled */ -#define MIPS_HFLAG_F64 0x0040 /* 64-bit FPU enabled */ +#define MIPS_HFLAG_KSU 0x00003 /* kernel/supervisor/user mode mask */ +#define MIPS_HFLAG_UM 0x00002 /* user mode flag */ +#define MIPS_HFLAG_SM 0x00001 /* supervisor mode flag */ +#define MIPS_HFLAG_KM 0x00000 /* kernel mode flag */ +#define MIPS_HFLAG_DM 0x00004 /* Debug mode */ +#define MIPS_HFLAG_64 0x00008 /* 64-bit instructions enabled */ +#define MIPS_HFLAG_CP0 0x00010 /* CP0 enabled */ +#define MIPS_HFLAG_FPU 0x00020 /* FPU enabled */ +#define MIPS_HFLAG_F64 0x00040 /* 64-bit FPU enabled */ /* True if the MIPS IV COP1X instructions can be used. This also controls the non-COP1X instructions RECIP.S, RECIP.D, RSQRT.S and RSQRT.D. */ -#define MIPS_HFLAG_COP1X 0x0080 /* COP1X instructions enabled */ -#define MIPS_HFLAG_RE 0x0100 /* Reversed endianness */ -#define MIPS_HFLAG_UX 0x0200 /* 64-bit user mode */ +#define MIPS_HFLAG_COP1X 0x00080 /* COP1X instructions enabled */ +#define MIPS_HFLAG_RE 0x00100 /* Reversed endianness */ +#define MIPS_HFLAG_UX 0x00200 /* 64-bit user mode */ +#define MIPS_HFLAG_M16 0x00400 /* MIPS16 mode flag */ +#define MIPS_HFLAG_M16_SHIFT 10 /* If translation is interrupted between the branch instruction and * 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_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) */ +#define MIPS_HFLAG_BMASK_BASE 0x03800 +#define MIPS_HFLAG_B 0x00800 /* Unconditional branch */ +#define MIPS_HFLAG_BC 0x01000 /* Conditional branch */ +#define MIPS_HFLAG_BL 0x01800 /* Likely branch */ +#define MIPS_HFLAG_BR 0x02000 /* branch to register (can't link TB) */ + /* Extra flags about the current pending branch. */ +#define MIPS_HFLAG_BMASK_EXT 0x3C000 +#define MIPS_HFLAG_B16 0x04000 /* branch instruction was 16 bits */ +#define MIPS_HFLAG_BDS16 0x08000 /* branch requires 16-bit delay slot */ +#define MIPS_HFLAG_BDS32 0x10000 /* branch requires 32-bit delay slot */ +#define MIPS_HFLAG_BX 0x20000 /* branch exchanges 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] 13+ messages in thread
* [Qemu-devel] [PATCH 02/11] target-mips: change interrupt bits to be mips16-aware 2009-12-08 16:06 [Qemu-devel] [PATCH v2 00/11] target-mips: add mips16 support Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 01/11] target-mips: add new HFLAGs for JALX and 16/32-bit delay slots Nathan Froyd @ 2009-12-08 16:06 ` Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 03/11] target-mips: move ROTR and ROTRV inside gen_shift_{imm, } Nathan Froyd ` (8 subsequent siblings) 10 siblings, 0 replies; 13+ messages in thread From: Nathan Froyd @ 2009-12-08 16:06 UTC (permalink / raw) To: qemu-devel We need to stash the operating mode into the low bit of the error PC and restore it on return from interrupts. Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/helper.c | 51 +++++++++++++++++++++++++++------------------- target-mips/op_helper.c | 17 ++++++++++++-- 2 files changed, 44 insertions(+), 24 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index 1e7e016..903987b 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -369,6 +369,24 @@ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_CACHE] = "cache error", }; +#if !defined(CONFIG_USER_ONLY) +static target_ulong exception_resume_pc (CPUState *env) +{ + target_ulong bad_pc; + target_ulong isa_mode; + + isa_mode = !!(env->hflags & MIPS_HFLAG_M16); + bad_pc = env->active_tc.PC | isa_mode; + 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_B16 ? 2 : 4); + } + + return bad_pc; +} +#endif + void do_interrupt (CPUState *env) { #if !defined(CONFIG_USER_ONLY) @@ -396,7 +414,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->hflags & MIPS_HFLAG_M16); goto enter_debug_mode; case EXCP_DINT: env->CP0_Debug |= 1 << CP0DB_DINT; @@ -413,14 +431,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); @@ -428,6 +440,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->hflags &= ~(MIPS_HFLAG_M16); break; case EXCP_RESET: cpu_reset(env); @@ -439,20 +453,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->hflags &= ~(MIPS_HFLAG_M16); break; case EXCP_EXT_INTERRUPT: cause = 0; @@ -554,13 +564,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); @@ -574,6 +581,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->hflags &= ~(MIPS_HFLAG_M16); 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 be75af5..cccfd8e 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1684,14 +1684,24 @@ static void debug_post_eret (void) } } +static void set_pc (target_ulong error_pc) +{ + env->active_tc.PC = error_pc & ~(target_ulong)1; + if (error_pc & 1) { + env->hflags |= MIPS_HFLAG_M16; + } else { + env->hflags &= ~(MIPS_HFLAG_M16); + } +} + void helper_eret (void) { debug_pre_eret(); if (env->CP0_Status & (1 << CP0St_ERL)) { - env->active_tc.PC = env->CP0_ErrorEPC; + set_pc(env->CP0_ErrorEPC); env->CP0_Status &= ~(1 << CP0St_ERL); } else { - env->active_tc.PC = env->CP0_EPC; + set_pc(env->CP0_EPC); env->CP0_Status &= ~(1 << CP0St_EXL); } compute_hflags(env); @@ -1702,7 +1712,8 @@ void helper_eret (void) void helper_deret (void) { debug_pre_eret(); - env->active_tc.PC = env->CP0_DEPC; + set_pc(env->CP0_DEPC); + env->hflags &= MIPS_HFLAG_DM; compute_hflags(env); debug_post_eret(); -- 1.6.3.2 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 03/11] target-mips: move ROTR and ROTRV inside gen_shift_{imm, } 2009-12-08 16:06 [Qemu-devel] [PATCH v2 00/11] target-mips: add mips16 support Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 01/11] target-mips: add new HFLAGs for JALX and 16/32-bit delay slots Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 02/11] target-mips: change interrupt bits to be mips16-aware Nathan Froyd @ 2009-12-08 16:06 ` Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 04/11] target-mips: make gen_compute_branch 16/32-bit-aware Nathan Froyd ` (7 subsequent siblings) 10 siblings, 0 replies; 13+ messages in thread From: Nathan Froyd @ 2009-12-08 16:06 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 9d62b64..d403c56 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, @@ -1431,43 +1436,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: @@ -1479,28 +1465,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); @@ -1511,26 +1483,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 } @@ -1879,40 +1837,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) @@ -1927,29 +1870,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 } @@ -7661,9 +7589,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); @@ -7673,10 +7616,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); @@ -7754,14 +7712,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); @@ -7769,11 +7761,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] 13+ messages in thread
* [Qemu-devel] [PATCH 04/11] target-mips: make gen_compute_branch 16/32-bit-aware 2009-12-08 16:06 [Qemu-devel] [PATCH v2 00/11] target-mips: add mips16 support Nathan Froyd ` (2 preceding siblings ...) 2009-12-08 16:06 ` [Qemu-devel] [PATCH 03/11] target-mips: move ROTR and ROTRV inside gen_shift_{imm, } Nathan Froyd @ 2009-12-08 16:06 ` Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 05/11] target-mips: add gen_base_offset_addr Nathan Froyd ` (6 subsequent siblings) 10 siblings, 0 replies; 13+ messages in thread From: Nathan Froyd @ 2009-12-08 16:06 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 d403c56..3751516 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -2390,6 +2390,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; @@ -2418,7 +2419,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: @@ -2437,12 +2438,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: @@ -7654,7 +7655,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: @@ -7943,7 +7944,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: @@ -8062,11 +8063,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] 13+ messages in thread
* [Qemu-devel] [PATCH 05/11] target-mips: add gen_base_offset_addr 2009-12-08 16:06 [Qemu-devel] [PATCH v2 00/11] target-mips: add mips16 support Nathan Froyd ` (3 preceding siblings ...) 2009-12-08 16:06 ` [Qemu-devel] [PATCH 04/11] target-mips: make gen_compute_branch 16/32-bit-aware Nathan Froyd @ 2009-12-08 16:06 ` Nathan Froyd 2009-12-08 18:01 ` Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 06/11] target-mips: split out delay slot handling Nathan Froyd ` (5 subsequent siblings) 10 siblings, 1 reply; 13+ messages in thread From: Nathan Froyd @ 2009-12-08 16:06 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 3751516..b38b97f 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -981,6 +981,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) @@ -989,14 +1002,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) { @@ -1147,14 +1153,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. */ @@ -1186,14 +1185,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] 13+ messages in thread
* Re: [Qemu-devel] [PATCH 05/11] target-mips: add gen_base_offset_addr 2009-12-08 16:06 ` [Qemu-devel] [PATCH 05/11] target-mips: add gen_base_offset_addr Nathan Froyd @ 2009-12-08 18:01 ` Nathan Froyd 0 siblings, 0 replies; 13+ messages in thread From: Nathan Froyd @ 2009-12-08 18:01 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> --- Argh, please use this one instead; the arguments passed to gen_op_addr_add in gen_base_offset_addr are in the "proper" order. 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 3751516..b38b97f 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -981,6 +981,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, cpu_gpr[base], addr); + } +} + /* Load and store */ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, int base, int16_t offset) @@ -989,14 +1002,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) { @@ -1147,14 +1153,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. */ @@ -1186,14 +1185,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] 13+ messages in thread
* [Qemu-devel] [PATCH 06/11] target-mips: split out delay slot handling 2009-12-08 16:06 [Qemu-devel] [PATCH v2 00/11] target-mips: add mips16 support Nathan Froyd ` (4 preceding siblings ...) 2009-12-08 16:06 ` [Qemu-devel] [PATCH 05/11] target-mips: add gen_base_offset_addr Nathan Froyd @ 2009-12-08 16:06 ` Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 07/11] target-mips: add enums for MIPS16 opcodes Nathan Froyd ` (4 subsequent siblings) 10 siblings, 0 replies; 13+ messages in thread From: Nathan Froyd @ 2009-12-08 16:06 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 b38b97f..36bfdeb 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -7532,6 +7532,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 */ @@ -7542,7 +7592,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; @@ -7557,7 +7607,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); @@ -7648,7 +7698,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); @@ -7937,7 +7988,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); @@ -8056,11 +8108,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: @@ -8121,7 +8175,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: @@ -8226,51 +8281,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 @@ -8284,6 +8294,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); @@ -8343,9 +8355,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] 13+ messages in thread
* [Qemu-devel] [PATCH 07/11] target-mips: add enums for MIPS16 opcodes 2009-12-08 16:06 [Qemu-devel] [PATCH v2 00/11] target-mips: add mips16 support Nathan Froyd ` (5 preceding siblings ...) 2009-12-08 16:06 ` [Qemu-devel] [PATCH 06/11] target-mips: split out delay slot handling Nathan Froyd @ 2009-12-08 16:06 ` Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 08/11] target-mips: add mips16 instruction decoding Nathan Froyd ` (3 subsequent siblings) 10 siblings, 0 replies; 13+ messages in thread From: Nathan Froyd @ 2009-12-08 16:06 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 36bfdeb..7aac6bf 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -7584,6 +7584,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] 13+ messages in thread
* [Qemu-devel] [PATCH 08/11] target-mips: add mips16 instruction decoding 2009-12-08 16:06 [Qemu-devel] [PATCH v2 00/11] target-mips: add mips16 support Nathan Froyd ` (6 preceding siblings ...) 2009-12-08 16:06 ` [Qemu-devel] [PATCH 07/11] target-mips: add enums for MIPS16 opcodes Nathan Froyd @ 2009-12-08 16:06 ` Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 09/11] gdbstub: add MIPS16 support Nathan Froyd ` (2 subsequent siblings) 10 siblings, 0 replies; 13+ messages in thread From: Nathan Froyd @ 2009-12-08 16:06 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. Also, since we're now adding bits that can be in MIPS_HFLAG_BMASK_EXT, make sure we use MIPS_HFLAG_BMASK_BASE in the places where we just want basic information about a branch. Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/translate.c | 1072 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 1063 insertions(+), 9 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 7aac6bf..ef5e250 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), @@ -97,6 +98,7 @@ enum { OPC_LL = (0x30 << 26), OPC_LLD = (0x34 << 26), OPC_LD = (0x37 << 26), + OPC_LDPC = OPC_LD | 0x5, OPC_SC = (0x38 << 26), OPC_SCD = (0x3C << 26), OPC_SD = (0x3F << 26), @@ -173,6 +175,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, @@ -763,7 +766,7 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc) if (ctx->hflags != ctx->saved_hflags) { tcg_gen_movi_i32(hflags, ctx->hflags); ctx->saved_hflags = ctx->hflags; - switch (ctx->hflags & MIPS_HFLAG_BMASK) { + switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) { case MIPS_HFLAG_BR: break; case MIPS_HFLAG_BC: @@ -778,7 +781,7 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc) static inline void restore_cpu_state (CPUState *env, DisasContext *ctx) { ctx->saved_hflags = ctx->hflags; - switch (ctx->hflags & MIPS_HFLAG_BMASK) { + switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) { case MIPS_HFLAG_BR: break; case MIPS_HFLAG_BC: @@ -994,6 +997,20 @@ static void gen_base_offset_addr (DisasContext *ctx, TCGv addr, } } +static target_ulong pc_relative_pc (DisasContext *ctx) +{ + target_ulong pc = ctx->pc; + + if (ctx->hflags & MIPS_HFLAG_BMASK) { + int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4; + + pc -= branch_bytes; + } + + pc &= ~(target_ulong)3; + return pc; +} + /* Load and store */ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, int base, int16_t offset) @@ -1057,7 +1074,21 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, gen_helper_2i(sdr, t1, t0, ctx->mem_idx); opn = "sdr"; break; + case OPC_LDPC: + save_cpu_state(ctx, 1); + tcg_gen_movi_tl(t1, pc_relative_pc(ctx)); + gen_op_addr_add(ctx, t0, t0, t1); + op_ldst_ld(t0, t0, ctx); + gen_store_gpr(t0, rt); + break; #endif + case OPC_LWPC: + save_cpu_state(ctx, 1); + tcg_gen_movi_tl(t1, pc_relative_pc(ctx)); + 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); @@ -2434,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 @@ -2501,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->hflags & MIPS_HFLAG_M16 + ? MIPS_HFLAG_BDS16 + : MIPS_HFLAG_BDS32); MIPS_DEBUG("jal " TARGET_FMT_lx, btgt); break; case OPC_JR: ctx->hflags |= MIPS_HFLAG_BR; + if (ctx->hflags & MIPS_HFLAG_M16) + 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->hflags & MIPS_HFLAG_M16) + ctx->hflags |= MIPS_HFLAG_BDS16; MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]); break; default: @@ -2609,10 +2653,18 @@ 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->hflags & MIPS_HFLAG_M16); + + 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: + if (insn_bytes == 2) + ctx->hflags |= MIPS_HFLAG_B16; tcg_temp_free(t0); tcg_temp_free(t1); } @@ -7536,16 +7588,19 @@ 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; + int proc_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) { + switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) { case MIPS_HFLAG_B: /* unconditional branch */ MIPS_DEBUG("unconditional branch"); + if (proc_hflags & MIPS_HFLAG_BX) { + tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16); + } gen_goto_tb(ctx, 0, ctx->btarget); break; case MIPS_HFLAG_BL: @@ -7568,7 +7623,22 @@ 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_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16); + tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT); + tcg_gen_or_i32(hflags, hflags, t1); + 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); @@ -7681,7 +7751,7 @@ enum { I64_SDRASP = 0x2, I64_DADJSP = 0x3, I64_LDPC = 0x4, - I64_DADDIU = 0x5, + I64_DADDIU5 = 0x5, I64_DADDIUPC = 0x6, I64_DADDIUSP = 0x7 }; @@ -7696,6 +7766,984 @@ 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, + int is_64_bit, int extended) +{ + TCGv t0; + + if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) { + generate_exception(ctx, EXCP_RI); + return; + } + + t0 = tcg_temp_new(); + + tcg_gen_movi_tl(t0, pc_relative_pc(ctx)); + tcg_gen_addi_tl(cpu_gpr[rx], t0, imm); + if (!is_64_bit) { + tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]); + } + + tcg_temp_free(t0); +} + +#if defined(TARGET_MIPS64) +static void decode_i64_mips16 (CPUState *env, DisasContext *ctx, + int ry, int funct, int16_t offset, + int extended) +{ + switch (funct) { + case I64_LDSP: + check_mips_64(ctx); + offset = extended ? offset : offset << 3; + gen_ldst(ctx, OPC_LD, ry, 29, offset); + break; + case I64_SDSP: + check_mips_64(ctx); + offset = extended ? offset : offset << 3; + gen_ldst(ctx, OPC_SD, ry, 29, offset); + break; + case I64_SDRASP: + check_mips_64(ctx); + offset = extended ? offset : (ctx->opcode & 0xff) << 3; + gen_ldst(ctx, OPC_SD, 31, 29, offset); + break; + case I64_DADJSP: + check_mips_64(ctx); + offset = extended ? offset : ((int8_t)ctx->opcode) << 3; + gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset); + break; + case I64_LDPC: + if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) { + generate_exception(ctx, EXCP_RI); + } else { + offset = extended ? offset : offset << 3; + gen_ldst(ctx, OPC_LDPC, ry, 0, offset); + } + break; + case I64_DADDIU5: + check_mips_64(ctx); + offset = extended ? offset : ((int8_t)(offset << 3)) >> 3; + gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset); + break; + case I64_DADDIUPC: + check_mips_64(ctx); + offset = extended ? offset : offset << 2; + gen_addiupc(ctx, ry, offset, 1, extended); + break; + case I64_DADDIUSP: + check_mips_64(ctx); + offset = extended ? offset : offset << 2; + gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset); + break; + } +} +#endif + +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, 0, 1); + 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) + check_mips_64(ctx); + 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: + check_mips_64(ctx); + 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) + check_mips_64(ctx); + 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; +#if defined(TARGET_MIPS64) + case M16_OPC_I64: + decode_i64_mips16(env, ctx, ry, funct, offset, 1); + break; +#endif + 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, 0, 0); + 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) + check_mips_64(ctx); + 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: + check_mips_64(ctx); + 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) + check_mips_64(ctx); + 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: + check_mips_64(ctx); + 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: + check_mips_64(ctx); + 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; + check_mips_64(ctx); + break; + case RRR_DSUBU: + mips32_op = OPC_DSUBU; + check_mips_64(ctx); + 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: + check_mips_64(ctx); + 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: + check_mips_64(ctx); + tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; + case RR_RY_CNVT_SEW: + check_mips_64(ctx); + 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: + check_mips_64(ctx); + gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa); + break; + case RR_DSLLV: + check_mips_64(ctx); + gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry); + break; + case RR_DSRLV: + check_mips_64(ctx); + gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry); + break; + case RR_DSRAV: + check_mips_64(ctx); + 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: + check_mips_64(ctx); + gen_muldiv(ctx, OPC_DMULT, rx, ry); + break; + case RR_DMULTU: + check_mips_64(ctx); + gen_muldiv(ctx, OPC_DMULTU, rx, ry); + break; + case RR_DDIV: + check_mips_64(ctx); + gen_muldiv(ctx, OPC_DDIV, rx, ry); + break; + case RR_DDIVU: + check_mips_64(ctx); + 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; + decode_i64_mips16(env, ctx, ry, funct, offset, 0); + break; +#endif + default: + generate_exception(ctx, EXCP_RI); + break; + } + + return n_bytes; +} + /* SmartMIPS extension to MIPS32 */ #if defined(TARGET_MIPS64) @@ -8384,7 +9432,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. */ @@ -8469,10 +9520,13 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, gen_io_start(); is_branch = 0; - if (ctx.isa_mode == 0) { + if (!(ctx.hflags & MIPS_HFLAG_M16)) { 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] 13+ messages in thread
* [Qemu-devel] [PATCH 09/11] gdbstub: add MIPS16 support 2009-12-08 16:06 [Qemu-devel] [PATCH v2 00/11] target-mips: add mips16 support Nathan Froyd ` (7 preceding siblings ...) 2009-12-08 16:06 ` [Qemu-devel] [PATCH 08/11] target-mips: add mips16 instruction decoding Nathan Froyd @ 2009-12-08 16:06 ` Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 10/11] target-mips: add copyright notice for mips16 work Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 11/11] target-mips: set Config1.CA for MIPS16-aware CPUs Nathan Froyd 10 siblings, 0 replies; 13+ messages in thread From: Nathan Froyd @ 2009-12-08 16:06 UTC (permalink / raw) To: qemu-devel The only thing to do here is to expose the current processor mode to GDB and to set the processor mode properly when we change the PC. Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- gdbstub.c | 18 +++++++++++++++--- 1 files changed, 15 insertions(+), 3 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index 5320b1c..6180171 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->hflags & MIPS_HFLAG_M16)); case 72: GET_REGL(0); /* fp */ case 89: GET_REGL((int32_t)env->CP0_PRid); } @@ -1114,7 +1114,14 @@ 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; + if (tmp & 1) { + env->hflags |= MIPS_HFLAG_M16; + } else { + env->hflags &= ~(MIPS_HFLAG_M16); + } + break; case 72: /* fp, ignored */ break; default: if (n > 89) @@ -1658,7 +1665,12 @@ 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; + if (pc & 1) { + s->c_cpu->hflags |= MIPS_HFLAG_M16; + } else { + s->c_cpu->hflags &= ~(MIPS_HFLAG_M16); + } #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] 13+ messages in thread
* [Qemu-devel] [PATCH 10/11] target-mips: add copyright notice for mips16 work 2009-12-08 16:06 [Qemu-devel] [PATCH v2 00/11] target-mips: add mips16 support Nathan Froyd ` (8 preceding siblings ...) 2009-12-08 16:06 ` [Qemu-devel] [PATCH 09/11] gdbstub: add MIPS16 support Nathan Froyd @ 2009-12-08 16:06 ` Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 11/11] target-mips: set Config1.CA for MIPS16-aware CPUs Nathan Froyd 10 siblings, 0 replies; 13+ messages in thread From: Nathan Froyd @ 2009-12-08 16:06 UTC (permalink / raw) To: qemu-devel Also cross off mips16 ASE in TODO. Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/TODO | 1 - target-mips/translate.c | 1 + 2 files changed, 1 insertions(+), 1 deletions(-) diff --git a/target-mips/TODO b/target-mips/TODO index 4769e2a..9101881 100644 --- a/target-mips/TODO +++ b/target-mips/TODO @@ -4,7 +4,6 @@ Unsolved issues/bugs in the mips/mipsel backend General ------- - Unimplemented ASEs: - - MIPS16 - MDMX - SmartMIPS - DSP r1 diff --git a/target-mips/translate.c b/target-mips/translate.c index ef5e250..91dd13a 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] 13+ messages in thread
* [Qemu-devel] [PATCH 11/11] target-mips: set Config1.CA for MIPS16-aware CPUs 2009-12-08 16:06 [Qemu-devel] [PATCH v2 00/11] target-mips: add mips16 support Nathan Froyd ` (9 preceding siblings ...) 2009-12-08 16:06 ` [Qemu-devel] [PATCH 10/11] target-mips: add copyright notice for mips16 work Nathan Froyd @ 2009-12-08 16:06 ` Nathan Froyd 10 siblings, 0 replies; 13+ messages in thread From: Nathan Froyd @ 2009-12-08 16:06 UTC (permalink / raw) To: qemu-devel Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/translate_init.c | 27 ++++++++++++++++++--------- 1 files changed, 18 insertions(+), 9 deletions(-) diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index c950eab..6f50555 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -104,7 +104,8 @@ static const mips_def_t mips_defs[] = .CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT), .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | + (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, .CP0_Config3 = MIPS_CONFIG3, .CP0_LLAddr_rw_bitmask = 0, @@ -125,7 +126,8 @@ static const mips_def_t mips_defs[] = .CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT), .CP0_Config1 = MIPS_CONFIG1 | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | + (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, .CP0_Config3 = MIPS_CONFIG3, .CP0_LLAddr_rw_bitmask = 0, @@ -144,7 +146,8 @@ static const mips_def_t mips_defs[] = .CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT), .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | + (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, .CP0_Config3 = MIPS_CONFIG3, .CP0_LLAddr_rw_bitmask = 0, @@ -163,7 +166,8 @@ static const mips_def_t mips_defs[] = .CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT), .CP0_Config1 = MIPS_CONFIG1 | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | + (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, .CP0_Config3 = MIPS_CONFIG3, .CP0_LLAddr_rw_bitmask = 0, @@ -183,7 +187,8 @@ static const mips_def_t mips_defs[] = (MMU_TYPE_R4000 << CP0C0_MT), .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | + (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt), .CP0_LLAddr_rw_bitmask = 0, @@ -203,7 +208,8 @@ static const mips_def_t mips_defs[] = (MMU_TYPE_FMT << CP0C0_MT), .CP0_Config1 = MIPS_CONFIG1 | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | + (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, .CP0_Config3 = MIPS_CONFIG3, .CP0_LLAddr_rw_bitmask = 0, @@ -223,7 +229,8 @@ static const mips_def_t mips_defs[] = (MMU_TYPE_R4000 << CP0C0_MT), .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | + (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt), .CP0_LLAddr_rw_bitmask = 0, @@ -244,7 +251,8 @@ static const mips_def_t mips_defs[] = (MMU_TYPE_R4000 << CP0C0_MT), .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | + (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt), .CP0_LLAddr_rw_bitmask = 0, @@ -267,7 +275,8 @@ static const mips_def_t mips_defs[] = (MMU_TYPE_R4000 << CP0C0_MT), .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | + (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt) | (1 << CP0C3_MT), .CP0_LLAddr_rw_bitmask = 0, -- 1.6.3.2 ^ permalink raw reply related [flat|nested] 13+ messages in thread
end of thread, other threads:[~2009-12-08 21:57 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-12-08 16:06 [Qemu-devel] [PATCH v2 00/11] target-mips: add mips16 support Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 01/11] target-mips: add new HFLAGs for JALX and 16/32-bit delay slots Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 02/11] target-mips: change interrupt bits to be mips16-aware Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 03/11] target-mips: move ROTR and ROTRV inside gen_shift_{imm, } Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 04/11] target-mips: make gen_compute_branch 16/32-bit-aware Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 05/11] target-mips: add gen_base_offset_addr Nathan Froyd 2009-12-08 18:01 ` Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 06/11] target-mips: split out delay slot handling Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 07/11] target-mips: add enums for MIPS16 opcodes Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 08/11] target-mips: add mips16 instruction decoding Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 09/11] gdbstub: add MIPS16 support Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 10/11] target-mips: add copyright notice for mips16 work Nathan Froyd 2009-12-08 16:06 ` [Qemu-devel] [PATCH 11/11] target-mips: set Config1.CA for MIPS16-aware CPUs Nathan Froyd
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).