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