]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/erc32/exec.c
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / sim / erc32 / exec.c
1 /*
2 * This file is part of SIS.
3 *
4 * SIS, SPARC instruction simulator V1.8 Copyright (C) 1995 Jiri Gaisler,
5 * European Space Agency
6 *
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 675
19 * Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22
23 #include "sis.h"
24 #include "end.h"
25 #include <math.h>
26 #include <stdio.h>
27
28 extern int32 ext_irl, irqpend, iurev0, sis_verbose;
29
30 /* Load/store interlock delay */
31 #define FLSTHOLD 1
32
33 /* Load delay (delete if unwanted - speeds up simulation) */
34 #define LOAD_DEL 1
35
36 #define T_LD 2
37 #define T_LDD 3
38 #define T_ST 3
39 #define T_STD 4
40 #define T_LDST 4
41 #define T_JMPL 2
42 #define T_RETT 2
43
44 #define FSR_QNE 0x2000
45 #define FP_EXE_MODE 0
46 #define FP_EXC_PE 1
47 #define FP_EXC_MODE 2
48
49 #define FBA 8
50 #define FBN 0
51 #define FBNE 1
52 #define FBLG 2
53 #define FBUL 3
54 #define FBL 4
55 #define FBUG 5
56 #define FBG 6
57 #define FBU 7
58
59 #define FCC_E 0
60 #define FCC_L 1
61 #define FCC_G 2
62 #define FCC_U 3
63
64 #define PSR_ET 0x20
65 #define PSR_EF 0x1000
66 #define PSR_PS 0x40
67 #define PSR_S 0x80
68 #define PSR_N 0x0800000
69 #define PSR_Z 0x0400000
70 #define PSR_V 0x0200000
71 #define PSR_C 0x0100000
72 #define PSR_CC 0x0F00000
73 #define PSR_CWP 0x7
74 #define PSR_PIL 0x0f00
75
76 #define ICC_N sregs->psr
77 #define ICC_Z (sregs->psr << 1)
78 #define ICC_V (sregs->psr << 2)
79 #define ICC_C (sregs->psr << 3)
80
81 #define TRAP_IEXC 1
82 #define TRAP_UNIMP 2
83 #define TRAP_PRIVI 3
84 #define TRAP_FPDIS 4
85 #define TRAP_WOFL 5
86 #define TRAP_WUFL 6
87 #define TRAP_UNALI 7
88 #define TRAP_FPEXC 8
89 #define TRAP_DEXC 9
90 #define TRAP_TAG 10
91
92 #define FSR_TT 0x1C000
93 #define FP_IEEE 0x04000
94 #define FP_UNIMP 0x0C000
95 #define FP_SEQ_ERR 0x10000
96
97 #define BICC_BN 0
98 #define BICC_BE 1
99 #define BICC_BLE 2
100 #define BICC_BL 3
101 #define BICC_BLEU 4
102 #define BICC_BCS 5
103 #define BICC_NEG 6
104 #define BICC_BVS 7
105 #define BICC_BA 8
106
107 #define INST_SIMM13 0x1fff
108 #define INST_RS2 0x1f
109 #define INST_I 0x2000
110 #define ADD 0x00
111 #define ADDCC 0x10
112 #define ADDX 0x08
113 #define ADDXCC 0x18
114 #define TADDCC 0x20
115 #define TADDCCTV 0x22
116 #define IAND 0x01
117 #define IANDCC 0x11
118 #define IANDN 0x05
119 #define IANDNCC 0x15
120 #define MULScc 0x24
121 #define IOR 0x02
122 #define IORCC 0x12
123 #define IORN 0x06
124 #define IORNCC 0x16
125 #define SLL 0x25
126 #define SRA 0x27
127 #define SRL 0x26
128 #define SUB 0x04
129 #define SUBCC 0x14
130 #define SUBX 0x0C
131 #define SUBXCC 0x1C
132 #define IXNOR 0x07
133 #define IXNORCC 0x17
134 #define IXOR 0x03
135 #define IXORCC 0x13
136 #define SETHI 0x04
137 #define BICC 0x02
138 #define FPBCC 0x06
139 #define RDY 0x28
140 #define RDPSR 0x29
141 #define RDWIM 0x2A
142 #define RDTBR 0x2B
143 #define WRY 0x30
144 #define WRPSR 0x31
145 #define WRWIM 0x32
146 #define WRTBR 0x33
147 #define JMPL 0x38
148 #define RETT 0x39
149 #define TICC 0x3A
150 #define SAVE 0x3C
151 #define RESTORE 0x3D
152 #define LDD 0x03
153 #define LDDA 0x13
154 #define LD 0x00
155 #define LDA 0x10
156 #define LDF 0x20
157 #define LDDF 0x23
158 #define LDSTUB 0x0D
159 #define LDSTUBA 0x1D
160 #define LDUB 0x01
161 #define LDUBA 0x11
162 #define LDSB 0x09
163 #define LDSBA 0x19
164 #define LDUH 0x02
165 #define LDUHA 0x12
166 #define LDSH 0x0A
167 #define LDSHA 0x1A
168 #define LDFSR 0x21
169 #define ST 0x04
170 #define STA 0x14
171 #define STB 0x05
172 #define STBA 0x15
173 #define STD 0x07
174 #define STDA 0x17
175 #define STF 0x24
176 #define STDFQ 0x26
177 #define STDF 0x27
178 #define STFSR 0x25
179 #define STH 0x06
180 #define STHA 0x16
181 #define SWAP 0x0F
182 #define SWAPA 0x1F
183
184 /* # of cycles overhead when a trap is taken */
185 #define TRAP_C 3
186
187 int32 fpexec();
188 extern struct estate ebase;
189 extern int32 nfp;
190
191 sub_cc(operand1, operand2, result, sregs)
192 int32 operand1;
193 int32 operand2;
194 int32 result;
195 struct pstate *sregs;
196 {
197 sregs->psr = ((sregs->psr & ~PSR_N) | ((result >> 8) & PSR_N));
198 if (result)
199 sregs->psr &= ~PSR_Z;
200 else
201 sregs->psr |= PSR_Z;
202 sregs->psr = (sregs->psr & ~PSR_V) | ((
203 ((operand1 & ~operand2 & ~result) |
204 (~operand1 & operand2 & result)) >> 10) & PSR_V);
205 sregs->psr = (sregs->psr & ~PSR_C) | ((
206 ((~operand1 & operand2) |
207 ((~operand1 | operand2) & result)) >> 11) & PSR_C);
208 }
209
210 add_cc(operand1, operand2, result, psr)
211 int32 operand1;
212 int32 operand2;
213 int32 result;
214 uint32 *psr;
215 {
216 *psr = ((*psr & ~PSR_N) | ((result >> 8) & PSR_N));
217 if (result)
218 *psr &= ~PSR_Z;
219 else
220 *psr |= PSR_Z;
221 *psr = (*psr & ~PSR_V) | ((
222 ((operand1 & operand2 & ~result) |
223 (~operand1 & ~operand2 & result)) >> 10) & PSR_V);
224 *psr = (*psr & ~PSR_C) | ((
225 ((operand1 & operand2) |
226 ((operand1 | operand2) & ~result)) >> 11) & PSR_C);
227 }
228
229 log_cc(result, sregs)
230 int32 result;
231 struct pstate *sregs;
232 {
233 sregs->psr &= ~(PSR_CC); /* Zero CC bits */
234 sregs->psr = (sregs->psr | ((result >> 8) & PSR_N));
235 if (result == 0)
236 sregs->psr |= PSR_Z;
237 }
238
239 int
240 dispatch_instruction(sregs)
241 struct pstate *sregs;
242 {
243
244 uint32 cwp, op, op2, op3, opf, opc, asi, a, rd, cond, rs1,
245 rs2;
246 uint32 ldep;
247 int32 operand1, operand2, *rdd, result, i, disp22, eicc,
248 new_cwp;
249 int32 pc, npc, data, address, ws, mexc, fcc;
250
251 sregs->ninst++;
252 sregs->icnt = 1;
253 cwp = ((sregs->psr & PSR_CWP) << 4);
254 op = sregs->inst >> 30;
255 pc = sregs->npc;
256 npc = sregs->npc + 4;
257 if (op > 1) {
258
259 op3 = (sregs->inst >> 19) & 0x3f;
260 rs1 = (sregs->inst >> 14) & 0x1f;
261 rd = (sregs->inst >> 25) & 0x1f;
262
263 #ifdef LOAD_DEL
264
265 /* Check if load dependecy is possible */
266 ldep = ((ebase.simtime <= sregs->ildtime) && ((op3 & 0x38) != 0x28) &&
267 ((op3 & 0x3e) != 0x34) && (sregs->ildreg != 0));
268 if (sregs->inst & INST_I) {
269 if (ldep && (sregs->ildreg == rs1))
270 sregs->hold++;
271 operand2 = sregs->inst & INST_SIMM13;
272 if (operand2 > 0x0fff)
273 operand2 |= 0xfffff000;
274 } else {
275 rs2 = sregs->inst & INST_RS2;
276 if (rs2 > 7)
277 operand2 = sregs->r[(cwp + rs2) & 0x7f];
278 else
279 operand2 = sregs->g[rs2];
280 if (ldep && ((sregs->ildreg == rs1) || (sregs->ildreg == rs2)))
281 sregs->hold++;
282 }
283 #else
284 if (sregs->inst & INST_I) {
285 operand2 = sregs->inst & INST_SIMM13;
286 if (operand2 > 0x0fff)
287 operand2 |= 0xfffff000;
288 } else {
289 rs2 = sregs->inst & INST_RS2;
290 if (rs2 > 7)
291 operand2 = sregs->r[(cwp + rs2) & 0x7f];
292 else
293 operand2 = sregs->g[rs2];
294 }
295 #endif
296
297 if (rd > 7)
298 rdd = &(sregs->r[(cwp + rd) & 0x7f]);
299 else
300 rdd = &(sregs->g[rd]);
301 if (rs1 > 7)
302 rs1 = sregs->r[(cwp + rs1) & 0x7f];
303 else
304 rs1 = sregs->g[rs1];
305 }
306 switch (op) {
307 case 0:
308 op2 = (sregs->inst >> 22) & 0x7;
309 switch (op2) {
310 case SETHI:
311 rd = (sregs->inst >> 25) & 0x1f;
312 if (rd > 7)
313 rdd = &(sregs->r[(cwp + rd) & 0x7f]);
314 else
315 rdd = &(sregs->g[rd]);
316 *rdd = sregs->inst << 10;
317 break;
318 case BICC:
319 #ifdef STAT
320 sregs->nbranch++;
321 #endif
322 cond = ((sregs->inst >> 25) & 0x0f);
323 switch (cond & 0x7) {
324 case BICC_BN:
325 eicc = 0;
326 break;
327 case BICC_BE:
328 eicc = ICC_Z;
329 break;
330 case BICC_BLE:
331 eicc = ICC_Z | (ICC_N ^ ICC_V);
332 break;
333 case BICC_BL:
334 eicc = (ICC_N ^ ICC_V);
335 break;
336 case BICC_BLEU:
337 eicc = ICC_C | ICC_Z;
338 break;
339 case BICC_BCS:
340 eicc = ICC_C;
341 break;
342 case BICC_NEG:
343 eicc = ICC_N;
344 break;
345 case BICC_BVS:
346 eicc = ICC_V;
347 break;
348 }
349 eicc &= PSR_N;
350 if (sregs->inst & 0x10000000)
351 eicc = !eicc;
352 a = sregs->inst & 0x20000000;
353 if (eicc) {
354 operand1 = sregs->inst & 0x3fffff;
355 if (sregs->inst & 0x200000)
356 operand1 |= 0xffc00000;
357 npc = sregs->pc + (operand1 << 2);
358 if ((cond == BICC_BA) && (a))
359 sregs->annul = 1;
360 } else {
361 if (a)
362 sregs->annul = 1;
363 }
364 break;
365 case FPBCC:
366 #ifdef STAT
367 sregs->nbranch++;
368 #endif
369 if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
370 sregs->trap = TRAP_FPDIS;
371 break;
372 }
373 if (ebase.simtime < sregs->ftime) {
374 sregs->ftime = ebase.simtime + sregs->hold;
375 }
376 cond = ((sregs->inst >> 25) & 0x0f);
377 fcc = (sregs->fsr >> 10) & 0x3;
378 switch (cond & 0x7) {
379 case FBN:
380 eicc = 0;
381 break;
382 case FBNE:
383 eicc = (fcc != FCC_E);
384 break;
385 case FBLG:
386 eicc = (fcc == FCC_L) || (fcc == FCC_G);
387 break;
388 case FBUL:
389 eicc = (fcc == FCC_L) || (fcc == FCC_U);
390 break;
391 case FBL:
392 eicc = (fcc == FCC_L);
393 break;
394 case FBUG:
395 eicc = (fcc == FCC_G) || (fcc == FCC_U);
396 break;
397 case FBG:
398 eicc = (fcc == FCC_G);
399 break;
400 case FBU:
401 eicc = (fcc == FCC_U);
402 break;
403 }
404 if (sregs->inst & 0x10000000)
405 eicc = !eicc;
406 a = sregs->inst & 0x20000000;
407 if (eicc) {
408 operand1 = sregs->inst & 0x3fffff;
409 if (sregs->inst & 0x200000)
410 operand1 |= 0xffc00000;
411 npc = sregs->pc + (operand1 << 2);
412 if ((cond == FBA) && (a))
413 sregs->annul = 1;
414 } else {
415 if (a)
416 sregs->annul = 1;
417 }
418 break;
419
420 default:
421 sregs->trap = TRAP_UNIMP;
422 break;
423 }
424 break;
425 case 1: /* CALL */
426 #ifdef STAT
427 sregs->nbranch++;
428 #endif
429 sregs->r[(cwp + 15) & 0x7f] = sregs->pc;
430 npc = sregs->pc + (sregs->inst << 2);
431 break;
432
433 case 2:
434 if ((op3 >> 1) == 0x1a) {
435 if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
436 sregs->trap = TRAP_FPDIS;
437 } else {
438 rs1 = (sregs->inst >> 14) & 0x1f;
439 rs2 = sregs->inst & 0x1f;
440 sregs->trap = fpexec(op3, rd, rs1, rs2, sregs);
441 }
442 } else {
443
444 switch (op3) {
445 case TICC:
446 cond = ((sregs->inst >> 25) & 0x0f);
447 switch (cond & 0x7) {
448 case BICC_BN:
449 eicc = 0;
450 break;
451 case BICC_BE:
452 eicc = ICC_Z;
453 break;
454 case BICC_BLE:
455 eicc = ICC_Z | (ICC_N ^ ICC_V);
456 break;
457 case BICC_BL:
458 eicc = (ICC_N ^ ICC_V);
459 break;
460 case BICC_BLEU:
461 eicc = ICC_C | ICC_Z;
462 break;
463 case BICC_BCS:
464 eicc = ICC_C;
465 break;
466 case BICC_NEG:
467 eicc = ICC_N;
468 break;
469 case BICC_BVS:
470 eicc = ICC_V;
471 break;
472 }
473 eicc &= PSR_N;
474 if (sregs->inst & 0x10000000)
475 eicc = !eicc;
476 if (eicc) {
477 sregs->trap = (0x80 | ((rs1 + operand2) & 0x7f));
478 }
479 break;
480
481 case MULScc:
482 operand1 =
483 (((sregs->psr & PSR_V) ^ ((sregs->psr & PSR_N) >> 2))
484 << 10) | (rs1 >> 1);
485 if ((sregs->y & 1) == 0)
486 operand2 = 0;
487 *rdd = operand1 + operand2;
488 sregs->y = (rs1 << 31) | (sregs->y >> 1);
489 add_cc(operand1, operand2, *rdd, &sregs->psr);
490 break;
491 case IXNOR:
492 *rdd = rs1 ^ ~operand2;
493 break;
494 case IXNORCC:
495 *rdd = rs1 ^ ~operand2;
496 log_cc(*rdd, sregs);
497 break;
498 case IXOR:
499 *rdd = rs1 ^ operand2;
500 break;
501 case IXORCC:
502 *rdd = rs1 ^ operand2;
503 log_cc(*rdd, sregs);
504 break;
505 case IOR:
506 *rdd = rs1 | operand2;
507 break;
508 case IORCC:
509 *rdd = rs1 | operand2;
510 log_cc(*rdd, sregs);
511 break;
512 case IORN:
513 *rdd = rs1 | ~operand2;
514 break;
515 case IORNCC:
516 *rdd = rs1 | ~operand2;
517 log_cc(*rdd, sregs);
518 break;
519 case IANDNCC:
520 *rdd = rs1 & ~operand2;
521 log_cc(*rdd, sregs);
522 break;
523 case IANDN:
524 *rdd = rs1 & ~operand2;
525 break;
526 case IAND:
527 *rdd = rs1 & operand2;
528 break;
529 case IANDCC:
530 *rdd = rs1 & operand2;
531 log_cc(*rdd, sregs);
532 break;
533 case SUB:
534 *rdd = rs1 - operand2;
535 break;
536 case SUBCC:
537 *rdd = rs1 - operand2;
538 sub_cc(rs1, operand2, *rdd, sregs);
539 break;
540 case SUBX:
541 *rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);
542 break;
543 case SUBXCC:
544 *rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);
545 sub_cc(rs1, operand2, *rdd, sregs);
546 break;
547 case ADD:
548 *rdd = rs1 + operand2;
549 break;
550 case ADDCC:
551 *rdd = rs1 + operand2;
552 add_cc(rs1, operand2, *rdd, &sregs->psr);
553 break;
554 case ADDX:
555 *rdd = rs1 + operand2 + ((sregs->psr >> 20) & 1);
556 break;
557 case ADDXCC:
558 *rdd = rs1 + operand2 + ((sregs->psr >> 20) & 1);
559 add_cc(rs1, operand2, *rdd, &sregs->psr);
560 break;
561 case TADDCC:
562 *rdd = rs1 + operand2;
563 add_cc(rs1, operand2, *rdd, &sregs->psr);
564 if ((rs1 | operand2) & 0x3)
565 sregs->psr |= PSR_V;
566 break;
567 case TADDCCTV:
568 *rdd = rs1 + operand2;
569 result = 0;
570 add_cc(rs1, operand2, *rdd, &result);
571 if ((rs1 | operand2) & 0x3)
572 result |= PSR_V;
573 if (result & PSR_V) {
574 sregs->trap = TRAP_TAG;
575 } else {
576 sregs->psr = (sregs->psr & PSR_CC) | result;
577 }
578 break;
579 case SLL:
580 *rdd = rs1 << (operand2 & 0x1f);
581 break;
582 case SRL:
583 *rdd = rs1 >> (operand2 & 0x1f);
584 break;
585 case SRA:
586 *rdd = ((int) rs1) >> (operand2 & 0x1f);
587 break;
588 case SAVE:
589 new_cwp = ((sregs->psr & PSR_CWP) - 1) & PSR_CWP;
590 if (sregs->wim & (1 << new_cwp)) {
591 sregs->trap = TRAP_WOFL;
592 break;
593 }
594 if (rd > 7)
595 rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);
596 *rdd = rs1 + operand2;
597 sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;
598 break;
599 case RESTORE:
600
601 #ifdef IUREV0
602 if ((iurev0) && ((sregs->jmpltime + 1) == sregs->ninst)) {
603 if (!(sregs->rett_err)) {
604 sregs->rett_err = 1;
605 if (sis_verbose)
606 printf("IU rev.0 bug mode entered\n");
607 }
608 }
609 #endif
610
611 new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;
612 if (sregs->wim & (1 << new_cwp)) {
613 sregs->trap = TRAP_WUFL;
614 break;
615 }
616 if (rd > 7)
617 rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);
618 *rdd = rs1 + operand2;
619 sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;
620 break;
621 case RDPSR:
622 if (!(sregs->psr & PSR_S)) {
623 sregs->trap = TRAP_PRIVI;
624 break;
625 }
626 *rdd = sregs->psr;
627 #ifdef IUREV0
628
629 if (iurev0 & sregs->rett_err) {
630 operand2 = sregs->psr;
631 *rdd |= PSR_ET;
632 *rdd &= ~(PSR_S);
633 *rdd |= ((*rdd & PSR_PS) << 1);
634 if (sis_verbose) {
635 if (operand2 != *rdd)
636 printf("rdpsr failed: %08X -> %08X\n", operand2, *rdd);
637 }
638 }
639 #endif
640 break;
641 case RDY:
642 if (!(sregs->psr & PSR_S)) {
643 sregs->trap = TRAP_PRIVI;
644 break;
645 }
646 *rdd = sregs->y;
647 break;
648 case RDWIM:
649 if (!(sregs->psr & PSR_S)) {
650 sregs->trap = TRAP_PRIVI;
651 break;
652 }
653 *rdd = sregs->wim;
654 break;
655 case RDTBR:
656 if (!(sregs->psr & PSR_S)) {
657 sregs->trap = TRAP_PRIVI;
658 break;
659 }
660 *rdd = sregs->tbr;
661 break;
662 case WRPSR:
663 if ((sregs->psr & 0x1f) > 7) {
664 sregs->trap = TRAP_UNIMP;
665 break;
666 }
667 if (!(sregs->psr & PSR_S)) {
668 sregs->trap = TRAP_PRIVI;
669 break;
670 }
671 sregs->psr = (rs1 ^ operand2) & 0x00f03fff;
672 break;
673 case WRWIM:
674 if (!(sregs->psr & PSR_S)) {
675 sregs->trap = TRAP_PRIVI;
676 break;
677 }
678 sregs->wim = (rs1 ^ operand2) & 0x0ff;
679 break;
680 case WRTBR:
681 if (!(sregs->psr & PSR_S)) {
682 sregs->trap = TRAP_PRIVI;
683 break;
684 }
685 sregs->tbr = (sregs->tbr & 0x00000ff0) |
686 ((rs1 ^ operand2) & 0xfffff000);
687 break;
688 case WRY:
689 sregs->y = (rs1 ^ operand2);
690 break;
691 case JMPL:
692
693 #ifdef IUREV0
694 if (iurev0)
695 sregs->jmpltime = sregs->ninst;
696 #endif
697 #ifdef STAT
698 sregs->nbranch++;
699 #endif
700 sregs->icnt = T_JMPL; /* JMPL takes two cycles */
701 if (rs1 & 0x3) {
702 sregs->trap = TRAP_UNALI;
703 break;
704 }
705 *rdd = sregs->pc;
706 npc = rs1 + operand2;
707 break;
708 case RETT:
709 #ifdef IUREV0
710 if (iurev0 && sregs->rett_err) {
711 sregs->rett_err = 0;
712 if (sis_verbose)
713 printf("IU rev.0 bug mode reset\n");
714 }
715 #endif
716
717 address = rs1 + operand2;
718 new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;
719 sregs->icnt = T_RETT; /* RETT takes two cycles */
720 if (sregs->psr & PSR_ET) {
721 sregs->trap = TRAP_UNIMP;
722 break;
723 }
724 if (!(sregs->psr & PSR_S)) {
725 sregs->trap = TRAP_PRIVI;
726 break;
727 }
728 if (sregs->wim & (1 << new_cwp)) {
729 sregs->trap = TRAP_WUFL;
730 break;
731 }
732 if (address & 0x3) {
733 sregs->trap = TRAP_UNALI;
734 break;
735 }
736 sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp | PSR_ET;
737 sregs->psr =
738 (sregs->psr & ~PSR_S) | ((sregs->psr & PSR_PS) << 1);
739 npc = address;
740 break;
741
742 default:
743 sregs->trap = TRAP_UNIMP;
744 break;
745 }
746 }
747 break;
748 case 3: /* Load/store instructions */
749
750 address = rs1 + operand2;
751
752 /* Check for load/store to alternate address space */
753
754 if ((op3 >> 4) == 1) {
755 if (!(sregs->psr & PSR_S)) {
756 sregs->trap = TRAP_PRIVI;
757 break;
758 } else if (sregs->inst & INST_I) {
759 sregs->trap = TRAP_UNIMP;
760 break;
761 } else
762 asi = (sregs->inst >> 5) & 0x0ff;
763 } else {
764 if (sregs->psr & PSR_S)
765 asi = 11;
766 else
767 asi = 10;
768 #ifdef IUREV0
769 if (iurev0 && sregs->rett_err) {
770 asi &= ~0x1;
771 asi |= ((sregs->psr & PSR_PS) >> 6);
772 }
773 #endif
774 }
775
776 if (op3 & 4) {
777 sregs->icnt = T_ST; /* Set store instruction count */
778 #ifdef STAT
779 sregs->nstore++;
780 #endif
781 } else {
782 sregs->icnt = T_LD; /* Set load instruction count */
783 #ifdef STAT
784 sregs->nload++;
785 #endif
786 }
787
788 /* Decode load/store instructions */
789
790 switch (op3) {
791 case LDDA:
792 case LDD:
793 if (address & 0x7) {
794 sregs->trap = TRAP_UNALI;
795 break;
796 }
797 if (rd & 1) {
798 rd &= 0x1e;
799 if (rd > 7)
800 rdd = &(sregs->r[(cwp + rd) & 0x7f]);
801 else
802 rdd = &(sregs->g[rd]);
803 }
804 mexc = memory_read(asi, address, &data, &ws);
805 sregs->hold += ws;
806 sregs->icnt = T_LDD;
807 if (mexc) {
808 sregs->trap = TRAP_DEXC;
809 } else {
810 rdd[0] = data;
811 address += 4;
812 mexc = memory_read(asi, address, &data, &ws);
813 sregs->hold += ws;
814 #ifdef STAT
815 sregs->nload++; /* Double load counts twice */
816 #endif
817 if (mexc) {
818 sregs->trap = TRAP_DEXC;
819 } else {
820 rdd[1] = data;
821 }
822 }
823 break;
824
825 case LDA:
826 case LD:
827 if (address & 0x3) {
828 sregs->trap = TRAP_UNALI;
829 break;
830 }
831 mexc = memory_read(asi, address, &data, &ws);
832 sregs->hold += ws;
833 if (mexc) {
834 sregs->trap = TRAP_DEXC;
835 } else {
836 *rdd = data;
837 }
838 break;
839 case LDSTUB:
840 case LDSTUBA:
841 mexc = memory_read(asi, address, &data, &ws);
842 sregs->hold += ws;
843 sregs->icnt = T_LDST;
844 if (mexc) {
845 sregs->trap = TRAP_DEXC;
846 break;
847 }
848 data = (data >> ((3 - (address & 0x3)) << 3)) & 0x0ff;
849 *rdd = data;
850 data = 0x0ff;
851 mexc = memory_write(asi, address, &data, 0, &ws);
852 sregs->hold += ws;
853 if (mexc) {
854 sregs->trap = TRAP_DEXC;
855 }
856 #ifdef STAT
857 sregs->nload++;
858 #endif
859 break;
860 case LDSBA:
861 case LDUBA:
862 case LDSB:
863 case LDUB:
864 mexc = memory_read(asi, address, &data, &ws);
865 sregs->hold += ws;
866 if (mexc) {
867 sregs->trap = TRAP_DEXC;
868 break;
869 }
870 data = (data >> ((3 - (address & 0x3)) << 3)) & 0x0ff;
871 if ((op3 == LDSB) && (data >> 7))
872 data |= 0xffffff00;
873 *rdd = data;
874 break;
875 case LDSHA:
876 case LDUHA:
877 case LDSH:
878 case LDUH:
879 if (address & 0x1) {
880 sregs->trap = TRAP_UNALI;
881 break;
882 }
883 mexc = memory_read(asi, address, &data, &ws);
884 sregs->hold += ws;
885 if (mexc) {
886 sregs->trap = TRAP_DEXC;
887 break;
888 }
889 if (!(address & 0x2))
890 data >>= 16;
891 data &= 0x0ffff;
892 if ((op3 == LDSH) && (data >> 15))
893 data |= 0xffff0000;
894 *rdd = data;
895 break;
896 case LDF:
897 if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
898 sregs->trap = TRAP_FPDIS;
899 break;
900 }
901 if (address & 0x3) {
902 sregs->trap = TRAP_UNALI;
903 break;
904 }
905 if (ebase.simtime < sregs->ftime) {
906 if ((sregs->frd == rd) || (sregs->frs1 == rd) ||
907 (sregs->frs2 == rd))
908 sregs->fhold += (sregs->ftime - ebase.simtime);
909 }
910 mexc = memory_read(asi, address, &data, &ws);
911 sregs->hold += ws;
912 sregs->flrd = rd;
913 sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
914 sregs->hold + sregs->fhold;
915 if (mexc) {
916 sregs->trap = TRAP_DEXC;
917 } else {
918 sregs->fs[rd] = *((float32 *) & data);
919 }
920 break;
921 case LDDF:
922 if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
923 sregs->trap = TRAP_FPDIS;
924 break;
925 }
926 if (address & 0x7) {
927 sregs->trap = TRAP_UNALI;
928 break;
929 }
930 if (ebase.simtime < sregs->ftime) {
931 if (((sregs->frd >> 1) == (rd >> 1)) ||
932 ((sregs->frs1 >> 1) == (rd >> 1)) ||
933 ((sregs->frs2 >> 1) == (rd >> 1)))
934 sregs->fhold += (sregs->ftime - ebase.simtime);
935 }
936 mexc = memory_read(asi, address, &data, &ws);
937 sregs->hold += ws;
938 sregs->icnt = T_LDD;
939 if (mexc) {
940 sregs->trap = TRAP_DEXC;
941 } else {
942 rd &= 0x1E;
943 sregs->flrd = rd;
944 sregs->fs[rd] = *((float32 *) & data);
945 mexc = memory_read(asi, address + 4, &data, &ws);
946 sregs->hold += ws;
947 #ifdef STAT
948 sregs->nload++; /* Double load counts twice */
949 #endif
950 if (mexc) {
951 sregs->trap = TRAP_DEXC;
952 } else {
953 sregs->fs[rd + 1] = *((float32 *) & data);
954 sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
955 sregs->hold + sregs->fhold;
956 }
957 }
958 break;
959 case LDFSR:
960 if (ebase.simtime < sregs->ftime) {
961 sregs->fhold += (sregs->ftime - ebase.simtime);
962 }
963 if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
964 sregs->trap = TRAP_FPDIS;
965 break;
966 }
967 if (address & 0x3) {
968 sregs->trap = TRAP_UNALI;
969 break;
970 }
971 mexc = memory_read(asi, address, &data, &ws);
972 sregs->hold += ws;
973 if (mexc) {
974 sregs->trap = TRAP_DEXC;
975 } else {
976 sregs->fsr =
977 (sregs->fsr & 0x7FF000) | (data & ~0x7FF000);
978 set_fsr(sregs->fsr);
979 }
980 break;
981 case STFSR:
982 if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
983 sregs->trap = TRAP_FPDIS;
984 break;
985 }
986 if (address & 0x3) {
987 sregs->trap = TRAP_UNALI;
988 break;
989 }
990 if (ebase.simtime < sregs->ftime) {
991 sregs->fhold += (sregs->ftime - ebase.simtime);
992 }
993 mexc = memory_write(asi, address, &sregs->fsr, 2, &ws);
994 sregs->hold += ws;
995 if (mexc) {
996 sregs->trap = TRAP_DEXC;
997 }
998 break;
999
1000 case ST:
1001 case STA:
1002 if (address & 0x3) {
1003 sregs->trap = TRAP_UNALI;
1004 break;
1005 }
1006 mexc = memory_write(asi, address, rdd, 2, &ws);
1007 sregs->hold += ws;
1008 if (mexc) {
1009 sregs->trap = TRAP_DEXC;
1010 }
1011 break;
1012 case STB:
1013 case STBA:
1014 mexc = memory_write(asi, address, rdd, 0, &ws);
1015 sregs->hold += ws;
1016 if (mexc) {
1017 sregs->trap = TRAP_DEXC;
1018 }
1019 break;
1020 case STD:
1021 case STDA:
1022 if (address & 0x7) {
1023 sregs->trap = TRAP_UNALI;
1024 break;
1025 }
1026 if (rd & 1) {
1027 rd &= 0x1e;
1028 if (rd > 7)
1029 rdd = &(sregs->r[(cwp + rd) & 0x7f]);
1030 else
1031 rdd = &(sregs->g[rd]);
1032 }
1033 mexc = memory_write(asi, address, rdd, 3, &ws);
1034 sregs->hold += ws;
1035 sregs->icnt = T_STD;
1036 #ifdef STAT
1037 sregs->nstore++; /* Double store counts twice */
1038 #endif
1039 if (mexc) {
1040 sregs->trap = TRAP_DEXC;
1041 break;
1042 }
1043 break;
1044 case STDFQ:
1045 if ((sregs->psr & 0x1f) > 7) {
1046 sregs->trap = TRAP_UNIMP;
1047 break;
1048 }
1049 if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
1050 sregs->trap = TRAP_FPDIS;
1051 break;
1052 }
1053 if (address & 0x7) {
1054 sregs->trap = TRAP_UNALI;
1055 break;
1056 }
1057 if (!(sregs->fsr & FSR_QNE)) {
1058 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;
1059 break;
1060 }
1061 rdd = &(sregs->fpq[0]);
1062 mexc = memory_write(asi, address, rdd, 3, &ws);
1063 sregs->hold += ws;
1064 sregs->icnt = T_STD;
1065 #ifdef STAT
1066 sregs->nstore++; /* Double store counts twice */
1067 #endif
1068 if (mexc) {
1069 sregs->trap = TRAP_DEXC;
1070 break;
1071 } else {
1072 sregs->fsr &= ~FSR_QNE;
1073 sregs->fpstate = FP_EXE_MODE;
1074 }
1075 break;
1076 case STHA:
1077 case STH:
1078 if (address & 0x1) {
1079 sregs->trap = TRAP_UNALI;
1080 break;
1081 }
1082 mexc = memory_write(asi, address, rdd, 1, &ws);
1083 sregs->hold += ws;
1084 if (mexc) {
1085 sregs->trap = TRAP_DEXC;
1086 }
1087 break;
1088 case STF:
1089 if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
1090 sregs->trap = TRAP_FPDIS;
1091 break;
1092 }
1093 if (address & 0x3) {
1094 sregs->trap = TRAP_UNALI;
1095 break;
1096 }
1097 if (ebase.simtime < sregs->ftime) {
1098 if (sregs->frd == rd)
1099 sregs->fhold += (sregs->ftime - ebase.simtime);
1100 }
1101 mexc = memory_write(asi, address, &sregs->fsi[rd], 2, &ws);
1102 sregs->hold += ws;
1103 if (mexc) {
1104 sregs->trap = TRAP_DEXC;
1105 }
1106 break;
1107 case STDF:
1108 if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
1109 sregs->trap = TRAP_FPDIS;
1110 break;
1111 }
1112 if (address & 0x7) {
1113 sregs->trap = TRAP_UNALI;
1114 break;
1115 }
1116 rd &= 0x1E;
1117 if (ebase.simtime < sregs->ftime) {
1118 if ((sregs->frd == rd) || (sregs->frd + 1 == rd))
1119 sregs->fhold += (sregs->ftime - ebase.simtime);
1120 }
1121 mexc = memory_write(asi, address, &sregs->fsi[rd], 3, &ws);
1122 sregs->hold += ws;
1123 sregs->icnt = T_STD;
1124 #ifdef STAT
1125 sregs->nstore++; /* Double store counts twice */
1126 #endif
1127 if (mexc) {
1128 sregs->trap = TRAP_DEXC;
1129 }
1130 break;
1131 case SWAP:
1132 case SWAPA:
1133 if (address & 0x3) {
1134 sregs->trap = TRAP_UNALI;
1135 break;
1136 }
1137 mexc = memory_read(asi, address, &data, &ws);
1138 sregs->hold += ws;
1139 if (mexc) {
1140 sregs->trap = TRAP_DEXC;
1141 break;
1142 }
1143 mexc = memory_write(asi, address, rdd, 2, &ws);
1144 sregs->hold += ws;
1145 sregs->icnt = T_LDST;
1146 if (mexc) {
1147 sregs->trap = TRAP_DEXC;
1148 break;
1149 } else
1150 *rdd = data;
1151 #ifdef STAT
1152 sregs->nload++;
1153 #endif
1154 break;
1155
1156
1157 default:
1158 sregs->trap = TRAP_UNIMP;
1159 break;
1160 }
1161
1162 #ifdef LOAD_DEL
1163
1164 if (!(op3 & 4)) {
1165 sregs->ildtime = ebase.simtime + sregs->hold + sregs->icnt;
1166 sregs->ildreg = rd;
1167 if ((op3 | 0x10) == 0x13)
1168 sregs->ildreg |= 1; /* Double load, odd register loaded
1169 * last */
1170 }
1171 #endif
1172 break;
1173
1174 default:
1175 sregs->trap = TRAP_UNIMP;
1176 break;
1177 }
1178 sregs->g[0] = 0;
1179 if (!sregs->trap) {
1180 sregs->pc = pc;
1181 sregs->npc = npc;
1182 }
1183 return (0);
1184 }
1185
1186 #define T_FABSs 2
1187 #define T_FADDs 4
1188 #define T_FADDd 4
1189 #define T_FCMPs 4
1190 #define T_FCMPd 4
1191 #define T_FDIVs 20
1192 #define T_FDIVd 35
1193 #define T_FMOVs 2
1194 #define T_FMULs 5
1195 #define T_FMULd 9
1196 #define T_FNEGs 2
1197 #define T_FSQRTs 37
1198 #define T_FSQRTd 65
1199 #define T_FSUBs 4
1200 #define T_FSUBd 4
1201 #define T_FdTOi 7
1202 #define T_FdTOs 3
1203 #define T_FiTOs 6
1204 #define T_FiTOd 6
1205 #define T_FsTOi 6
1206 #define T_FsTOd 2
1207
1208 #define FABSs 0x09
1209 #define FADDs 0x41
1210 #define FADDd 0x42
1211 #define FCMPs 0x51
1212 #define FCMPd 0x52
1213 #define FCMPEs 0x55
1214 #define FCMPEd 0x56
1215 #define FDIVs 0x4D
1216 #define FDIVd 0x4E
1217 #define FMOVs 0x01
1218 #define FMULs 0x49
1219 #define FMULd 0x4A
1220 #define FNEGs 0x05
1221 #define FSQRTs 0x29
1222 #define FSQRTd 0x2A
1223 #define FSUBs 0x45
1224 #define FSUBd 0x46
1225 #define FdTOi 0xD2
1226 #define FdTOs 0xC6
1227 #define FiTOs 0xC4
1228 #define FiTOd 0xC8
1229 #define FsTOi 0xD1
1230 #define FsTOd 0xC9
1231
1232
1233 int
1234 fpexec(op3, rd, rs1, rs2, sregs)
1235 uint32 op3, rd, rs1, rs2;
1236 struct pstate *sregs;
1237 {
1238 uint32 opf, tem, accex;
1239 float32 ftmps;
1240 float64 ftmpd;
1241 int32 fcc;
1242 char *res;
1243 uint32 ldadj;
1244
1245 if (sregs->fpstate == FP_EXC_MODE) {
1246 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;
1247 sregs->fpstate == FP_EXC_PE;
1248 return (0);
1249 }
1250 if (sregs->fpstate == FP_EXC_PE) {
1251 sregs->fpstate = FP_EXC_MODE;
1252 return (TRAP_FPEXC);
1253 }
1254 opf = (sregs->inst >> 5) & 0x1ff;
1255
1256 /*
1257 * Check if we already have an FPop in the pipe. If so, halt until it is
1258 * finished by incrementing fhold with the remaining execution time
1259 */
1260
1261 if (ebase.simtime < sregs->ftime) {
1262 sregs->fhold = (sregs->ftime - ebase.simtime);
1263 } else {
1264 sregs->fhold = 0;
1265
1266 /* Check load dependencies. */
1267
1268 if (ebase.simtime < sregs->ltime) {
1269
1270 /* Don't check rs1 if single operand instructions */
1271
1272 if (((opf >> 6) == 0) || ((opf >> 6) == 3))
1273 rs1 = 32;
1274
1275 /* Adjust for double floats */
1276
1277 ldadj = opf & 1;
1278 if (!(((sregs->flrd - rs1) >> ldadj) && ((sregs->flrd - rs2) >> ldadj)))
1279 sregs->fhold++;
1280 }
1281 }
1282
1283 sregs->finst++;
1284
1285 sregs->frs1 = rs1; /* Store src and dst for dependecy check */
1286 sregs->frs2 = rs2;
1287 sregs->frd = rd;
1288
1289 sregs->ftime = ebase.simtime + sregs->hold + sregs->fhold;
1290
1291 /* SPARC is big-endian - swap double floats if host is little-endian */
1292 /* This is ugly - I know ... */
1293 #ifdef HOST_LITTLE_ENDIAN_FLOAT
1294 rs1 &= 0x1f;
1295 switch (opf) {
1296 case FADDd:
1297 case FDIVd:
1298 case FMULd:
1299 case FSQRTd:
1300 case FSUBd:
1301 case FCMPd:
1302 case FCMPEd:
1303 case FdTOi:
1304 case FdTOs:
1305 sregs->fdp[rs1 | 1] = sregs->fs[rs1 & ~1];
1306 sregs->fdp[rs1 & ~1] = sregs->fs[rs1 | 1];
1307 sregs->fdp[rs2 | 1] = sregs->fs[rs2 & ~1];
1308 sregs->fdp[rs2 & ~1] = sregs->fs[rs2 | 1];
1309 default:
1310 }
1311 #endif
1312
1313 clear_accex();
1314
1315 switch (opf) {
1316 case FABSs:
1317 sregs->fs[rd] = fabs(sregs->fs[rs2]);
1318 sregs->ftime += T_FABSs;
1319 sregs->frs1 = 32; /* rs1 ignored */
1320 break;
1321 case FADDs:
1322 sregs->fs[rd] = sregs->fs[rs1] + sregs->fs[rs2];
1323 sregs->ftime += T_FADDs;
1324 break;
1325 case FADDd:
1326 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] + sregs->fd[rs2 >> 1];
1327 sregs->ftime += T_FADDd;
1328 break;
1329 case FCMPs:
1330 case FCMPEs:
1331 if (sregs->fs[rs1] == sregs->fs[rs2])
1332 fcc = 3;
1333 else if (sregs->fs[rs1] < sregs->fs[rs2])
1334 fcc = 2;
1335 else if (sregs->fs[rs1] > sregs->fs[rs2])
1336 fcc = 1;
1337 else
1338 fcc = 0;
1339 sregs->fsr |= 0x0C00;
1340 sregs->fsr &= ~(fcc << 10);
1341 sregs->ftime += T_FCMPs;
1342 sregs->frd = 32; /* rd ignored */
1343 if ((fcc == 0) && (opf == FCMPEs)) {
1344 sregs->fpstate == FP_EXC_PE;
1345 sregs->fsr = (sregs->fsr & ~0x1C000) | (1 << 14);
1346 }
1347 break;
1348 case FCMPd:
1349 case FCMPEd:
1350 if (sregs->fd[rs1 >> 1] == sregs->fd[rs2 >> 1])
1351 fcc = 3;
1352 else if (sregs->fd[rs1 >> 1] < sregs->fd[rs2 >> 1])
1353 fcc = 2;
1354 else if (sregs->fd[rs1 >> 1] > sregs->fd[rs2 >> 1])
1355 fcc = 1;
1356 else
1357 fcc = 0;
1358 sregs->fsr |= 0x0C00;
1359 sregs->fsr &= ~(fcc << 10);
1360 sregs->ftime += T_FCMPd;
1361 sregs->frd = 32; /* rd ignored */
1362 if ((fcc == 0) && (opf == FCMPEd)) {
1363 sregs->fpstate == FP_EXC_PE;
1364 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1365 }
1366 break;
1367 case FDIVs:
1368 sregs->fs[rd] = sregs->fs[rs1] / sregs->fs[rs2];
1369 sregs->ftime += T_FDIVs;
1370 break;
1371 case FDIVd:
1372 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] / sregs->fd[rs2 >> 1];
1373 sregs->ftime += T_FDIVd;
1374 break;
1375 case FMOVs:
1376 sregs->fs[rd] = sregs->fs[rs2];
1377 sregs->ftime += T_FMOVs;
1378 sregs->frs1 = 32; /* rs1 ignored */
1379 break;
1380 case FMULs:
1381 sregs->fs[rd] = sregs->fs[rs1] * sregs->fs[rs2];
1382 sregs->ftime += T_FMULs;
1383 break;
1384 case FMULd:
1385 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] * sregs->fd[rs2 >> 1];
1386 sregs->ftime += T_FMULd;
1387 break;
1388 case FNEGs:
1389 sregs->fs[rd] = -sregs->fs[rs2];
1390 sregs->ftime += T_FNEGs;
1391 sregs->frs1 = 32; /* rs1 ignored */
1392 break;
1393 case FSQRTs:
1394 if (sregs->fs[rs2] < 0.0) {
1395 sregs->fpstate == FP_EXC_PE;
1396 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1397 sregs->fsr = (sregs->fsr & 0x1f) | 0x10;
1398 break;
1399 }
1400 sregs->fs[rd] = sqrt(sregs->fs[rs2]);
1401 sregs->ftime += T_FSQRTs;
1402 sregs->frs1 = 32; /* rs1 ignored */
1403 break;
1404 case FSQRTd:
1405 if (sregs->fd[rs2 >> 1] < 0.0) {
1406 sregs->fpstate == FP_EXC_PE;
1407 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1408 sregs->fsr = (sregs->fsr & 0x1f) | 0x10;
1409 break;
1410 }
1411 sregs->fd[rd >> 1] = sqrt(sregs->fd[rs2 >> 1]);
1412 sregs->ftime += T_FSQRTd;
1413 sregs->frs1 = 32; /* rs1 ignored */
1414 break;
1415 case FSUBs:
1416 sregs->fs[rd] = sregs->fs[rs1] - sregs->fs[rs2];
1417 sregs->ftime += T_FSUBs;
1418 break;
1419 case FSUBd:
1420 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] - sregs->fd[rs2 >> 1];
1421 sregs->ftime += T_FSUBd;
1422 break;
1423 case FdTOi:
1424 sregs->fsi[rd] = (int) sregs->fd[rs2 >> 1];
1425 sregs->ftime += T_FdTOi;
1426 sregs->frs1 = 32; /* rs1 ignored */
1427 break;
1428 case FdTOs:
1429 sregs->fs[rd] = (float32) sregs->fd[rs2 >> 1];
1430 sregs->ftime += T_FdTOs;
1431 sregs->frs1 = 32; /* rs1 ignored */
1432 break;
1433 case FiTOs:
1434 sregs->fs[rd] = (float32) sregs->fsi[rs2];
1435 sregs->ftime += T_FiTOs;
1436 sregs->frs1 = 32; /* rs1 ignored */
1437 break;
1438 case FiTOd:
1439 sregs->fd[rd >> 1] = (float64) sregs->fsi[rs2];
1440 sregs->ftime += T_FiTOd;
1441 sregs->frs1 = 32; /* rs1 ignored */
1442 break;
1443 case FsTOi:
1444 sregs->fsi[rd] = (int) sregs->fs[rs2];
1445 sregs->ftime += T_FsTOi;
1446 sregs->frs1 = 32; /* rs1 ignored */
1447 break;
1448 case FsTOd:
1449 sregs->fd[rd >> 1] = sregs->fs[rs2];
1450 sregs->ftime += T_FsTOd;
1451 sregs->frs1 = 32; /* rs1 ignored */
1452 break;
1453
1454 default:
1455 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_UNIMP;
1456 sregs->fpstate == FP_EXC_PE;
1457 }
1458
1459 accex = get_accex();
1460
1461 #ifdef HOST_LITTLE_ENDIAN_FLOAT
1462 switch (opf) {
1463 case FADDd:
1464 case FDIVd:
1465 case FMULd:
1466 case FSQRTd:
1467 case FSUBd:
1468 case FiTOd:
1469 case FsTOd:
1470 sregs->fs[rd & ~1] = sregs->fdp[rd | 1];
1471 sregs->fs[rd | 1] = sregs->fdp[rd & ~1];
1472 default:
1473 }
1474 #endif
1475 if (sregs->fpstate == FP_EXC_PE) {
1476 sregs->fpq[0] = sregs->pc;
1477 sregs->fpq[1] = sregs->inst;
1478 sregs->fsr |= FSR_QNE;
1479 } else {
1480 tem = (sregs->fsr >> 23) & 0x1f;
1481 if (tem & accex) {
1482 sregs->fpstate = FP_EXC_PE;
1483 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1484 sregs->fsr = ((sregs->fsr & ~0x1f) | accex);
1485 } else {
1486 sregs->fsr = ((((sregs->fsr >> 5) | accex) << 5) | accex);
1487 }
1488 if (sregs->fpstate == FP_EXC_PE) {
1489 sregs->fpq[0] = sregs->pc;
1490 sregs->fpq[1] = sregs->inst;
1491 sregs->fsr |= FSR_QNE;
1492 }
1493 }
1494 clear_accex();
1495
1496 return (0);
1497
1498
1499 }
1500
1501 int
1502 execute_trap(sregs)
1503 struct pstate *sregs;
1504 {
1505 int32 cwp;
1506
1507 if (sregs->trap == 256) {
1508 sregs->pc = 0;
1509 sregs->npc = 4;
1510 sregs->trap = 0;
1511 } else {
1512
1513 if ((sregs->psr & PSR_ET) == 0)
1514 return (ERROR);
1515
1516 sregs->tbr = (sregs->tbr & 0xfffff000) | (sregs->trap << 4);
1517 sregs->trap = 0;
1518 sregs->psr &= ~PSR_ET;
1519 sregs->psr |= ((sregs->psr & PSR_S) >> 1);
1520 sregs->annul = 0;
1521 sregs->psr = (((sregs->psr & PSR_CWP) - 1) & 0x7) | (sregs->psr & ~PSR_CWP);
1522 cwp = ((sregs->psr & PSR_CWP) << 4);
1523 sregs->r[(cwp + 17) & 0x7f] = sregs->pc;
1524 sregs->r[(cwp + 18) & 0x7f] = sregs->npc;
1525 sregs->psr |= PSR_S;
1526 sregs->pc = sregs->tbr;
1527 sregs->npc = sregs->tbr + 4;
1528
1529 /* Increase simulator time */
1530 sregs->icnt = TRAP_C;
1531
1532 }
1533
1534
1535 return (0);
1536
1537 }
1538
1539 extern struct irqcell irqarr[16];
1540
1541 void
1542 check_interrupts(sregs)
1543 struct pstate *sregs;
1544 {
1545 if ((ext_irl) && (sregs->psr & PSR_ET) &&
1546 ((ext_irl == 15) || (ext_irl > ((sregs->psr & PSR_PIL) >> 8)))) {
1547 if (sregs->trap == 0) {
1548 sregs->trap = 16 + ext_irl;
1549 irqarr[ext_irl & 0x0f].callback(irqarr[ext_irl & 0x0f].arg);
1550 clear_int(ext_irl);
1551 }
1552 }
1553 }
1554
1555 init_regs(sregs)
1556 struct pstate *sregs;
1557 {
1558 int32 i;
1559
1560 sregs->pc = 0;
1561 sregs->npc = 4;
1562 sregs->trap = 0;
1563 sregs->psr &= 0x00f03fdf;
1564 sregs->psr |= 0x080; /* Set supervisor bit */
1565 sregs->breakpoint = 0;
1566 sregs->annul = 0;
1567 sregs->fpstate = FP_EXE_MODE;
1568 sregs->fpqn = 0;
1569 sregs->ftime = 0;
1570 sregs->ltime = 0;
1571 sregs->err_mode = 0;
1572 ext_irl = 0;
1573 irqpend = 0;
1574 sregs->g[0] = 0;
1575 #ifdef HOST_LITTLE_ENDIAN_FLOAT
1576 sregs->fdp = (float32 *) sregs->fd;
1577 sregs->fsi = (int32 *) sregs->fs;
1578 #else
1579 sregs->fs = (float32 *) sregs->fd;
1580 sregs->fsi = (int32 *) sregs->fd;
1581 #endif
1582 sregs->fsr = 0;
1583 sregs->fpu_pres = !nfp;
1584 set_fsr(sregs->fsr);
1585 sregs->bphit = 0;
1586 sregs->ildreg = 0;
1587 sregs->ildtime = 0;
1588
1589 sregs->rett_err = 0;
1590 sregs->jmpltime = 0;
1591 }
1592
1593 chk_fp(sregs)
1594 struct pstate *sregs;
1595 {
1596 return (sregs->fpu_pres);
1597 }