This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.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 }