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:
ths 2007-12-25 20:46:56 +00:00
parent 29fe0e3490
commit e9c71dd1c1
6 changed files with 405 additions and 7 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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