123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- // -*- C -*-
- //
- // NEC specific instructions
- //
- :%s::::MFHI:int hi
- {
- return hi ? "hi" : "";
- }
- :%s::::SAT:int s
- {
- return s ? "s" : "";
- }
- :%s::::UNS:int u
- {
- return u ? "u" : "";
- }
- // 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
- {
- 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;
- }
- // VR4100 instructions.
- 000000,5.RS,5.RT,00000,00000,101000::32::MADD16
- "madd16 r<RS>, r<RT>"
- *vr4100:
- {
- 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 */);
- }
- 000000,5.RS,5.RT,00000,00000,101001::64::DMADD16
- "dmadd16 r<RS>, r<RT>"
- *vr4100:
- {
- 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 */);
- }
- // VR4120 and VR4130 instructions.
- 000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101001::64::DMACC
- "dmacc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>"
- *vr4120:
- {
- do_vr_mul_op (SD_, RD, RS, RT,
- 1 /* accumulate */,
- MFHI, UNS, SAT,
- 0 /* don't subtract */,
- SAT /* short */,
- 1 /* double */);
- }
- 000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101000::32::MACC_4120
- "macc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>"
- *vr4120:
- {
- 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.
- 000000,5.RS,5.RT,5.RD,0,1.MFHI,001,01100,1.UNS::32::MUL
- "mul%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
- *vr5400:
- *vr5500:
- {
- 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<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
- *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 */);
- }
- 000000,5.RS,5.RT,5.RD,0,1.MFHI,101,01100,1.UNS::32::MACC_5xxx
- "macc%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
- *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<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
- *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<FD>, r<INDEX>(r<BASE>)"
- *vr5500:
- {
- 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<FS>, r<INDEX>(r<BASE>)"
- *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<RT>, r<DR>"
- *vr5400:
- *vr5500:
- 011100,00100,5.RT,5.DR,00000,111101:SPECIAL:64::MTDR
- "mtdr r<RT>, r<DR>"
- *vr5400:
- *vr5500:
- 011100,00000,00000,00000,00000,111110:SPECIAL:64::DRET
- "dret"
- *vr5400:
- *vr5500:
|