Home | History | Annotate | Line # | Download | only in mips
      1 // -*- C -*-
      2 //
      3 // NEC specific instructions
      4 //
      5 
      6 :%s::::MFHI:int hi
      7 {
      8   return hi ? "hi" : "";
      9 }
     10 
     11 :%s::::SAT:int s
     12 {
     13   return s ? "s" : "";
     14 }
     15 
     16 :%s::::UNS:int u
     17 {
     18   return u ? "u" : "";
     19 }
     20 
     21 // Simulate the various kinds of multiply and multiply-accumulate instructions.
     22 // Perform an operation of the form:
     23 //
     24 //	LHS (+/-) GPR[RS] * GPR[RT]
     25 //
     26 // and store it in the 64-bit accumulator.  Optionally copy either LO or
     27 // HI into a general purpose register.
     28 //
     29 // - RD is the destination register of the LO or HI move
     30 // - RS are RT are the multiplication source registers
     31 // - ACCUMULATE_P is true if LHS should be the value of the 64-bit accumulator,
     32 //     false if it should be 0.
     33 // - STORE_HI_P is true if HI should be stored in RD, false if LO should be.
     34 // - UNSIGNED_P is true if the operation should be unsigned.
     35 // - SATURATE_P is true if the result should be saturated to a 32-bit value.
     36 // - SUBTRACT_P is true if the right hand side should be subtraced from LHS,
     37 //     false if it should be added.
     38 // - SHORT_P is true if RS and RT must be 16-bit numbers.
     39 // - DOUBLE_P is true if the 64-bit accumulator is in LO, false it is a
     40 //     concatenation of the low 32 bits of HI and LO.
     41 :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
     42 {
     43   uint64_t lhs, x, y, xcut, ycut, product, result;
     44 
     45   check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
     46 
     47   lhs = (!accumulate_p ? 0 : double_p ? LO : U8_4 (HI, LO));
     48   x = GPR[rs];
     49   y = GPR[rt];
     50 
     51   /* Work out the canonical form of X and Y from their significant bits.  */
     52   if (!short_p)
     53     {
     54       /* Normal sign-extension rule for 32-bit operands.  */
     55       xcut = EXTEND32 (x);
     56       ycut = EXTEND32 (y);
     57     }
     58   else if (unsigned_p)
     59     {
     60       /* Operands must be zero-extended 16-bit numbers.  */
     61       xcut = x & 0xffff;
     62       ycut = y & 0xffff;
     63     }
     64   else
     65     {
     66       /* Likewise but sign-extended.  */
     67       xcut = EXTEND16 (x);
     68       ycut = EXTEND16 (y);
     69     }
     70   if (x != xcut || y != ycut)
     71     sim_engine_abort (SD, CPU, CIA,
     72 		      "invalid multiplication operand at 0x%08lx\n",
     73 		      (long) CIA);
     74 
     75   TRACE_ALU_INPUT2 (x, y);
     76   product = (unsigned_p
     77 	     ? V8_4 (x, 1) * V8_4 (y, 1)
     78 	     : EXTEND32 (x) * EXTEND32 (y));
     79   result = (subtract_p ? lhs - product : lhs + product);
     80   if (saturate_p)
     81     {
     82       /* Saturate the result to 32 bits.  An unsigned, unsaturated
     83 	 result is zero-extended to 64 bits, but unsigned overflow
     84 	 causes all 64 bits to be set.  */
     85       if (!unsigned_p && (uint64_t) EXTEND32 (result) != result)
     86 	result = ((int64_t) result < 0 ? -0x7fffffff - 1 : 0x7fffffff);
     87       else if (unsigned_p && (result >> 32) != 0)
     88 	result = (uint64_t) 0 - 1;
     89     }
     90   TRACE_ALU_RESULT (result);
     91 
     92   if (double_p)
     93     LO = result;
     94   else
     95     {
     96       LO = EXTEND32 (result);
     97       HI = EXTEND32 (VH4_8 (result));
     98     }
     99   if (rd != 0)
    100     GPR[rd] = store_hi_p ? HI : LO;
    101 }
    102 
    103 // VR4100 instructions.
    104 
    105 000000,5.RS,5.RT,00000,00000,101000::32::MADD16
    106 "madd16 r<RS>, r<RT>"
    107 *vr4100:
    108 {
    109   do_vr_mul_op (SD_, 0, RS, RT,
    110 		1 /* accumulate */,
    111 		0 /* store in LO */,
    112 		0 /* signed arithmetic */,
    113 		0 /* don't saturate */,
    114 		0 /* don't subtract */,
    115 		1 /* short */,
    116 		0 /* single */);
    117 }
    118 
    119 000000,5.RS,5.RT,00000,00000,101001::64::DMADD16
    120 "dmadd16 r<RS>, r<RT>"
    121 *vr4100:
    122 {
    123   do_vr_mul_op (SD_, 0, RS, RT,
    124 		1 /* accumulate */,
    125 		0 /* store in LO */,
    126 		0 /* signed arithmetic */,
    127 		0 /* don't saturate */,
    128 		0 /* don't subtract */,
    129 		1 /* short */,
    130 		1 /* double */);
    131 }
    132 
    133 
    134 
    135 // VR4120 and VR4130 instructions.
    136 
    137 000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101001::64::DMACC
    138 "dmacc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>"
    139 *vr4120:
    140 {
    141   do_vr_mul_op (SD_, RD, RS, RT,
    142 		1 /* accumulate */,
    143 		MFHI, UNS, SAT,
    144 		0 /* don't subtract */,
    145 		SAT /* short */,
    146 		1 /* double */);
    147 }
    148 
    149 000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101000::32::MACC_4120
    150 "macc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>"
    151 *vr4120:
    152 {
    153   do_vr_mul_op (SD_, RD, RS, RT,
    154 		1 /* accumulate */,
    155 		MFHI, UNS, SAT,
    156 		0 /* don't subtract */,
    157 		SAT /* short */,
    158 		0 /* single */);
    159 }
    160 
    161 
    162 // VR5400 and VR5500 instructions.
    163 
    164 000000,5.RS,5.RT,5.RD,0,1.MFHI,001,01100,1.UNS::32::MUL
    165 "mul%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
    166 *vr5400:
    167 *vr5500:
    168 {
    169   do_vr_mul_op (SD_, RD, RS, RT,
    170 		0 /* don't accumulate */,
    171 		MFHI, UNS,
    172 		0 /* don't saturate */,
    173 		0 /* don't subtract */,
    174 		0 /* not short */,
    175 		0 /* single */);
    176 }
    177 
    178 000000,5.RS,5.RT,5.RD,0,1.MFHI,011,01100,1.UNS::32::MULS
    179 "muls%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
    180 *vr5400:
    181 *vr5500:
    182 {
    183   do_vr_mul_op (SD_, RD, RS, RT,
    184 		0 /* don't accumulate */,
    185 		MFHI, UNS,
    186 		0 /* don't saturate */,
    187 		1 /* subtract */,
    188 		0 /* not short */,
    189 		0 /* single */);
    190 }
    191 
    192 000000,5.RS,5.RT,5.RD,0,1.MFHI,101,01100,1.UNS::32::MACC_5xxx
    193 "macc%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
    194 *vr5400:
    195 *vr5500:
    196 {
    197   do_vr_mul_op (SD_, RD, RS, RT,
    198 		1 /* accumulate */,
    199 		MFHI, UNS,
    200 		0 /* don't saturate */,
    201 		0 /* don't subtract */,
    202 		0 /* not short */,
    203 		0 /* single */);
    204 }
    205 
    206 000000,5.RS,5.RT,5.RD,0,1.MFHI,111,01100,1.UNS::32::MSAC
    207 "msac%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
    208 *vr5400:
    209 *vr5500:
    210 {
    211   do_vr_mul_op (SD_, RD, RS, RT,
    212 		1 /* accumulate */,
    213 		MFHI, UNS,
    214 		0 /* don't saturate */,
    215 		1 /* subtract */,
    216 		0 /* not short */,
    217 		0 /* single */);
    218 }
    219 
    220 
    221 010011,5.BASE,5.INDEX,5.0,5.FD,000101:COP1X:64::LUXC1
    222 "luxc1 f<FD>, r<INDEX>(r<BASE>)"
    223 *vr5500:
    224 {
    225   check_fpu (SD_);
    226   COP_LD (1, FD, do_load (SD_, AccessLength_DOUBLEWORD,
    227 			  (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0));
    228 }
    229 
    230 010011,5.BASE,5.INDEX,5.FS,00000,001101:COP1X:64::SUXC1
    231 "suxc1 f<FS>, r<INDEX>(r<BASE>)"
    232 *vr5500:
    233 {
    234   check_fpu (SD_);
    235   do_store (SD_, AccessLength_DOUBLEWORD,
    236 	    (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0,
    237 	    COP_SD (1, FS));
    238 }
    239 
    240 010000,1,19.*,100000:COP0:32::WAIT
    241 "wait"
    242 *vr5500:
    243 
    244 011100,00000,5.RT,5.DR,00000,111101:SPECIAL:64::MFDR
    245 "mfdr r<RT>, r<DR>"
    246 *vr5400:
    247 *vr5500:
    248 
    249 011100,00100,5.RT,5.DR,00000,111101:SPECIAL:64::MTDR
    250 "mtdr r<RT>, r<DR>"
    251 *vr5400:
    252 *vr5500:
    253 
    254 011100,00000,00000,00000,00000,111110:SPECIAL:64::DRET
    255 "dret"
    256 *vr5400:
    257 *vr5500:
    258