Commit | Line | Data |
---|---|---|
c906108c SS |
1 | // -*- C -*- |
2 | // | |
3 | // NEC specific instructions | |
4 | // | |
5 | ||
4c54fc26 CD |
6 | :%s::::MFHI:int hi |
7 | { | |
8 | return hi ? "hi" : ""; | |
9 | } | |
c906108c | 10 | |
4c54fc26 CD |
11 | :%s::::SAT:int s |
12 | { | |
13 | return s ? "s" : ""; | |
14 | } | |
c906108c | 15 | |
4c54fc26 | 16 | :%s::::UNS:int u |
c906108c | 17 | { |
4c54fc26 | 18 | return u ? "u" : ""; |
c906108c SS |
19 | } |
20 | ||
4c54fc26 CD |
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 | |
c906108c | 42 | { |
4c54fc26 CD |
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); | |
bcd0068e CD |
76 | product = (unsigned_p |
77 | ? V8_4 (x, 1) * V8_4 (y, 1) | |
78 | : EXTEND32 (x) * EXTEND32 (y)); | |
4c54fc26 CD |
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; | |
c906108c SS |
101 | } |
102 | ||
4c54fc26 CD |
103 | // VR4100 instructions. |
104 | ||
105 | 000000,5.RS,5.RT,00000,00000,101000::32::MADD16 | |
106 | "madd16 r<RS>, r<RT>" | |
c906108c SS |
107 | *vr4100: |
108 | { | |
4c54fc26 CD |
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 */); | |
c906108c SS |
117 | } |
118 | ||
4c54fc26 CD |
119 | 000000,5.RS,5.RT,00000,00000,101001::64::DMADD16 |
120 | "dmadd16 r<RS>, r<RT>" | |
c906108c SS |
121 | *vr4100: |
122 | { | |
4c54fc26 CD |
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 */); | |
c906108c SS |
131 | } |
132 | ||
133 | ||
134 | ||
4c54fc26 CD |
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: | |
c906108c | 140 | { |
4c54fc26 CD |
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 */); | |
c906108c SS |
147 | } |
148 | ||
4c54fc26 CD |
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 | } | |
c906108c | 160 | |
4c54fc26 CD |
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: | |
c906108c | 168 | { |
4c54fc26 CD |
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 */); | |
c906108c SS |
176 | } |
177 | ||
4c54fc26 CD |
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 | ||
4c54fc26 CD |
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: | |
c906108c | 248 | |
4c54fc26 CD |
249 | 011100,00100,5.RT,5.DR,00000,111101:SPECIAL:64::MTDR |
250 | "mtdr r<RT>, r<DR>" | |
251 | *vr5400: | |
252 | *vr5500: | |
c906108c | 253 | |
4c54fc26 CD |
254 | 011100,00000,00000,00000,00000,111110:SPECIAL:64::DRET |
255 | "dret" | |
256 | *vr5400: | |
257 | *vr5500: |