Support for VR5432, and some of its special instructions. Original patch
by Dirk Behme. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3859 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
29fe0e3490
commit
e9c71dd1c1
@ -79,6 +79,20 @@ void do_madd (void);
|
||||
void do_maddu (void);
|
||||
void do_msub (void);
|
||||
void do_msubu (void);
|
||||
void do_muls (void);
|
||||
void do_mulsu (void);
|
||||
void do_macc (void);
|
||||
void do_macchi (void);
|
||||
void do_maccu (void);
|
||||
void do_macchiu (void);
|
||||
void do_msac (void);
|
||||
void do_msachi (void);
|
||||
void do_msacu (void);
|
||||
void do_msachiu (void);
|
||||
void do_mulhi (void);
|
||||
void do_mulhiu (void);
|
||||
void do_mulshi (void);
|
||||
void do_mulshiu (void);
|
||||
#endif
|
||||
#if defined(TARGET_MIPS64)
|
||||
void do_ddiv (void);
|
||||
|
@ -4,7 +4,7 @@
|
||||
/* If we want to use host float regs... */
|
||||
//#define USE_HOST_FLOAT_REGS
|
||||
|
||||
/* real pages are variable size... */
|
||||
/* Real pages are variable size... */
|
||||
#define TARGET_PAGE_BITS 12
|
||||
#define MIPS_TLB_MAX 128
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
#define ISA_MIPS64 0x00000080
|
||||
#define ISA_MIPS64R2 0x00000100
|
||||
|
||||
/* MIPS ASE */
|
||||
/* MIPS ASEs. */
|
||||
#define ASE_MIPS16 0x00001000
|
||||
#define ASE_MIPS3D 0x00002000
|
||||
#define ASE_MDMX 0x00004000
|
||||
@ -38,19 +38,23 @@
|
||||
#define ASE_MT 0x00020000
|
||||
#define ASE_SMARTMIPS 0x00040000
|
||||
|
||||
/* Chip specific instructions. */
|
||||
/* Currently void */
|
||||
/* Chip specific instructions. */
|
||||
#define INSN_VR54XX 0x80000000
|
||||
|
||||
/* MIPS CPU defines. */
|
||||
/* MIPS CPU defines. */
|
||||
#define CPU_MIPS1 (ISA_MIPS1)
|
||||
#define CPU_MIPS2 (CPU_MIPS1 | ISA_MIPS2)
|
||||
#define CPU_MIPS3 (CPU_MIPS2 | ISA_MIPS3)
|
||||
#define CPU_MIPS4 (CPU_MIPS3 | ISA_MIPS4)
|
||||
#define CPU_VR54XX (CPU_MIPS4 | INSN_VR54XX)
|
||||
|
||||
#define CPU_MIPS5 (CPU_MIPS4 | ISA_MIPS5)
|
||||
|
||||
/* MIPS Technologies "Release 1" */
|
||||
#define CPU_MIPS32 (CPU_MIPS2 | ISA_MIPS32)
|
||||
#define CPU_MIPS64 (CPU_MIPS5 | CPU_MIPS32 | ISA_MIPS64)
|
||||
|
||||
/* MIPS Technologies "Release 2" */
|
||||
#define CPU_MIPS32R2 (CPU_MIPS32 | ISA_MIPS32R2)
|
||||
#define CPU_MIPS64R2 (CPU_MIPS64 | CPU_MIPS32R2 | ISA_MIPS64R2)
|
||||
|
||||
|
182
target-mips/op.c
182
target-mips/op.c
@ -781,6 +781,90 @@ void op_msubu (void)
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
/* Multiplication variants of the vr54xx. */
|
||||
void op_muls (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_muls);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_mulsu (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_mulsu);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_macc (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_macc);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_macchi (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_macchi);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_maccu (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_maccu);
|
||||
FORCE_RET();
|
||||
}
|
||||
void op_macchiu (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_macchiu);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_msac (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_msac);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_msachi (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_msachi);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_msacu (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_msacu);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_msachiu (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_msachiu);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_mulhi (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_mulhi);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_mulhiu (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_mulhiu);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_mulshi (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_mulshi);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_mulshiu (void)
|
||||
{
|
||||
CALL_FROM_TB0(do_mulshiu);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
|
||||
|
||||
static always_inline uint64_t get_HILO (void)
|
||||
@ -795,6 +879,18 @@ static always_inline void set_HILO (uint64_t HILO)
|
||||
env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
|
||||
}
|
||||
|
||||
static always_inline void set_HIT0_LO (uint64_t HILO)
|
||||
{
|
||||
env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
|
||||
T0 = env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
|
||||
}
|
||||
|
||||
static always_inline void set_HI_LOT0 (uint64_t HILO)
|
||||
{
|
||||
T0 = env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
|
||||
env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
|
||||
}
|
||||
|
||||
void op_mult (void)
|
||||
{
|
||||
set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
|
||||
@ -842,6 +938,92 @@ void op_msubu (void)
|
||||
set_HILO(get_HILO() - tmp);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
/* Multiplication variants of the vr54xx. */
|
||||
void op_muls (void)
|
||||
{
|
||||
set_HI_LOT0(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_mulsu (void)
|
||||
{
|
||||
set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_macc (void)
|
||||
{
|
||||
set_HI_LOT0(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_macchi (void)
|
||||
{
|
||||
set_HIT0_LO(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_maccu (void)
|
||||
{
|
||||
set_HI_LOT0(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_macchiu (void)
|
||||
{
|
||||
set_HIT0_LO(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_msac (void)
|
||||
{
|
||||
set_HI_LOT0(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_msachi (void)
|
||||
{
|
||||
set_HIT0_LO(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_msacu (void)
|
||||
{
|
||||
set_HI_LOT0(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_msachiu (void)
|
||||
{
|
||||
set_HIT0_LO(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_mulhi (void)
|
||||
{
|
||||
set_HIT0_LO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_mulhiu (void)
|
||||
{
|
||||
set_HIT0_LO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_mulshi (void)
|
||||
{
|
||||
set_HIT0_LO(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_mulshiu (void)
|
||||
{
|
||||
set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
|
@ -172,6 +172,18 @@ static always_inline void set_HILO (uint64_t HILO)
|
||||
env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
|
||||
}
|
||||
|
||||
static always_inline void set_HIT0_LO (uint64_t HILO)
|
||||
{
|
||||
env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
|
||||
T0 = env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
|
||||
}
|
||||
|
||||
static always_inline void set_HI_LOT0 (uint64_t HILO)
|
||||
{
|
||||
T0 = env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
|
||||
env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
|
||||
}
|
||||
|
||||
void do_mult (void)
|
||||
{
|
||||
set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
|
||||
@ -213,7 +225,78 @@ void do_msubu (void)
|
||||
tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
|
||||
set_HILO(get_HILO() - tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Multiplication variants of the vr54xx. */
|
||||
void do_muls (void)
|
||||
{
|
||||
set_HI_LOT0(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
|
||||
}
|
||||
|
||||
void do_mulsu (void)
|
||||
{
|
||||
set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
|
||||
}
|
||||
|
||||
void do_macc (void)
|
||||
{
|
||||
set_HI_LOT0(((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
|
||||
}
|
||||
|
||||
void do_macchi (void)
|
||||
{
|
||||
set_HIT0_LO(((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
|
||||
}
|
||||
|
||||
void do_maccu (void)
|
||||
{
|
||||
set_HI_LOT0(((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
|
||||
}
|
||||
|
||||
void do_macchiu (void)
|
||||
{
|
||||
set_HIT0_LO(((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
|
||||
}
|
||||
|
||||
void do_msac (void)
|
||||
{
|
||||
set_HI_LOT0(((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
|
||||
}
|
||||
|
||||
void do_msachi (void)
|
||||
{
|
||||
set_HIT0_LO(((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
|
||||
}
|
||||
|
||||
void do_msacu (void)
|
||||
{
|
||||
set_HI_LOT0(((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
|
||||
}
|
||||
|
||||
void do_msachiu (void)
|
||||
{
|
||||
set_HIT0_LO(((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
|
||||
}
|
||||
|
||||
void do_mulhi (void)
|
||||
{
|
||||
set_HIT0_LO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
|
||||
}
|
||||
|
||||
void do_mulhiu (void)
|
||||
{
|
||||
set_HIT0_LO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
|
||||
}
|
||||
|
||||
void do_mulshi (void)
|
||||
{
|
||||
set_HIT0_LO(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
|
||||
}
|
||||
|
||||
void do_mulshiu (void)
|
||||
{
|
||||
set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
|
||||
}
|
||||
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
|
||||
|
||||
#if HOST_LONG_BITS < 64
|
||||
void do_div (void)
|
||||
|
@ -214,6 +214,26 @@ enum {
|
||||
OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
|
||||
};
|
||||
|
||||
/* Multiplication variants of the vr54xx. */
|
||||
#define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
|
||||
|
||||
enum {
|
||||
OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
|
||||
OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
|
||||
OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
|
||||
OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
|
||||
OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
|
||||
OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
|
||||
OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
|
||||
OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
|
||||
OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
|
||||
OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
|
||||
OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
|
||||
OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
|
||||
OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
|
||||
OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
|
||||
};
|
||||
|
||||
/* REGIMM (rt field) opcodes */
|
||||
#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
|
||||
|
||||
@ -1530,6 +1550,80 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
||||
MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
|
||||
}
|
||||
|
||||
static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
|
||||
int rd, int rs, int rt)
|
||||
{
|
||||
const char *opn = "mul vr54xx";
|
||||
|
||||
GEN_LOAD_REG_T0(rs);
|
||||
GEN_LOAD_REG_T1(rt);
|
||||
|
||||
switch (opc) {
|
||||
case OPC_VR54XX_MULS:
|
||||
gen_op_muls();
|
||||
opn = "muls";
|
||||
break;
|
||||
case OPC_VR54XX_MULSU:
|
||||
gen_op_mulsu();
|
||||
opn = "mulsu";
|
||||
break;
|
||||
case OPC_VR54XX_MACC:
|
||||
gen_op_macc();
|
||||
opn = "macc";
|
||||
break;
|
||||
case OPC_VR54XX_MACCU:
|
||||
gen_op_maccu();
|
||||
opn = "maccu";
|
||||
break;
|
||||
case OPC_VR54XX_MSAC:
|
||||
gen_op_msac();
|
||||
opn = "msac";
|
||||
break;
|
||||
case OPC_VR54XX_MSACU:
|
||||
gen_op_msacu();
|
||||
opn = "msacu";
|
||||
break;
|
||||
case OPC_VR54XX_MULHI:
|
||||
gen_op_mulhi();
|
||||
opn = "mulhi";
|
||||
break;
|
||||
case OPC_VR54XX_MULHIU:
|
||||
gen_op_mulhiu();
|
||||
opn = "mulhiu";
|
||||
break;
|
||||
case OPC_VR54XX_MULSHI:
|
||||
gen_op_mulshi();
|
||||
opn = "mulshi";
|
||||
break;
|
||||
case OPC_VR54XX_MULSHIU:
|
||||
gen_op_mulshiu();
|
||||
opn = "mulshiu";
|
||||
break;
|
||||
case OPC_VR54XX_MACCHI:
|
||||
gen_op_macchi();
|
||||
opn = "macchi";
|
||||
break;
|
||||
case OPC_VR54XX_MACCHIU:
|
||||
gen_op_macchiu();
|
||||
opn = "macchiu";
|
||||
break;
|
||||
case OPC_VR54XX_MSACHI:
|
||||
gen_op_msachi();
|
||||
opn = "msachi";
|
||||
break;
|
||||
case OPC_VR54XX_MSACHIU:
|
||||
gen_op_msachiu();
|
||||
opn = "msachiu";
|
||||
break;
|
||||
default:
|
||||
MIPS_INVAL("mul vr54xx");
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
return;
|
||||
}
|
||||
GEN_STORE_T0_REG(rd);
|
||||
MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
|
||||
}
|
||||
|
||||
static void gen_cl (DisasContext *ctx, uint32_t opc,
|
||||
int rd, int rs)
|
||||
{
|
||||
@ -5973,7 +6067,12 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
gen_arith(env, ctx, op1, rd, rs, rt);
|
||||
break;
|
||||
case OPC_MULT ... OPC_DIVU:
|
||||
gen_muldiv(ctx, op1, rs, rt);
|
||||
if (sa) {
|
||||
check_insn(env, ctx, INSN_VR54XX);
|
||||
op1 = MASK_MUL_VR54XX(ctx->opcode);
|
||||
gen_mul_vr54xx(ctx, op1, rd, rs, rt);
|
||||
} else
|
||||
gen_muldiv(ctx, op1, rs, rt);
|
||||
break;
|
||||
case OPC_JR ... OPC_JALR:
|
||||
gen_compute_branch(ctx, op1, rs, rd, sa);
|
||||
|
@ -305,6 +305,22 @@ static mips_def_t mips_defs[] =
|
||||
.insn_flags = CPU_MIPS3,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "VR5432",
|
||||
.CP0_PRid = 0x00005400,
|
||||
/* No L2 cache, icache size 8k, dcache size 8k, uncached coherency. */
|
||||
.CP0_Config0 = (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << CP0C0_K0),
|
||||
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
|
||||
.SYNCI_Step = 16,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x3678FFFF,
|
||||
/* The VR5432 has a full 64bit FPU but doesn't use the fcr0 bits. */
|
||||
.CP1_fcr0 = (0x54 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.SEGBITS = 40,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_VR54XX,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "5Kc",
|
||||
.CP0_PRid = 0x00018100,
|
||||
|
Loading…
Reference in New Issue
Block a user