target-mips: microMIPS ASE support

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 <froydnj@codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Nathan Froyd 2010-06-08 13:29:59 -07:00 committed by Aurelien Jarno
parent 620e48f663
commit 3c824109da
4 changed files with 2531 additions and 5 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)

File diff suppressed because it is too large Load Diff