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 unsigned64 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 && (unsigned64) EXTEND32 (result) != result) 86 result = ((signed64) result < 0 ? -0x7fffffff - 1 : 0x7fffffff); 87 else if (unsigned_p && (result >> 32) != 0) 88 result = (unsigned64) 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 105000000,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 119000000,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 137000000,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 149000000,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 164000000,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 178000000,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 192000000,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 206000000,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 221010011,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 230010011,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 240010000,1,19.*,100000:COP0:32::WAIT 241"wait" 242*vr5500: 243 244011100,00000,5.RT,5.DR,00000,111101:SPECIAL:64::MFDR 245"mfdr r<RT>, r<DR>" 246*vr5400: 247*vr5500: 248 249011100,00100,5.RT,5.DR,00000,111101:SPECIAL:64::MTDR 250"mtdr r<RT>, r<DR>" 251*vr5400: 252*vr5500: 253 254011100,00000,00000,00000,00000,111110:SPECIAL:64::DRET 255"dret" 256*vr5400: 257*vr5500: 258