2003-01-04 Richard Sandiford <rsandifo@redhat.com>
[deliverable/binutils-gdb.git] / sim / mips / vr.igen
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 ? x * y : EXTEND32 (x) * EXTEND32 (y));
77 result = (subtract_p ? lhs - product : lhs + product);
78 if (saturate_p)
79 {
80 /* Saturate the result to 32 bits. An unsigned, unsaturated
81 result is zero-extended to 64 bits, but unsigned overflow
82 causes all 64 bits to be set. */
83 if (!unsigned_p && (unsigned64) EXTEND32 (result) != result)
84 result = ((signed64) result < 0 ? -0x7fffffff - 1 : 0x7fffffff);
85 else if (unsigned_p && (result >> 32) != 0)
86 result = (unsigned64) 0 - 1;
87 }
88 TRACE_ALU_RESULT (result);
89
90 if (double_p)
91 LO = result;
92 else
93 {
94 LO = EXTEND32 (result);
95 HI = EXTEND32 (VH4_8 (result));
96 }
97 if (rd != 0)
98 GPR[rd] = store_hi_p ? HI : LO;
99 }
100
101 // 32-bit rotate right of X by Y bits.
102 :function:::unsigned64:do_ror:unsigned32 x,unsigned32 y
103 *vr5400:
104 *vr5500:
105 {
106 unsigned64 result;
107
108 y &= 31;
109 TRACE_ALU_INPUT2 (x, y);
110 result = EXTEND32 (ROTR32 (x, y));
111 TRACE_ALU_RESULT (result);
112 return result;
113 }
114
115 // Likewise 64-bit
116 :function:::unsigned64:do_dror:unsigned64 x,unsigned64 y
117 *vr5400:
118 *vr5500:
119 {
120 unsigned64 result;
121
122 y &= 63;
123 TRACE_ALU_INPUT2 (x, y);
124 result = ROTR64 (x, y);
125 TRACE_ALU_RESULT (result);
126 return result;
127 }
128
129
130 // VR4100 instructions.
131
132 000000,5.RS,5.RT,00000,00000,101000::32::MADD16
133 "madd16 r<RS>, r<RT>"
134 *vr4100:
135 {
136 do_vr_mul_op (SD_, 0, RS, RT,
137 1 /* accumulate */,
138 0 /* store in LO */,
139 0 /* signed arithmetic */,
140 0 /* don't saturate */,
141 0 /* don't subtract */,
142 1 /* short */,
143 0 /* single */);
144 }
145
146 000000,5.RS,5.RT,00000,00000,101001::64::DMADD16
147 "dmadd16 r<RS>, r<RT>"
148 *vr4100:
149 {
150 do_vr_mul_op (SD_, 0, RS, RT,
151 1 /* accumulate */,
152 0 /* store in LO */,
153 0 /* signed arithmetic */,
154 0 /* don't saturate */,
155 0 /* don't subtract */,
156 1 /* short */,
157 1 /* double */);
158 }
159
160
161
162 // VR4120 and VR4130 instructions.
163
164 000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101001::64::DMACC
165 "dmacc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>"
166 *vr4120:
167 {
168 do_vr_mul_op (SD_, RD, RS, RT,
169 1 /* accumulate */,
170 MFHI, UNS, SAT,
171 0 /* don't subtract */,
172 SAT /* short */,
173 1 /* double */);
174 }
175
176 000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101000::32::MACC_4120
177 "macc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>"
178 *vr4120:
179 {
180 do_vr_mul_op (SD_, RD, RS, RT,
181 1 /* accumulate */,
182 MFHI, UNS, SAT,
183 0 /* don't subtract */,
184 SAT /* short */,
185 0 /* single */);
186 }
187
188
189 // VR5400 and VR5500 instructions.
190
191 000000,5.RS,5.RT,5.RD,0,1.MFHI,001,01100,1.UNS::32::MUL
192 "mul%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
193 *vr5400:
194 *vr5500:
195 {
196 do_vr_mul_op (SD_, RD, RS, RT,
197 0 /* don't accumulate */,
198 MFHI, UNS,
199 0 /* don't saturate */,
200 0 /* don't subtract */,
201 0 /* not short */,
202 0 /* single */);
203 }
204
205 000000,5.RS,5.RT,5.RD,0,1.MFHI,011,01100,1.UNS::32::MULS
206 "muls%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
207 *vr5400:
208 *vr5500:
209 {
210 do_vr_mul_op (SD_, RD, RS, RT,
211 0 /* don't accumulate */,
212 MFHI, UNS,
213 0 /* don't saturate */,
214 1 /* subtract */,
215 0 /* not short */,
216 0 /* single */);
217 }
218
219 000000,5.RS,5.RT,5.RD,0,1.MFHI,101,01100,1.UNS::32::MACC_5xxx
220 "macc%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
221 *vr5400:
222 *vr5500:
223 {
224 do_vr_mul_op (SD_, RD, RS, RT,
225 1 /* accumulate */,
226 MFHI, UNS,
227 0 /* don't saturate */,
228 0 /* don't subtract */,
229 0 /* not short */,
230 0 /* single */);
231 }
232
233 000000,5.RS,5.RT,5.RD,0,1.MFHI,111,01100,1.UNS::32::MSAC
234 "msac%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
235 *vr5400:
236 *vr5500:
237 {
238 do_vr_mul_op (SD_, RD, RS, RT,
239 1 /* accumulate */,
240 MFHI, UNS,
241 0 /* don't saturate */,
242 1 /* subtract */,
243 0 /* not short */,
244 0 /* single */);
245 }
246
247 000000,00001,5.RT,5.RD,5.SHIFT,000010::32::ROR
248 "ror r<RD>, r<RT>, <SHIFT>"
249 *vr5400:
250 *vr5500:
251 {
252 GPR[RD] = do_ror (SD_, GPR[RT], SHIFT);
253 }
254
255 000000,5.RS,5.RT,5.RD,00001,000110::32::RORV
256 "rorv r<RD>, r<RT>, r<RS>"
257 *vr5400:
258 *vr5500:
259 {
260 GPR[RD] = do_ror (SD_, GPR[RT], GPR[RS]);
261 }
262
263 000000,00001,5.RT,5.RD,5.SHIFT,111010::64::DROR
264 "dror r<RD>, r<RT>, <SHIFT>"
265 *vr5400:
266 *vr5500:
267 {
268 GPR[RD] = do_dror (SD_, GPR[RT], SHIFT);
269 }
270
271 000000,00001,5.RT,5.RD,5.SHIFT,111110::64::DROR32
272 "dror32 r<RD>, r<RT>, <SHIFT>"
273 *vr5400:
274 *vr5500:
275 {
276 GPR[RD] = do_dror (SD_, GPR[RT], SHIFT + 32);
277 }
278
279 000000,5.RS,5.RT,5.RD,00001,010110::64::DRORV
280 "drorv r<RD>, r<RT>, r<RS>"
281 *vr5400:
282 *vr5500:
283 {
284 GPR[RD] = do_dror (SD_, GPR[RT], GPR[RS]);
285 }
286
287 010011,5.BASE,5.INDEX,5.0,5.FD,000101:COP1X:64::LUXC1
288 "luxc1 f<FD>, r<INDEX>(r<BASE>)"
289 *vr5500:
290 {
291 check_fpu (SD_);
292 COP_LD (1, FD, do_load (SD_, AccessLength_DOUBLEWORD,
293 (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0));
294 }
295
296 010011,5.BASE,5.INDEX,5.FS,00000,001101:COP1X:64::SUXC1
297 "suxc1 f<FS>, r<INDEX>(r<BASE>)"
298 *vr5500:
299 {
300 check_fpu (SD_);
301 do_store (SD_, AccessLength_DOUBLEWORD,
302 (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0,
303 COP_SD (1, FS));
304 }
305
306 010000,1,19.*,100000:COP0:32::WAIT
307 "wait"
308 *vr5500:
309
310 011100,00000,5.RT,5.DR,00000,111101:SPECIAL:64::MFDR
311 "mfdr r<RT>, r<DR>"
312 *vr5400:
313 *vr5500:
314
315 011100,00100,5.RT,5.DR,00000,111101:SPECIAL:64::MTDR
316 "mtdr r<RT>, r<DR>"
317 *vr5400:
318 *vr5500:
319
320 011100,00000,00000,00000,00000,111110:SPECIAL:64::DRET
321 "dret"
322 *vr5400:
323 *vr5500:
This page took 0.035894 seconds and 4 git commands to generate.