422 |
422 |
};
|
423 |
423 |
|
424 |
424 |
/* global register indices */
|
425 |
|
static TCGv cpu_env, current_tc_regs, cpu_T[2];
|
|
425 |
static TCGv cpu_env, current_tc_gprs, cpu_T[2];
|
426 |
426 |
|
|
427 |
/* General purpose registers moves */
|
427 |
428 |
const unsigned char *regnames[] =
|
428 |
429 |
{ "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
|
429 |
430 |
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
|
430 |
431 |
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
|
431 |
432 |
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
|
432 |
433 |
|
433 |
|
/* Warning: no function for r0 register (hard wired to zero) */
|
434 |
|
#define GEN32(func, NAME) \
|
435 |
|
static GenOpFunc *NAME ## _table [32] = { \
|
436 |
|
NULL, NAME ## 1, NAME ## 2, NAME ## 3, \
|
437 |
|
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
|
438 |
|
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
|
439 |
|
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
|
440 |
|
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
|
441 |
|
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
|
442 |
|
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
|
443 |
|
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
|
444 |
|
}; \
|
445 |
|
static always_inline void func(int n) \
|
446 |
|
{ \
|
447 |
|
NAME ## _table[n](); \
|
|
434 |
static inline void gen_op_load_gpr_TN(int t_index, int reg)
|
|
435 |
{
|
|
436 |
tcg_gen_ld_tl(cpu_T[t_index], current_tc_gprs, sizeof(target_ulong) * reg);
|
448 |
437 |
}
|
449 |
438 |
|
450 |
|
/* General purpose registers moves */
|
451 |
|
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
|
452 |
|
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
|
|
439 |
static inline void gen_op_load_gpr_T0(int reg)
|
|
440 |
{
|
|
441 |
gen_op_load_gpr_TN(0, reg);
|
|
442 |
}
|
|
443 |
|
|
444 |
static inline void gen_op_load_gpr_T1(int reg)
|
|
445 |
{
|
|
446 |
gen_op_load_gpr_TN(1, reg);
|
|
447 |
}
|
|
448 |
|
|
449 |
static inline void gen_op_store_gpr_TN(int t_index, int reg)
|
|
450 |
{
|
|
451 |
tcg_gen_st_tl(cpu_T[t_index], current_tc_gprs, sizeof(target_ulong) * reg);
|
|
452 |
}
|
|
453 |
|
|
454 |
static inline void gen_op_store_gpr_T0(int reg)
|
|
455 |
{
|
|
456 |
gen_op_store_gpr_TN(0, reg);
|
|
457 |
}
|
453 |
458 |
|
454 |
|
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
|
455 |
|
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
|
|
459 |
static inline void gen_op_store_gpr_T1(int reg)
|
|
460 |
{
|
|
461 |
gen_op_store_gpr_TN(1, reg);
|
|
462 |
}
|
456 |
463 |
|
457 |
464 |
/* Moves to/from shadow registers */
|
458 |
|
GEN32(gen_op_load_srsgpr_T0, gen_op_load_srsgpr_T0_gpr);
|
459 |
|
GEN32(gen_op_store_T0_srsgpr, gen_op_store_T0_srsgpr_gpr);
|
|
465 |
static inline void gen_op_load_srsgpr_T0(int reg)
|
|
466 |
{
|
|
467 |
int r_tmp = tcg_temp_new(TCG_TYPE_I32);
|
|
468 |
|
|
469 |
tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_SRSCtl));
|
|
470 |
tcg_gen_shri_i32(r_tmp, r_tmp, CP0SRSCtl_PSS);
|
|
471 |
tcg_gen_andi_i32(r_tmp, r_tmp, 0xf);
|
|
472 |
tcg_gen_muli_i32(r_tmp, r_tmp, sizeof(target_ulong) * 32);
|
|
473 |
tcg_gen_add_i32(r_tmp, cpu_env, r_tmp);
|
|
474 |
|
|
475 |
tcg_gen_ld_tl(cpu_T[0], r_tmp, sizeof(target_ulong) * reg);
|
|
476 |
}
|
|
477 |
|
|
478 |
static inline void gen_op_store_srsgpr_T0(int reg)
|
|
479 |
{
|
|
480 |
int r_tmp = tcg_temp_new(TCG_TYPE_I32);
|
|
481 |
|
|
482 |
tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_SRSCtl));
|
|
483 |
tcg_gen_shri_i32(r_tmp, r_tmp, CP0SRSCtl_PSS);
|
|
484 |
tcg_gen_andi_i32(r_tmp, r_tmp, 0xf);
|
|
485 |
tcg_gen_muli_i32(r_tmp, r_tmp, sizeof(target_ulong) * 32);
|
|
486 |
tcg_gen_add_i32(r_tmp, cpu_env, r_tmp);
|
|
487 |
|
|
488 |
tcg_gen_st_tl(cpu_T[0], r_tmp, sizeof(target_ulong) * reg);
|
|
489 |
}
|
460 |
490 |
|
461 |
491 |
static const char *fregnames[] =
|
462 |
492 |
{ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
|
... | ... | |
634 |
664 |
#define GEN_STORE_T0_REG(Rn) \
|
635 |
665 |
do { \
|
636 |
666 |
if (Rn != 0) { \
|
637 |
|
glue(gen_op_store_T0,_gpr)(Rn); \
|
|
667 |
gen_op_store_gpr_T0(Rn); \
|
638 |
668 |
ctx->glue(last_T0,_store) = gen_opc_ptr; \
|
639 |
669 |
ctx->glue(last_T0,_gpr) = Rn; \
|
640 |
670 |
} \
|
... | ... | |
643 |
673 |
#define GEN_STORE_T1_REG(Rn) \
|
644 |
674 |
do { \
|
645 |
675 |
if (Rn != 0) \
|
646 |
|
glue(gen_op_store_T1,_gpr)(Rn); \
|
|
676 |
gen_op_store_gpr_T1(Rn); \
|
647 |
677 |
} while (0)
|
648 |
678 |
|
649 |
679 |
#define GEN_STORE_TN_SRSREG(Rn, Tn) \
|
650 |
680 |
do { \
|
651 |
|
if (Rn != 0) { \
|
652 |
|
glue(glue(gen_op_store_, Tn),_srsgpr)(Rn); \
|
653 |
|
} \
|
|
681 |
if (Rn != 0) \
|
|
682 |
glue(gen_op_store_srsgpr_, Tn)(Rn); \
|
654 |
683 |
} while (0)
|
655 |
684 |
|
656 |
685 |
#define GEN_LOAD_FREG_FTN(FTn, Fn) \
|
... | ... | |
813 |
842 |
generate_exception(ctx, EXCP_RI);
|
814 |
843 |
}
|
815 |
844 |
|
|
845 |
/* load/store instructions. */
|
816 |
846 |
#if defined(CONFIG_USER_ONLY)
|
817 |
847 |
#define op_ldst(name) gen_op_##name##_raw()
|
818 |
848 |
#define OP_LD_TABLE(width)
|
... | ... | |
1638 |
1668 |
generate_exception(ctx, EXCP_RI);
|
1639 |
1669 |
return;
|
1640 |
1670 |
}
|
1641 |
|
gen_op_store_T0_gpr(rd);
|
|
1671 |
gen_op_store_gpr_T0(rd);
|
1642 |
1672 |
MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
|
1643 |
1673 |
}
|
1644 |
1674 |
|
... | ... | |
1870 |
1900 |
return;
|
1871 |
1901 |
case OPC_BLTZAL: /* 0 < 0 */
|
1872 |
1902 |
GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
|
1873 |
|
gen_op_store_T0_gpr(31);
|
|
1903 |
gen_op_store_gpr_T0(31);
|
1874 |
1904 |
MIPS_DEBUG("bnever and link");
|
1875 |
1905 |
return;
|
1876 |
1906 |
case OPC_BLTZALL: /* 0 < 0 likely */
|
1877 |
1907 |
GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
|
1878 |
|
gen_op_store_T0_gpr(31);
|
|
1908 |
gen_op_store_gpr_T0(31);
|
1879 |
1909 |
/* Skip the instruction in the delay slot */
|
1880 |
1910 |
MIPS_DEBUG("bnever, link and skip");
|
1881 |
1911 |
ctx->pc += 4;
|
... | ... | |
2002 |
2032 |
ctx->btarget = btarget;
|
2003 |
2033 |
if (blink > 0) {
|
2004 |
2034 |
GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
|
2005 |
|
gen_op_store_T0_gpr(blink);
|
|
2035 |
gen_op_store_gpr_T0(blink);
|
2006 |
2036 |
}
|
2007 |
2037 |
}
|
2008 |
2038 |
|
... | ... | |
4721 |
4751 |
return;
|
4722 |
4752 |
}
|
4723 |
4753 |
gen_mfc0(env, ctx, rd, ctx->opcode & 0x7);
|
4724 |
|
gen_op_store_T0_gpr(rt);
|
|
4754 |
gen_op_store_gpr_T0(rt);
|
4725 |
4755 |
opn = "mfc0";
|
4726 |
4756 |
break;
|
4727 |
4757 |
case OPC_MTC0:
|
... | ... | |
4738 |
4768 |
return;
|
4739 |
4769 |
}
|
4740 |
4770 |
gen_dmfc0(env, ctx, rd, ctx->opcode & 0x7);
|
4741 |
|
gen_op_store_T0_gpr(rt);
|
|
4771 |
gen_op_store_gpr_T0(rt);
|
4742 |
4772 |
opn = "dmfc0";
|
4743 |
4773 |
break;
|
4744 |
4774 |
case OPC_DMTC0:
|
... | ... | |
4757 |
4787 |
}
|
4758 |
4788 |
gen_mftr(env, ctx, rt, (ctx->opcode >> 5) & 1,
|
4759 |
4789 |
ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
|
4760 |
|
gen_op_store_T0_gpr(rd);
|
|
4790 |
gen_op_store_gpr_T0(rd);
|
4761 |
4791 |
opn = "mftr";
|
4762 |
4792 |
break;
|
4763 |
4793 |
case OPC_MTTR:
|
... | ... | |
6806 |
6836 |
void dump_fpu (CPUState *env)
|
6807 |
6837 |
{
|
6808 |
6838 |
if (loglevel) {
|
6809 |
|
fprintf(logfile, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
|
6810 |
|
env->PC[env->current_tc], env->HI[env->current_tc][0], env->LO[env->current_tc][0], env->hflags, env->btarget, env->bcond);
|
|
6839 |
fprintf(logfile,
|
|
6840 |
"pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
|
|
6841 |
" LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx
|
|
6842 |
" %04x\n",
|
|
6843 |
env->PC[env->current_tc], env->HI[env->current_tc][0],
|
|
6844 |
env->LO[env->current_tc][0], env->hflags, env->btarget,
|
|
6845 |
env->bcond);
|
6811 |
6846 |
fpu_dump_state(env, logfile, fprintf, 0);
|
6812 |
6847 |
}
|
6813 |
6848 |
}
|
... | ... | |
6881 |
6916 |
return;
|
6882 |
6917 |
|
6883 |
6918 |
cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
|
6884 |
|
current_tc_regs = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG1, "current_tc_regs");
|
|
6919 |
current_tc_gprs = tcg_global_mem_new(TCG_TYPE_PTR,
|
|
6920 |
TCG_AREG0,
|
|
6921 |
offsetof(CPUState, current_tc_gprs),
|
|
6922 |
"current_tc_gprs");
|
6885 |
6923 |
#if TARGET_LONG_BITS > HOST_LONG_BITS
|
6886 |
6924 |
cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL,
|
6887 |
6925 |
TCG_AREG0, offsetof(CPUState, t0), "T0");
|
6888 |
6926 |
cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL,
|
6889 |
6927 |
TCG_AREG0, offsetof(CPUState, t1), "T1");
|
6890 |
6928 |
#else
|
6891 |
|
cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T0");
|
6892 |
|
cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "T1");
|
|
6929 |
cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG1, "T0");
|
|
6930 |
cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1");
|
6893 |
6931 |
#endif
|
6894 |
6932 |
|
6895 |
6933 |
inited = 1;
|