diff options
author | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-12-25 20:46:56 +0000 |
---|---|---|
committer | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-12-25 20:46:56 +0000 |
commit | e9c71dd1c1f5aeb3732261a02dcfae031973f053 (patch) | |
tree | de9b88fe2a6e0ffbb6b2f1fa63f401e14aa66e6a | |
parent | 29fe0e3490ef63f564f426fc526d4415f44e7052 (diff) |
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
-rw-r--r-- | target-mips/exec.h | 14 | ||||
-rw-r--r-- | target-mips/mips-defs.h | 14 | ||||
-rw-r--r-- | target-mips/op.c | 182 | ||||
-rw-r--r-- | target-mips/op_helper.c | 85 | ||||
-rw-r--r-- | target-mips/translate.c | 101 | ||||
-rw-r--r-- | target-mips/translate_init.c | 16 |
6 files changed, 405 insertions, 7 deletions
diff --git a/target-mips/exec.h b/target-mips/exec.h index 307049ed31..7b2c4687f6 100644 --- a/target-mips/exec.h +++ b/target-mips/exec.h @@ -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); diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h index 76ea8d019b..2d0c1383dd 100644 --- a/target-mips/mips-defs.h +++ b/target-mips/mips-defs.h @@ -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) diff --git a/target-mips/op.c b/target-mips/op.c index b5c24b2316..cf965fa874 100644 --- a/target-mips/op.c +++ b/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) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 36c4b73f93..93ba79c7e4 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -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) diff --git a/target-mips/translate.c b/target-mips/translate.c index be29357f10..1d8aea185b 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -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); diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index a2dec0af9f..57666d4db7 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -306,6 +306,22 @@ static mips_def_t mips_defs[] = .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, .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) | |