* dsp.igen (do_ph_shift, do_w_shra): Fix bugs for rounding instructions.
[external/binutils.git] / sim / mips / dsp.igen
1 // -*- C -*-
2
3 // Simulator definition for the MIPS DSP ASE.
4 // Copyright (C) 2005 Free Software Foundation, Inc.
5 // Contributed by MIPS Technologies, Inc.  Written by Chao-ying Fu.
6 //
7 // This file is part of GDB, the GNU debugger.
8 //
9 // This program is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2, or (at your option)
12 // any later version.
13 // 
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 // 
19 // You should have received a copy of the GNU General Public License along
20 // with this program; if not, write to the Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23
24 // op: 0 = ADD, 1 = SUB
25 // sat: 0 = no saturation, 1 = saturation
26 :function:::void:do_ph_op:int rd, int rs, int rt, int op, int sat
27 {
28   int i;
29   signed32 h0;
30   signed16 h1, h2;
31   unsigned32 v1 = GPR[rs];
32   unsigned32 v2 = GPR[rt];
33   unsigned32 result = 0;
34   for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
35     {
36       h1 = (signed16)(v1 & 0xffff);
37       h2 = (signed16)(v2 & 0xffff);
38       if (op == 0) // ADD
39         h0 = (signed32)h1 + (signed32)h2;
40       else // SUB
41         h0 = (signed32)h1 - (signed32)h2;
42       if (((h0 & 0x10000) >> 1) != (h0 & 0x8000))
43         {
44           DSPCR |= DSPCR_OUFLAG4;
45           if (sat == 1)
46             {
47               if (h0 & 0x10000)
48                 h0 = 0x8000;
49               else
50                 h0 = 0x7fff;
51             }
52         }
53       result |= ((unsigned32)((unsigned16)h0) << i);
54     }
55   GPR[rd] = EXTEND32 (result);
56 }
57
58 // op: 0 = ADD, 1 = SUB
59 :function:::void:do_w_op:int rd, int rs, int rt, int op
60 {
61   signed64 h0;
62   signed32 h1, h2;
63   unsigned32 v1 = GPR[rs];
64   unsigned32 v2 = GPR[rt];
65   unsigned32 result = 0;
66   h1 = (signed32)v1;
67   h2 = (signed32)v2;
68   if (op == 0) // ADD
69     h0 = (signed64)h1 + (signed64)h2;
70   else // SUB
71     h0 = (signed64)h1 - (signed64)h2;
72   if (((h0 & 0x100000000) >> 1) != (h0 & 0x80000000))
73     {
74       DSPCR |= DSPCR_OUFLAG4;
75       if (h0 & 0x100000000)
76         h0 = 0x80000000;
77       else
78         h0 = 0x7fffffff;
79     }
80   GPR[rd] = EXTEND32 (h0);
81 }
82
83 // op: 0 = ADD, 1 = SUB
84 // sat: 0 = no saturation, 1 = saturation
85 :function:::void:do_qb_op:int rd, int rs, int rt, int op, int sat
86 {
87   int i;
88   unsigned32 h0;
89   unsigned8 h1, h2;
90   unsigned32 v1 = GPR[rs];
91   unsigned32 v2 = GPR[rt];
92   unsigned32 result = 0;
93   for (i = 0; i < 32; i += 8, v1 >>= 8, v2 >>= 8)
94     {
95       h1 = (unsigned8)(v1 & 0xff);
96       h2 = (unsigned8)(v2 & 0xff);
97       if (op == 0) // ADD
98         h0 = (unsigned32)h1 + (unsigned32)h2;
99       else // SUB
100         h0 = (unsigned32)h1 - (unsigned32)h2;
101       if (h0 & 0x100)
102         {
103           DSPCR |= DSPCR_OUFLAG4;
104           if (sat == 1)
105             {
106               if (op == 0) // ADD
107                 h0 = 0xff;
108               else // SUB
109                 h0 = 0;
110             }
111         }
112       result |= ((unsigned32)((unsigned8)h0) << i);
113     }
114   GPR[rd] = EXTEND32 (result);
115 }
116
117 // op: 0 = left, 1 = right
118 :function:::void:do_qb_shift:int rd, int rt, int shift, int op
119 {
120   int i, j;
121   unsigned8 h0;
122   unsigned32 v1 = GPR[rt];
123   unsigned32 result = 0;
124   for (i = 0; i < 32; i += 8, v1 >>= 8)
125     {
126       h0 = (unsigned8)(v1 & 0xff);
127       if (op == 0) // left
128         {
129           for (j = 7; j >= 8 - shift; j--)
130             {
131               if (h0 & (1<<j))
132                 {
133                   DSPCR |= DSPCR_OUFLAG6;
134                   break;
135                 }
136             }
137           h0 = h0 << shift;
138         }
139       else // right
140         h0 = h0 >> shift;
141       result |= ((unsigned32)h0 << i);
142     }
143   GPR[rd] = EXTEND32 (result);
144 }
145
146 // op: 0 = left, 1 = right
147 // sat: 0 = no saturation/rounding, 1 = saturation/rounding
148 :function:::void:do_ph_shift:int rd, int rt, int shift, int op, int sat
149 {
150   int i, j;
151   signed16 h0;
152   unsigned32 v1 = GPR[rt];
153   unsigned32 result = 0;
154   int setcond;
155   for (i = 0; i < 32; i += 16, v1 >>= 16)
156     {
157       h0 = (signed16)(v1 & 0xffff);
158       if (op == 0) // left
159         {
160           setcond = 0;
161           if (h0 & (1<<15))
162             {
163               for (j = 14; j >= 15 - shift; j--)
164                 {
165                   if (!(h0 & (1 << j)))
166                     {
167                       DSPCR |= DSPCR_OUFLAG6;
168                       setcond = 1;
169                       break;
170                     }
171                 }
172             }
173           else
174             {
175               for (j = 14; j >= 15 - shift; j--)
176                 {
177                   if (h0 & (1 << j))
178                     {
179                       DSPCR |= DSPCR_OUFLAG6;
180                       setcond = 2;
181                       break;
182                     }
183                 }
184             }
185           h0 = h0 << shift;
186           if (sat == 1)
187             {
188               if (setcond == 2)
189                 h0 = 0x7fff; 
190               else if (setcond == 1)
191                 h0 = 0x8000;
192             }
193         }
194       else // right
195         {
196           if (sat == 1 && shift != 0 && (h0 & (1 << (shift-1))))
197             h0 = (h0 >> shift) + 1;
198           else
199             h0 = h0 >> shift;
200         }
201
202       result |= ((unsigned32)((unsigned16)h0) << i);
203     }
204   GPR[rd] = EXTEND32 (result);
205 }
206
207 :function:::void:do_w_shll:int rd, int rt, int shift
208 {
209   int i;
210   unsigned32 v1 = GPR[rt];
211   unsigned32 result = 0;
212   int setcond = 0;
213   if (v1 & (1 << 31))
214     {
215       for (i = 30; i >= 31 - shift; i--)
216         {
217           if (!(v1 & (1 << i)))
218             {
219               DSPCR |= DSPCR_OUFLAG6;
220               setcond = 1;
221               break;
222             }
223         }
224     }
225   else
226     {
227       for (i = 30; i >= 31 - shift; i--)
228         {
229           if (v1 & (1 << i))
230             {
231               DSPCR |= DSPCR_OUFLAG6;
232               setcond = 2;
233               break;
234             }
235         }
236     }
237   if (setcond == 2)
238     result = 0x7fffffff; 
239   else if (setcond == 1)
240     result = 0x80000000;
241   else
242     result = v1 << shift; 
243   GPR[rd] = EXTEND32 (result);
244 }
245
246 :function:::void:do_w_shra:int rd, int rt, int shift
247 {
248   unsigned32 result = GPR[rt];
249   signed32 h0 = (signed32)result;
250   if (shift != 0 && (h0 & (1 << (shift-1))))
251     h0 = (h0 >> shift) + 1;
252   else
253     h0 = h0 >> shift;
254   GPR[rd] = EXTEND32 (h0);
255 }
256
257 011111,5.RS,5.RT,5.RD,01010,010000:SPECIAL3:32::ADDQ.PH
258 "addq.ph r<RD>, r<RS>, r<RT>"
259 *dsp:
260 {
261   do_ph_op (SD_, RD, RS, RT, 0, 0);
262 }
263
264 011111,5.RS,5.RT,5.RD,01110,010000:SPECIAL3:32::ADDQ_S.PH
265 "addq_s.ph r<RD>, r<RS>, r<RT>"
266 *dsp:
267 {
268   do_ph_op (SD_, RD, RS, RT, 0, 1);
269 }
270
271 011111,5.RS,5.RT,5.RD,10110,010000:SPECIAL3:32::ADDQ_S.W
272 "addq_s.w r<RD>, r<RS>, r<RT>"
273 *dsp:
274 {
275   do_w_op (SD_, RD, RS, RT, 0);
276 }
277
278 011111,5.RS,5.RT,5.RD,00000,010000:SPECIAL3:32::ADDU.QB
279 "addu.qb r<RD>, r<RS>, r<RT>"
280 *dsp:
281 {
282   do_qb_op (SD_, RD, RS, RT, 0, 0);
283 }
284
285 011111,5.RS,5.RT,5.RD,00100,010000:SPECIAL3:32::ADDU_S.QB
286 "addu_s.qb r<RD>, r<RS>, r<RT>"
287 *dsp:
288 {
289   do_qb_op (SD_, RD, RS, RT, 0, 1);
290 }
291
292 011111,5.RS,5.RT,5.RD,01011,010000:SPECIAL3:32::SUBQ.PH
293 "subq.ph r<RD>, r<RS>, r<RT>"
294 *dsp:
295 {
296   do_ph_op (SD_, RD, RS, RT, 1, 0);
297 }
298
299 011111,5.RS,5.RT,5.RD,01111,010000:SPECIAL3:32::SUBQ_S.PH
300 "subq_s.ph r<RD>, r<RS>, r<RT>"
301 *dsp:
302 {
303   do_ph_op (SD_, RD, RS, RT, 1, 1);
304 }
305
306 011111,5.RS,5.RT,5.RD,10111,010000:SPECIAL3:32::SUBQ_S.W
307 "subq_s.w r<RD>, r<RS>, r<RT>"
308 *dsp:
309 {
310   do_w_op (SD_, RD, RS, RT, 1);
311 }
312
313 011111,5.RS,5.RT,5.RD,00001,010000:SPECIAL3:32::SUBU.QB
314 "subu.qb r<RD>, r<RS>, r<RT>"
315 *dsp:
316 {
317   do_qb_op (SD_, RD, RS, RT, 1, 0);
318 }
319
320 011111,5.RS,5.RT,5.RD,00101,010000:SPECIAL3:32::SUBU_S.QB
321 "subu_s.qb r<RD>, r<RS>, r<RT>"
322 *dsp:
323 {
324   do_qb_op (SD_, RD, RS, RT, 1, 1);
325 }
326
327 011111,5.RS,5.RT,5.RD,10000,010000:SPECIAL3:32::ADDSC
328 "addsc r<RD>, r<RS>, r<RT>"
329 *dsp:
330 {
331   unsigned32 v1 = GPR[RS];
332   unsigned32 v2 = GPR[RT];
333   unsigned64 h0;
334   h0 = (unsigned64)v1 + (unsigned64)v2;
335   if (h0 & 0x100000000LL)
336     DSPCR |= DSPCR_CARRY;
337   GPR[RD] = EXTEND32 (h0);
338 }
339
340 011111,5.RS,5.RT,5.RD,10001,010000:SPECIAL3:32::ADDWC
341 "addwc r<RD>, r<RS>, r<RT>"
342 *dsp:
343 {
344   unsigned32 v1 = GPR[RS];
345   unsigned32 v2 = GPR[RT];
346   unsigned64 h0;
347   signed32 h1 = (signed32) v1;
348   signed32 h2 = (signed32) v2;
349   h0 = (signed64)h1 + (signed64)h2
350        + (signed64)((DSPCR >> DSPCR_CARRY_SHIFT) & DSPCR_CARRY_MASK);
351   if (((h0 & 0x100000000LL) >> 1) != (h0 & 0x80000000))
352     DSPCR |= DSPCR_OUFLAG4;
353   GPR[RD] = EXTEND32 (h0);
354 }
355
356 011111,5.RS,5.RT,5.RD,10010,010000:SPECIAL3:32::MODSUB
357 "modsub r<RD>, r<RS>, r<RT>"
358 *dsp:
359 {
360   unsigned32 result = 0;
361   unsigned32 v1 = GPR[RS];
362   unsigned32 v2 = GPR[RT];
363   unsigned32 decr = v2 & 0xff;
364   unsigned32 lastindex = (v2 & 0xffff00) >> 8;
365   if (v1 == 0)
366     result = lastindex;
367   else
368     result =  v1 - decr;
369   GPR[RD] = EXTEND32 (result);
370 }
371
372 011111,5.RS,00000,5.RD,10100,010000:SPECIAL3:32::RADDU.W.QB
373 "raddu.w.qb r<RD>, r<RS>"
374 *dsp:
375 {
376   int i;
377   unsigned8 h0;
378   unsigned32 v1 = GPR[RS];
379   unsigned32 result = 0;
380   for (i = 0; i < 32; i += 8, v1 >>= 8)
381     {
382       h0 = (unsigned8)(v1 & 0xff);
383       result += (unsigned32)h0;
384     }
385   GPR[RD] = EXTEND32 (result);
386 }
387
388 011111,00000,5.RT,5.RD,01001,010010:SPECIAL3:32::ABSQ_S.PH
389 "absq_s.ph r<RD>, r<RT>"
390 *dsp:
391 {
392   int i;
393   signed16 h0;
394   unsigned32 v1 = GPR[RT];
395   unsigned32 result = 0;
396   for (i = 0; i < 32; i += 16, v1 >>= 16)
397     {
398       h0 = (signed16)(v1 & 0xffff);
399       if (h0 == (signed16)0x8000)
400         {
401           DSPCR |= DSPCR_OUFLAG4;
402           h0 = 0x7fff;
403         }
404       else if (h0 & 0x8000)
405         h0 = -h0; 
406       result |= ((unsigned32)((unsigned16)h0) << i);
407     }
408   GPR[RD] = EXTEND32 (result);
409 }
410
411 011111,00000,5.RT,5.RD,10001,010010:SPECIAL3:32::ABSQ_S.W
412 "absq_s.w r<RD>, r<RT>"
413 *dsp:
414 {
415   unsigned32 v1 = GPR[RT];
416   signed32 h0 = (signed32)v1;
417   if (h0 == (signed32)0x80000000)
418     {
419       DSPCR |= DSPCR_OUFLAG4;
420       h0 = 0x7fffffff;
421     }
422   else if (h0 & 0x80000000)
423     h0 = -h0; 
424   GPR[RD] = EXTEND32 (h0);
425 }
426
427 011111,5.RS,5.RT,5.RD,01100,010001:SPECIAL3:32::PRECRQ.QB.PH
428 "precrq.qb.ph r<RD>, r<RS>, r<RT>"
429 *dsp:
430 {
431   unsigned32 v1 = GPR[RS];
432   unsigned32 v2 = GPR[RT];
433   unsigned32 tempu = (v1 & 0xff000000) >> 24;
434   unsigned32 tempv = (v1 & 0xff00) >> 8;
435   unsigned32 tempw = (v2 & 0xff000000) >> 24;
436   unsigned32 tempx = (v2 & 0xff00) >> 8;
437   GPR[RD] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx);
438 }
439
440 011111,5.RS,5.RT,5.RD,10100,010001:SPECIAL3:32::PRECRQ.PH.W
441 "precrq.ph.w r<RD>, r<RS>, r<RT>"
442 *dsp:
443 {
444   unsigned32 v1 = GPR[RS];
445   unsigned32 v2 = GPR[RT];
446   unsigned32 tempu = (v1 & 0xffff0000) >> 16;
447   unsigned32 tempv = (v2 & 0xffff0000) >> 16;
448   GPR[RD] = EXTEND32 ((tempu << 16) | tempv);
449 }
450
451 011111,5.RS,5.RT,5.RD,10101,010001:SPECIAL3:32::PRECRQ_RS.PH.W
452 "precrq_rs.ph.w r<RD>, r<RS>, r<RT>"
453 *dsp:
454 {
455   unsigned32 v1 = GPR[RS];
456   unsigned32 v2 = GPR[RT];
457   signed32 h1 = (signed32)v1;
458   signed32 h2 = (signed32)v2;
459   signed64 temp1 = (signed64)h1 + (signed64)0x8000;
460   signed32 temp2;
461   signed64 temp3 = (signed64)h2 + (signed64)0x8000;
462   signed32 temp4;
463   if (((temp1 & 0x100000000LL) >> 1) != (temp1 & 0x80000000))
464     {
465       DSPCR |= DSPCR_OUFLAG6;
466       temp2 = 0x7fff;
467     }
468   else
469     temp2 = (signed32)((temp1 & 0xffff0000) >> 16);
470   if (((temp3 & 0x100000000LL) >> 1) != (temp3 & 0x80000000))
471     {
472       DSPCR |= DSPCR_OUFLAG6;
473       temp4 = 0x7fff;
474     }
475   else
476     temp4 = (signed32)((temp3 & 0xffff0000) >> 16);
477   GPR[RD] = EXTEND32 ((temp2 << 16) | temp4);
478 }
479
480 011111,5.RS,5.RT,5.RD,01111,010001:SPECIAL3:32::PRECRQU_S.QB.PH
481 "precrqu_s.qb.ph r<RD>, r<RS>, r<RT>"
482 *dsp:
483 {
484   unsigned32 v1 = GPR[RS];
485   unsigned32 v2 = GPR[RT];
486   unsigned32 tempu, tempv, tempw, tempx;
487   if (v1 & 0x80000000)
488     {
489       DSPCR |= DSPCR_OUFLAG6;
490       tempu = 0;
491     }
492   else if (!(v1 & 0x80000000) && ((v1 >> 16) > (unsigned32)0x7f80))
493     {
494       DSPCR |= DSPCR_OUFLAG6;
495       tempu = 0xff;
496     }
497   else
498     tempu = (v1 & 0x7f800000) >> 23;
499   if (v1 & 0x8000)
500     {
501       DSPCR |= DSPCR_OUFLAG6;
502       tempv = 0;
503     }
504   else if (!(v1 & 0x8000) && ((v1 & 0xffff) > (unsigned32)0x7f80))
505     {
506       DSPCR |= DSPCR_OUFLAG6;
507       tempv = 0xff;
508     }
509   else
510     tempv = (v1 & 0x7f80) >> 7;
511   if (v2 & 0x80000000)
512     {
513       DSPCR |= DSPCR_OUFLAG6;
514       tempw = 0;
515     }
516   else if (!(v2 & 0x80000000) && ((v2 >> 16) > (unsigned32)0x7f80))
517     {
518       DSPCR |= DSPCR_OUFLAG6;
519       tempw = 0xff;
520     }
521   else
522     tempw = (v2 & 0x7f800000) >> 23;
523   if (v2 & 0x8000)
524     {
525       DSPCR |= DSPCR_OUFLAG6;
526       tempx = 0;
527     }
528   else if (!(v2 & 0x8000) && ((v2 & 0xffff) > (unsigned32)0x7f80))
529     {
530       DSPCR |= DSPCR_OUFLAG6;
531       tempx = 0xff;
532     }
533   else
534     tempx = (v2 & 0x7f80) >> 7;
535   GPR[RD] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx);
536 }
537
538 011111,00000,5.RT,5.RD,01100,010010:SPECIAL3:32::PRECEQ.W.PHL
539 "preceq.w.phl r<RD>, r<RT>"
540 *dsp:
541 {
542   unsigned32 v1 = GPR[RT];
543   GPR[RD] = EXTEND32 (v1 & 0xffff0000);
544 }
545
546 011111,00000,5.RT,5.RD,01101,010010:SPECIAL3:32::PRECEQ.W.PHR
547 "preceq.w.phr r<RD>, r<RT>"
548 *dsp:
549 {
550   unsigned32 v1 = GPR[RT];
551   GPR[RD] = EXTEND32 ((v1 & 0xffff) << 16);
552 }
553
554 011111,00000,5.RT,5.RD,00100,010010:SPECIAL3:32::PRECEQU.PH.QBL
555 "precequ.ph.qbl r<RD>, r<RT>"
556 *dsp:
557 {
558   unsigned32 v1 = GPR[RT];
559   GPR[RD] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff0000) >> 9);
560 }
561
562 011111,00000,5.RT,5.RD,00101,010010:SPECIAL3:32::PRECEQU.PH.QBR
563 "precequ.ph.qbr r<RD>, r<RT>"
564 *dsp:
565 {
566   unsigned32 v1 = GPR[RT];
567   GPR[RD] = EXTEND32 ((v1 & 0xff00) << 15) | ((v1 & 0xff) << 7);
568 }
569
570 011111,00000,5.RT,5.RD,00110,010010:SPECIAL3:32::PRECEQU.PH.QBLA
571 "precequ.ph.qbla r<RD>, r<RT>"
572 *dsp:
573 {
574   unsigned32 v1 = GPR[RT];
575   GPR[RD] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff00) >> 1);
576 }
577
578 011111,00000,5.RT,5.RD,00111,010010:SPECIAL3:32::PRECEQU.PH.QBRA
579 "precequ.ph.qbra r<RD>, r<RT>"
580 *dsp:
581 {
582   unsigned32 v1 = GPR[RT];
583   GPR[RD] = EXTEND32 ((v1 & 0xff0000) << 7) | ((v1 & 0xff) << 7);
584 }
585
586 011111,00000,5.RT,5.RD,11100,010010:SPECIAL3:32::PRECEU.PH.QBL
587 "preceu.ph.qbl r<RD>, r<RT>"
588 *dsp:
589 {
590   unsigned32 v1 = GPR[RT];
591   GPR[RD] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff0000) >> 16);
592 }
593
594 011111,00000,5.RT,5.RD,11101,010010:SPECIAL3:32::PRECEU.PH.QBR
595 "preceu.ph.qbr r<RD>, r<RT>"
596 *dsp:
597 {
598   unsigned32 v1 = GPR[RT];
599   GPR[RD] = EXTEND32 ((v1 & 0xff00) << 8) | (v1 & 0xff);
600 }
601
602 011111,00000,5.RT,5.RD,11110,010010:SPECIAL3:32::PRECEU.PH.QBLA
603 "preceu.ph.qbla r<RD>, r<RT>"
604 *dsp:
605 {
606   unsigned32 v1 = GPR[RT];
607   GPR[RD] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff00) >> 8);
608 }
609
610 011111,00000,5.RT,5.RD,11111,010010:SPECIAL3:32::PRECEU.PH.QBRA
611 "preceu.ph.qbra r<RD>, r<RT>"
612 *dsp:
613 {
614   unsigned32 v1 = GPR[RT];
615   GPR[RD] = EXTEND32 ((v1 & 0xff0000) | (v1 & 0xff));
616 }
617
618 011111,00,3.SHIFT3,5.RT,5.RD,00000,010011:SPECIAL3:32::SHLL.QB
619 "shll.qb r<RD>, r<RT>, <SHIFT3>"
620 *dsp:
621 {
622   do_qb_shift (SD_, RD, RT, SHIFT3, 0);
623 }
624
625 011111,5.RS,5.RT,5.RD,00010,010011:SPECIAL3:32::SHLLV.QB
626 "shllv.qb r<RD>, r<RT>, r<RS>"
627 *dsp:
628 {
629   unsigned32 shift = GPR[RS] & 0x7;
630   do_qb_shift (SD_, RD, RT, shift, 0);
631 }
632
633 011111,0,4.SHIFT4,5.RT,5.RD,01000,010011:SPECIAL3:32::SHLL.PH
634 "shll.ph r<RD>, r<RT>, <SHIFT4>"
635 *dsp:
636 {
637   do_ph_shift (SD_, RD, RT, SHIFT4, 0, 0);
638 }
639
640 011111,5.RS,5.RT,5.RD,01010,010011:SPECIAL3:32::SHLLV.PH
641 "shllv.ph r<RD>, r<RT>, r<RS>"
642 *dsp:
643 {
644   unsigned32 shift = GPR[RS] & 0xf;
645   do_ph_shift (SD_, RD, RT, shift, 0, 0);
646 }
647
648 011111,0,4.SHIFT4,5.RT,5.RD,01100,010011:SPECIAL3:32::SHLL_S.PH
649 "shll_s.ph r<RD>, r<RT>, <SHIFT4>"
650 *dsp:
651 {
652   do_ph_shift (SD_, RD, RT, SHIFT4, 0, 1);
653 }
654
655 011111,5.RS,5.RT,5.RD,01110,010011:SPECIAL3:32::SHLLV_S.PH
656 "shllv_s.ph r<RD>, r<RT>, r<RS>"
657 *dsp:
658 {
659   unsigned32 shift = GPR[RS] & 0xf;
660   do_ph_shift (SD_, RD, RT, shift, 0, 1);
661 }
662
663 011111,5.SHIFT5,5.RT,5.RD,10100,010011:SPECIAL3:32::SHLL_S.W
664 "shll_s.w r<RD>, r<RT>, <SHIFT5>"
665 *dsp:
666 {
667   do_w_shll (SD_, RD, RT, SHIFT5);
668 }
669
670 011111,5.RS,5.RT,5.RD,10110,010011:SPECIAL3:32::SHLLV_S.W
671 "shllv_s.w r<RD>, r<RT>, r<RS>"
672 *dsp:
673 {
674   unsigned32 shift = GPR[RS] & 0x1f;
675   do_w_shll (SD_, RD, RT, shift);
676 }
677
678 011111,00,3.SHIFT3,5.RT,5.RD,00001,010011:SPECIAL3:32::SHRL.QB
679 "shrl.qb r<RD>, r<RT>, <SHIFT3>"
680 *dsp:
681 {
682   do_qb_shift (SD_, RD, RT, SHIFT3, 1);
683 }
684
685 011111,5.RS,5.RT,5.RD,00011,010011:SPECIAL3:32::SHRLV.QB
686 "shrlv.qb r<RD>, r<RT>, r<RS>"
687 *dsp:
688 {
689   unsigned32 shift = GPR[RS] & 0x7;
690   do_qb_shift (SD_, RD, RT, shift, 1);
691 }
692
693 011111,0,4.SHIFT4,5.RT,5.RD,01001,010011:SPECIAL3:32::SHRA.PH
694 "shra.ph r<RD>, r<RT>, <SHIFT4>"
695 *dsp:
696 {
697   do_ph_shift (SD_, RD, RT, SHIFT4, 1, 0);
698 }
699
700 011111,5.RS,5.RT,5.RD,01011,010011:SPECIAL3:32::SHRAV.PH
701 "shrav.ph r<RD>, r<RT>, r<RS>"
702 *dsp:
703 {
704   unsigned32 shift = GPR[RS] & 0xf;
705   do_ph_shift (SD_, RD, RT, shift, 1, 0);
706 }
707
708 011111,0,4.SHIFT4,5.RT,5.RD,01101,010011:SPECIAL3:32::SHRA_R.PH
709 "shra_r.ph r<RD>, r<RT>, <SHIFT4>"
710 *dsp:
711 {
712   do_ph_shift (SD_, RD, RT, SHIFT4, 1, 1);
713 }
714
715 011111,5.RS,5.RT,5.RD,01111,010011:SPECIAL3:32::SHRAV_R.PH
716 "shrav_r.ph r<RD>, r<RT>, r<RS>"
717 *dsp:
718 {
719   unsigned32 shift = GPR[RS] & 0xf;
720   do_ph_shift (SD_, RD, RT, shift, 1, 1);
721 }
722
723 011111,5.SHIFT5,5.RT,5.RD,10101,010011:SPECIAL3:32::SHRA_R.W
724 "shra_r.w r<RD>, r<RT>, <SHIFT5>"
725 *dsp:
726 {
727   do_w_shra (SD_, RD, RT, SHIFT5);
728 }
729
730 011111,5.RS,5.RT,5.RD,10111,010011:SPECIAL3:32::SHRAV_R.W
731 "shrav_r.w r<RD>, r<RT>, r<RS>"
732 *dsp:
733 {
734   unsigned32 shift = GPR[RS] & 0x1f;
735   do_w_shra (SD_, RD, RT, shift);
736 }
737
738 // loc: 0 = qhl, 1 = qhr
739 :function:::void:do_qb_muleu:int rd, int rs, int rt, int loc
740 {
741   int i;
742   unsigned32 result = 0;
743   unsigned32 v1 = GPR[rs];
744   unsigned32 v2 = GPR[rt];
745   unsigned16 h1, h2;
746   unsigned32 prod;
747   if (loc == 0)
748     v1 >>= 16;
749   for (i = 0; i < 32; i += 16, v1 >>= 8, v2 >>= 16)
750     {
751       h1 = (unsigned16)(v1 & 0xff);
752       h2 = (unsigned16)(v2 & 0xffff);
753       prod = (unsigned32)h1 * (unsigned32)h2;
754       if (prod > 0xffff)
755         {
756           DSPCR |= DSPCR_OUFLAG5;
757           prod = 0xffff;
758         }
759       result |= ((unsigned32)prod << i);
760     }
761   GPR[rd] = EXTEND32 (result);
762 }
763
764 011111,5.RS,5.RT,5.RD,00110,010000:SPECIAL3:32::MULEU_S.PH.QBL
765 "muleu_s.ph.qbl r<RD>, r<RS>, r<RT>"
766 *dsp:
767 {
768   do_qb_muleu (SD_, RD, RS, RT, 0);
769 }
770
771 011111,5.RS,5.RT,5.RD,00111,010000:SPECIAL3:32::MULEU_S.PH.QBR
772 "muleu_s.ph.qbr r<RD>, r<RS>, r<RT>"
773 *dsp:
774 {
775   do_qb_muleu (SD_, RD, RS, RT, 1);
776 }
777
778 011111,5.RS,5.RT,5.RD,11111,010000:SPECIAL3:32::MULQ_RS.PH
779 "mulq_rs.ph r<RD>, r<RS>, r<RT>"
780 *dsp:
781 {
782   int i;
783   unsigned32 result = 0;
784   unsigned32 v1 = GPR[RS];
785   unsigned32 v2 = GPR[RT];
786   signed16 h1, h2;
787   signed32 prod;
788   for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
789     {
790       h1 = (signed16)(v1 & 0xffff);
791       h2 = (signed16)(v2 & 0xffff);
792       if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
793         {
794           DSPCR |= DSPCR_OUFLAG5;
795           prod = 0x7fffffff;
796         }
797       else
798         prod = (((signed32)h1 * (signed32)h2) << 1) + (signed32)0x8000;
799
800       result |= (((unsigned32)prod >> 16) << i);
801     }
802   GPR[RD] = EXTEND32 (result);
803 }
804
805 // loc: 0 = phl, 1 = phr
806 :function:::void:do_ph_muleq:int rd, int rs, int rt, int loc
807 {
808   unsigned32 v1 = GPR[rs];
809   unsigned32 v2 = GPR[rt];
810   signed16 h1, h2;
811   signed32 prod;
812   if (loc == 0)
813     {
814       h1 = (signed16)(v1 >> 16);
815       h2 = (signed16)(v2 >> 16);
816     }
817   else
818     {
819       h1 = (signed16)(v1 & 0xffff);
820       h2 = (signed16)(v2 & 0xffff);
821     }
822   if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
823     {
824       DSPCR |= DSPCR_OUFLAG5;
825       prod = 0x7fffffff;
826     }
827   else
828     prod = ((signed32)h1 * (signed32)h2) << 1;
829   GPR[rd] = EXTEND32 (prod);
830 }
831
832 011111,5.RS,5.RT,5.RD,11100,010000:SPECIAL3:32::MULEQ_S.W.PHL
833 "muleq_s.w.phl r<RD>, r<RS>, r<RT>"
834 *dsp:
835 {
836   do_ph_muleq (SD_, RD, RS, RT, 0);
837 }
838
839 011111,5.RS,5.RT,5.RD,11101,010000:SPECIAL3:32::MULEQ_S.W.PHR
840 "muleq_s.w.phr r<RD>, r<RS>, r<RT>"
841 *dsp:
842 {
843   do_ph_muleq (SD_, RD, RS, RT, 1);
844 }
845
846 // op: 0 = DPAU 1 = DPSU
847 // loc: 0 = qbl, 1 = qbr
848 :function:::void:do_qb_dot_product:int ac, int rs, int rt, int op, int loc
849 {
850   int i;
851   unsigned32 v1 = GPR[rs];
852   unsigned32 v2 = GPR[rt];
853   unsigned8 h1, h2;
854   unsigned32 lo = DSPLO(ac);
855   unsigned32 hi = DSPHI(ac);
856   unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
857   if (loc == 0)
858     {
859       v1 >>= 16;
860       v2 >>= 16;
861     }
862   for (i = 0; i < 16; i += 8, v1 >>= 8, v2 >>= 8)
863     {
864       h1 = (unsigned8)(v1 & 0xff);
865       h2 = (unsigned8)(v2 & 0xff);
866       if (op == 0) // DPAU
867         prod += (unsigned64)h1 * (unsigned64)h2;
868       else // DPSU
869         prod -= (unsigned64)h1 * (unsigned64)h2;
870     }
871   DSPLO(ac) = EXTEND32 (prod);
872   DSPHI(ac) = EXTEND32 (prod >> 32);
873 }
874
875 011111,5.RS,5.RT,000,2.AC,00011,110000:SPECIAL3:32::DPAU.H.QBL
876 "dpau.h.qbl ac<AC>, r<RS>, r<RT>"
877 *dsp:
878 {
879   do_qb_dot_product (SD_, AC, RS, RT, 0, 0);
880 }
881
882 011111,5.RS,5.RT,000,2.AC,00111,110000:SPECIAL3:32::DPAU.H.QBR
883 "dpau.h.qbr ac<AC>, r<RS>, r<RT>"
884 *dsp:
885 {
886   do_qb_dot_product (SD_, AC, RS, RT, 0, 1);
887 }
888
889 011111,5.RS,5.RT,000,2.AC,01011,110000:SPECIAL3:32::DPSU.H.QBL
890 "dpsu.h.qbl ac<AC>, r<RS>, r<RT>"
891 *dsp:
892 {
893   do_qb_dot_product (SD_, AC, RS, RT, 1, 0);
894 }
895
896 011111,5.RS,5.RT,000,2.AC,01111,110000:SPECIAL3:32::DPSU.H.QBR
897 "dpsu.h.qbr ac<AC>, r<RS>, r<RT>"
898 *dsp:
899 {
900   do_qb_dot_product (SD_, AC, RS, RT, 1, 1);
901 }
902
903 // op: 0 = DPAQ 1 = DPSQ
904 :function:::void:do_ph_dot_product:int ac, int rs, int rt, int op
905 {
906   int i;
907   unsigned32 v1 = GPR[rs];
908   unsigned32 v2 = GPR[rt];
909   signed16 h1, h2;
910   signed32 result;
911   unsigned32 lo = DSPLO(ac);
912   unsigned32 hi = DSPHI(ac);
913   signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo);
914   for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
915     {
916       h1 = (signed16)(v1 & 0xffff);
917       h2 = (signed16)(v2 & 0xffff);
918       if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
919         {
920           DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
921           result = (signed32)0x7fffffff;
922         }
923       else
924         result = ((signed32)h1 * (signed32)h2) << 1;
925
926       if (op == 0) // DPAQ
927         prod += (signed64)result;
928       else // DPSQ
929         prod -= (signed64)result;
930     }
931   DSPLO(ac) = EXTEND32 (prod);
932   DSPHI(ac) = EXTEND32 (prod >> 32);
933 }
934
935 011111,5.RS,5.RT,000,2.AC,00100,110000:SPECIAL3:32::DPAQ_S.W.PH
936 "dpaq_s.w.ph ac<AC>, r<RS>, r<RT>"
937 *dsp:
938 {
939   do_ph_dot_product (SD_, AC, RS, RT, 0);
940 }
941
942 011111,5.RS,5.RT,000,2.AC,00101,110000:SPECIAL3:32::DPSQ_S.W.PH
943 "dpsq_s.w.ph ac<AC>, r<RS>, r<RT>"
944 *dsp:
945 {
946   do_ph_dot_product (SD_, AC, RS, RT, 1);
947 }
948
949 011111,5.RS,5.RT,000,2.AC,00110,110000:SPECIAL3:32::MULSAQ_S.W.PH
950 "mulsaq_s.w.ph ac<AC>, r<RS>, r<RT>"
951 *dsp:
952 {
953   int i;
954   unsigned32 v1 = GPR[RS];
955   unsigned32 v2 = GPR[RT];
956   signed16 h1, h2;
957   signed32 result;
958   unsigned32 lo = DSPLO(AC);
959   unsigned32 hi = DSPHI(AC);
960   signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo);
961   for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
962     {
963       h1 = (signed16)(v1 & 0xffff);
964       h2 = (signed16)(v2 & 0xffff);
965       if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
966         {
967           DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + AC));
968           result = (signed32) 0x7fffffff;
969         }
970       else
971         result = ((signed32)h1 * (signed32)h2) << 1;
972
973       if (i == 0)
974         prod -= (signed64) result;
975       else
976         prod += (signed64) result;
977     }
978   DSPLO(AC) = EXTEND32 (prod);
979   DSPHI(AC) = EXTEND32 (prod >> 32);
980 }
981
982 // op: 0 = DPAQ 1 = DPSQ
983 :function:::void:do_w_dot_product:int ac, int rs, int rt, int op
984 {
985   unsigned32 v1 = GPR[rs];
986   unsigned32 v2 = GPR[rt];
987   signed32 h1, h2;
988   signed64 result;
989   unsigned32 lo = DSPLO(ac);
990   unsigned32 hi = DSPHI(ac);
991   unsigned32 resultlo;
992   unsigned32 resulthi;
993   unsigned32 carry;
994   unsigned64 temp1;
995   signed64 temp2;
996   h1 = (signed32) v1;
997   h2 = (signed32) v2;
998   if (h1 == 0x80000000 && h2 == 0x80000000)
999     {
1000       DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1001       result = (signed64) 0x7fffffffffffffffLL;
1002     }
1003   else
1004     result = ((signed64)h1 * (signed64)h2) << 1;
1005   resultlo = (unsigned32)(result);
1006   resulthi = (unsigned32)(result >> 32);
1007   if (op ==0) // DPAQ
1008     {
1009       temp1 = (unsigned64)lo + (unsigned64)resultlo;
1010       carry = (unsigned32)((temp1 >> 32) & 1);
1011       temp2 = (signed64)((signed32)hi) + (signed64)((signed32)resulthi) +
1012               (signed64)((signed32)carry);
1013     }
1014   else // DPSQ
1015     {
1016       temp1 = (unsigned64)lo - (unsigned64)resultlo;
1017       carry = (unsigned32)((temp1 >> 32) & 1);
1018       temp2 = (signed64)((signed32)hi) - (signed64)((signed32)resulthi) -
1019               (signed64)((signed32)carry);
1020     }
1021   if (((temp2 & 0x100000000LL) >> 1) != (temp2 & 0x80000000LL))
1022     {
1023       DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1024       if (temp2 & 0x100000000LL)
1025         {
1026           DSPLO(ac) = EXTEND32 (0x00000000);
1027           DSPHI(ac) = EXTEND32 (0x80000000);
1028         }
1029       else
1030         {
1031           DSPLO(ac) = EXTEND32 (0xffffffff);
1032           DSPHI(ac) = EXTEND32 (0x7fffffff);
1033         }
1034     }
1035   else
1036     {
1037       DSPLO(ac) = EXTEND32 (temp1);
1038       DSPHI(ac) = EXTEND32 (temp2);
1039     }
1040 }
1041
1042 011111,5.RS,5.RT,000,2.AC,01100,110000:SPECIAL3:32::DPAQ_SA.L.W
1043 "dpaq_sa.l.w ac<AC>, r<RS>, r<RT>"
1044 *dsp:
1045 {
1046   do_w_dot_product (SD_, AC, RS, RT, 0);
1047 }
1048
1049 011111,5.RS,5.RT,000,2.AC,01101,110000:SPECIAL3:32::DPSQ_SA.L.W
1050 "dpsq_sa.l.w ac<AC>, r<RS>, r<RT>"
1051 *dsp:
1052 {
1053   do_w_dot_product (SD_, AC, RS, RT, 1);
1054 }
1055
1056 // op: 0 = MAQ_S 1 = MAQ_SA
1057 // loc: 0 = phl, 1 = phr
1058 :function:::void:do_ph_maq:int ac, int rs, int rt, int op, int loc
1059 {
1060   int i;
1061   unsigned32 v1 = GPR[rs];
1062   unsigned32 v2 = GPR[rt];
1063   signed16 h1, h2;
1064   signed32 result;
1065   unsigned32 lo = DSPLO(ac);
1066   unsigned32 hi = DSPHI(ac);
1067   signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo);
1068   if (loc == 0)
1069     {
1070       h1 = (signed16)(v1 >> 16);
1071       h2 = (signed16)(v2 >> 16);
1072     }
1073   else
1074     {
1075       h1 = (signed16)(v1 & 0xffff);
1076       h2 = (signed16)(v2 & 0xffff);
1077     }
1078   if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
1079     {
1080       DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1081       result = (signed32)0x7fffffff;
1082     }
1083   else
1084     result = ((signed32)h1 * (signed32)h2) << 1;
1085   prod += (signed64)result;
1086   if (op == 1) // MAQ_SA
1087     {
1088       if (prod & 0x8000000000000000LL)
1089         {
1090           for (i = 62; i >= 31; i--)
1091             {
1092               if (!(prod & ((signed64)1 << i)))
1093                 {
1094                   DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1095                   prod = 0xffffffff80000000LL;
1096                   break;
1097                 }
1098             }
1099         }
1100       else
1101         {
1102           for (i = 62; i >= 31; i--)
1103             {
1104               if (prod & ((signed64)1 << i))
1105                 {
1106                   DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1107                   prod = 0x7fffffff;
1108                   break;
1109                 }
1110             }
1111         }
1112     }
1113   DSPLO(ac) = EXTEND32 (prod);
1114   DSPHI(ac) = EXTEND32 (prod >> 32);
1115 }
1116
1117 011111,5.RS,5.RT,000,2.AC,10100,110000:SPECIAL3:32::MAQ_S.W.PHL
1118 "maq_s.w.phl ac<AC>, r<RS>, r<RT>"
1119 *dsp:
1120 {
1121   do_ph_maq (SD_, AC, RS, RT, 0, 0);
1122 }
1123
1124 011111,5.RS,5.RT,000,2.AC,10110,110000:SPECIAL3:32::MAQ_S.W.PHR
1125 "maq_s.w.phr ac<AC>, r<RS>, r<RT>"
1126 *dsp:
1127 {
1128   do_ph_maq (SD_, AC, RS, RT, 0, 1);
1129 }
1130
1131 011111,5.RS,5.RT,000,2.AC,10000,110000:SPECIAL3:32::MAQ_SA.W.PHL
1132 "maq_sa.w.phl ac<AC>, r<RS>, r<RT>"
1133 *dsp:
1134 {
1135   do_ph_maq (SD_, AC, RS, RT, 1, 0);
1136 }
1137
1138 011111,5.RS,5.RT,000,2.AC,10010,110000:SPECIAL3:32::MAQ_SA.W.PHR
1139 "maq_sa.w.phr ac<AC>, r<RS>, r<RT>"
1140 *dsp:
1141 {
1142   do_ph_maq (SD_, AC, RS, RT, 1, 1);
1143 }
1144
1145 011111,00000,5.RT,5.RD,11011,010010:SPECIAL3:32::BITREV
1146 "bitrev r<RD>, r<RT>"
1147 *dsp:
1148 {
1149   int i;
1150   unsigned32 v1 = GPR[RT];
1151   unsigned32 h1 = 0;
1152   for (i = 0; i < 16; i++)
1153     {
1154       if (v1 & (1 << i))
1155         h1 |= (1 << (15 - i));
1156     }
1157   GPR[RD] = EXTEND32 (h1);
1158 }
1159
1160 011111,5.RS,5.RT,00000,00000,001100:SPECIAL3:32::INSV
1161 "insv r<RT>, r<RS>"
1162 *dsp:
1163 {
1164   unsigned32 v1 = GPR[RS];
1165   unsigned32 v2 = GPR[RT];
1166   unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
1167   unsigned32 size = (DSPCR >> DSPCR_SCOUNT_SHIFT) & DSPCR_SCOUNT_MASK;
1168   unsigned32 mask1, mask2, mask3, result;
1169   if (size < 32)
1170     mask1 = (1 << size) - 1;
1171   else
1172     mask1 = 0xffffffff;
1173   mask2 = (1 << pos) - 1;
1174   if (pos + size < 32)
1175     mask3 = ~((1 << (pos + size)) - 1);
1176   else
1177     mask3 = 0;
1178   result = (v2 & mask3) | ((v1 & mask1) << pos) | (v2 & mask2);
1179   GPR[RT] = EXTEND32 (result);
1180 }
1181
1182 011111,00,8.IMM8,5.RD,00010,010010:SPECIAL3:32::REPL.QB
1183 "repl.qb r<RD>, <IMM8>"
1184 *dsp:
1185 {
1186   GPR[RD] = EXTEND32 ((IMM8 << 24) | (IMM8 << 16) | (IMM8 << 8) | IMM8);
1187 }
1188
1189 011111,00000,5.RT,5.RD,00011,010010:SPECIAL3:32::REPLV.QB
1190 "replv.qb r<RD>, r<RT>"
1191 *dsp:
1192 {
1193   unsigned32 v1 = GPR[RT];
1194   v1 = v1 & 0xff;
1195   GPR[RD] = EXTEND32 ((v1 << 24) | (v1 << 16) | (v1 << 8) | v1);
1196 }
1197
1198 011111,10.IMM10,5.RD,01010,010010:SPECIAL3:32::REPL.PH
1199 "repl.ph r<RD>, <IMM10>"
1200 *dsp:
1201 {
1202   signed32 v1 = IMM10;
1203   if (v1 & 0x200)
1204     v1 |= 0xfffffc00;
1205   GPR[RD] = EXTEND32 ((v1 << 16) | (v1 & 0xffff));
1206 }
1207
1208 011111,00000,5.RT,5.RD,01011,010010:SPECIAL3:32::REPLV.PH
1209 "replv.ph r<RD>, r<RT>"
1210 *dsp:
1211 {
1212   unsigned32 v1 = GPR[RT];
1213   v1 = v1 & 0xffff;
1214   GPR[RD] = EXTEND32 ((v1 << 16) | v1);
1215 }
1216
1217 // op: 0 = EQ, 1 = LT, 2 = LE
1218 :function:::void:do_qb_cmpu:int rs, int rt, int op
1219 {
1220   int i, j;
1221   unsigned32 v1 = GPR[rs];
1222   unsigned32 v2 = GPR[rt];
1223   unsigned8 h1, h2;
1224   unsigned32 mask;
1225   for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1226     {
1227       h1 = (unsigned8)(v1 & 0xff);
1228       h2 = (unsigned8)(v2 & 0xff);
1229       mask = ~(1 << (DSPCR_CCOND_SHIFT + j));
1230       DSPCR &= mask;
1231       if (op == 0) // EQ
1232         DSPCR |= ((h1 == h2) << (DSPCR_CCOND_SHIFT + j));
1233       else if (op == 1) // LT
1234         DSPCR |= ((h1 < h2) << (DSPCR_CCOND_SHIFT + j));
1235       else // LE
1236         DSPCR |= ((h1 <= h2) << (DSPCR_CCOND_SHIFT + j));
1237     }
1238 }
1239
1240 011111,5.RS,5.RT,00000,00000,010001:SPECIAL3:32::CMPU.EQ.QB
1241 "cmpu.eq.qb r<RS>, r<RT>"
1242 *dsp:
1243 {
1244   do_qb_cmpu (SD_, RS, RT, 0);
1245 }
1246
1247 011111,5.RS,5.RT,00000,00001,010001:SPECIAL3:32::CMPU.LT.QB
1248 "cmpu.lt.qb r<RS>, r<RT>"
1249 *dsp:
1250 {
1251   do_qb_cmpu (SD_, RS, RT, 1);
1252 }
1253
1254 011111,5.RS,5.RT,00000,00010,010001:SPECIAL3:32::CMPU.LE.QB
1255 "cmpu.le.qb r<RS>, r<RT>"
1256 *dsp:
1257 {
1258   do_qb_cmpu (SD_, RS, RT, 2);
1259 }
1260
1261 // op: 0 = EQ, 1 = LT, 2 = LE
1262 :function:::void:do_qb_cmpgu:int rd, int rs, int rt, int op
1263 {
1264   int i, j;
1265   unsigned32 v1 = GPR[rs];
1266   unsigned32 v2 = GPR[rt];
1267   unsigned8 h1, h2;
1268   unsigned32 result = 0;
1269   for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1270     {
1271       h1 = (unsigned8)(v1 & 0xff);
1272       h2 = (unsigned8)(v2 & 0xff);
1273       if (op == 0) // EQ
1274         result |= ((h1 == h2) << j);
1275       else if (op == 1) // LT
1276         result |= ((h1 < h2) << j);
1277       else // LE
1278         result |= ((h1 <= h2) << j);
1279     }
1280   GPR[rd] = EXTEND32 (result);
1281 }
1282
1283 011111,5.RS,5.RT,5.RD,00100,010001:SPECIAL3:32::CMPGU.EQ.QB
1284 "cmpgu.eq.qb r<RD>, r<RS>, r<RT>"
1285 *dsp:
1286 {
1287   do_qb_cmpgu (SD_, RD, RS, RT, 0);
1288 }
1289
1290 011111,5.RS,5.RT,5.RD,00101,010001:SPECIAL3:32::CMPGU.LT.QB
1291 "cmpgu.lt.qb r<RD>, r<RS>, r<RT>"
1292 *dsp:
1293 {
1294   do_qb_cmpgu (SD_, RD, RS, RT, 1);
1295 }
1296
1297 011111,5.RS,5.RT,5.RD,00110,010001:SPECIAL3:32::CMPGU.LE.QB
1298 "cmpgu.le.qb r<RD>, r<RS>, r<RT>"
1299 *dsp:
1300 {
1301   do_qb_cmpgu (SD_, RD, RS, RT, 2);
1302 }
1303
1304 // op: 0 = EQ, 1 = LT, 2 = LE
1305 :function:::void:do_ph_cmpu:int rs, int rt, int op
1306 {
1307   int i, j;
1308   unsigned32 v1 = GPR[rs];
1309   unsigned32 v2 = GPR[rt];
1310   signed16 h1, h2;
1311   unsigned32 mask;
1312   for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16)
1313     {
1314       h1 = (signed16)(v1 & 0xffff);
1315       h2 = (signed16)(v2 & 0xffff);
1316       mask = ~(1 << (DSPCR_CCOND_SHIFT + j));
1317       DSPCR &= mask;
1318       if (op == 0) // EQ
1319         DSPCR |= ((h1 == h2) << (DSPCR_CCOND_SHIFT + j));
1320       else if (op == 1) // LT
1321         DSPCR |= ((h1 < h2) << (DSPCR_CCOND_SHIFT + j));
1322       else // LE
1323         DSPCR |= ((h1 <= h2) << (DSPCR_CCOND_SHIFT + j));
1324     }
1325 }
1326
1327 011111,5.RS,5.RT,00000,01000,010001:SPECIAL3:32::CMP.EQ.PH
1328 "cmp.eq.ph r<RS>, r<RT>"
1329 *dsp:
1330 {
1331   do_ph_cmpu (SD_, RS, RT, 0);
1332 }
1333
1334 011111,5.RS,5.RT,00000,01001,010001:SPECIAL3:32::CMP.LT.PH
1335 "cmp.lt.ph r<RS>, r<RT>"
1336 *dsp:
1337 {
1338   do_ph_cmpu (SD_, RS, RT, 1);
1339 }
1340
1341 011111,5.RS,5.RT,00000,01010,010001:SPECIAL3:32::CMP.LE.PH
1342 "cmp.le.ph r<RS>, r<RT>"
1343 *dsp:
1344 {
1345   do_ph_cmpu (SD_, RS, RT, 2);
1346 }
1347
1348 011111,5.RS,5.RT,5.RD,00011,010001:SPECIAL3:32::PICK.QB
1349 "pick.qb r<RD>, r<RS>, r<RT>"
1350 *dsp:
1351 {
1352   int i, j;
1353   unsigned32 v1 = GPR[RS];
1354   unsigned32 v2 = GPR[RT];
1355   unsigned8 h1, h2;
1356   unsigned32 result = 0;
1357   for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1358     {
1359       h1 = (unsigned8)(v1 & 0xff);
1360       h2 = (unsigned8)(v2 & 0xff);
1361       if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j)))
1362         result |= (unsigned32)(h1 << i);
1363       else
1364         result |= (unsigned32)(h2 << i);
1365     }
1366   GPR[RD] = EXTEND32 (result);
1367 }
1368
1369 011111,5.RS,5.RT,5.RD,01011,010001:SPECIAL3:32::PICK.PH
1370 "pick.ph r<RD>, r<RS>, r<RT>"
1371 *dsp:
1372 {
1373   int i, j;
1374   unsigned32 v1 = GPR[RS];
1375   unsigned32 v2 = GPR[RT];
1376   unsigned16 h1, h2;
1377   unsigned32 result = 0;
1378   for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16)
1379     {
1380       h1 = (unsigned16)(v1 & 0xffff);
1381       h2 = (unsigned16)(v2 & 0xffff);
1382       if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j)))
1383         result |= (unsigned32)(h1 << i);
1384       else
1385         result |= (unsigned32)(h2 << i);
1386     }
1387   GPR[RD] = EXTEND32 (result);
1388 }
1389
1390 011111,5.RS,5.RT,5.RD,01110,010001:SPECIAL3:32::PACKRL.PH
1391 "packrl.ph r<RD>, r<RS>, r<RT>"
1392 *dsp:
1393 {
1394   unsigned32 v1 = GPR[RS];
1395   unsigned32 v2 = GPR[RT];
1396   GPR[RD] = EXTEND32 ((v1 << 16) + (v2 >> 16));
1397 }
1398
1399 // op: 0 = EXTR, 1 = EXTR_R, 2 = EXTR_RS
1400 :function:::void:do_w_extr:int rt, int ac, int shift, int op
1401 {
1402   int i;
1403   unsigned32 lo = DSPLO(ac);
1404   unsigned32 hi = DSPHI(ac);
1405   unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1406   signed64 result = (signed64)prod;
1407   int setcond = 0;
1408   if (!(prod & 0x8000000000000000LL))
1409     {
1410       for (i = 62; i >= (shift + 31); i--)
1411         {
1412           if (prod & ((unsigned64)1 << i))
1413             {
1414               DSPCR |= DSPCR_OUFLAG7;
1415               setcond = 1;
1416               break;
1417             }
1418         }
1419       if (((prod >> (shift - 1)) & 0xffffffffLL) == 0xffffffffLL)
1420         {
1421           DSPCR |= DSPCR_OUFLAG7;
1422           setcond = 1;
1423         }
1424     }
1425   else
1426     {
1427       for (i = 62; i >= (shift + 31); i--)
1428         {
1429           if (!(prod & ((unsigned64)1 << i)))
1430             {
1431               DSPCR |= DSPCR_OUFLAG7;
1432               setcond = 2;
1433               break;
1434             }
1435         }
1436     }
1437   if (op == 0) // EXTR
1438     result = result >> shift;
1439   else if (op == 1) // EXTR_R
1440     {
1441       if (shift != 0)
1442         result = ((result >> (shift - 1)) + 1) >> 1;
1443       else
1444         result = result >> shift;
1445     }
1446   else // EXTR_RS
1447     {
1448       if (setcond == 1)
1449         result = 0x7fffffff;
1450       else if (setcond == 2)
1451         result = 0x80000000;
1452       else 
1453         {
1454           if (shift != 0)
1455             result = ((result >> (shift - 1)) + 1) >> 1;
1456           else
1457             result = result >> shift;
1458         }
1459     }
1460   GPR[rt] = EXTEND32 (result);
1461 }
1462
1463 011111,5.SHIFT,5.RT,000,2.AC,00000,111000:SPECIAL3:32::EXTR.W
1464 "extr.w r<RT>, ac<AC>, <SHIFT>"
1465 *dsp:
1466 {
1467   do_w_extr (SD_, RT, AC, SHIFT, 0);
1468 }
1469
1470 011111,5.RS,5.RT,000,2.AC,00001,111000:SPECIAL3:32::EXTRV.W
1471 "extrv.w r<RT>, ac<AC>, r<RS>"
1472 *dsp:
1473 {
1474   unsigned32 shift = GPR[RS] & 0x1f;
1475   do_w_extr (SD_, RT, AC, shift, 0);
1476 }
1477
1478 011111,5.SHIFT,5.RT,000,2.AC,00100,111000:SPECIAL3:32::EXTR_R.W
1479 "extr_r.w r<RT>, ac<AC>, <SHIFT>"
1480 *dsp:
1481 {
1482   do_w_extr (SD_, RT, AC, SHIFT, 1);
1483 }
1484
1485 011111,5.RS,5.RT,000,2.AC,00101,111000:SPECIAL3:32::EXTRV_R.W
1486 "extrv_r.w r<RT>, ac<AC>, r<RS>"
1487 *dsp:
1488 {
1489   unsigned32 shift = GPR[RS] & 0x1f;
1490   do_w_extr (SD_, RT, AC, shift, 1);
1491 }
1492
1493 011111,5.SHIFT,5.RT,000,2.AC,00110,111000:SPECIAL3:32::EXTR_RS.W
1494 "extr_rs.w r<RT>, ac<AC>, <SHIFT>"
1495 *dsp:
1496 {
1497   do_w_extr (SD_, RT, AC, SHIFT, 2);
1498 }
1499
1500 011111,5.RS,5.RT,000,2.AC,00111,111000:SPECIAL3:32::EXTRV_RS.W
1501 "extrv_rs.w r<RT>, ac<AC>, r<RS>"
1502 *dsp:
1503 {
1504   unsigned32 shift = GPR[RS] & 0x1f;
1505   do_w_extr (SD_, RT, AC, shift, 2);
1506 }
1507
1508 :function:::void:do_h_extr:int rt, int ac, int shift
1509 {
1510   int i;
1511   unsigned32 lo = DSPLO(ac);
1512   unsigned32 hi = DSPHI(ac);
1513   unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1514   signed64 result = (signed64)prod;
1515   signed64 value = 0xffffffffffff8000LL;
1516   result >>= shift;
1517   if (result > 0x7fff)
1518     {
1519       result = 0x7fff;
1520       DSPCR |= DSPCR_OUFLAG7;
1521     }
1522   else if (result < value)
1523     {
1524       result = value;
1525       DSPCR |= DSPCR_OUFLAG7;
1526     }
1527   GPR[rt] = EXTEND32 (result);
1528 }
1529
1530 011111,5.SHIFT,5.RT,000,2.AC,01110,111000:SPECIAL3:32::EXTR_S.H
1531 "extr_s.h r<RT>, ac<AC>, <SHIFT>"
1532 *dsp:
1533 {
1534   do_h_extr (SD_, RT, AC, SHIFT);
1535 }
1536
1537 011111,5.RS,5.RT,000,2.AC,01111,111000:SPECIAL3:32::EXTRV_S.H
1538 "extrv_s.h r<RT>, ac<AC>, r<RS>"
1539 *dsp:
1540 {
1541   unsigned32 shift = GPR[RS] & 0x1f;
1542   do_h_extr (SD_, RT, AC, shift);
1543 }
1544
1545 // op: 0 = EXTP, 1 = EXTPDP
1546 :function:::void:do_extp:int rt, int ac, int size, int op
1547 {
1548   signed32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
1549   unsigned32 lo = DSPLO(ac);
1550   unsigned32 hi = DSPHI(ac);
1551   unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1552   unsigned64 result = 0;
1553   if (pos - (size + 1) >= -1)
1554     {
1555       prod >>= (pos - size);
1556       result = prod & (((unsigned64)1 << (size + 1)) - 1);
1557       DSPCR &= (~DSPCR_EFI_SMASK);
1558       if (op == 1) // EXTPDP
1559         {
1560           if (pos - (size + 1) >= 0)
1561             {
1562               DSPCR &= (~DSPCR_POS_SMASK);
1563               DSPCR |= ((pos - (size + 1)) & DSPCR_POS_MASK) << DSPCR_POS_SHIFT;
1564             }
1565           else if (pos - (size + 1) == -1)
1566             {
1567               DSPCR |= DSPCR_POS_SMASK;
1568             }
1569         }
1570     }
1571   else
1572     {
1573       DSPCR |= DSPCR_EFI;
1574       Unpredictable ();
1575     }
1576   GPR[rt] = EXTEND32 (result);
1577 }
1578
1579 011111,5.SIZE,5.RT,000,2.AC,00010,111000:SPECIAL3:32::EXTP
1580 "extp r<RT>, ac<AC>, <SIZE>"
1581 *dsp:
1582 {
1583   do_extp (SD_, RT, AC, SIZE, 0);
1584 }
1585
1586 011111,5.RS,5.RT,000,2.AC,00011,111000:SPECIAL3:32::EXTPV
1587 "extpv r<RT>, ac<AC>, r<RS>"
1588 *dsp:
1589 {
1590   unsigned32 size = GPR[RS] & 0x1f;
1591   do_extp (SD_, RT, AC, size, 0);
1592 }
1593
1594 011111,5.SIZE,5.RT,000,2.AC,01010,111000:SPECIAL3:32::EXTPDP
1595 "extpdp r<RT>, ac<AC>, <SIZE>"
1596 *dsp:
1597 {
1598   do_extp (SD_, RT, AC, SIZE, 1);
1599 }
1600
1601 011111,5.RS,5.RT,000,2.AC,01011,111000:SPECIAL3:32::EXTPDPV
1602 "extpdpv r<RT>, ac<AC>, r<RS>"
1603 *dsp:
1604 {
1605   unsigned32 size = GPR[RS] & 0x1f;
1606   do_extp (SD_, RT, AC, size, 1);
1607 }
1608
1609 :function:::void:do_shilo:int ac, int shift
1610 {
1611   unsigned32 lo = DSPLO(ac);
1612   unsigned32 hi = DSPHI(ac);
1613   unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1614   if (shift > 31)
1615     shift = shift - 64;
1616   if (shift >= 0)
1617     prod >>= shift;
1618   else
1619     prod <<= (-shift);
1620   DSPLO(ac) = EXTEND32 (prod);
1621   DSPHI(ac) = EXTEND32 (prod >> 32);
1622 }
1623
1624 011111,6.SHIFT6,0000,000,2.AC,11010,111000:SPECIAL3:32::SHILO
1625 "shilo ac<AC>, <SHIFT6>"
1626 *dsp:
1627 {
1628   do_shilo (SD_, AC, SHIFT6);
1629 }
1630
1631 011111,5.RS,00000,000,2.AC,11011,111000:SPECIAL3:32::SHILOV
1632 "shilov ac<AC>, r<RS>"
1633 *dsp:
1634 {
1635   signed32 shift = GPR[RS] & 0x3f;
1636   do_shilo (SD_, AC, shift);
1637 }
1638
1639 011111,5.RS,00000,000,2.AC,11111,111000:SPECIAL3:32::MTHLIP
1640 "mthlip r<RS>, ac<AC>"
1641 *dsp:
1642 {
1643   unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
1644   DSPHI(AC) = DSPLO(AC);
1645   DSPLO(AC) = GPR[RS];
1646   if (pos >= 32)
1647     Unpredictable ();
1648   else
1649     pos += 32;
1650   DSPCR &= (~DSPCR_POS_SMASK);
1651   DSPCR |= (pos & DSPCR_POS_MASK) << DSPCR_POS_SHIFT;
1652 }
1653
1654 000000,000,2.AC,00000,5.RD,00000,010000:SPECIAL:32::MFHIdsp
1655 "mfhi r<RD>":AC == 0
1656 "mfhi r<RD>, ac<AC>"
1657 *mips32:
1658 *mips32r2:
1659 *mips64:
1660 *mips64r2:
1661 *dsp:
1662 {
1663   if (AC == 0)
1664     do_mfhi (SD_, RD);
1665   else
1666     GPR[RD] = DSPHI(AC);
1667 }
1668
1669 000000,000,2.AC,00000,5.RD,00000,010010:SPECIAL:32::MFLOdsp
1670 "mflo r<RD>":AC == 0
1671 "mflo r<RD>, ac<AC>"
1672 *mips32:
1673 *mips32r2:
1674 *mips64:
1675 *mips64r2:
1676 *dsp:
1677 {
1678   if (AC == 0)
1679     do_mflo (SD_, RD);
1680   else
1681     GPR[RD] = DSPLO(AC);
1682 }
1683
1684 000000,5.RS,00000,000,2.AC,00000,010001:SPECIAL:32::MTHIdsp
1685 "mthi r<RS>":AC == 0
1686 "mthi r<RS>, ac<AC>"
1687 *mips32:
1688 *mips32r2:
1689 *mips64:
1690 *mips64r2:
1691 *dsp:
1692 {
1693   if (AC == 0)
1694     check_mt_hilo (SD_, HIHISTORY);
1695   DSPHI(AC) = GPR[RS];
1696 }
1697
1698 000000,5.RS,00000,000,2.AC,00000,010011:SPECIAL:32::MTLOdsp
1699 "mtlo r<RS>":AC == 0
1700 "mtlo r<RS>, ac<AC>"
1701 *mips32:
1702 *mips32r2:
1703 *mips64:
1704 *mips64r2:
1705 *dsp:
1706 {
1707   if (AC == 0)
1708     check_mt_hilo (SD_, LOHISTORY);
1709   DSPLO(AC) = GPR[RS];
1710 }
1711
1712 011111,5.RS,10.MASK10,10011,111000:SPECIAL3:32::WRDSP
1713 "wrdsp r<RS>":MASK10 == 1111111111
1714 "wrdsp r<RS>, <MASK10>"
1715 *dsp:
1716 {
1717   unsigned32 v1 = GPR[RS];
1718   if (MASK10 & 0x1)
1719     {
1720       DSPCR &= (~DSPCR_POS_SMASK);
1721       DSPCR |= (v1 & DSPCR_POS_SMASK);
1722     }
1723   if (MASK10 & 0x2)
1724     {
1725       DSPCR &= (~DSPCR_SCOUNT_SMASK);
1726       DSPCR |= (v1 & DSPCR_SCOUNT_SMASK);
1727     }
1728   if (MASK10 & 0x4)
1729     {
1730       DSPCR &= (~DSPCR_CARRY_SMASK);
1731       DSPCR |= (v1 & DSPCR_CARRY_SMASK);
1732     }
1733   if (MASK10 & 0x8)
1734     {
1735       DSPCR &= (~DSPCR_OUFLAG_SMASK);
1736       DSPCR |= (v1 & DSPCR_OUFLAG_SMASK);
1737     }
1738   if (MASK10 & 0x10)
1739     {
1740       DSPCR &= (~DSPCR_CCOND_SMASK);
1741       DSPCR |= (v1 & DSPCR_CCOND_SMASK);
1742     }
1743   if (MASK10 & 0x20)
1744     {
1745       DSPCR &= (~DSPCR_EFI_SMASK);
1746       DSPCR |= (v1 & DSPCR_EFI_SMASK);
1747     }
1748 }
1749
1750 011111,10.MASK10,5.RD,10010,111000:SPECIAL3:32::RDDSP
1751 "rddsp r<RD>":MASK10 == 1111111111
1752 "rddsp r<RD>, <MASK10>"
1753 *dsp:
1754 {
1755   unsigned32 result = 0;
1756   if (MASK10 & 0x1)
1757     {
1758       result &= (~DSPCR_POS_SMASK);
1759       result |= (DSPCR & DSPCR_POS_SMASK);
1760     }
1761   if (MASK10 & 0x2)
1762     {
1763       result &= (~DSPCR_SCOUNT_SMASK);
1764       result |= (DSPCR & DSPCR_SCOUNT_SMASK);
1765     }
1766   if (MASK10 & 0x4)
1767     {
1768       result &= (~DSPCR_CARRY_SMASK);
1769       result |= (DSPCR & DSPCR_CARRY_SMASK);
1770     }
1771   if (MASK10 & 0x8)
1772     {
1773       result &= (~DSPCR_OUFLAG_SMASK);
1774       result |= (DSPCR & DSPCR_OUFLAG_SMASK);
1775     }
1776   if (MASK10 & 0x10)
1777     {
1778       result &= (~DSPCR_CCOND_SMASK);
1779       result |= (DSPCR & DSPCR_CCOND_SMASK);
1780     }
1781   if (MASK10 & 0x20)
1782     {
1783       result &= (~DSPCR_EFI_SMASK);
1784       result |= (DSPCR & DSPCR_EFI_SMASK);
1785     }
1786   GPR[RD] = EXTEND32 (result);
1787 }
1788
1789 011111,5.BASE,5.INDEX,5.RD,00110,001010:SPECIAL3:32::LBUX
1790 "lbux r<RD>, r<INDEX>(r<BASE>)"
1791 *dsp:
1792 {
1793   GPR[RD] = do_load (SD_, AccessLength_BYTE, GPR[BASE], GPR[INDEX]);
1794 }
1795
1796 011111,5.BASE,5.INDEX,5.RD,00100,001010:SPECIAL3:32::LHX
1797 "lhx r<RD>, r<INDEX>(r<BASE>)"
1798 *dsp:
1799 {
1800   GPR[RD] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[BASE], GPR[INDEX]));
1801 }
1802
1803 011111,5.BASE,5.INDEX,5.RD,00000,001010:SPECIAL3:32::LWX
1804 "lwx r<RD>, r<INDEX>(r<BASE>)"
1805 *dsp:
1806 {
1807   GPR[RD] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[BASE], GPR[INDEX]));
1808 }
1809
1810 000001,00000,11100,16.OFFSET:REGIMM:32::BPOSGE32
1811 "bposge32 <OFFSET>"
1812 *dsp:
1813 {
1814   unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
1815   address_word offset = EXTEND16 (OFFSET) << 2;
1816   if (pos >= 32)
1817     {
1818       DELAY_SLOT (NIA + offset);
1819     }
1820 }