1 /* This file is part of SIS (SPARC instruction simulator)
2 
3    Copyright (C) 1995-2024 Free Software Foundation, Inc.
4    Contributed by Jiri Gaisler, European Space Agency
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18 
19 /* This must come before any other includes.  */
20 #include "defs.h"
21 
22 #include "sis.h"
23 #include <math.h>
24 #include <stdio.h>
25 
26 extern int32_t    sis_verbose, sparclite;
27 int ext_irl = 0;
28 
29 /* Load/store interlock delay */
30 #define FLSTHOLD 1
31 
32 /* Load delay (delete if unwanted - speeds up simulation) */
33 #define LOAD_DEL 1
34 
35 #define T_LD        2
36 #define T_LDD       3
37 #define T_ST        3
38 #define T_STD       4
39 #define T_LDST      4
40 #define T_JMPL      2
41 #define T_RETT      2
42 
43 #define FSR_QNE     0x2000
44 #define FP_EXE_MODE 0
45 #define   FP_EXC_PE   1
46 #define FP_EXC_MODE 2
47 
48 #define   FBA       8
49 #define   FBN       0
50 #define   FBNE      1
51 #define   FBLG      2
52 #define   FBUL      3
53 #define   FBL       4
54 #define   FBUG      5
55 #define   FBG       6
56 #define   FBU       7
57 #define FBA         8
58 #define FBE         9
59 #define FBUE        10
60 #define FBGE        11
61 #define FBUGE       12
62 #define FBLE        13
63 #define FBULE       14
64 #define FBO         15
65 
66 #define   FCC_E     0
67 #define   FCC_L     1
68 #define   FCC_G     2
69 #define   FCC_U     3
70 
71 #define PSR_ET 0x20
72 #define PSR_EF 0x1000
73 #define PSR_PS 0x40
74 #define PSR_S  0x80
75 #define PSR_N  0x0800000
76 #define PSR_Z  0x0400000
77 #define PSR_V  0x0200000
78 #define PSR_C  0x0100000
79 #define PSR_CC 0x0F00000
80 #define PSR_CWP 0x7
81 #define PSR_PIL 0x0f00
82 
83 #define ICC_N       (icc >> 3)
84 #define ICC_Z       (icc >> 2)
85 #define ICC_V       (icc >> 1)
86 #define ICC_C       (icc)
87 
88 #define FP_PRES     (sregs->fpu_pres)
89 
90 #define TRAP_IEXC 1
91 #define TRAP_UNIMP 2
92 #define TRAP_PRIVI 3
93 #define TRAP_FPDIS 4
94 #define TRAP_WOFL 5
95 #define TRAP_WUFL 6
96 #define TRAP_UNALI 7
97 #define TRAP_FPEXC 8
98 #define TRAP_DEXC 9
99 #define TRAP_TAG 10
100 #define TRAP_DIV0 0x2a
101 
102 #define FSR_TT                0x1C000
103 #define FP_IEEE               0x04000
104 #define FP_UNIMP    0x0C000
105 #define FP_SEQ_ERR  0x10000
106 
107 #define   BICC_BN             0
108 #define   BICC_BE             1
109 #define   BICC_BLE  2
110 #define   BICC_BL             3
111 #define   BICC_BLEU 4
112 #define   BICC_BCS  5
113 #define   BICC_NEG  6
114 #define   BICC_BVS  7
115 #define   BICC_BA             8
116 #define   BICC_BNE  9
117 #define   BICC_BG             10
118 #define   BICC_BGE  11
119 #define   BICC_BGU  12
120 #define   BICC_BCC  13
121 #define   BICC_POS  14
122 #define   BICC_BVC  15
123 
124 #define INST_SIMM13 0x1fff
125 #define INST_RS2    0x1f
126 #define INST_I          0x2000
127 #define ADD         0x00
128 #define ADDCC       0x10
129 #define ADDX        0x08
130 #define ADDXCC      0x18
131 #define TADDCC      0x20
132 #define TSUBCC  0x21
133 #define TADDCCTV 0x22
134 #define TSUBCCTV 0x23
135 #define IAND        0x01
136 #define IANDCC      0x11
137 #define IANDN       0x05
138 #define IANDNCC     0x15
139 #define MULScc      0x24
140 #define DIVScc      0x1D
141 #define SMUL        0x0B
142 #define SMULCC      0x1B
143 #define UMUL        0x0A
144 #define UMULCC      0x1A
145 #define SDIV        0x0F
146 #define SDIVCC      0x1F
147 #define UDIV        0x0E
148 #define UDIVCC      0x1E
149 #define IOR         0x02
150 #define IORCC       0x12
151 #define IORN        0x06
152 #define IORNCC      0x16
153 #define SLL         0x25
154 #define SRA         0x27
155 #define SRL         0x26
156 #define SUB         0x04
157 #define SUBCC       0x14
158 #define SUBX        0x0C
159 #define SUBXCC      0x1C
160 #define IXNOR       0x07
161 #define IXNORCC     0x17
162 #define IXOR        0x03
163 #define IXORCC      0x13
164 #define SETHI       0x04
165 #define BICC        0x02
166 #define FPBCC       0x06
167 #define RDY         0x28
168 #define RDPSR       0x29
169 #define RDWIM       0x2A
170 #define RDTBR       0x2B
171 #define SCAN        0x2C
172 #define WRY         0x30
173 #define WRPSR       0x31
174 #define WRWIM       0x32
175 #define WRTBR       0x33
176 #define JMPL        0x38
177 #define RETT        0x39
178 #define TICC        0x3A
179 #define SAVE        0x3C
180 #define RESTORE 0x3D
181 #define LDD         0x03
182 #define LDDA        0x13
183 #define LD          0x00
184 #define LDA         0x10
185 #define LDF         0x20
186 #define LDDF        0x23
187 #define LDSTUB      0x0D
188 #define LDSTUBA     0x1D
189 #define LDUB        0x01
190 #define LDUBA       0x11
191 #define LDSB        0x09
192 #define LDSBA       0x19
193 #define LDUH        0x02
194 #define LDUHA       0x12
195 #define LDSH        0x0A
196 #define LDSHA       0x1A
197 #define LDFSR       0x21
198 #define ST          0x04
199 #define STA         0x14
200 #define STB         0x05
201 #define STBA        0x15
202 #define STD         0x07
203 #define STDA        0x17
204 #define STF         0x24
205 #define STDFQ       0x26
206 #define STDF        0x27
207 #define STFSR       0x25
208 #define STH         0x06
209 #define STHA        0x16
210 #define SWAP        0x0F
211 #define SWAPA       0x1F
212 #define FLUSH       0x3B
213 
214 #define SIGN_BIT 0x80000000
215 
216 /* # of cycles overhead when a trap is taken */
217 #define TRAP_C  3
218 
219 /* Forward declarations */
220 
221 static uint32_t     sub_cc (uint32_t psr, int32_t operand1, int32_t operand2,
222                               int32_t result);
223 static uint32_t     add_cc (uint32_t psr, int32_t operand1, int32_t operand2,
224                               int32_t result);
225 static void         log_cc (int32_t result, struct pstate *sregs);
226 static int          fpexec (uint32_t op3, uint32_t rd, uint32_t rs1, uint32_t rs2,
227                               struct pstate *sregs);
228 static int          chk_asi (struct pstate *sregs, uint32_t *asi, uint32_t op3);
229 
230 
231 extern struct estate ebase;
232 extern int32_t    nfp,ift;
233 
234 #ifdef ERRINJ
235 extern uint32_t errtt, errftt;
236 #endif
237 
238 static uint32_t
sub_cc(uint32_t psr,int32_t operand1,int32_t operand2,int32_t result)239 sub_cc(uint32_t psr, int32_t operand1, int32_t operand2, int32_t result)
240 {
241     psr = ((psr & ~PSR_N) | ((result >> 8) & PSR_N));
242     if (result)
243           psr &= ~PSR_Z;
244     else
245           psr |= PSR_Z;
246     psr = (psr & ~PSR_V) | ((((operand1 & ~operand2 & ~result) |
247                                  (~operand1 & operand2 & result)) >> 10) & PSR_V);
248     psr = (psr & ~PSR_C) | ((((~operand1 & operand2) |
249                                ((~operand1 | operand2) & result)) >> 11) & PSR_C);
250     return psr;
251 }
252 
253 uint32_t
add_cc(uint32_t psr,int32_t operand1,int32_t operand2,int32_t result)254 add_cc(uint32_t psr, int32_t operand1, int32_t operand2, int32_t result)
255 {
256     psr = ((psr & ~PSR_N) | ((result >> 8) & PSR_N));
257     if (result)
258           psr &= ~PSR_Z;
259     else
260           psr |= PSR_Z;
261     psr = (psr & ~PSR_V) | ((((operand1 & operand2 & ~result) |
262                                 (~operand1 & ~operand2 & result)) >> 10) & PSR_V);
263     psr = (psr & ~PSR_C) | ((((operand1 & operand2) |
264                                ((operand1 | operand2) & ~result)) >> 11) & PSR_C);
265     return psr;
266 }
267 
268 static void
log_cc(int32_t result,struct pstate * sregs)269 log_cc(int32_t result, struct pstate *sregs)
270 {
271     sregs->psr &= ~(PSR_CC);  /* Zero CC bits */
272     sregs->psr = (sregs->psr | ((result >> 8) & PSR_N));
273     if (result == 0)
274           sregs->psr |= PSR_Z;
275 }
276 
277 /* Add two unsigned 32-bit integers, and calculate the carry out. */
278 
279 static uint32_t
add32(uint32_t n1,uint32_t n2,int * carry)280 add32 (uint32_t n1, uint32_t n2, int *carry)
281 {
282   uint32_t result = n1 + n2;
283 
284   *carry = result < n1 || result < n2;
285   return result;
286 }
287 
288 /* Multiply two 32-bit integers.  */
289 
290 static void
mul64(uint32_t n1,uint32_t n2,uint32_t * result_hi,uint32_t * result_lo,int msigned)291 mul64 (uint32_t n1, uint32_t n2, uint32_t *result_hi, uint32_t *result_lo, int msigned)
292 {
293   uint32_t lo, mid1, mid2, hi, reg_lo, reg_hi;
294   int carry;
295   int sign = 0;
296 
297   /* If this is a signed multiply, calculate the sign of the result
298      and make the operands positive.  */
299   if (msigned)
300     {
301       sign = (n1 ^ n2) & SIGN_BIT;
302       if (n1 & SIGN_BIT)
303           n1 = -n1;
304       if (n2 & SIGN_BIT)
305           n2 = -n2;
306 
307     }
308 
309   /* We can split the 32x32 into four 16x16 operations. This ensures
310      that we do not lose precision on 32bit only hosts: */
311   lo =   ((n1 & 0xFFFF) * (n2 & 0xFFFF));
312   mid1 = ((n1 & 0xFFFF) * ((n2 >> 16) & 0xFFFF));
313   mid2 = (((n1 >> 16) & 0xFFFF) * (n2 & 0xFFFF));
314   hi =   (((n1 >> 16) & 0xFFFF) * ((n2 >> 16) & 0xFFFF));
315 
316   /* We now need to add all of these results together, taking care
317      to propogate the carries from the additions: */
318   reg_lo = add32 (lo, (mid1 << 16), &carry);
319   reg_hi = carry;
320   reg_lo = add32 (reg_lo, (mid2 << 16), &carry);
321   reg_hi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
322 
323   /* Negate result if necessary. */
324   if (sign)
325     {
326       reg_hi = ~ reg_hi;
327       reg_lo = - reg_lo;
328       if (reg_lo == 0)
329           reg_hi++;
330     }
331 
332   *result_lo = reg_lo;
333   *result_hi = reg_hi;
334 }
335 
336 
337 /* Divide a 64-bit integer by a 32-bit integer.  We cheat and assume
338    that the host compiler supports long long operations.  */
339 
340 static void
div64(uint32_t n1_hi,uint32_t n1_low,uint32_t n2,uint32_t * result,int msigned)341 div64 (uint32_t n1_hi, uint32_t n1_low, uint32_t n2, uint32_t *result, int msigned)
342 {
343   uint64_t n1;
344 
345   n1 = ((uint64_t) n1_hi) << 32;
346   n1 |= ((uint64_t) n1_low) & 0xffffffff;
347 
348   if (msigned)
349     {
350       int64_t n1_s = (int64_t) n1;
351       int32_t n2_s = (int32_t) n2;
352       n1_s = n1_s / n2_s;
353       n1 = (uint64_t) n1_s;
354     }
355   else
356     n1 = n1 / n2;
357 
358   *result = (uint32_t) (n1 & 0xffffffff);
359 }
360 
361 
362 static int
extract_short(uint32_t data,uint32_t address)363 extract_short (uint32_t data, uint32_t address)
364 {
365     return ((data >> ((2 - (address & 2)) * 8)) & 0xffff);
366 }
367 
368 static int
extract_short_signed(uint32_t data,uint32_t address)369 extract_short_signed (uint32_t data, uint32_t address)
370 {
371     uint32_t tmp = ((data >> ((2 - (address & 2)) * 8)) & 0xffff);
372     if (tmp & 0x8000)
373         tmp |= 0xffff0000;
374     return tmp;
375 }
376 
377 static int
extract_byte(uint32_t data,uint32_t address)378 extract_byte (uint32_t data, uint32_t address)
379 {
380     return ((data >> ((3 - (address & 3)) * 8)) & 0xff);
381 }
382 
383 static int
extract_byte_signed(uint32_t data,uint32_t address)384 extract_byte_signed (uint32_t data, uint32_t address)
385 {
386     uint32_t tmp = ((data >> ((3 - (address & 3)) * 8)) & 0xff);
387     if (tmp & 0x80)
388         tmp |= 0xffffff00;
389     return tmp;
390 }
391 
392 int
dispatch_instruction(struct pstate * sregs)393 dispatch_instruction(struct pstate *sregs)
394 {
395 
396     uint32_t          cwp, op, op2, op3, asi, rd, cond, rs1,
397                     rs2;
398     uint32_t          ldep, icc, data, *rdd;
399     int32_t           operand1, operand2, result, eicc,
400                     new_cwp;
401     int32_t           pc, npc, address, ws, mexc, fcc;
402     uint32_t            ddata[2];
403 
404     sregs->ninst++;
405     cwp = ((sregs->psr & PSR_CWP) << 4);
406     op = sregs->inst >> 30;
407     pc = sregs->npc;
408     npc = sregs->npc + 4;
409     op3 = rd = rs1 = operand2 = eicc = 0;
410     rdd = 0;
411     if (op & 2) {
412 
413           op3 = (sregs->inst >> 19) & 0x3f;
414           rs1 = (sregs->inst >> 14) & 0x1f;
415           rd = (sregs->inst >> 25) & 0x1f;
416 
417 #ifdef LOAD_DEL
418 
419           /* Check if load dependecy is possible */
420           if (ebase.simtime <= sregs->ildtime)
421               ldep = (((op3 & 0x38) != 0x28) && ((op3 & 0x3e) != 0x34) && (sregs->ildreg != 0));
422         else
423               ldep = 0;
424           if (sregs->inst & INST_I) {
425               if (ldep && (sregs->ildreg == rs1))
426                     sregs->hold++;
427               operand2 = sregs->inst;
428               operand2 = ((operand2 << 19) >> 19);          /* sign extend */
429           } else {
430               rs2 = sregs->inst & INST_RS2;
431               if (rs2 > 7)
432                     operand2 = sregs->r[(cwp + rs2) & 0x7f];
433               else
434                     operand2 = sregs->g[rs2];
435               if (ldep && ((sregs->ildreg == rs1) || (sregs->ildreg == rs2)))
436                     sregs->hold++;
437           }
438 #else
439           if (sregs->inst & INST_I) {
440               operand2 = sregs->inst;
441               operand2 = ((operand2 << 19) >> 19);          /* sign extend */
442           } else {
443               rs2 = sregs->inst & INST_RS2;
444               if (rs2 > 7)
445                     operand2 = sregs->r[(cwp + rs2) & 0x7f];
446               else
447                     operand2 = sregs->g[rs2];
448           }
449 #endif
450 
451           if (rd > 7)
452               rdd = &(sregs->r[(cwp + rd) & 0x7f]);
453           else
454               rdd = &(sregs->g[rd]);
455           if (rs1 > 7)
456               rs1 = sregs->r[(cwp + rs1) & 0x7f];
457           else
458               rs1 = sregs->g[rs1];
459     }
460     switch (op) {
461     case 0:
462           op2 = (sregs->inst >> 22) & 0x7;
463           switch (op2) {
464           case SETHI:
465               rd = (sregs->inst >> 25) & 0x1f;
466               if (rd > 7)
467                     rdd = &(sregs->r[(cwp + rd) & 0x7f]);
468               else
469                     rdd = &(sregs->g[rd]);
470               *rdd = sregs->inst << 10;
471               break;
472           case BICC:
473 #ifdef STAT
474               sregs->nbranch++;
475 #endif
476               icc = sregs->psr >> 20;
477               cond = ((sregs->inst >> 25) & 0x0f);
478               switch (cond) {
479               case BICC_BN:
480                     eicc = 0;
481                     break;
482               case BICC_BE:
483                     eicc = ICC_Z;
484                     break;
485               case BICC_BLE:
486                     eicc = ICC_Z | (ICC_N ^ ICC_V);
487                     break;
488               case BICC_BL:
489                     eicc = (ICC_N ^ ICC_V);
490                     break;
491               case BICC_BLEU:
492                     eicc = ICC_C | ICC_Z;
493                     break;
494               case BICC_BCS:
495                     eicc = ICC_C;
496                     break;
497               case BICC_NEG:
498                     eicc = ICC_N;
499                     break;
500               case BICC_BVS:
501                     eicc = ICC_V;
502                     break;
503               case BICC_BA:
504                     eicc = 1;
505                     if (sregs->inst & 0x20000000)
506                         sregs->annul = 1;
507                     break;
508               case BICC_BNE:
509                     eicc = ~(ICC_Z);
510                     break;
511               case BICC_BG:
512                     eicc = ~(ICC_Z | (ICC_N ^ ICC_V));
513                     break;
514               case BICC_BGE:
515                     eicc = ~(ICC_N ^ ICC_V);
516                     break;
517               case BICC_BGU:
518                     eicc = ~(ICC_C | ICC_Z);
519                     break;
520               case BICC_BCC:
521                     eicc = ~(ICC_C);
522                     break;
523               case BICC_POS:
524                     eicc = ~(ICC_N);
525                     break;
526               case BICC_BVC:
527                     eicc = ~(ICC_V);
528                     break;
529               }
530               if (eicc & 1) {
531                     operand1 = sregs->inst;
532                     operand1 = ((operand1 << 10) >> 8);     /* sign extend */
533                     npc = sregs->pc + operand1;
534               } else {
535                     if (sregs->inst & 0x20000000)
536                         sregs->annul = 1;
537               }
538               break;
539           case FPBCC:
540 #ifdef STAT
541               sregs->nbranch++;
542 #endif
543               if (!((sregs->psr & PSR_EF) && FP_PRES)) {
544                     sregs->trap = TRAP_FPDIS;
545                     break;
546               }
547               if (ebase.simtime < sregs->ftime) {
548                     sregs->ftime = ebase.simtime + sregs->hold;
549               }
550               cond = ((sregs->inst >> 25) & 0x0f);
551               fcc = (sregs->fsr >> 10) & 0x3;
552               switch (cond) {
553               case FBN:
554                     eicc = 0;
555                     break;
556               case FBNE:
557                     eicc = (fcc != FCC_E);
558                     break;
559               case FBLG:
560                     eicc = (fcc == FCC_L) || (fcc == FCC_G);
561                     break;
562               case FBUL:
563                     eicc = (fcc == FCC_L) || (fcc == FCC_U);
564                     break;
565               case FBL:
566                     eicc = (fcc == FCC_L);
567                     break;
568               case FBUG:
569                     eicc = (fcc == FCC_G) || (fcc == FCC_U);
570                     break;
571               case FBG:
572                     eicc = (fcc == FCC_G);
573                     break;
574               case FBU:
575                     eicc = (fcc == FCC_U);
576                     break;
577               case FBA:
578                     eicc = 1;
579                     if (sregs->inst & 0x20000000)
580                         sregs->annul = 1;
581                     break;
582               case FBE:
583                     eicc = !(fcc != FCC_E);
584                     break;
585               case FBUE:
586                     eicc = !((fcc == FCC_L) || (fcc == FCC_G));
587                     break;
588               case FBGE:
589                     eicc = !((fcc == FCC_L) || (fcc == FCC_U));
590                     break;
591               case FBUGE:
592                     eicc = !(fcc == FCC_L);
593                     break;
594               case FBLE:
595                     eicc = !((fcc == FCC_G) || (fcc == FCC_U));
596                     break;
597               case FBULE:
598                     eicc = !(fcc == FCC_G);
599                     break;
600               case FBO:
601                     eicc = !(fcc == FCC_U);
602                     break;
603               }
604               if (eicc) {
605                     operand1 = sregs->inst;
606                     operand1 = ((operand1 << 10) >> 8);     /* sign extend */
607                     npc = sregs->pc + operand1;
608               } else {
609                     if (sregs->inst & 0x20000000)
610                         sregs->annul = 1;
611               }
612               break;
613 
614           default:
615               sregs->trap = TRAP_UNIMP;
616               break;
617           }
618           break;
619     case 1:                             /* CALL */
620 #ifdef STAT
621           sregs->nbranch++;
622 #endif
623           sregs->r[(cwp + 15) & 0x7f] = sregs->pc;
624           npc = sregs->pc + (sregs->inst << 2);
625           break;
626 
627     case 2:
628           if ((op3 >> 1) == 0x1a) {
629               if (!((sregs->psr & PSR_EF) && FP_PRES)) {
630                     sregs->trap = TRAP_FPDIS;
631               } else {
632                     rs1 = (sregs->inst >> 14) & 0x1f;
633                     rs2 = sregs->inst & 0x1f;
634                     sregs->trap = fpexec(op3, rd, rs1, rs2, sregs);
635               }
636           } else {
637 
638               switch (op3) {
639               case TICC:
640                   icc = sregs->psr >> 20;
641                   cond = ((sregs->inst >> 25) & 0x0f);
642                   switch (cond) {
643                     case BICC_BN:
644                         eicc = 0;
645                         break;
646                     case BICC_BE:
647                         eicc = ICC_Z;
648                         break;
649                     case BICC_BLE:
650                         eicc = ICC_Z | (ICC_N ^ ICC_V);
651                         break;
652                     case BICC_BL:
653                         eicc = (ICC_N ^ ICC_V);
654                         break;
655                     case BICC_BLEU:
656                         eicc = ICC_C | ICC_Z;
657                         break;
658                     case BICC_BCS:
659                         eicc = ICC_C;
660                         break;
661                     case BICC_NEG:
662                         eicc = ICC_N;
663                         break;
664                     case BICC_BVS:
665                         eicc = ICC_V;
666                         break;
667                   case BICC_BA:
668                         eicc = 1;
669                         break;
670                   case BICC_BNE:
671                         eicc = ~(ICC_Z);
672                         break;
673                   case BICC_BG:
674                         eicc = ~(ICC_Z | (ICC_N ^ ICC_V));
675                         break;
676                   case BICC_BGE:
677                         eicc = ~(ICC_N ^ ICC_V);
678                         break;
679                   case BICC_BGU:
680                         eicc = ~(ICC_C | ICC_Z);
681                         break;
682                   case BICC_BCC:
683                         eicc = ~(ICC_C);
684                         break;
685                   case BICC_POS:
686                         eicc = ~(ICC_N);
687                         break;
688                   case BICC_BVC:
689                         eicc = ~(ICC_V);
690                         break;
691                     }
692                     if (eicc & 1) {
693                         sregs->trap = (0x80 | ((rs1 + operand2) & 0x7f));
694                     }
695                     break;
696 
697               case MULScc:
698                     operand1 =
699                         (((sregs->psr & PSR_V) ^ ((sregs->psr & PSR_N) >> 2))
700                          << 10) | (rs1 >> 1);
701                     if ((sregs->y & 1) == 0)
702                         operand2 = 0;
703                     *rdd = operand1 + operand2;
704                     sregs->y = (rs1 << 31) | (sregs->y >> 1);
705                     sregs->psr = add_cc(sregs->psr, operand1, operand2, *rdd);
706                     break;
707               case DIVScc:
708                     {
709                       int sign;
710                       uint32_t uresult, remainder;
711                       int c0, y31;
712 
713                       if (!sparclite) {
714                          sregs->trap = TRAP_UNIMP;
715                      break;
716                       }
717 
718                       sign = ((sregs->psr & PSR_V) != 0) ^ ((sregs->psr & PSR_N) != 0);
719 
720                       remainder = (sregs->y << 1) | (rs1 >> 31);
721 
722                       /* If true sign is positive, calculate remainder - divisor.
723                          Otherwise, calculate remainder + divisor.  */
724                       if (sign == 0)
725                         operand2 = ~operand2 + 1;
726                       uresult = remainder + operand2;
727 
728                       /* The SPARClite User's Manual is not clear on how
729                          the "carry out" of the above ALU operation is to
730                          be calculated.  From trial and error tests
731                          on the the chip itself, it appears that it is
732                          a normal addition carry, and not a subtraction borrow,
733                          even in cases where the divisor is subtracted
734                          from the remainder.  FIXME: get the true story
735                          from Fujitsu. */
736                       c0 = uresult < remainder || uresult < (uint32_t) operand2;
737 
738                       if (uresult & 0x80000000)
739                         sregs->psr |= PSR_N;
740                       else
741                         sregs->psr &= ~PSR_N;
742 
743                       y31 = (sregs->y & 0x80000000) == 0x80000000;
744 
745                       if (uresult == 0 && sign == y31)
746                         sregs->psr |= PSR_Z;
747                       else
748                         sregs->psr &= ~PSR_Z;
749 
750                       sign = (sign && !y31) || (!c0 && (sign || !y31));
751 
752                       if (sign ^ (uresult >> 31))
753                         sregs->psr |= PSR_V;
754                       else
755                         sregs->psr &= ~PSR_V;
756 
757                       if (!sign)
758                         sregs->psr |= PSR_C;
759                       else
760                         sregs->psr &= ~PSR_C;
761 
762                       sregs->y = uresult;
763 
764                       if (rd != 0)
765                         *rdd = (rs1 << 1) | !sign;
766                     }
767                     break;
768               case SMUL:
769                     {
770                       mul64 (rs1, operand2, &sregs->y, rdd, 1);
771                     }
772                     break;
773               case SMULCC:
774                     {
775                       uint32_t uresult;
776 
777                       mul64 (rs1, operand2, &sregs->y, &uresult, 1);
778 
779                       if (uresult & 0x80000000)
780                         sregs->psr |= PSR_N;
781                       else
782                         sregs->psr &= ~PSR_N;
783 
784                       if (uresult == 0)
785                         sregs->psr |= PSR_Z;
786                       else
787                         sregs->psr &= ~PSR_Z;
788 
789                       *rdd = uresult;
790                     }
791                     break;
792               case UMUL:
793                     {
794                       mul64 (rs1, operand2, &sregs->y, rdd, 0);
795                     }
796                     break;
797               case UMULCC:
798                     {
799                       uint32_t uresult;
800 
801                       mul64 (rs1, operand2, &sregs->y, &uresult, 0);
802 
803                       if (uresult & 0x80000000)
804                         sregs->psr |= PSR_N;
805                       else
806                         sregs->psr &= ~PSR_N;
807 
808                       if (uresult == 0)
809                         sregs->psr |= PSR_Z;
810                       else
811                         sregs->psr &= ~PSR_Z;
812 
813                       *rdd = uresult;
814                     }
815                     break;
816               case SDIV:
817                     {
818                       if (sparclite) {
819                          sregs->trap = TRAP_UNIMP;
820                      break;
821                       }
822 
823                       if (operand2 == 0) {
824                         sregs->trap = TRAP_DIV0;
825                         break;
826                       }
827 
828                       div64 (sregs->y, rs1, operand2, rdd, 1);
829                     }
830                     break;
831               case SDIVCC:
832                     {
833                       uint32_t uresult;
834 
835                       if (sparclite) {
836                          sregs->trap = TRAP_UNIMP;
837                      break;
838                       }
839 
840                       if (operand2 == 0) {
841                         sregs->trap = TRAP_DIV0;
842                         break;
843                       }
844 
845                       div64 (sregs->y, rs1, operand2, &uresult, 1);
846 
847                       if (uresult & 0x80000000)
848                         sregs->psr |= PSR_N;
849                       else
850                         sregs->psr &= ~PSR_N;
851 
852                       if (uresult == 0)
853                         sregs->psr |= PSR_Z;
854                       else
855                         sregs->psr &= ~PSR_Z;
856 
857                       /* FIXME: should set overflow flag correctly.  */
858                       sregs->psr &= ~(PSR_C | PSR_V);
859 
860                       *rdd = uresult;
861                     }
862                     break;
863               case UDIV:
864                     {
865                       if (sparclite) {
866                          sregs->trap = TRAP_UNIMP;
867                      break;
868                       }
869 
870                       if (operand2 == 0) {
871                         sregs->trap = TRAP_DIV0;
872                         break;
873                       }
874 
875                       div64 (sregs->y, rs1, operand2, rdd, 0);
876                     }
877                     break;
878               case UDIVCC:
879                     {
880                       uint32_t uresult;
881 
882                       if (sparclite) {
883                          sregs->trap = TRAP_UNIMP;
884                      break;
885                       }
886 
887                       if (operand2 == 0) {
888                         sregs->trap = TRAP_DIV0;
889                         break;
890                       }
891 
892                       div64 (sregs->y, rs1, operand2, &uresult, 0);
893 
894                       if (uresult & 0x80000000)
895                         sregs->psr |= PSR_N;
896                       else
897                         sregs->psr &= ~PSR_N;
898 
899                       if (uresult == 0)
900                         sregs->psr |= PSR_Z;
901                       else
902                         sregs->psr &= ~PSR_Z;
903 
904                       /* FIXME: should set overflow flag correctly.  */
905                       sregs->psr &= ~(PSR_C | PSR_V);
906 
907                       *rdd = uresult;
908                     }
909                     break;
910               case IXNOR:
911                     *rdd = rs1 ^ ~operand2;
912                     break;
913               case IXNORCC:
914                     *rdd = rs1 ^ ~operand2;
915                     log_cc(*rdd, sregs);
916                     break;
917               case IXOR:
918                     *rdd = rs1 ^ operand2;
919                     break;
920               case IXORCC:
921                     *rdd = rs1 ^ operand2;
922                     log_cc(*rdd, sregs);
923                     break;
924               case IOR:
925                     *rdd = rs1 | operand2;
926                     break;
927               case IORCC:
928                     *rdd = rs1 | operand2;
929                     log_cc(*rdd, sregs);
930                     break;
931               case IORN:
932                     *rdd = rs1 | ~operand2;
933                     break;
934               case IORNCC:
935                     *rdd = rs1 | ~operand2;
936                     log_cc(*rdd, sregs);
937                     break;
938               case IANDNCC:
939                     *rdd = rs1 & ~operand2;
940                     log_cc(*rdd, sregs);
941                     break;
942               case IANDN:
943                     *rdd = rs1 & ~operand2;
944                     break;
945               case IAND:
946                     *rdd = rs1 & operand2;
947                     break;
948               case IANDCC:
949                     *rdd = rs1 & operand2;
950                     log_cc(*rdd, sregs);
951                     break;
952               case SUB:
953                     *rdd = rs1 - operand2;
954                     break;
955               case SUBCC:
956                     *rdd = rs1 - operand2;
957                     sregs->psr = sub_cc(sregs->psr, rs1, operand2, *rdd);
958                     break;
959               case SUBX:
960                     *rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);
961                     break;
962               case SUBXCC:
963                     *rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);
964                     sregs->psr = sub_cc(sregs->psr, rs1, operand2, *rdd);
965                     break;
966               case ADD:
967                     *rdd = rs1 + operand2;
968                     break;
969               case ADDCC:
970                     *rdd = rs1 + operand2;
971                     sregs->psr = add_cc(sregs->psr, rs1, operand2, *rdd);
972                     break;
973               case ADDX:
974                     *rdd = rs1 + operand2 + ((sregs->psr >> 20) & 1);
975                     break;
976               case ADDXCC:
977                     *rdd = rs1 + operand2 + ((sregs->psr >> 20) & 1);
978                     sregs->psr = add_cc(sregs->psr, rs1, operand2, *rdd);
979                     break;
980               case TADDCC:
981                     *rdd = rs1 + operand2;
982                     sregs->psr = add_cc(sregs->psr, rs1, operand2, *rdd);
983                     if ((rs1 | operand2) & 0x3)
984                         sregs->psr |= PSR_V;
985                     break;
986               case TSUBCC:
987                     *rdd = rs1 - operand2;
988                     sregs->psr = sub_cc (sregs->psr, rs1, operand2, *rdd);
989                     if ((rs1 | operand2) & 0x3)
990                         sregs->psr |= PSR_V;
991                     break;
992               case TADDCCTV:
993                     *rdd = rs1 + operand2;
994                     result = add_cc(0, rs1, operand2, *rdd);
995                     if ((rs1 | operand2) & 0x3)
996                         result |= PSR_V;
997                     if (result & PSR_V) {
998                         sregs->trap = TRAP_TAG;
999                     } else {
1000                         sregs->psr = (sregs->psr & ~PSR_CC) | result;
1001                     }
1002                     break;
1003               case TSUBCCTV:
1004                     *rdd = rs1 - operand2;
1005                     result = add_cc (0, rs1, operand2, *rdd);
1006                     if ((rs1 | operand2) & 0x3)
1007                         result |= PSR_V;
1008                     if (result & PSR_V)
1009                       {
1010                           sregs->trap = TRAP_TAG;
1011                       }
1012                     else
1013                       {
1014                           sregs->psr = (sregs->psr & ~PSR_CC) | result;
1015                       }
1016                     break;
1017               case SLL:
1018                     *rdd = rs1 << (operand2 & 0x1f);
1019                     break;
1020               case SRL:
1021                     *rdd = rs1 >> (operand2 & 0x1f);
1022                     break;
1023               case SRA:
1024                     *rdd = ((int) rs1) >> (operand2 & 0x1f);
1025                     break;
1026               case FLUSH:
1027                     if (ift) sregs->trap = TRAP_UNIMP;
1028                     break;
1029               case SAVE:
1030                     new_cwp = ((sregs->psr & PSR_CWP) - 1) & PSR_CWP;
1031                     if (sregs->wim & (1 << new_cwp)) {
1032                         sregs->trap = TRAP_WOFL;
1033                         break;
1034                     }
1035                     if (rd > 7)
1036                         rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);
1037                     *rdd = rs1 + operand2;
1038                     sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;
1039                     break;
1040               case RESTORE:
1041 
1042                     new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;
1043                     if (sregs->wim & (1 << new_cwp)) {
1044                         sregs->trap = TRAP_WUFL;
1045                         break;
1046                     }
1047                     if (rd > 7)
1048                         rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);
1049                     *rdd = rs1 + operand2;
1050                     sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;
1051                     break;
1052               case RDPSR:
1053                     if (!(sregs->psr & PSR_S)) {
1054                         sregs->trap = TRAP_PRIVI;
1055                         break;
1056                     }
1057                     *rdd = sregs->psr;
1058                     break;
1059               case RDY:
1060                 if (!sparclite)
1061                     *rdd = sregs->y;
1062                 else {
1063                     int rs1_is_asr = (sregs->inst >> 14) & 0x1f;
1064                     if ( 0 == rs1_is_asr )
1065                         *rdd = sregs->y;
1066                     else if ( 17 == rs1_is_asr )
1067                         *rdd = sregs->asr17;
1068                     else {
1069                         sregs->trap = TRAP_UNIMP;
1070                         break;
1071                     }
1072                 }
1073                     break;
1074               case RDWIM:
1075                     if (!(sregs->psr & PSR_S)) {
1076                         sregs->trap = TRAP_PRIVI;
1077                         break;
1078                     }
1079                     *rdd = sregs->wim;
1080                     break;
1081               case RDTBR:
1082                     if (!(sregs->psr & PSR_S)) {
1083                         sregs->trap = TRAP_PRIVI;
1084                         break;
1085                     }
1086                     *rdd = sregs->tbr;
1087                     break;
1088               case WRPSR:
1089                     if ((sregs->psr & 0x1f) > 7) {
1090                         sregs->trap = TRAP_UNIMP;
1091                         break;
1092                     }
1093                     if (!(sregs->psr & PSR_S)) {
1094                         sregs->trap = TRAP_PRIVI;
1095                         break;
1096                     }
1097                     sregs->psr = (sregs->psr & 0xff000000) |
1098                               ((rs1 ^ operand2) & 0x00f03fff);
1099                     break;
1100               case WRWIM:
1101                     if (!(sregs->psr & PSR_S)) {
1102                         sregs->trap = TRAP_PRIVI;
1103                         break;
1104                     }
1105                     sregs->wim = (rs1 ^ operand2) & 0x0ff;
1106                     break;
1107               case WRTBR:
1108                     if (!(sregs->psr & PSR_S)) {
1109                         sregs->trap = TRAP_PRIVI;
1110                         break;
1111                     }
1112                     sregs->tbr = (sregs->tbr & 0x00000ff0) |
1113                         ((rs1 ^ operand2) & 0xfffff000);
1114                     break;
1115               case WRY:
1116                 if (!sparclite)
1117                     sregs->y = (rs1 ^ operand2);
1118                 else {
1119                     if ( 0 == rd )
1120                         sregs->y = (rs1 ^ operand2);
1121                     else if ( 17 == rd )
1122                         sregs->asr17 = (rs1 ^ operand2);
1123                     else {
1124                         sregs->trap = TRAP_UNIMP;
1125                         break;
1126                     }
1127                 }
1128                     break;
1129               case JMPL:
1130 
1131 #ifdef STAT
1132                     sregs->nbranch++;
1133 #endif
1134                     sregs->icnt = T_JMPL;         /* JMPL takes two cycles */
1135                     if (rs1 & 0x3) {
1136                         sregs->trap = TRAP_UNALI;
1137                         break;
1138                     }
1139                     *rdd = sregs->pc;
1140                     npc = rs1 + operand2;
1141                     break;
1142               case RETT:
1143                     address = rs1 + operand2;
1144                     new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;
1145                     sregs->icnt = T_RETT;         /* RETT takes two cycles */
1146                     if (sregs->psr & PSR_ET) {
1147                         sregs->trap = TRAP_UNIMP;
1148                         break;
1149                     }
1150                     if (!(sregs->psr & PSR_S)) {
1151                         sregs->trap = TRAP_PRIVI;
1152                         break;
1153                     }
1154                     if (sregs->wim & (1 << new_cwp)) {
1155                         sregs->trap = TRAP_WUFL;
1156                         break;
1157                     }
1158                     if (address & 0x3) {
1159                         sregs->trap = TRAP_UNALI;
1160                         break;
1161                     }
1162                     sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp | PSR_ET;
1163                     sregs->psr =
1164                         (sregs->psr & ~PSR_S) | ((sregs->psr & PSR_PS) << 1);
1165                     npc = address;
1166                     break;
1167 
1168               case SCAN:
1169                     {
1170                       uint32_t uresult, mask;
1171                       int i;
1172 
1173                       if (!sparclite) {
1174                          sregs->trap = TRAP_UNIMP;
1175                      break;
1176                       }
1177                       mask = (operand2 & 0x80000000) | (operand2 >> 1);
1178                       uresult = rs1 ^ mask;
1179 
1180                       for (i = 0; i < 32; i++) {
1181                         if (uresult & 0x80000000)
1182                           break;
1183                         uresult <<= 1;
1184                       }
1185 
1186                       *rdd = i == 32 ? 63 : i;
1187                     }
1188                     break;
1189 
1190               default:
1191                     sregs->trap = TRAP_UNIMP;
1192                     break;
1193               }
1194           }
1195           break;
1196     case 3:                             /* Load/store instructions */
1197 
1198           address = rs1 + operand2;
1199 
1200           if (sregs->psr & PSR_S)
1201               asi = 11;
1202            else
1203               asi = 10;
1204 
1205           if (op3 & 4) {
1206               sregs->icnt = T_ST;       /* Set store instruction count */
1207 #ifdef STAT
1208               sregs->nstore++;
1209 #endif
1210           } else {
1211               sregs->icnt = T_LD;       /* Set load instruction count */
1212 #ifdef STAT
1213               sregs->nload++;
1214 #endif
1215           }
1216 
1217           /* Decode load/store instructions */
1218 
1219           switch (op3) {
1220           case LDDA:
1221               if (!chk_asi(sregs, &asi, op3)) break;
1222               ATTRIBUTE_FALLTHROUGH;
1223           case LDD:
1224               if (address & 0x7) {
1225                     sregs->trap = TRAP_UNALI;
1226                     break;
1227               }
1228               if (rd & 1) {
1229                     rd &= 0x1e;
1230                     if (rd > 7)
1231                         rdd = &(sregs->r[(cwp + rd) & 0x7f]);
1232                     else
1233                         rdd = &(sregs->g[rd]);
1234               }
1235               mexc = memory_read (asi, address, ddata, 2, &ws);
1236               sregs->hold += ws;
1237               mexc |= memory_read (asi, address+4, &ddata[1], 2, &ws);
1238               sregs->hold += ws;
1239               sregs->icnt = T_LDD;
1240               if (mexc) {
1241                     sregs->trap = TRAP_DEXC;
1242               } else {
1243                     rdd[0] = ddata[0];
1244                     rdd[1] = ddata[1];
1245 #ifdef STAT
1246                     sregs->nload++;     /* Double load counts twice */
1247 #endif
1248               }
1249               break;
1250 
1251           case LDA:
1252               if (!chk_asi(sregs, &asi, op3)) break;
1253               ATTRIBUTE_FALLTHROUGH;
1254           case LD:
1255               if (address & 0x3) {
1256                     sregs->trap = TRAP_UNALI;
1257                     break;
1258               }
1259               mexc = memory_read(asi, address, &data, 2, &ws);
1260               sregs->hold += ws;
1261               if (mexc) {
1262                     sregs->trap = TRAP_DEXC;
1263               } else {
1264                     *rdd = data;
1265               }
1266               break;
1267           case LDSTUBA:
1268               if (!chk_asi(sregs, &asi, op3)) break;
1269               ATTRIBUTE_FALLTHROUGH;
1270           case LDSTUB:
1271               mexc = memory_read(asi, address, &data, 0, &ws);
1272               sregs->hold += ws;
1273               sregs->icnt = T_LDST;
1274               if (mexc) {
1275                     sregs->trap = TRAP_DEXC;
1276                     break;
1277               }
1278               data = extract_byte (data, address);
1279               *rdd = data;
1280               data = 0x0ff;
1281               mexc = memory_write(asi, address, &data, 0, &ws);
1282               sregs->hold += ws;
1283               if (mexc) {
1284                     sregs->trap = TRAP_DEXC;
1285               }
1286 #ifdef STAT
1287               sregs->nload++;
1288 #endif
1289               break;
1290           case LDSBA:
1291           case LDUBA:
1292               if (!chk_asi(sregs, &asi, op3)) break;
1293               ATTRIBUTE_FALLTHROUGH;
1294           case LDSB:
1295           case LDUB:
1296               mexc = memory_read(asi, address, &data, 0, &ws);
1297               sregs->hold += ws;
1298               if (mexc) {
1299                     sregs->trap = TRAP_DEXC;
1300                     break;
1301               }
1302               if (op3 == LDSB)
1303                   data = extract_byte_signed (data, address);
1304               else
1305                   data = extract_byte (data, address);
1306               *rdd = data;
1307               break;
1308           case LDSHA:
1309           case LDUHA:
1310               if (!chk_asi(sregs, &asi, op3)) break;
1311               ATTRIBUTE_FALLTHROUGH;
1312           case LDSH:
1313           case LDUH:
1314               if (address & 0x1) {
1315                     sregs->trap = TRAP_UNALI;
1316                     break;
1317               }
1318               mexc = memory_read(asi, address, &data, 1, &ws);
1319               sregs->hold += ws;
1320               if (mexc) {
1321                     sregs->trap = TRAP_DEXC;
1322                     break;
1323               }
1324               if (op3 == LDSH)
1325                   data = extract_short_signed (data, address);
1326               else
1327                   data = extract_short (data, address);
1328               *rdd = data;
1329               break;
1330           case LDF:
1331               if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1332                     sregs->trap = TRAP_FPDIS;
1333                     break;
1334               }
1335               if (address & 0x3) {
1336                     sregs->trap = TRAP_UNALI;
1337                     break;
1338               }
1339               if (ebase.simtime < sregs->ftime) {
1340                     if ((sregs->frd == rd) || (sregs->frs1 == rd) ||
1341                         (sregs->frs2 == rd))
1342                         sregs->fhold += (sregs->ftime - ebase.simtime);
1343               }
1344               mexc = memory_read(asi, address, &data, 2, &ws);
1345               sregs->hold += ws;
1346               sregs->flrd = rd;
1347               sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
1348                     sregs->hold + sregs->fhold;
1349               if (mexc) {
1350                     sregs->trap = TRAP_DEXC;
1351               } else {
1352                     memcpy (&sregs->fs[rd], &data, sizeof (sregs->fs[rd]));
1353               }
1354               break;
1355           case LDDF:
1356               if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1357                     sregs->trap = TRAP_FPDIS;
1358                     break;
1359               }
1360               if (address & 0x7) {
1361                     sregs->trap = TRAP_UNALI;
1362                     break;
1363               }
1364               if (ebase.simtime < sregs->ftime) {
1365                     if (((sregs->frd >> 1) == (rd >> 1)) ||
1366                         ((sregs->frs1 >> 1) == (rd >> 1)) ||
1367                         ((sregs->frs2 >> 1) == (rd >> 1)))
1368                         sregs->fhold += (sregs->ftime - ebase.simtime);
1369               }
1370               mexc = memory_read (asi, address, ddata, 2, &ws);
1371               sregs->hold += ws;
1372               mexc |= memory_read (asi, address+4, &ddata[1], 2, &ws);
1373               sregs->hold += ws;
1374               sregs->icnt = T_LDD;
1375               if (mexc) {
1376                     sregs->trap = TRAP_DEXC;
1377               } else {
1378                     rd &= 0x1E;
1379                     sregs->flrd = rd;
1380                     memcpy (&sregs->fs[rd], &ddata[0], sizeof (sregs->fs[rd]));
1381 #ifdef STAT
1382                     sregs->nload++;     /* Double load counts twice */
1383 #endif
1384                     memcpy (&sregs->fs[rd + 1], &ddata[1],
1385                               sizeof (sregs->fs[rd + 1]));
1386                     sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
1387                                      sregs->hold + sregs->fhold;
1388               }
1389               break;
1390           case LDFSR:
1391               if (ebase.simtime < sregs->ftime) {
1392                     sregs->fhold += (sregs->ftime - ebase.simtime);
1393               }
1394               if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1395                     sregs->trap = TRAP_FPDIS;
1396                     break;
1397               }
1398               if (address & 0x3) {
1399                     sregs->trap = TRAP_UNALI;
1400                     break;
1401               }
1402               mexc = memory_read(asi, address, &data, 2, &ws);
1403               sregs->hold += ws;
1404               if (mexc) {
1405                     sregs->trap = TRAP_DEXC;
1406               } else {
1407                     sregs->fsr =
1408                         (sregs->fsr & 0x7FF000) | (data & ~0x7FF000);
1409                     set_fsr(sregs->fsr);
1410               }
1411               break;
1412           case STFSR:
1413               if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1414                     sregs->trap = TRAP_FPDIS;
1415                     break;
1416               }
1417               if (address & 0x3) {
1418                     sregs->trap = TRAP_UNALI;
1419                     break;
1420               }
1421               if (ebase.simtime < sregs->ftime) {
1422                     sregs->fhold += (sregs->ftime - ebase.simtime);
1423               }
1424               mexc = memory_write(asi, address, &sregs->fsr, 2, &ws);
1425               sregs->hold += ws;
1426               if (mexc) {
1427                     sregs->trap = TRAP_DEXC;
1428               }
1429               break;
1430 
1431           case STA:
1432               if (!chk_asi(sregs, &asi, op3)) break;
1433               ATTRIBUTE_FALLTHROUGH;
1434           case ST:
1435               if (address & 0x3) {
1436                     sregs->trap = TRAP_UNALI;
1437                     break;
1438               }
1439               mexc = memory_write(asi, address, rdd, 2, &ws);
1440               sregs->hold += ws;
1441               if (mexc) {
1442                     sregs->trap = TRAP_DEXC;
1443               }
1444               break;
1445           case STBA:
1446               if (!chk_asi(sregs, &asi, op3)) break;
1447               ATTRIBUTE_FALLTHROUGH;
1448           case STB:
1449               mexc = memory_write(asi, address, rdd, 0, &ws);
1450               sregs->hold += ws;
1451               if (mexc) {
1452                     sregs->trap = TRAP_DEXC;
1453               }
1454               break;
1455           case STDA:
1456               if (!chk_asi(sregs, &asi, op3)) break;
1457               ATTRIBUTE_FALLTHROUGH;
1458           case STD:
1459               if (address & 0x7) {
1460                     sregs->trap = TRAP_UNALI;
1461                     break;
1462               }
1463               if (rd & 1) {
1464                     rd &= 0x1e;
1465                     if (rd > 7)
1466                         rdd = &(sregs->r[(cwp + rd) & 0x7f]);
1467                     else
1468                         rdd = &(sregs->g[rd]);
1469               }
1470               mexc = memory_write(asi, address, rdd, 3, &ws);
1471               sregs->hold += ws;
1472               sregs->icnt = T_STD;
1473 #ifdef STAT
1474               sregs->nstore++;          /* Double store counts twice */
1475 #endif
1476               if (mexc) {
1477                     sregs->trap = TRAP_DEXC;
1478                     break;
1479               }
1480               break;
1481           case STDFQ:
1482               if ((sregs->psr & 0x1f) > 7) {
1483                     sregs->trap = TRAP_UNIMP;
1484                     break;
1485               }
1486               if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1487                     sregs->trap = TRAP_FPDIS;
1488                     break;
1489               }
1490               if (address & 0x7) {
1491                     sregs->trap = TRAP_UNALI;
1492                     break;
1493               }
1494               if (!(sregs->fsr & FSR_QNE)) {
1495                     sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;
1496                     break;
1497               }
1498               rdd = &(sregs->fpq[0]);
1499               mexc = memory_write(asi, address, rdd, 3, &ws);
1500               sregs->hold += ws;
1501               sregs->icnt = T_STD;
1502 #ifdef STAT
1503               sregs->nstore++;          /* Double store counts twice */
1504 #endif
1505               if (mexc) {
1506                     sregs->trap = TRAP_DEXC;
1507                     break;
1508               } else {
1509                     sregs->fsr &= ~FSR_QNE;
1510                     sregs->fpstate = FP_EXE_MODE;
1511               }
1512               break;
1513           case STHA:
1514               if (!chk_asi(sregs, &asi, op3)) break;
1515               ATTRIBUTE_FALLTHROUGH;
1516           case STH:
1517               if (address & 0x1) {
1518                     sregs->trap = TRAP_UNALI;
1519                     break;
1520               }
1521               mexc = memory_write(asi, address, rdd, 1, &ws);
1522               sregs->hold += ws;
1523               if (mexc) {
1524                     sregs->trap = TRAP_DEXC;
1525               }
1526               break;
1527           case STF:
1528               if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1529                     sregs->trap = TRAP_FPDIS;
1530                     break;
1531               }
1532               if (address & 0x3) {
1533                     sregs->trap = TRAP_UNALI;
1534                     break;
1535               }
1536               if (ebase.simtime < sregs->ftime) {
1537                     if (sregs->frd == rd)
1538                         sregs->fhold += (sregs->ftime - ebase.simtime);
1539               }
1540               mexc = memory_write(asi, address, (uint32_t *)&sregs->fsi[rd], 2, &ws);
1541               sregs->hold += ws;
1542               if (mexc) {
1543                     sregs->trap = TRAP_DEXC;
1544               }
1545               break;
1546           case STDF:
1547               if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1548                     sregs->trap = TRAP_FPDIS;
1549                     break;
1550               }
1551               if (address & 0x7) {
1552                     sregs->trap = TRAP_UNALI;
1553                     break;
1554               }
1555               rd &= 0x1E;
1556               if (ebase.simtime < sregs->ftime) {
1557                     if ((sregs->frd == rd) || (sregs->frd + 1 == rd))
1558                         sregs->fhold += (sregs->ftime - ebase.simtime);
1559               }
1560               mexc = memory_write(asi, address, (uint32_t *)&sregs->fsi[rd], 3, &ws);
1561               sregs->hold += ws;
1562               sregs->icnt = T_STD;
1563 #ifdef STAT
1564               sregs->nstore++;          /* Double store counts twice */
1565 #endif
1566               if (mexc) {
1567                     sregs->trap = TRAP_DEXC;
1568               }
1569               break;
1570           case SWAPA:
1571               if (!chk_asi(sregs, &asi, op3)) break;
1572               ATTRIBUTE_FALLTHROUGH;
1573           case SWAP:
1574               if (address & 0x3) {
1575                     sregs->trap = TRAP_UNALI;
1576                     break;
1577               }
1578               mexc = memory_read(asi, address, &data, 2, &ws);
1579               sregs->hold += ws;
1580               if (mexc) {
1581                     sregs->trap = TRAP_DEXC;
1582                     break;
1583               }
1584               mexc = memory_write(asi, address, rdd, 2, &ws);
1585               sregs->hold += ws;
1586               sregs->icnt = T_LDST;
1587               if (mexc) {
1588                     sregs->trap = TRAP_DEXC;
1589                     break;
1590               } else
1591                     *rdd = data;
1592 #ifdef STAT
1593               sregs->nload++;
1594 #endif
1595               break;
1596 
1597 
1598           default:
1599               sregs->trap = TRAP_UNIMP;
1600               break;
1601           }
1602 
1603 #ifdef LOAD_DEL
1604 
1605           if (!(op3 & 4)) {
1606               sregs->ildtime = ebase.simtime + sregs->hold + sregs->icnt;
1607               sregs->ildreg = rd;
1608               if ((op3 | 0x10) == 0x13)
1609                     sregs->ildreg |= 1; /* Double load, odd register loaded
1610                                                    * last */
1611           }
1612 #endif
1613           break;
1614 
1615     default:
1616           sregs->trap = TRAP_UNIMP;
1617           break;
1618     }
1619     sregs->g[0] = 0;
1620     if (!sregs->trap) {
1621           sregs->pc = pc;
1622           sregs->npc = npc;
1623     }
1624     return 0;
1625 }
1626 
1627 #define T_FABSs               2
1628 #define T_FADDs               4
1629 #define T_FADDd               4
1630 #define T_FCMPs               4
1631 #define T_FCMPd               4
1632 #define T_FDIVs               20
1633 #define T_FDIVd               35
1634 #define T_FMOVs               2
1635 #define T_FMULs               5
1636 #define T_FMULd               9
1637 #define T_FNEGs               2
1638 #define T_FSQRTs    37
1639 #define T_FSQRTd    65
1640 #define T_FSUBs               4
1641 #define T_FSUBd               4
1642 #define T_FdTOi               7
1643 #define T_FdTOs               3
1644 #define T_FiTOs               6
1645 #define T_FiTOd               6
1646 #define T_FsTOi               6
1647 #define T_FsTOd               2
1648 
1649 #define FABSs       0x09
1650 #define FADDs       0x41
1651 #define FADDd       0x42
1652 #define FCMPs       0x51
1653 #define FCMPd       0x52
1654 #define FCMPEs      0x55
1655 #define FCMPEd      0x56
1656 #define FDIVs       0x4D
1657 #define FDIVd       0x4E
1658 #define FMOVs       0x01
1659 #define FMULs       0x49
1660 #define FMULd       0x4A
1661 #define FNEGs       0x05
1662 #define FSQRTs      0x29
1663 #define FSQRTd      0x2A
1664 #define FSUBs       0x45
1665 #define FSUBd       0x46
1666 #define FdTOi       0xD2
1667 #define FdTOs       0xC6
1668 #define FiTOs       0xC4
1669 #define FiTOd       0xC8
1670 #define FsTOi       0xD1
1671 #define FsTOd       0xC9
1672 
1673 
1674 static int
fpexec(uint32_t op3,uint32_t rd,uint32_t rs1,uint32_t rs2,struct pstate * sregs)1675 fpexec(uint32_t op3, uint32_t rd, uint32_t rs1, uint32_t rs2, struct pstate *sregs)
1676 {
1677     uint32_t          opf, tem, accex;
1678     int32_t           fcc;
1679     uint32_t          ldadj;
1680 
1681     if (sregs->fpstate == FP_EXC_MODE) {
1682           sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;
1683           sregs->fpstate = FP_EXC_PE;
1684           return 0;
1685     }
1686     if (sregs->fpstate == FP_EXC_PE) {
1687           sregs->fpstate = FP_EXC_MODE;
1688           return TRAP_FPEXC;
1689     }
1690     opf = (sregs->inst >> 5) & 0x1ff;
1691 
1692     /*
1693      * Check if we already have an FPop in the pipe. If so, halt until it is
1694      * finished by incrementing fhold with the remaining execution time
1695      */
1696 
1697     if (ebase.simtime < sregs->ftime) {
1698           sregs->fhold = (sregs->ftime - ebase.simtime);
1699     } else {
1700           sregs->fhold = 0;
1701 
1702           /* Check load dependencies. */
1703 
1704           if (ebase.simtime < sregs->ltime) {
1705 
1706               /* Don't check rs1 if single operand instructions */
1707 
1708               if (((opf >> 6) == 0) || ((opf >> 6) == 3))
1709                     rs1 = 32;
1710 
1711               /* Adjust for double floats */
1712 
1713               ldadj = opf & 1;
1714               if (!(((sregs->flrd - rs1) >> ldadj) && ((sregs->flrd - rs2) >> ldadj)))
1715                     sregs->fhold++;
1716           }
1717     }
1718 
1719     sregs->finst++;
1720 
1721     sregs->frs1 = rs1;                  /* Store src and dst for dependecy check */
1722     sregs->frs2 = rs2;
1723     sregs->frd = rd;
1724 
1725     sregs->ftime = ebase.simtime + sregs->hold + sregs->fhold;
1726 
1727     /* SPARC is big-endian - swap double floats if host is little-endian */
1728     /* This is ugly - I know ... */
1729 
1730     /* FIXME: should use (HOST_BYTE_ORDER == CURRENT_TARGET_BYTE_ORDER)
1731        but what about machines where float values are different endianness
1732        from integer values? */
1733 
1734 #ifdef HOST_LITTLE_ENDIAN
1735     rs1 &= 0x1f;
1736     switch (opf) {
1737           case FADDd:
1738           case FDIVd:
1739           case FMULd:
1740           case FSQRTd:
1741           case FSUBd:
1742         case FCMPd:
1743         case FCMPEd:
1744           case FdTOi:
1745           case FdTOs:
1746               sregs->fdp[rs1 | 1] = sregs->fs[rs1 & ~1];
1747               sregs->fdp[rs1 & ~1] = sregs->fs[rs1 | 1];
1748               sregs->fdp[rs2 | 1] = sregs->fs[rs2 & ~1];
1749               sregs->fdp[rs2 & ~1] = sregs->fs[rs2 | 1];
1750     default:
1751       break;
1752     }
1753 #endif
1754 
1755     clear_accex();
1756 
1757     switch (opf) {
1758     case FABSs:
1759           sregs->fs[rd] = fabs(sregs->fs[rs2]);
1760           sregs->ftime += T_FABSs;
1761           sregs->frs1 = 32;   /* rs1 ignored */
1762           break;
1763     case FADDs:
1764           sregs->fs[rd] = sregs->fs[rs1] + sregs->fs[rs2];
1765           sregs->ftime += T_FADDs;
1766           break;
1767     case FADDd:
1768           sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] + sregs->fd[rs2 >> 1];
1769           sregs->ftime += T_FADDd;
1770           break;
1771     case FCMPs:
1772     case FCMPEs:
1773           if (sregs->fs[rs1] == sregs->fs[rs2])
1774               fcc = 3;
1775           else if (sregs->fs[rs1] < sregs->fs[rs2])
1776               fcc = 2;
1777           else if (sregs->fs[rs1] > sregs->fs[rs2])
1778               fcc = 1;
1779           else
1780               fcc = 0;
1781           sregs->fsr |= 0x0C00;
1782           sregs->fsr &= ~(fcc << 10);
1783           sregs->ftime += T_FCMPs;
1784           sregs->frd = 32;    /* rd ignored */
1785           if ((fcc == 0) && (opf == FCMPEs)) {
1786               sregs->fpstate = FP_EXC_PE;
1787               sregs->fsr = (sregs->fsr & ~0x1C000) | (1 << 14);
1788           }
1789           break;
1790     case FCMPd:
1791     case FCMPEd:
1792           if (sregs->fd[rs1 >> 1] == sregs->fd[rs2 >> 1])
1793               fcc = 3;
1794           else if (sregs->fd[rs1 >> 1] < sregs->fd[rs2 >> 1])
1795               fcc = 2;
1796           else if (sregs->fd[rs1 >> 1] > sregs->fd[rs2 >> 1])
1797               fcc = 1;
1798           else
1799               fcc = 0;
1800           sregs->fsr |= 0x0C00;
1801           sregs->fsr &= ~(fcc << 10);
1802           sregs->ftime += T_FCMPd;
1803           sregs->frd = 32;    /* rd ignored */
1804           if ((fcc == 0) && (opf == FCMPEd)) {
1805               sregs->fpstate = FP_EXC_PE;
1806               sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1807           }
1808           break;
1809     case FDIVs:
1810           sregs->fs[rd] = sregs->fs[rs1] / sregs->fs[rs2];
1811           sregs->ftime += T_FDIVs;
1812           break;
1813     case FDIVd:
1814           sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] / sregs->fd[rs2 >> 1];
1815           sregs->ftime += T_FDIVd;
1816           break;
1817     case FMOVs:
1818           sregs->fs[rd] = sregs->fs[rs2];
1819           sregs->ftime += T_FMOVs;
1820           sregs->frs1 = 32;   /* rs1 ignored */
1821           break;
1822     case FMULs:
1823           sregs->fs[rd] = sregs->fs[rs1] * sregs->fs[rs2];
1824           sregs->ftime += T_FMULs;
1825           break;
1826     case FMULd:
1827           sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] * sregs->fd[rs2 >> 1];
1828           sregs->ftime += T_FMULd;
1829           break;
1830     case FNEGs:
1831           sregs->fs[rd] = -sregs->fs[rs2];
1832           sregs->ftime += T_FNEGs;
1833           sregs->frs1 = 32;   /* rs1 ignored */
1834           break;
1835     case FSQRTs:
1836           if (sregs->fs[rs2] < 0.0) {
1837               sregs->fpstate = FP_EXC_PE;
1838               sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1839               sregs->fsr = (sregs->fsr & 0x1f) | 0x10;
1840               break;
1841           }
1842           sregs->fs[rd] = sqrt(sregs->fs[rs2]);
1843           sregs->ftime += T_FSQRTs;
1844           sregs->frs1 = 32;   /* rs1 ignored */
1845           break;
1846     case FSQRTd:
1847           if (sregs->fd[rs2 >> 1] < 0.0) {
1848               sregs->fpstate = FP_EXC_PE;
1849               sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1850               sregs->fsr = (sregs->fsr & 0x1f) | 0x10;
1851               break;
1852           }
1853           sregs->fd[rd >> 1] = sqrt(sregs->fd[rs2 >> 1]);
1854           sregs->ftime += T_FSQRTd;
1855           sregs->frs1 = 32;   /* rs1 ignored */
1856           break;
1857     case FSUBs:
1858           sregs->fs[rd] = sregs->fs[rs1] - sregs->fs[rs2];
1859           sregs->ftime += T_FSUBs;
1860           break;
1861     case FSUBd:
1862           sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] - sregs->fd[rs2 >> 1];
1863           sregs->ftime += T_FSUBd;
1864           break;
1865     case FdTOi:
1866           sregs->fsi[rd] = (int) sregs->fd[rs2 >> 1];
1867           sregs->ftime += T_FdTOi;
1868           sregs->frs1 = 32;   /* rs1 ignored */
1869           break;
1870     case FdTOs:
1871           sregs->fs[rd] = (float32) sregs->fd[rs2 >> 1];
1872           sregs->ftime += T_FdTOs;
1873           sregs->frs1 = 32;   /* rs1 ignored */
1874           break;
1875     case FiTOs:
1876           sregs->fs[rd] = (float32) sregs->fsi[rs2];
1877           sregs->ftime += T_FiTOs;
1878           sregs->frs1 = 32;   /* rs1 ignored */
1879           break;
1880     case FiTOd:
1881           sregs->fd[rd >> 1] = (float64) sregs->fsi[rs2];
1882           sregs->ftime += T_FiTOd;
1883           sregs->frs1 = 32;   /* rs1 ignored */
1884           break;
1885     case FsTOi:
1886           sregs->fsi[rd] = (int) sregs->fs[rs2];
1887           sregs->ftime += T_FsTOi;
1888           sregs->frs1 = 32;   /* rs1 ignored */
1889           break;
1890     case FsTOd:
1891           sregs->fd[rd >> 1] = sregs->fs[rs2];
1892           sregs->ftime += T_FsTOd;
1893           sregs->frs1 = 32;   /* rs1 ignored */
1894           break;
1895 
1896     default:
1897           sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_UNIMP;
1898           sregs->fpstate = FP_EXC_PE;
1899     }
1900 
1901 #ifdef ERRINJ
1902     if (errftt) {
1903           sregs->fsr = (sregs->fsr & ~FSR_TT) | (errftt << 14);
1904           sregs->fpstate = FP_EXC_PE;
1905           if (sis_verbose) printf("Inserted fpu error %X\n",errftt);
1906           errftt = 0;
1907     }
1908 #endif
1909 
1910     accex = get_accex();
1911 
1912 #ifdef HOST_LITTLE_ENDIAN
1913     switch (opf) {
1914     case FADDd:
1915     case FDIVd:
1916     case FMULd:
1917     case FSQRTd:
1918     case FSUBd:
1919     case FiTOd:
1920     case FsTOd:
1921           sregs->fs[rd & ~1] = sregs->fdp[rd | 1];
1922           sregs->fs[rd | 1] = sregs->fdp[rd & ~1];
1923     default:
1924       break;
1925     }
1926 #endif
1927     if (sregs->fpstate == FP_EXC_PE) {
1928           sregs->fpq[0] = sregs->pc;
1929           sregs->fpq[1] = sregs->inst;
1930           sregs->fsr |= FSR_QNE;
1931     } else {
1932           tem = (sregs->fsr >> 23) & 0x1f;
1933           if (tem & accex) {
1934               sregs->fpstate = FP_EXC_PE;
1935               sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1936               sregs->fsr = ((sregs->fsr & ~0x1f) | accex);
1937           } else {
1938               sregs->fsr = ((((sregs->fsr >> 5) | accex) << 5) | accex);
1939           }
1940           if (sregs->fpstate == FP_EXC_PE) {
1941               sregs->fpq[0] = sregs->pc;
1942               sregs->fpq[1] = sregs->inst;
1943               sregs->fsr |= FSR_QNE;
1944           }
1945     }
1946     clear_accex();
1947 
1948     return 0;
1949 
1950 
1951 }
1952 
1953 static int
chk_asi(struct pstate * sregs,uint32_t * asi,uint32_t op3)1954 chk_asi(struct pstate *sregs, uint32_t *asi, uint32_t op3)
1955 {
1956     if (!(sregs->psr & PSR_S)) {
1957           sregs->trap = TRAP_PRIVI;
1958           return 0;
1959     } else if (sregs->inst & INST_I) {
1960           sregs->trap = TRAP_UNIMP;
1961           return 0;
1962     } else
1963           *asi = (sregs->inst >> 5) & 0x0ff;
1964     return 1;
1965 }
1966 
1967 int
execute_trap(struct pstate * sregs)1968 execute_trap(struct pstate *sregs)
1969 {
1970     int32_t           cwp;
1971 
1972     if (sregs->trap == 256) {
1973           sregs->pc = 0;
1974           sregs->npc = 4;
1975           sregs->trap = 0;
1976     } else if (sregs->trap == 257) {
1977               return ERROR;
1978     } else {
1979 
1980           if ((sregs->psr & PSR_ET) == 0)
1981               return ERROR;
1982 
1983           sregs->tbr = (sregs->tbr & 0xfffff000) | (sregs->trap << 4);
1984           sregs->trap = 0;
1985           sregs->psr &= ~PSR_ET;
1986           sregs->psr |= ((sregs->psr & PSR_S) >> 1);
1987           sregs->annul = 0;
1988           sregs->psr = (((sregs->psr & PSR_CWP) - 1) & 0x7) | (sregs->psr & ~PSR_CWP);
1989           cwp = ((sregs->psr & PSR_CWP) << 4);
1990           sregs->r[(cwp + 17) & 0x7f] = sregs->pc;
1991           sregs->r[(cwp + 18) & 0x7f] = sregs->npc;
1992           sregs->psr |= PSR_S;
1993           sregs->pc = sregs->tbr;
1994           sregs->npc = sregs->tbr + 4;
1995 
1996         if ( 0 != (1 & sregs->asr17) ) {
1997             /* single vector trapping! */
1998             sregs->pc = sregs->tbr & 0xfffff000;
1999             sregs->npc = sregs->pc + 4;
2000         }
2001 
2002           /* Increase simulator time */
2003           sregs->icnt = TRAP_C;
2004 
2005     }
2006 
2007 
2008     return 0;
2009 
2010 }
2011 
2012 extern struct irqcell irqarr[16];
2013 
2014 int
check_interrupts(struct pstate * sregs)2015 check_interrupts(struct pstate *sregs)
2016 {
2017 #ifdef ERRINJ
2018     if (errtt) {
2019           sregs->trap = errtt;
2020           if (sis_verbose) printf("Inserted error trap 0x%02X\n",errtt);
2021           errtt = 0;
2022     }
2023 #endif
2024 
2025     if ((ext_irl) && (sregs->psr & PSR_ET) &&
2026           ((ext_irl == 15) || (ext_irl > (int) ((sregs->psr & PSR_PIL) >> 8)))) {
2027           if (sregs->trap == 0) {
2028               sregs->trap = 16 + ext_irl;
2029               irqarr[ext_irl & 0x0f].callback(irqarr[ext_irl & 0x0f].arg);
2030               return 1;
2031           }
2032     }
2033     return 0;
2034 }
2035 
2036 void
init_regs(struct pstate * sregs)2037 init_regs(struct pstate *sregs)
2038 {
2039     sregs->pc = 0;
2040     sregs->npc = 4;
2041     sregs->trap = 0;
2042     sregs->psr &= 0x00f03fdf;
2043     sregs->psr |= 0x11000080; /* Set supervisor bit */
2044     sregs->breakpoint = 0;
2045     sregs->annul = 0;
2046     sregs->fpstate = FP_EXE_MODE;
2047     sregs->fpqn = 0;
2048     sregs->ftime = 0;
2049     sregs->ltime = 0;
2050     sregs->err_mode = 0;
2051     ext_irl = 0;
2052     sregs->g[0] = 0;
2053 #ifdef HOST_LITTLE_ENDIAN
2054     sregs->fdp = (float32 *) sregs->fd;
2055     sregs->fsi = (int32_t *) sregs->fs;
2056 #else
2057     sregs->fs = (float32 *) sregs->fd;
2058     sregs->fsi = (int32_t *) sregs->fd;
2059 #endif
2060     sregs->fsr = 0;
2061     sregs->fpu_pres = !nfp;
2062     set_fsr(sregs->fsr);
2063     sregs->bphit = 0;
2064     sregs->ildreg = 0;
2065     sregs->ildtime = 0;
2066 
2067     sregs->y = 0;
2068     sregs->asr17 = 0;
2069 
2070     sregs->rett_err = 0;
2071     sregs->jmpltime = 0;
2072 }
2073