On Tue, Jun 08, 2010 at 01:29:59PM -0700, Nathan Froyd wrote: > Add instruction decoding for the microMIPS ASE. All we do is decode and > then forward to the existing gen_* routines. > > Signed-off-by: Nathan Froyd <froy...@codesourcery.com> > --- > target-mips/helper.h | 9 + > target-mips/mips-defs.h | 1 + > target-mips/op_helper.c | 136 +++ > target-mips/translate.c | 2390 > ++++++++++++++++++++++++++++++++++++++++++++++- > 4 files changed, 2531 insertions(+), 5 deletions(-) > > diff --git a/target-mips/helper.h b/target-mips/helper.h > index ab47b1a..a6ba75d 100644 > --- a/target-mips/helper.h > +++ b/target-mips/helper.h > @@ -160,6 +160,15 @@ DEF_HELPER_1(emt, tl, tl) > DEF_HELPER_1(dvpe, tl, tl) > DEF_HELPER_1(evpe, tl, tl) > #endif /* !CONFIG_USER_ONLY */ > + > +/* microMIPS functions */ > +DEF_HELPER_3(lwm, void, tl, tl, i32); > +DEF_HELPER_3(swm, void, tl, tl, i32); > +#ifdef TARGET_MIPS64 > +DEF_HELPER_3(ldm, void, tl, tl, i32); > +DEF_HELPER_3(sdm, void, tl, tl, i32); > +#endif > + > DEF_HELPER_2(fork, void, tl, tl) > DEF_HELPER_1(yield, tl, tl) > > diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h > index c57de02..a7f4697 100644 > --- a/target-mips/mips-defs.h > +++ b/target-mips/mips-defs.h > @@ -38,6 +38,7 @@ > #define ASE_DSPR2 0x00010000 > #define ASE_MT 0x00020000 > #define ASE_SMARTMIPS 0x00040000 > +#define ASE_MICROMIPS 0x00080000 > > /* Chip specific instructions. */ > #define INSN_VR54XX 0x80000000 > diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c > index 2bfdd50..56c5e59 100644 > --- a/target-mips/op_helper.c > +++ b/target-mips/op_helper.c > @@ -565,6 +565,142 @@ void helper_sdr(target_ulong arg1, target_ulong arg2, > int mem_idx) > } > #endif /* TARGET_MIPS64 */ > > +static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 }; > + > +void helper_lwm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) > +{ > + target_ulong base_reglist = reglist & 0xf; > + target_ulong do_r31 = reglist & 0x10; > +#ifdef CONFIG_USER_ONLY > +#undef ldfun > +#define ldfun ldl_raw > +#else > + uint32_t (*ldfun)(target_ulong); > + > + switch (mem_idx) > + { > + case 0: ldfun = ldl_kernel; break; > + case 1: ldfun = ldl_super; break; > + default: > + case 2: ldfun = ldl_user; break; > + } > +#endif > + > + if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) { > + target_ulong i; > + > + for (i = 0; i < base_reglist; i++) { > + env->active_tc.gpr[multiple_regs[i]] = (target_long) ldfun(addr); > + addr += 4; > + } > + } > + > + if (do_r31) { > + env->active_tc.gpr[31] = (target_long) ldfun(addr); > + } > +} > + > +void helper_swm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) > +{ > + target_ulong base_reglist = reglist & 0xf; > + target_ulong do_r31 = reglist & 0x10; > +#ifdef CONFIG_USER_ONLY > +#undef stfun > +#define stfun stl_raw > +#else > + void (*stfun)(target_ulong, uint32_t); > + > + switch (mem_idx) > + { > + case 0: stfun = stl_kernel; break; > + case 1: stfun = stl_super; break; > + default: > + case 2: stfun = stl_user; break; > + } > +#endif > + > + if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) { > + target_ulong i; > + > + for (i = 0; i < base_reglist; i++) { > + stfun(addr, env->active_tc.gpr[multiple_regs[i]]); > + addr += 4; > + } > + } > + > + if (do_r31) { > + stfun(addr, env->active_tc.gpr[31]); > + } > +} > + > +#if defined(TARGET_MIPS64) > +void helper_ldm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) > +{ > + target_ulong base_reglist = reglist & 0xf; > + target_ulong do_r31 = reglist & 0x10; > +#ifdef CONFIG_USER_ONLY > +#undef ldfun > +#define ldfun ldq_raw > +#else > + uint64_t (*ldfun)(target_ulong); > + > + switch (mem_idx) > + { > + case 0: ldfun = ldq_kernel; break; > + case 1: ldfun = ldq_super; break; > + default: > + case 2: ldfun = ldq_user; break; > + } > +#endif > + > + if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) { > + target_ulong i; > + > + for (i = 0; i < base_reglist; i++) { > + env->active_tc.gpr[multiple_regs[i]] = ldfun(addr); > + addr += 8; > + } > + } > + > + if (do_r31) { > + env->active_tc.gpr[31] = ldfun(addr); > + } > +} > + > +void helper_sdm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) > +{ > + target_ulong base_reglist = reglist & 0xf; > + target_ulong do_r31 = reglist & 0x10; > +#ifdef CONFIG_USER_ONLY > +#undef stfun > +#define stfun stq_raw > +#else > + void (*stfun)(target_ulong, uint64_t); > + > + switch (mem_idx) > + { > + case 0: stfun = stq_kernel; break; > + case 1: stfun = stq_super; break; > + default: > + case 2: stfun = stq_user; break; > + } > +#endif > + > + if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) { > + target_ulong i; > + > + for (i = 0; i < base_reglist; i++) { > + stfun(addr, env->active_tc.gpr[multiple_regs[i]]); > + addr += 8; > + } > + } > + > + if (do_r31) { > + stfun(addr, env->active_tc.gpr[31]); > + } > +} > +#endif > + > #ifndef CONFIG_USER_ONLY > /* CP0 helpers */ > target_ulong helper_mfc0_mvpcontrol (void)
As the list of registers is included in the opcode, I do wonder if it wouldn't be better to do this directly in translate.c as TCG code. -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurel...@aurel32.net http://www.aurel32.net