arm: Support pac_key_* register operand for MRS/MSR in Armv8.1-M Mainline
[binutils-gdb.git] / sim / erc32 / exec.c
blobc84371f9dc272949948e239134cfa6707b11b5fc
1 /* This file is part of SIS (SPARC instruction simulator)
3 Copyright (C) 1995-2024 Free Software Foundation, Inc.
4 Contributed by Jiri Gaisler, European Space Agency
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.
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.
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/>. */
19 /* This must come before any other includes. */
20 #include "defs.h"
22 #include "sis.h"
23 #include <math.h>
24 #include <stdio.h>
26 extern int32_t sis_verbose, sparclite;
27 int ext_irl = 0;
29 /* Load/store interlock delay */
30 #define FLSTHOLD 1
32 /* Load delay (delete if unwanted - speeds up simulation) */
33 #define LOAD_DEL 1
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
43 #define FSR_QNE 0x2000
44 #define FP_EXE_MODE 0
45 #define FP_EXC_PE 1
46 #define FP_EXC_MODE 2
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
66 #define FCC_E 0
67 #define FCC_L 1
68 #define FCC_G 2
69 #define FCC_U 3
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
83 #define ICC_N (icc >> 3)
84 #define ICC_Z (icc >> 2)
85 #define ICC_V (icc >> 1)
86 #define ICC_C (icc)
88 #define FP_PRES (sregs->fpu_pres)
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
102 #define FSR_TT 0x1C000
103 #define FP_IEEE 0x04000
104 #define FP_UNIMP 0x0C000
105 #define FP_SEQ_ERR 0x10000
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
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
214 #define SIGN_BIT 0x80000000
216 /* # of cycles overhead when a trap is taken */
217 #define TRAP_C 3
219 /* Forward declarations */
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);
231 extern struct estate ebase;
232 extern int32_t nfp,ift;
234 #ifdef ERRINJ
235 extern uint32_t errtt, errftt;
236 #endif
238 static uint32_t
239 sub_cc(uint32_t psr, int32_t operand1, int32_t operand2, int32_t result)
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;
253 uint32_t
254 add_cc(uint32_t psr, int32_t operand1, int32_t operand2, int32_t result)
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;
268 static void
269 log_cc(int32_t result, struct pstate *sregs)
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;
277 /* Add two unsigned 32-bit integers, and calculate the carry out. */
279 static uint32_t
280 add32 (uint32_t n1, uint32_t n2, int *carry)
282 uint32_t result = n1 + n2;
284 *carry = result < n1 || result < n2;
285 return result;
288 /* Multiply two 32-bit integers. */
290 static void
291 mul64 (uint32_t n1, uint32_t n2, uint32_t *result_hi, uint32_t *result_lo, int msigned)
293 uint32_t lo, mid1, mid2, hi, reg_lo, reg_hi;
294 int carry;
295 int sign = 0;
297 /* If this is a signed multiply, calculate the sign of the result
298 and make the operands positive. */
299 if (msigned)
301 sign = (n1 ^ n2) & SIGN_BIT;
302 if (n1 & SIGN_BIT)
303 n1 = -n1;
304 if (n2 & SIGN_BIT)
305 n2 = -n2;
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));
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);
323 /* Negate result if necessary. */
324 if (sign)
326 reg_hi = ~ reg_hi;
327 reg_lo = - reg_lo;
328 if (reg_lo == 0)
329 reg_hi++;
332 *result_lo = reg_lo;
333 *result_hi = reg_hi;
337 /* Divide a 64-bit integer by a 32-bit integer. We cheat and assume
338 that the host compiler supports long long operations. */
340 static void
341 div64 (uint32_t n1_hi, uint32_t n1_low, uint32_t n2, uint32_t *result, int msigned)
343 uint64_t n1;
345 n1 = ((uint64_t) n1_hi) << 32;
346 n1 |= ((uint64_t) n1_low) & 0xffffffff;
348 if (msigned)
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;
355 else
356 n1 = n1 / n2;
358 *result = (uint32_t) (n1 & 0xffffffff);
362 static int
363 extract_short (uint32_t data, uint32_t address)
365 return ((data >> ((2 - (address & 2)) * 8)) & 0xffff);
368 static int
369 extract_short_signed (uint32_t data, uint32_t address)
371 uint32_t tmp = ((data >> ((2 - (address & 2)) * 8)) & 0xffff);
372 if (tmp & 0x8000)
373 tmp |= 0xffff0000;
374 return tmp;
377 static int
378 extract_byte (uint32_t data, uint32_t address)
380 return ((data >> ((3 - (address & 3)) * 8)) & 0xff);
383 static int
384 extract_byte_signed (uint32_t data, uint32_t address)
386 uint32_t tmp = ((data >> ((3 - (address & 3)) * 8)) & 0xff);
387 if (tmp & 0x80)
388 tmp |= 0xffffff00;
389 return tmp;
393 dispatch_instruction(struct pstate *sregs)
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];
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) {
413 op3 = (sregs->inst >> 19) & 0x3f;
414 rs1 = (sregs->inst >> 14) & 0x1f;
415 rd = (sregs->inst >> 25) & 0x1f;
417 #ifdef LOAD_DEL
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++;
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];
449 #endif
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];
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;
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;
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;
547 if (ebase.simtime < sregs->ftime) {
548 sregs->ftime = ebase.simtime + sregs->hold;
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;
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;
612 break;
614 default:
615 sregs->trap = TRAP_UNIMP;
616 break;
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;
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);
636 } else {
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;
692 if (eicc & 1) {
693 sregs->trap = (0x80 | ((rs1 + operand2) & 0x7f));
695 break;
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:
709 int sign;
710 uint32_t uresult, remainder;
711 int c0, y31;
713 if (!sparclite) {
714 sregs->trap = TRAP_UNIMP;
715 break;
718 sign = ((sregs->psr & PSR_V) != 0) ^ ((sregs->psr & PSR_N) != 0);
720 remainder = (sregs->y << 1) | (rs1 >> 31);
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;
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;
738 if (uresult & 0x80000000)
739 sregs->psr |= PSR_N;
740 else
741 sregs->psr &= ~PSR_N;
743 y31 = (sregs->y & 0x80000000) == 0x80000000;
745 if (uresult == 0 && sign == y31)
746 sregs->psr |= PSR_Z;
747 else
748 sregs->psr &= ~PSR_Z;
750 sign = (sign && !y31) || (!c0 && (sign || !y31));
752 if (sign ^ (uresult >> 31))
753 sregs->psr |= PSR_V;
754 else
755 sregs->psr &= ~PSR_V;
757 if (!sign)
758 sregs->psr |= PSR_C;
759 else
760 sregs->psr &= ~PSR_C;
762 sregs->y = uresult;
764 if (rd != 0)
765 *rdd = (rs1 << 1) | !sign;
767 break;
768 case SMUL:
770 mul64 (rs1, operand2, &sregs->y, rdd, 1);
772 break;
773 case SMULCC:
775 uint32_t uresult;
777 mul64 (rs1, operand2, &sregs->y, &uresult, 1);
779 if (uresult & 0x80000000)
780 sregs->psr |= PSR_N;
781 else
782 sregs->psr &= ~PSR_N;
784 if (uresult == 0)
785 sregs->psr |= PSR_Z;
786 else
787 sregs->psr &= ~PSR_Z;
789 *rdd = uresult;
791 break;
792 case UMUL:
794 mul64 (rs1, operand2, &sregs->y, rdd, 0);
796 break;
797 case UMULCC:
799 uint32_t uresult;
801 mul64 (rs1, operand2, &sregs->y, &uresult, 0);
803 if (uresult & 0x80000000)
804 sregs->psr |= PSR_N;
805 else
806 sregs->psr &= ~PSR_N;
808 if (uresult == 0)
809 sregs->psr |= PSR_Z;
810 else
811 sregs->psr &= ~PSR_Z;
813 *rdd = uresult;
815 break;
816 case SDIV:
818 if (sparclite) {
819 sregs->trap = TRAP_UNIMP;
820 break;
823 if (operand2 == 0) {
824 sregs->trap = TRAP_DIV0;
825 break;
828 div64 (sregs->y, rs1, operand2, rdd, 1);
830 break;
831 case SDIVCC:
833 uint32_t uresult;
835 if (sparclite) {
836 sregs->trap = TRAP_UNIMP;
837 break;
840 if (operand2 == 0) {
841 sregs->trap = TRAP_DIV0;
842 break;
845 div64 (sregs->y, rs1, operand2, &uresult, 1);
847 if (uresult & 0x80000000)
848 sregs->psr |= PSR_N;
849 else
850 sregs->psr &= ~PSR_N;
852 if (uresult == 0)
853 sregs->psr |= PSR_Z;
854 else
855 sregs->psr &= ~PSR_Z;
857 /* FIXME: should set overflow flag correctly. */
858 sregs->psr &= ~(PSR_C | PSR_V);
860 *rdd = uresult;
862 break;
863 case UDIV:
865 if (sparclite) {
866 sregs->trap = TRAP_UNIMP;
867 break;
870 if (operand2 == 0) {
871 sregs->trap = TRAP_DIV0;
872 break;
875 div64 (sregs->y, rs1, operand2, rdd, 0);
877 break;
878 case UDIVCC:
880 uint32_t uresult;
882 if (sparclite) {
883 sregs->trap = TRAP_UNIMP;
884 break;
887 if (operand2 == 0) {
888 sregs->trap = TRAP_DIV0;
889 break;
892 div64 (sregs->y, rs1, operand2, &uresult, 0);
894 if (uresult & 0x80000000)
895 sregs->psr |= PSR_N;
896 else
897 sregs->psr &= ~PSR_N;
899 if (uresult == 0)
900 sregs->psr |= PSR_Z;
901 else
902 sregs->psr &= ~PSR_Z;
904 /* FIXME: should set overflow flag correctly. */
905 sregs->psr &= ~(PSR_C | PSR_V);
907 *rdd = uresult;
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;
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)
1010 sregs->trap = TRAP_TAG;
1012 else
1014 sregs->psr = (sregs->psr & ~PSR_CC) | result;
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;
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:
1042 new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;
1043 if (sregs->wim & (1 << new_cwp)) {
1044 sregs->trap = TRAP_WUFL;
1045 break;
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;
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;
1073 break;
1074 case RDWIM:
1075 if (!(sregs->psr & PSR_S)) {
1076 sregs->trap = TRAP_PRIVI;
1077 break;
1079 *rdd = sregs->wim;
1080 break;
1081 case RDTBR:
1082 if (!(sregs->psr & PSR_S)) {
1083 sregs->trap = TRAP_PRIVI;
1084 break;
1086 *rdd = sregs->tbr;
1087 break;
1088 case WRPSR:
1089 if ((sregs->psr & 0x1f) > 7) {
1090 sregs->trap = TRAP_UNIMP;
1091 break;
1093 if (!(sregs->psr & PSR_S)) {
1094 sregs->trap = TRAP_PRIVI;
1095 break;
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;
1105 sregs->wim = (rs1 ^ operand2) & 0x0ff;
1106 break;
1107 case WRTBR:
1108 if (!(sregs->psr & PSR_S)) {
1109 sregs->trap = TRAP_PRIVI;
1110 break;
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;
1128 break;
1129 case JMPL:
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;
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;
1150 if (!(sregs->psr & PSR_S)) {
1151 sregs->trap = TRAP_PRIVI;
1152 break;
1154 if (sregs->wim & (1 << new_cwp)) {
1155 sregs->trap = TRAP_WUFL;
1156 break;
1158 if (address & 0x3) {
1159 sregs->trap = TRAP_UNALI;
1160 break;
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;
1168 case SCAN:
1170 uint32_t uresult, mask;
1171 int i;
1173 if (!sparclite) {
1174 sregs->trap = TRAP_UNIMP;
1175 break;
1177 mask = (operand2 & 0x80000000) | (operand2 >> 1);
1178 uresult = rs1 ^ mask;
1180 for (i = 0; i < 32; i++) {
1181 if (uresult & 0x80000000)
1182 break;
1183 uresult <<= 1;
1186 *rdd = i == 32 ? 63 : i;
1188 break;
1190 default:
1191 sregs->trap = TRAP_UNIMP;
1192 break;
1195 break;
1196 case 3: /* Load/store instructions */
1198 address = rs1 + operand2;
1200 if (sregs->psr & PSR_S)
1201 asi = 11;
1202 else
1203 asi = 10;
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
1217 /* Decode load/store instructions */
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;
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]);
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
1249 break;
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;
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;
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;
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;
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;
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;
1318 mexc = memory_read(asi, address, &data, 1, &ws);
1319 sregs->hold += ws;
1320 if (mexc) {
1321 sregs->trap = TRAP_DEXC;
1322 break;
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;
1335 if (address & 0x3) {
1336 sregs->trap = TRAP_UNALI;
1337 break;
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);
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]));
1354 break;
1355 case LDDF:
1356 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1357 sregs->trap = TRAP_FPDIS;
1358 break;
1360 if (address & 0x7) {
1361 sregs->trap = TRAP_UNALI;
1362 break;
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);
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;
1389 break;
1390 case LDFSR:
1391 if (ebase.simtime < sregs->ftime) {
1392 sregs->fhold += (sregs->ftime - ebase.simtime);
1394 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1395 sregs->trap = TRAP_FPDIS;
1396 break;
1398 if (address & 0x3) {
1399 sregs->trap = TRAP_UNALI;
1400 break;
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);
1411 break;
1412 case STFSR:
1413 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1414 sregs->trap = TRAP_FPDIS;
1415 break;
1417 if (address & 0x3) {
1418 sregs->trap = TRAP_UNALI;
1419 break;
1421 if (ebase.simtime < sregs->ftime) {
1422 sregs->fhold += (sregs->ftime - ebase.simtime);
1424 mexc = memory_write(asi, address, &sregs->fsr, 2, &ws);
1425 sregs->hold += ws;
1426 if (mexc) {
1427 sregs->trap = TRAP_DEXC;
1429 break;
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;
1439 mexc = memory_write(asi, address, rdd, 2, &ws);
1440 sregs->hold += ws;
1441 if (mexc) {
1442 sregs->trap = TRAP_DEXC;
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;
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;
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]);
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;
1480 break;
1481 case STDFQ:
1482 if ((sregs->psr & 0x1f) > 7) {
1483 sregs->trap = TRAP_UNIMP;
1484 break;
1486 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1487 sregs->trap = TRAP_FPDIS;
1488 break;
1490 if (address & 0x7) {
1491 sregs->trap = TRAP_UNALI;
1492 break;
1494 if (!(sregs->fsr & FSR_QNE)) {
1495 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;
1496 break;
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;
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;
1521 mexc = memory_write(asi, address, rdd, 1, &ws);
1522 sregs->hold += ws;
1523 if (mexc) {
1524 sregs->trap = TRAP_DEXC;
1526 break;
1527 case STF:
1528 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1529 sregs->trap = TRAP_FPDIS;
1530 break;
1532 if (address & 0x3) {
1533 sregs->trap = TRAP_UNALI;
1534 break;
1536 if (ebase.simtime < sregs->ftime) {
1537 if (sregs->frd == rd)
1538 sregs->fhold += (sregs->ftime - ebase.simtime);
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;
1545 break;
1546 case STDF:
1547 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1548 sregs->trap = TRAP_FPDIS;
1549 break;
1551 if (address & 0x7) {
1552 sregs->trap = TRAP_UNALI;
1553 break;
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);
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;
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;
1578 mexc = memory_read(asi, address, &data, 2, &ws);
1579 sregs->hold += ws;
1580 if (mexc) {
1581 sregs->trap = TRAP_DEXC;
1582 break;
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;
1598 default:
1599 sregs->trap = TRAP_UNIMP;
1600 break;
1603 #ifdef LOAD_DEL
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 */
1612 #endif
1613 break;
1615 default:
1616 sregs->trap = TRAP_UNIMP;
1617 break;
1619 sregs->g[0] = 0;
1620 if (!sregs->trap) {
1621 sregs->pc = pc;
1622 sregs->npc = npc;
1624 return 0;
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
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
1674 static int
1675 fpexec(uint32_t op3, uint32_t rd, uint32_t rs1, uint32_t rs2, struct pstate *sregs)
1677 uint32_t opf, tem, accex;
1678 int32_t fcc;
1679 uint32_t ldadj;
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;
1686 if (sregs->fpstate == FP_EXC_PE) {
1687 sregs->fpstate = FP_EXC_MODE;
1688 return TRAP_FPEXC;
1690 opf = (sregs->inst >> 5) & 0x1ff;
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
1697 if (ebase.simtime < sregs->ftime) {
1698 sregs->fhold = (sregs->ftime - ebase.simtime);
1699 } else {
1700 sregs->fhold = 0;
1702 /* Check load dependencies. */
1704 if (ebase.simtime < sregs->ltime) {
1706 /* Don't check rs1 if single operand instructions */
1708 if (((opf >> 6) == 0) || ((opf >> 6) == 3))
1709 rs1 = 32;
1711 /* Adjust for double floats */
1713 ldadj = opf & 1;
1714 if (!(((sregs->flrd - rs1) >> ldadj) && ((sregs->flrd - rs2) >> ldadj)))
1715 sregs->fhold++;
1719 sregs->finst++;
1721 sregs->frs1 = rs1; /* Store src and dst for dependecy check */
1722 sregs->frs2 = rs2;
1723 sregs->frd = rd;
1725 sregs->ftime = ebase.simtime + sregs->hold + sregs->fhold;
1727 /* SPARC is big-endian - swap double floats if host is little-endian */
1728 /* This is ugly - I know ... */
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? */
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;
1753 #endif
1755 clear_accex();
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);
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;
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;
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;
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;
1896 default:
1897 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_UNIMP;
1898 sregs->fpstate = FP_EXC_PE;
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;
1908 #endif
1910 accex = get_accex();
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;
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);
1940 if (sregs->fpstate == FP_EXC_PE) {
1941 sregs->fpq[0] = sregs->pc;
1942 sregs->fpq[1] = sregs->inst;
1943 sregs->fsr |= FSR_QNE;
1946 clear_accex();
1948 return 0;
1953 static int
1954 chk_asi(struct pstate *sregs, uint32_t *asi, uint32_t op3)
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;
1968 execute_trap(struct pstate *sregs)
1970 int32_t cwp;
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 {
1980 if ((sregs->psr & PSR_ET) == 0)
1981 return ERROR;
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;
1996 if ( 0 != (1 & sregs->asr17) ) {
1997 /* single vector trapping! */
1998 sregs->pc = sregs->tbr & 0xfffff000;
1999 sregs->npc = sregs->pc + 4;
2002 /* Increase simulator time */
2003 sregs->icnt = TRAP_C;
2008 return 0;
2012 extern struct irqcell irqarr[16];
2015 check_interrupts(struct pstate *sregs)
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;
2023 #endif
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;
2033 return 0;
2036 void
2037 init_regs(struct pstate *sregs)
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;
2067 sregs->y = 0;
2068 sregs->asr17 = 0;
2070 sregs->rett_err = 0;
2071 sregs->jmpltime = 0;