X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fmips%2Fvr.igen;h=9266ae6dc613865427e17cfa2060242fb26fed62;hb=50d036364fb2a71b3ac9a0b0cdbe58296832a1b2;hp=863bb556229cb72203f21bcd451c552e9055fc93;hpb=d0352a18a504a4e7b761f6b3264cf11347d8d056;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/mips/vr.igen b/sim/mips/vr.igen index 863bb55622..9266ae6dc6 100644 --- a/sim/mips/vr.igen +++ b/sim/mips/vr.igen @@ -3,76 +3,255 @@ // NEC specific instructions // -// Integer Instructions -// -------------------- -// -// MulAcc is the Multiply Accumulator. -// This register is mapped on the the HI and LO registers. -// Upper 32 bits of MulAcc is mapped on to lower 32 bits of HI register. -// Lower 32 bits of MulAcc is mapped on to lower 32 bits of LO register. +:%s::::MFHI:int hi +{ + return hi ? "hi" : ""; +} +:%s::::SAT:int s +{ + return s ? "s" : ""; +} -:function:::unsigned64:MulAcc: -*vr4100: +:%s::::UNS:int u { - unsigned64 result = U8_4 (HI, LO); - return result; + return u ? "u" : ""; } -:function:::void:SET_MulAcc:unsigned64 value -*vr4100: +// Simulate the various kinds of multiply and multiply-accumulate instructions. +// Perform an operation of the form: +// +// LHS (+/-) GPR[RS] * GPR[RT] +// +// and store it in the 64-bit accumulator. Optionally copy either LO or +// HI into a general purpose register. +// +// - RD is the destination register of the LO or HI move +// - RS are RT are the multiplication source registers +// - ACCUMULATE_P is true if LHS should be the value of the 64-bit accumulator, +// false if it should be 0. +// - STORE_HI_P is true if HI should be stored in RD, false if LO should be. +// - UNSIGNED_P is true if the operation should be unsigned. +// - SATURATE_P is true if the result should be saturated to a 32-bit value. +// - SUBTRACT_P is true if the right hand side should be subtraced from LHS, +// false if it should be added. +// - SHORT_P is true if RS and RT must be 16-bit numbers. +// - DOUBLE_P is true if the 64-bit accumulator is in LO, false it is a +// concatenation of the low 32 bits of HI and LO. +:function:::void:do_vr_mul_op:int rd, int rs, int rt, int accumulate_p, int store_hi_p, int unsigned_p, int saturate_p, int subtract_p, int short_p, int double_p { - /* 64 bit specific */ - *AL4_8 (&HI) = VH4_8 (value); - *AL4_8 (&LO) = VL4_8 (value); + unsigned64 lhs, x, y, xcut, ycut, product, result; + + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + + lhs = (!accumulate_p ? 0 : double_p ? LO : U8_4 (HI, LO)); + x = GPR[rs]; + y = GPR[rt]; + + /* Work out the canonical form of X and Y from their significant bits. */ + if (!short_p) + { + /* Normal sign-extension rule for 32-bit operands. */ + xcut = EXTEND32 (x); + ycut = EXTEND32 (y); + } + else if (unsigned_p) + { + /* Operands must be zero-extended 16-bit numbers. */ + xcut = x & 0xffff; + ycut = y & 0xffff; + } + else + { + /* Likewise but sign-extended. */ + xcut = EXTEND16 (x); + ycut = EXTEND16 (y); + } + if (x != xcut || y != ycut) + sim_engine_abort (SD, CPU, CIA, + "invalid multiplication operand at 0x%08lx\n", + (long) CIA); + + TRACE_ALU_INPUT2 (x, y); + product = (unsigned_p + ? V8_4 (x, 1) * V8_4 (y, 1) + : EXTEND32 (x) * EXTEND32 (y)); + result = (subtract_p ? lhs - product : lhs + product); + if (saturate_p) + { + /* Saturate the result to 32 bits. An unsigned, unsaturated + result is zero-extended to 64 bits, but unsigned overflow + causes all 64 bits to be set. */ + if (!unsigned_p && (unsigned64) EXTEND32 (result) != result) + result = ((signed64) result < 0 ? -0x7fffffff - 1 : 0x7fffffff); + else if (unsigned_p && (result >> 32) != 0) + result = (unsigned64) 0 - 1; + } + TRACE_ALU_RESULT (result); + + if (double_p) + LO = result; + else + { + LO = EXTEND32 (result); + HI = EXTEND32 (VH4_8 (result)); + } + if (rd != 0) + GPR[rd] = store_hi_p ? HI : LO; } -:function:::signed64:SignedMultiply:signed32 l, signed32 r +// VR4100 instructions. + +000000,5.RS,5.RT,00000,00000,101000::32::MADD16 +"madd16 r, r" *vr4100: { - signed64 result = (signed64) l * (signed64) r; - return result; + do_vr_mul_op (SD_, 0, RS, RT, + 1 /* accumulate */, + 0 /* store in LO */, + 0 /* signed arithmetic */, + 0 /* don't saturate */, + 0 /* don't subtract */, + 1 /* short */, + 0 /* single */); } -:function:::unsigned64:UnsignedMultiply:unsigned32 l, unsigned32 r +000000,5.RS,5.RT,00000,00000,101001::64::DMADD16 +"dmadd16 r, r" *vr4100: { - unsigned64 result = (unsigned64) l * (unsigned64) r; - return result; + do_vr_mul_op (SD_, 0, RS, RT, + 1 /* accumulate */, + 0 /* store in LO */, + 0 /* signed arithmetic */, + 0 /* don't saturate */, + 0 /* don't subtract */, + 1 /* short */, + 1 /* double */); } -:function:::unsigned64:Low32Bits:unsigned64 value -*vr4100: + + +// VR4120 and VR4130 instructions. + +000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101001::64::DMACC +"dmacc%s%s%s r, r, r" +*vr4120: { - unsigned64 result = (signed64) (signed32) VL4_8 (value); - return result; + do_vr_mul_op (SD_, RD, RS, RT, + 1 /* accumulate */, + MFHI, UNS, SAT, + 0 /* don't subtract */, + SAT /* short */, + 1 /* double */); } -:function:::unsigned64:High32Bits:unsigned64 value -*vr4100: +000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101000::32::MACC_4120 +"macc%s%s%s r, r, r" +*vr4120: { - unsigned64 result = (signed64) (signed32) VH4_8 (value); - return result; + do_vr_mul_op (SD_, RD, RS, RT, + 1 /* accumulate */, + MFHI, UNS, SAT, + 0 /* don't subtract */, + SAT /* short */, + 0 /* single */); } +// VR5400 and VR5500 instructions. -// Multiply, Accumulate -000000,5.RS,5.RT,00000,00000,101000::64::MAC -"mac r, r" -*vr4100: +000000,5.RS,5.RT,5.RD,0,1.MFHI,001,01100,1.UNS::32::MUL +"mul%s%s r, r, r" +*vr5400: +*vr5500: { - SET_MulAcc (SD_, MulAcc (SD_) + SignedMultiply (SD_, GPR[RS], GPR[RT])); + do_vr_mul_op (SD_, RD, RS, RT, + 0 /* don't accumulate */, + MFHI, UNS, + 0 /* don't saturate */, + 0 /* don't subtract */, + 0 /* not short */, + 0 /* single */); } +000000,5.RS,5.RT,5.RD,0,1.MFHI,011,01100,1.UNS::32::MULS +"muls%s%s r, r, r" +*vr5400: +*vr5500: +{ + do_vr_mul_op (SD_, RD, RS, RT, + 0 /* don't accumulate */, + MFHI, UNS, + 0 /* don't saturate */, + 1 /* subtract */, + 0 /* not short */, + 0 /* single */); +} -// D-Multiply, Accumulate -000000,5.RS,5.RT,00000,00000,101001::64::DMAC -"dmac r, r" -*vr4100: +000000,5.RS,5.RT,5.RD,0,1.MFHI,101,01100,1.UNS::32::MACC_5xxx +"macc%s%s r, r, r" +*vr5400: +*vr5500: +{ + do_vr_mul_op (SD_, RD, RS, RT, + 1 /* accumulate */, + MFHI, UNS, + 0 /* don't saturate */, + 0 /* don't subtract */, + 0 /* not short */, + 0 /* single */); +} + +000000,5.RS,5.RT,5.RD,0,1.MFHI,111,01100,1.UNS::32::MSAC +"msac%s%s r, r, r" +*vr5400: +*vr5500: +{ + do_vr_mul_op (SD_, RD, RS, RT, + 1 /* accumulate */, + MFHI, UNS, + 0 /* don't saturate */, + 1 /* subtract */, + 0 /* not short */, + 0 /* single */); +} + + +010011,5.BASE,5.INDEX,5.0,5.FD,000101:COP1X:64::LUXC1 +"luxc1 f, r(r)" +*vr5500: { - LO = LO + SignedMultiply (SD_, GPR[RS], GPR[RT]); + check_fpu (SD_); + COP_LD (1, FD, do_load (SD_, AccessLength_DOUBLEWORD, + (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0)); } +010011,5.BASE,5.INDEX,5.FS,00000,001101:COP1X:64::SUXC1 +"suxc1 f, r(r)" +*vr5500: +{ + check_fpu (SD_); + do_store (SD_, AccessLength_DOUBLEWORD, + (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0, + COP_SD (1, FS)); +} + +010000,1,19.*,100000:COP0:32::WAIT +"wait" +*vr5500: + +011100,00000,5.RT,5.DR,00000,111101:SPECIAL:64::MFDR +"mfdr r, r" +*vr5400: +*vr5500: +011100,00100,5.RT,5.DR,00000,111101:SPECIAL:64::MTDR +"mtdr r, r" +*vr5400: +*vr5500: +011100,00000,00000,00000,00000,111110:SPECIAL:64::DRET +"dret" +*vr5400: +*vr5500: