mirror of https://gitee.com/openkylin/qemu.git
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:
parent
620e48f663
commit
3c824109da
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue