]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/erc32/exec.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / sim / erc32 / exec.c
CommitLineData
296730a5
MF
1/* This file is part of SIS (SPARC instruction simulator)
2
213516ef 3 Copyright (C) 1995-2023 Free Software Foundation, Inc.
296730a5 4 Contributed by Jiri Gaisler, European Space Agency
17d88f73
JB
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/>. */
c906108c 18
6df01ab8
MF
19/* This must come before any other includes. */
20#include "defs.h"
21
c906108c 22#include "sis.h"
c906108c
SS
23#include <math.h>
24#include <stdio.h>
25
4a92dedc 26extern int32_t sis_verbose, sparclite;
c906108c
SS
27int 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
4a92dedc
MF
221static uint32_t sub_cc (uint32_t psr, int32_t operand1, int32_t operand2,
222 int32_t result);
223static uint32_t add_cc (uint32_t psr, int32_t operand1, int32_t operand2,
224 int32_t result);
225static void log_cc (int32_t result, struct pstate *sregs);
226static int fpexec (uint32_t op3, uint32_t rd, uint32_t rs1, uint32_t rs2,
bdca5ee4 227 struct pstate *sregs);
4a92dedc 228static int chk_asi (struct pstate *sregs, uint32_t *asi, uint32_t op3);
c906108c
SS
229
230
231extern struct estate ebase;
4a92dedc 232extern int32_t nfp,ift;
c906108c
SS
233
234#ifdef ERRINJ
4a92dedc 235extern uint32_t errtt, errftt;
c906108c
SS
236#endif
237
4a92dedc
MF
238static uint32_t
239sub_cc(uint32_t psr, int32_t operand1, int32_t operand2, int32_t result)
c906108c
SS
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);
5831e29b 250 return psr;
c906108c
SS
251}
252
4a92dedc
MF
253uint32_t
254add_cc(uint32_t psr, int32_t operand1, int32_t operand2, int32_t result)
c906108c
SS
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);
5831e29b 265 return psr;
c906108c
SS
266}
267
268static void
4a92dedc 269log_cc(int32_t result, struct pstate *sregs)
c906108c
SS
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
4a92dedc
MF
279static uint32_t
280add32 (uint32_t n1, uint32_t n2, int *carry)
c906108c 281{
4a92dedc 282 uint32_t result = n1 + n2;
c906108c 283
de7669bf 284 *carry = result < n1 || result < n2;
5831e29b 285 return result;
c906108c
SS
286}
287
288/* Multiply two 32-bit integers. */
289
290static void
4a92dedc 291mul64 (uint32_t n1, uint32_t n2, uint32_t *result_hi, uint32_t *result_lo, int msigned)
c906108c 292{
4a92dedc 293 uint32_t lo, mid1, mid2, hi, reg_lo, reg_hi;
c906108c
SS
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
340static void
4a92dedc 341div64 (uint32_t n1_hi, uint32_t n1_low, uint32_t n2, uint32_t *result, int msigned)
c906108c 342{
4a92dedc 343 uint64_t n1;
c906108c 344
4a92dedc
MF
345 n1 = ((uint64_t) n1_hi) << 32;
346 n1 |= ((uint64_t) n1_low) & 0xffffffff;
c906108c
SS
347
348 if (msigned)
349 {
4a92dedc
MF
350 int64_t n1_s = (int64_t) n1;
351 int32_t n2_s = (int32_t) n2;
c906108c 352 n1_s = n1_s / n2_s;
4a92dedc 353 n1 = (uint64_t) n1_s;
c906108c
SS
354 }
355 else
356 n1 = n1 / n2;
357
4a92dedc 358 *result = (uint32_t) (n1 & 0xffffffff);
c906108c
SS
359}
360
361
d3e9b40a 362static int
4a92dedc 363extract_short (uint32_t data, uint32_t address)
d3e9b40a
JG
364{
365 return ((data >> ((2 - (address & 2)) * 8)) & 0xffff);
366}
367
368static int
4a92dedc 369extract_short_signed (uint32_t data, uint32_t address)
d3e9b40a 370{
4a92dedc 371 uint32_t tmp = ((data >> ((2 - (address & 2)) * 8)) & 0xffff);
d3e9b40a
JG
372 if (tmp & 0x8000)
373 tmp |= 0xffff0000;
374 return tmp;
375}
376
377static int
4a92dedc 378extract_byte (uint32_t data, uint32_t address)
d3e9b40a
JG
379{
380 return ((data >> ((3 - (address & 3)) * 8)) & 0xff);
381}
382
383static int
4a92dedc 384extract_byte_signed (uint32_t data, uint32_t address)
d3e9b40a 385{
4a92dedc 386 uint32_t tmp = ((data >> ((3 - (address & 3)) * 8)) & 0xff);
d3e9b40a
JG
387 if (tmp & 0x80)
388 tmp |= 0xffffff00;
389 return tmp;
390}
391
c906108c 392int
81e6e8ae 393dispatch_instruction(struct pstate *sregs)
c906108c
SS
394{
395
4a92dedc 396 uint32_t cwp, op, op2, op3, asi, rd, cond, rs1,
c906108c 397 rs2;
4a92dedc
MF
398 uint32_t ldep, icc, data, *rdd;
399 int32_t operand1, operand2, result, eicc,
c906108c 400 new_cwp;
4a92dedc
MF
401 int32_t pc, npc, address, ws, mexc, fcc;
402 uint32_t ddata[2];
c906108c
SS
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;
4a92dedc 710 uint32_t result, remainder;
c906108c
SS
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 result = 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. */
4a92dedc
MF
736 c0 = result < (uint32_t) remainder
737 || result < (uint32_t) operand2;
c906108c
SS
738
739 if (result & 0x80000000)
740 sregs->psr |= PSR_N;
741 else
742 sregs->psr &= ~PSR_N;
743
744 y31 = (sregs->y & 0x80000000) == 0x80000000;
745
746 if (result == 0 && sign == y31)
747 sregs->psr |= PSR_Z;
748 else
749 sregs->psr &= ~PSR_Z;
750
751 sign = (sign && !y31) || (!c0 && (sign || !y31));
752
753 if (sign ^ (result >> 31))
754 sregs->psr |= PSR_V;
755 else
756 sregs->psr &= ~PSR_V;
757
758 if (!sign)
759 sregs->psr |= PSR_C;
760 else
761 sregs->psr &= ~PSR_C;
762
763 sregs->y = result;
764
765 if (rd != 0)
766 *rdd = (rs1 << 1) | !sign;
767 }
768 break;
769 case SMUL:
770 {
771 mul64 (rs1, operand2, &sregs->y, rdd, 1);
772 }
773 break;
774 case SMULCC:
775 {
4a92dedc 776 uint32_t result;
c906108c
SS
777
778 mul64 (rs1, operand2, &sregs->y, &result, 1);
779
780 if (result & 0x80000000)
781 sregs->psr |= PSR_N;
782 else
783 sregs->psr &= ~PSR_N;
784
785 if (result == 0)
786 sregs->psr |= PSR_Z;
787 else
788 sregs->psr &= ~PSR_Z;
789
790 *rdd = result;
791 }
792 break;
793 case UMUL:
794 {
795 mul64 (rs1, operand2, &sregs->y, rdd, 0);
796 }
797 break;
798 case UMULCC:
799 {
4a92dedc 800 uint32_t result;
c906108c
SS
801
802 mul64 (rs1, operand2, &sregs->y, &result, 0);
803
804 if (result & 0x80000000)
805 sregs->psr |= PSR_N;
806 else
807 sregs->psr &= ~PSR_N;
808
809 if (result == 0)
810 sregs->psr |= PSR_Z;
811 else
812 sregs->psr &= ~PSR_Z;
813
814 *rdd = result;
815 }
816 break;
817 case SDIV:
818 {
819 if (sparclite) {
820 sregs->trap = TRAP_UNIMP;
821 break;
822 }
823
824 if (operand2 == 0) {
825 sregs->trap = TRAP_DIV0;
826 break;
827 }
828
829 div64 (sregs->y, rs1, operand2, rdd, 1);
830 }
831 break;
832 case SDIVCC:
833 {
4a92dedc 834 uint32_t result;
c906108c
SS
835
836 if (sparclite) {
837 sregs->trap = TRAP_UNIMP;
838 break;
839 }
840
841 if (operand2 == 0) {
842 sregs->trap = TRAP_DIV0;
843 break;
844 }
845
846 div64 (sregs->y, rs1, operand2, &result, 1);
847
848 if (result & 0x80000000)
849 sregs->psr |= PSR_N;
850 else
851 sregs->psr &= ~PSR_N;
852
853 if (result == 0)
854 sregs->psr |= PSR_Z;
855 else
856 sregs->psr &= ~PSR_Z;
857
858 /* FIXME: should set overflow flag correctly. */
859 sregs->psr &= ~(PSR_C | PSR_V);
860
861 *rdd = result;
862 }
863 break;
864 case UDIV:
865 {
866 if (sparclite) {
867 sregs->trap = TRAP_UNIMP;
868 break;
869 }
870
871 if (operand2 == 0) {
872 sregs->trap = TRAP_DIV0;
873 break;
874 }
875
876 div64 (sregs->y, rs1, operand2, rdd, 0);
877 }
878 break;
879 case UDIVCC:
880 {
4a92dedc 881 uint32_t result;
c906108c
SS
882
883 if (sparclite) {
884 sregs->trap = TRAP_UNIMP;
885 break;
886 }
887
888 if (operand2 == 0) {
889 sregs->trap = TRAP_DIV0;
890 break;
891 }
892
893 div64 (sregs->y, rs1, operand2, &result, 0);
894
895 if (result & 0x80000000)
896 sregs->psr |= PSR_N;
897 else
898 sregs->psr &= ~PSR_N;
899
900 if (result == 0)
901 sregs->psr |= PSR_Z;
902 else
903 sregs->psr &= ~PSR_Z;
904
905 /* FIXME: should set overflow flag correctly. */
906 sregs->psr &= ~(PSR_C | PSR_V);
907
908 *rdd = result;
909 }
910 break;
911 case IXNOR:
912 *rdd = rs1 ^ ~operand2;
913 break;
914 case IXNORCC:
915 *rdd = rs1 ^ ~operand2;
916 log_cc(*rdd, sregs);
917 break;
918 case IXOR:
919 *rdd = rs1 ^ operand2;
920 break;
921 case IXORCC:
922 *rdd = rs1 ^ operand2;
923 log_cc(*rdd, sregs);
924 break;
925 case IOR:
926 *rdd = rs1 | operand2;
927 break;
928 case IORCC:
929 *rdd = rs1 | operand2;
930 log_cc(*rdd, sregs);
931 break;
932 case IORN:
933 *rdd = rs1 | ~operand2;
934 break;
935 case IORNCC:
936 *rdd = rs1 | ~operand2;
937 log_cc(*rdd, sregs);
938 break;
939 case IANDNCC:
940 *rdd = rs1 & ~operand2;
941 log_cc(*rdd, sregs);
942 break;
943 case IANDN:
944 *rdd = rs1 & ~operand2;
945 break;
946 case IAND:
947 *rdd = rs1 & operand2;
948 break;
949 case IANDCC:
950 *rdd = rs1 & operand2;
951 log_cc(*rdd, sregs);
952 break;
953 case SUB:
954 *rdd = rs1 - operand2;
955 break;
956 case SUBCC:
957 *rdd = rs1 - operand2;
958 sregs->psr = sub_cc(sregs->psr, rs1, operand2, *rdd);
959 break;
960 case SUBX:
961 *rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);
962 break;
963 case SUBXCC:
964 *rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);
965 sregs->psr = sub_cc(sregs->psr, rs1, operand2, *rdd);
966 break;
967 case ADD:
968 *rdd = rs1 + operand2;
969 break;
970 case ADDCC:
971 *rdd = rs1 + operand2;
972 sregs->psr = add_cc(sregs->psr, rs1, operand2, *rdd);
973 break;
974 case ADDX:
975 *rdd = rs1 + operand2 + ((sregs->psr >> 20) & 1);
976 break;
977 case ADDXCC:
978 *rdd = rs1 + operand2 + ((sregs->psr >> 20) & 1);
979 sregs->psr = add_cc(sregs->psr, rs1, operand2, *rdd);
980 break;
981 case TADDCC:
982 *rdd = rs1 + operand2;
983 sregs->psr = add_cc(sregs->psr, rs1, operand2, *rdd);
984 if ((rs1 | operand2) & 0x3)
985 sregs->psr |= PSR_V;
986 break;
987 case TSUBCC:
988 *rdd = rs1 - operand2;
989 sregs->psr = sub_cc (sregs->psr, rs1, operand2, *rdd);
990 if ((rs1 | operand2) & 0x3)
991 sregs->psr |= PSR_V;
992 break;
993 case TADDCCTV:
994 *rdd = rs1 + operand2;
995 result = add_cc(0, rs1, operand2, *rdd);
996 if ((rs1 | operand2) & 0x3)
997 result |= PSR_V;
998 if (result & PSR_V) {
999 sregs->trap = TRAP_TAG;
1000 } else {
1001 sregs->psr = (sregs->psr & ~PSR_CC) | result;
1002 }
1003 break;
1004 case TSUBCCTV:
1005 *rdd = rs1 - operand2;
1006 result = add_cc (0, rs1, operand2, *rdd);
1007 if ((rs1 | operand2) & 0x3)
1008 result |= PSR_V;
1009 if (result & PSR_V)
1010 {
1011 sregs->trap = TRAP_TAG;
1012 }
1013 else
1014 {
1015 sregs->psr = (sregs->psr & ~PSR_CC) | result;
1016 }
1017 break;
1018 case SLL:
1019 *rdd = rs1 << (operand2 & 0x1f);
1020 break;
1021 case SRL:
1022 *rdd = rs1 >> (operand2 & 0x1f);
1023 break;
1024 case SRA:
1025 *rdd = ((int) rs1) >> (operand2 & 0x1f);
1026 break;
1027 case FLUSH:
1028 if (ift) sregs->trap = TRAP_UNIMP;
1029 break;
1030 case SAVE:
1031 new_cwp = ((sregs->psr & PSR_CWP) - 1) & PSR_CWP;
1032 if (sregs->wim & (1 << new_cwp)) {
1033 sregs->trap = TRAP_WOFL;
1034 break;
1035 }
1036 if (rd > 7)
1037 rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);
1038 *rdd = rs1 + operand2;
1039 sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;
1040 break;
1041 case RESTORE:
1042
1043 new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;
1044 if (sregs->wim & (1 << new_cwp)) {
1045 sregs->trap = TRAP_WUFL;
1046 break;
1047 }
1048 if (rd > 7)
1049 rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);
1050 *rdd = rs1 + operand2;
1051 sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;
1052 break;
1053 case RDPSR:
1054 if (!(sregs->psr & PSR_S)) {
1055 sregs->trap = TRAP_PRIVI;
1056 break;
1057 }
1058 *rdd = sregs->psr;
1059 break;
1060 case RDY:
1061 if (!sparclite)
1062 *rdd = sregs->y;
1063 else {
1064 int rs1_is_asr = (sregs->inst >> 14) & 0x1f;
1065 if ( 0 == rs1_is_asr )
1066 *rdd = sregs->y;
1067 else if ( 17 == rs1_is_asr )
1068 *rdd = sregs->asr17;
1069 else {
1070 sregs->trap = TRAP_UNIMP;
1071 break;
1072 }
1073 }
1074 break;
1075 case RDWIM:
1076 if (!(sregs->psr & PSR_S)) {
1077 sregs->trap = TRAP_PRIVI;
1078 break;
1079 }
1080 *rdd = sregs->wim;
1081 break;
1082 case RDTBR:
1083 if (!(sregs->psr & PSR_S)) {
1084 sregs->trap = TRAP_PRIVI;
1085 break;
1086 }
1087 *rdd = sregs->tbr;
1088 break;
1089 case WRPSR:
1090 if ((sregs->psr & 0x1f) > 7) {
1091 sregs->trap = TRAP_UNIMP;
1092 break;
1093 }
1094 if (!(sregs->psr & PSR_S)) {
1095 sregs->trap = TRAP_PRIVI;
1096 break;
1097 }
d3e9b40a 1098 sregs->psr = (sregs->psr & 0xff000000) |
4ab6404b 1099 ((rs1 ^ operand2) & 0x00f03fff);
c906108c
SS
1100 break;
1101 case WRWIM:
1102 if (!(sregs->psr & PSR_S)) {
1103 sregs->trap = TRAP_PRIVI;
1104 break;
1105 }
1106 sregs->wim = (rs1 ^ operand2) & 0x0ff;
1107 break;
1108 case WRTBR:
1109 if (!(sregs->psr & PSR_S)) {
1110 sregs->trap = TRAP_PRIVI;
1111 break;
1112 }
1113 sregs->tbr = (sregs->tbr & 0x00000ff0) |
1114 ((rs1 ^ operand2) & 0xfffff000);
1115 break;
1116 case WRY:
1117 if (!sparclite)
1118 sregs->y = (rs1 ^ operand2);
1119 else {
1120 if ( 0 == rd )
1121 sregs->y = (rs1 ^ operand2);
1122 else if ( 17 == rd )
1123 sregs->asr17 = (rs1 ^ operand2);
1124 else {
1125 sregs->trap = TRAP_UNIMP;
1126 break;
1127 }
1128 }
1129 break;
1130 case JMPL:
1131
1132#ifdef STAT
1133 sregs->nbranch++;
1134#endif
1135 sregs->icnt = T_JMPL; /* JMPL takes two cycles */
1136 if (rs1 & 0x3) {
1137 sregs->trap = TRAP_UNALI;
1138 break;
1139 }
1140 *rdd = sregs->pc;
1141 npc = rs1 + operand2;
1142 break;
1143 case RETT:
1144 address = rs1 + operand2;
1145 new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;
1146 sregs->icnt = T_RETT; /* RETT takes two cycles */
1147 if (sregs->psr & PSR_ET) {
1148 sregs->trap = TRAP_UNIMP;
1149 break;
1150 }
1151 if (!(sregs->psr & PSR_S)) {
1152 sregs->trap = TRAP_PRIVI;
1153 break;
1154 }
1155 if (sregs->wim & (1 << new_cwp)) {
1156 sregs->trap = TRAP_WUFL;
1157 break;
1158 }
1159 if (address & 0x3) {
1160 sregs->trap = TRAP_UNALI;
1161 break;
1162 }
1163 sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp | PSR_ET;
1164 sregs->psr =
1165 (sregs->psr & ~PSR_S) | ((sregs->psr & PSR_PS) << 1);
1166 npc = address;
1167 break;
1168
1169 case SCAN:
1170 {
4a92dedc 1171 uint32_t result, mask;
c906108c
SS
1172 int i;
1173
1174 if (!sparclite) {
1175 sregs->trap = TRAP_UNIMP;
1176 break;
1177 }
1178 mask = (operand2 & 0x80000000) | (operand2 >> 1);
1179 result = rs1 ^ mask;
1180
1181 for (i = 0; i < 32; i++) {
1182 if (result & 0x80000000)
1183 break;
1184 result <<= 1;
1185 }
1186
1187 *rdd = i == 32 ? 63 : i;
1188 }
1189 break;
1190
1191 default:
1192 sregs->trap = TRAP_UNIMP;
1193 break;
1194 }
1195 }
1196 break;
1197 case 3: /* Load/store instructions */
1198
1199 address = rs1 + operand2;
1200
1201 if (sregs->psr & PSR_S)
1202 asi = 11;
1203 else
1204 asi = 10;
1205
1206 if (op3 & 4) {
1207 sregs->icnt = T_ST; /* Set store instruction count */
1208#ifdef STAT
1209 sregs->nstore++;
1210#endif
1211 } else {
1212 sregs->icnt = T_LD; /* Set load instruction count */
1213#ifdef STAT
1214 sregs->nload++;
1215#endif
1216 }
1217
1218 /* Decode load/store instructions */
1219
1220 switch (op3) {
1221 case LDDA:
1222 if (!chk_asi(sregs, &asi, op3)) break;
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 }
d3e9b40a
JG
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;
c906108c
SS
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 case LD:
1254 if (address & 0x3) {
1255 sregs->trap = TRAP_UNALI;
1256 break;
1257 }
1258 mexc = memory_read(asi, address, &data, 2, &ws);
1259 sregs->hold += ws;
1260 if (mexc) {
1261 sregs->trap = TRAP_DEXC;
1262 } else {
1263 *rdd = data;
1264 }
1265 break;
1266 case LDSTUBA:
1267 if (!chk_asi(sregs, &asi, op3)) break;
1268 case LDSTUB:
1269 mexc = memory_read(asi, address, &data, 0, &ws);
1270 sregs->hold += ws;
1271 sregs->icnt = T_LDST;
1272 if (mexc) {
1273 sregs->trap = TRAP_DEXC;
1274 break;
1275 }
d3e9b40a 1276 data = extract_byte (data, address);
c906108c
SS
1277 *rdd = data;
1278 data = 0x0ff;
1279 mexc = memory_write(asi, address, &data, 0, &ws);
1280 sregs->hold += ws;
1281 if (mexc) {
1282 sregs->trap = TRAP_DEXC;
1283 }
1284#ifdef STAT
1285 sregs->nload++;
1286#endif
1287 break;
1288 case LDSBA:
1289 case LDUBA:
1290 if (!chk_asi(sregs, &asi, op3)) break;
1291 case LDSB:
1292 case LDUB:
1293 mexc = memory_read(asi, address, &data, 0, &ws);
1294 sregs->hold += ws;
1295 if (mexc) {
1296 sregs->trap = TRAP_DEXC;
1297 break;
1298 }
d3e9b40a
JG
1299 if (op3 == LDSB)
1300 data = extract_byte_signed (data, address);
1301 else
1302 data = extract_byte (data, address);
c906108c
SS
1303 *rdd = data;
1304 break;
1305 case LDSHA:
1306 case LDUHA:
1307 if (!chk_asi(sregs, &asi, op3)) break;
1308 case LDSH:
1309 case LDUH:
1310 if (address & 0x1) {
1311 sregs->trap = TRAP_UNALI;
1312 break;
1313 }
1314 mexc = memory_read(asi, address, &data, 1, &ws);
1315 sregs->hold += ws;
1316 if (mexc) {
1317 sregs->trap = TRAP_DEXC;
1318 break;
1319 }
d3e9b40a
JG
1320 if (op3 == LDSH)
1321 data = extract_short_signed (data, address);
1322 else
1323 data = extract_short (data, address);
c906108c
SS
1324 *rdd = data;
1325 break;
1326 case LDF:
1327 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1328 sregs->trap = TRAP_FPDIS;
1329 break;
1330 }
1331 if (address & 0x3) {
1332 sregs->trap = TRAP_UNALI;
1333 break;
1334 }
1335 if (ebase.simtime < sregs->ftime) {
1336 if ((sregs->frd == rd) || (sregs->frs1 == rd) ||
1337 (sregs->frs2 == rd))
1338 sregs->fhold += (sregs->ftime - ebase.simtime);
1339 }
1340 mexc = memory_read(asi, address, &data, 2, &ws);
1341 sregs->hold += ws;
1342 sregs->flrd = rd;
1343 sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
1344 sregs->hold + sregs->fhold;
1345 if (mexc) {
1346 sregs->trap = TRAP_DEXC;
1347 } else {
d0a7ca87 1348 memcpy (&sregs->fs[rd], &data, sizeof (sregs->fs[rd]));
c906108c
SS
1349 }
1350 break;
1351 case LDDF:
1352 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1353 sregs->trap = TRAP_FPDIS;
1354 break;
1355 }
1356 if (address & 0x7) {
1357 sregs->trap = TRAP_UNALI;
1358 break;
1359 }
1360 if (ebase.simtime < sregs->ftime) {
1361 if (((sregs->frd >> 1) == (rd >> 1)) ||
1362 ((sregs->frs1 >> 1) == (rd >> 1)) ||
1363 ((sregs->frs2 >> 1) == (rd >> 1)))
1364 sregs->fhold += (sregs->ftime - ebase.simtime);
1365 }
d3e9b40a
JG
1366 mexc = memory_read (asi, address, ddata, 2, &ws);
1367 sregs->hold += ws;
1368 mexc |= memory_read (asi, address+4, &ddata[1], 2, &ws);
1369 sregs->hold += ws;
c906108c
SS
1370 sregs->icnt = T_LDD;
1371 if (mexc) {
1372 sregs->trap = TRAP_DEXC;
1373 } else {
1374 rd &= 0x1E;
1375 sregs->flrd = rd;
d0a7ca87 1376 memcpy (&sregs->fs[rd], &ddata[0], sizeof (sregs->fs[rd]));
c906108c
SS
1377#ifdef STAT
1378 sregs->nload++; /* Double load counts twice */
1379#endif
d0a7ca87
AB
1380 memcpy (&sregs->fs[rd + 1], &ddata[1],
1381 sizeof (sregs->fs[rd + 1]));
c906108c
SS
1382 sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
1383 sregs->hold + sregs->fhold;
1384 }
1385 break;
1386 case LDFSR:
1387 if (ebase.simtime < sregs->ftime) {
1388 sregs->fhold += (sregs->ftime - ebase.simtime);
1389 }
1390 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1391 sregs->trap = TRAP_FPDIS;
1392 break;
1393 }
1394 if (address & 0x3) {
1395 sregs->trap = TRAP_UNALI;
1396 break;
1397 }
1398 mexc = memory_read(asi, address, &data, 2, &ws);
1399 sregs->hold += ws;
1400 if (mexc) {
1401 sregs->trap = TRAP_DEXC;
1402 } else {
1403 sregs->fsr =
1404 (sregs->fsr & 0x7FF000) | (data & ~0x7FF000);
1405 set_fsr(sregs->fsr);
1406 }
1407 break;
1408 case STFSR:
1409 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1410 sregs->trap = TRAP_FPDIS;
1411 break;
1412 }
1413 if (address & 0x3) {
1414 sregs->trap = TRAP_UNALI;
1415 break;
1416 }
1417 if (ebase.simtime < sregs->ftime) {
1418 sregs->fhold += (sregs->ftime - ebase.simtime);
1419 }
1420 mexc = memory_write(asi, address, &sregs->fsr, 2, &ws);
1421 sregs->hold += ws;
1422 if (mexc) {
1423 sregs->trap = TRAP_DEXC;
1424 }
1425 break;
1426
1427 case STA:
1428 if (!chk_asi(sregs, &asi, op3)) break;
1429 case ST:
1430 if (address & 0x3) {
1431 sregs->trap = TRAP_UNALI;
1432 break;
1433 }
1434 mexc = memory_write(asi, address, rdd, 2, &ws);
1435 sregs->hold += ws;
1436 if (mexc) {
1437 sregs->trap = TRAP_DEXC;
1438 }
1439 break;
1440 case STBA:
1441 if (!chk_asi(sregs, &asi, op3)) break;
1442 case STB:
1443 mexc = memory_write(asi, address, rdd, 0, &ws);
1444 sregs->hold += ws;
1445 if (mexc) {
1446 sregs->trap = TRAP_DEXC;
1447 }
1448 break;
1449 case STDA:
1450 if (!chk_asi(sregs, &asi, op3)) break;
1451 case STD:
1452 if (address & 0x7) {
1453 sregs->trap = TRAP_UNALI;
1454 break;
1455 }
1456 if (rd & 1) {
1457 rd &= 0x1e;
1458 if (rd > 7)
1459 rdd = &(sregs->r[(cwp + rd) & 0x7f]);
1460 else
1461 rdd = &(sregs->g[rd]);
1462 }
1463 mexc = memory_write(asi, address, rdd, 3, &ws);
1464 sregs->hold += ws;
1465 sregs->icnt = T_STD;
1466#ifdef STAT
1467 sregs->nstore++; /* Double store counts twice */
1468#endif
1469 if (mexc) {
1470 sregs->trap = TRAP_DEXC;
1471 break;
1472 }
1473 break;
1474 case STDFQ:
1475 if ((sregs->psr & 0x1f) > 7) {
1476 sregs->trap = TRAP_UNIMP;
1477 break;
1478 }
1479 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1480 sregs->trap = TRAP_FPDIS;
1481 break;
1482 }
1483 if (address & 0x7) {
1484 sregs->trap = TRAP_UNALI;
1485 break;
1486 }
1487 if (!(sregs->fsr & FSR_QNE)) {
1488 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;
1489 break;
1490 }
1491 rdd = &(sregs->fpq[0]);
1492 mexc = memory_write(asi, address, rdd, 3, &ws);
1493 sregs->hold += ws;
1494 sregs->icnt = T_STD;
1495#ifdef STAT
1496 sregs->nstore++; /* Double store counts twice */
1497#endif
1498 if (mexc) {
1499 sregs->trap = TRAP_DEXC;
1500 break;
1501 } else {
1502 sregs->fsr &= ~FSR_QNE;
1503 sregs->fpstate = FP_EXE_MODE;
1504 }
1505 break;
1506 case STHA:
1507 if (!chk_asi(sregs, &asi, op3)) break;
1508 case STH:
1509 if (address & 0x1) {
1510 sregs->trap = TRAP_UNALI;
1511 break;
1512 }
1513 mexc = memory_write(asi, address, rdd, 1, &ws);
1514 sregs->hold += ws;
1515 if (mexc) {
1516 sregs->trap = TRAP_DEXC;
1517 }
1518 break;
1519 case STF:
1520 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1521 sregs->trap = TRAP_FPDIS;
1522 break;
1523 }
1524 if (address & 0x3) {
1525 sregs->trap = TRAP_UNALI;
1526 break;
1527 }
1528 if (ebase.simtime < sregs->ftime) {
1529 if (sregs->frd == rd)
1530 sregs->fhold += (sregs->ftime - ebase.simtime);
1531 }
4a92dedc 1532 mexc = memory_write(asi, address, (uint32_t *)&sregs->fsi[rd], 2, &ws);
c906108c
SS
1533 sregs->hold += ws;
1534 if (mexc) {
1535 sregs->trap = TRAP_DEXC;
1536 }
1537 break;
1538 case STDF:
1539 if (!((sregs->psr & PSR_EF) && FP_PRES)) {
1540 sregs->trap = TRAP_FPDIS;
1541 break;
1542 }
1543 if (address & 0x7) {
1544 sregs->trap = TRAP_UNALI;
1545 break;
1546 }
1547 rd &= 0x1E;
1548 if (ebase.simtime < sregs->ftime) {
1549 if ((sregs->frd == rd) || (sregs->frd + 1 == rd))
1550 sregs->fhold += (sregs->ftime - ebase.simtime);
1551 }
4a92dedc 1552 mexc = memory_write(asi, address, (uint32_t *)&sregs->fsi[rd], 3, &ws);
c906108c
SS
1553 sregs->hold += ws;
1554 sregs->icnt = T_STD;
1555#ifdef STAT
1556 sregs->nstore++; /* Double store counts twice */
1557#endif
1558 if (mexc) {
1559 sregs->trap = TRAP_DEXC;
1560 }
1561 break;
1562 case SWAPA:
1563 if (!chk_asi(sregs, &asi, op3)) break;
1564 case SWAP:
1565 if (address & 0x3) {
1566 sregs->trap = TRAP_UNALI;
1567 break;
1568 }
1569 mexc = memory_read(asi, address, &data, 2, &ws);
1570 sregs->hold += ws;
1571 if (mexc) {
1572 sregs->trap = TRAP_DEXC;
1573 break;
1574 }
1575 mexc = memory_write(asi, address, rdd, 2, &ws);
1576 sregs->hold += ws;
1577 sregs->icnt = T_LDST;
1578 if (mexc) {
1579 sregs->trap = TRAP_DEXC;
1580 break;
1581 } else
1582 *rdd = data;
1583#ifdef STAT
1584 sregs->nload++;
1585#endif
1586 break;
1587
1588
1589 default:
1590 sregs->trap = TRAP_UNIMP;
1591 break;
1592 }
1593
1594#ifdef LOAD_DEL
1595
1596 if (!(op3 & 4)) {
1597 sregs->ildtime = ebase.simtime + sregs->hold + sregs->icnt;
1598 sregs->ildreg = rd;
1599 if ((op3 | 0x10) == 0x13)
1600 sregs->ildreg |= 1; /* Double load, odd register loaded
1601 * last */
1602 }
1603#endif
1604 break;
1605
1606 default:
1607 sregs->trap = TRAP_UNIMP;
1608 break;
1609 }
1610 sregs->g[0] = 0;
1611 if (!sregs->trap) {
1612 sregs->pc = pc;
1613 sregs->npc = npc;
1614 }
5831e29b 1615 return 0;
c906108c
SS
1616}
1617
1618#define T_FABSs 2
1619#define T_FADDs 4
1620#define T_FADDd 4
1621#define T_FCMPs 4
1622#define T_FCMPd 4
1623#define T_FDIVs 20
1624#define T_FDIVd 35
1625#define T_FMOVs 2
1626#define T_FMULs 5
1627#define T_FMULd 9
1628#define T_FNEGs 2
1629#define T_FSQRTs 37
1630#define T_FSQRTd 65
1631#define T_FSUBs 4
1632#define T_FSUBd 4
1633#define T_FdTOi 7
1634#define T_FdTOs 3
1635#define T_FiTOs 6
1636#define T_FiTOd 6
1637#define T_FsTOi 6
1638#define T_FsTOd 2
1639
1640#define FABSs 0x09
1641#define FADDs 0x41
1642#define FADDd 0x42
1643#define FCMPs 0x51
1644#define FCMPd 0x52
1645#define FCMPEs 0x55
1646#define FCMPEd 0x56
1647#define FDIVs 0x4D
1648#define FDIVd 0x4E
1649#define FMOVs 0x01
1650#define FMULs 0x49
1651#define FMULd 0x4A
1652#define FNEGs 0x05
1653#define FSQRTs 0x29
1654#define FSQRTd 0x2A
1655#define FSUBs 0x45
1656#define FSUBd 0x46
1657#define FdTOi 0xD2
1658#define FdTOs 0xC6
1659#define FiTOs 0xC4
1660#define FiTOd 0xC8
1661#define FsTOi 0xD1
1662#define FsTOd 0xC9
1663
1664
1665static int
4a92dedc 1666fpexec(uint32_t op3, uint32_t rd, uint32_t rs1, uint32_t rs2, struct pstate *sregs)
c906108c 1667{
4a92dedc
MF
1668 uint32_t opf, tem, accex;
1669 int32_t fcc;
1670 uint32_t ldadj;
c906108c
SS
1671
1672 if (sregs->fpstate == FP_EXC_MODE) {
1673 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;
1674 sregs->fpstate = FP_EXC_PE;
5831e29b 1675 return 0;
c906108c
SS
1676 }
1677 if (sregs->fpstate == FP_EXC_PE) {
1678 sregs->fpstate = FP_EXC_MODE;
5831e29b 1679 return TRAP_FPEXC;
c906108c
SS
1680 }
1681 opf = (sregs->inst >> 5) & 0x1ff;
1682
1683 /*
1684 * Check if we already have an FPop in the pipe. If so, halt until it is
1685 * finished by incrementing fhold with the remaining execution time
1686 */
1687
1688 if (ebase.simtime < sregs->ftime) {
1689 sregs->fhold = (sregs->ftime - ebase.simtime);
1690 } else {
1691 sregs->fhold = 0;
1692
1693 /* Check load dependencies. */
1694
1695 if (ebase.simtime < sregs->ltime) {
1696
1697 /* Don't check rs1 if single operand instructions */
1698
1699 if (((opf >> 6) == 0) || ((opf >> 6) == 3))
1700 rs1 = 32;
1701
1702 /* Adjust for double floats */
1703
1704 ldadj = opf & 1;
1705 if (!(((sregs->flrd - rs1) >> ldadj) && ((sregs->flrd - rs2) >> ldadj)))
1706 sregs->fhold++;
1707 }
1708 }
1709
1710 sregs->finst++;
1711
1712 sregs->frs1 = rs1; /* Store src and dst for dependecy check */
1713 sregs->frs2 = rs2;
1714 sregs->frd = rd;
1715
1716 sregs->ftime = ebase.simtime + sregs->hold + sregs->fhold;
1717
1718 /* SPARC is big-endian - swap double floats if host is little-endian */
1719 /* This is ugly - I know ... */
1720
0cb8d851 1721 /* FIXME: should use (HOST_BYTE_ORDER == CURRENT_TARGET_BYTE_ORDER)
c906108c
SS
1722 but what about machines where float values are different endianness
1723 from integer values? */
1724
9c5f41df 1725#ifdef HOST_LITTLE_ENDIAN
c906108c
SS
1726 rs1 &= 0x1f;
1727 switch (opf) {
1728 case FADDd:
1729 case FDIVd:
1730 case FMULd:
1731 case FSQRTd:
1732 case FSUBd:
1733 case FCMPd:
1734 case FCMPEd:
1735 case FdTOi:
1736 case FdTOs:
1737 sregs->fdp[rs1 | 1] = sregs->fs[rs1 & ~1];
1738 sregs->fdp[rs1 & ~1] = sregs->fs[rs1 | 1];
1739 sregs->fdp[rs2 | 1] = sregs->fs[rs2 & ~1];
1740 sregs->fdp[rs2 & ~1] = sregs->fs[rs2 | 1];
1741 default:
d68c23cd 1742 break;
c906108c
SS
1743 }
1744#endif
1745
1746 clear_accex();
1747
1748 switch (opf) {
1749 case FABSs:
1750 sregs->fs[rd] = fabs(sregs->fs[rs2]);
1751 sregs->ftime += T_FABSs;
1752 sregs->frs1 = 32; /* rs1 ignored */
1753 break;
1754 case FADDs:
1755 sregs->fs[rd] = sregs->fs[rs1] + sregs->fs[rs2];
1756 sregs->ftime += T_FADDs;
1757 break;
1758 case FADDd:
1759 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] + sregs->fd[rs2 >> 1];
1760 sregs->ftime += T_FADDd;
1761 break;
1762 case FCMPs:
1763 case FCMPEs:
1764 if (sregs->fs[rs1] == sregs->fs[rs2])
1765 fcc = 3;
1766 else if (sregs->fs[rs1] < sregs->fs[rs2])
1767 fcc = 2;
1768 else if (sregs->fs[rs1] > sregs->fs[rs2])
1769 fcc = 1;
1770 else
1771 fcc = 0;
1772 sregs->fsr |= 0x0C00;
1773 sregs->fsr &= ~(fcc << 10);
1774 sregs->ftime += T_FCMPs;
1775 sregs->frd = 32; /* rd ignored */
1776 if ((fcc == 0) && (opf == FCMPEs)) {
1777 sregs->fpstate = FP_EXC_PE;
1778 sregs->fsr = (sregs->fsr & ~0x1C000) | (1 << 14);
1779 }
1780 break;
1781 case FCMPd:
1782 case FCMPEd:
1783 if (sregs->fd[rs1 >> 1] == sregs->fd[rs2 >> 1])
1784 fcc = 3;
1785 else if (sregs->fd[rs1 >> 1] < sregs->fd[rs2 >> 1])
1786 fcc = 2;
1787 else if (sregs->fd[rs1 >> 1] > sregs->fd[rs2 >> 1])
1788 fcc = 1;
1789 else
1790 fcc = 0;
1791 sregs->fsr |= 0x0C00;
1792 sregs->fsr &= ~(fcc << 10);
1793 sregs->ftime += T_FCMPd;
1794 sregs->frd = 32; /* rd ignored */
1795 if ((fcc == 0) && (opf == FCMPEd)) {
1796 sregs->fpstate = FP_EXC_PE;
1797 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1798 }
1799 break;
1800 case FDIVs:
1801 sregs->fs[rd] = sregs->fs[rs1] / sregs->fs[rs2];
1802 sregs->ftime += T_FDIVs;
1803 break;
1804 case FDIVd:
1805 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] / sregs->fd[rs2 >> 1];
1806 sregs->ftime += T_FDIVd;
1807 break;
1808 case FMOVs:
1809 sregs->fs[rd] = sregs->fs[rs2];
1810 sregs->ftime += T_FMOVs;
1811 sregs->frs1 = 32; /* rs1 ignored */
1812 break;
1813 case FMULs:
1814 sregs->fs[rd] = sregs->fs[rs1] * sregs->fs[rs2];
1815 sregs->ftime += T_FMULs;
1816 break;
1817 case FMULd:
1818 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] * sregs->fd[rs2 >> 1];
1819 sregs->ftime += T_FMULd;
1820 break;
1821 case FNEGs:
1822 sregs->fs[rd] = -sregs->fs[rs2];
1823 sregs->ftime += T_FNEGs;
1824 sregs->frs1 = 32; /* rs1 ignored */
1825 break;
1826 case FSQRTs:
1827 if (sregs->fs[rs2] < 0.0) {
1828 sregs->fpstate = FP_EXC_PE;
1829 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1830 sregs->fsr = (sregs->fsr & 0x1f) | 0x10;
1831 break;
1832 }
1833 sregs->fs[rd] = sqrt(sregs->fs[rs2]);
1834 sregs->ftime += T_FSQRTs;
1835 sregs->frs1 = 32; /* rs1 ignored */
1836 break;
1837 case FSQRTd:
1838 if (sregs->fd[rs2 >> 1] < 0.0) {
1839 sregs->fpstate = FP_EXC_PE;
1840 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1841 sregs->fsr = (sregs->fsr & 0x1f) | 0x10;
1842 break;
1843 }
1844 sregs->fd[rd >> 1] = sqrt(sregs->fd[rs2 >> 1]);
1845 sregs->ftime += T_FSQRTd;
1846 sregs->frs1 = 32; /* rs1 ignored */
1847 break;
1848 case FSUBs:
1849 sregs->fs[rd] = sregs->fs[rs1] - sregs->fs[rs2];
1850 sregs->ftime += T_FSUBs;
1851 break;
1852 case FSUBd:
1853 sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] - sregs->fd[rs2 >> 1];
1854 sregs->ftime += T_FSUBd;
1855 break;
1856 case FdTOi:
1857 sregs->fsi[rd] = (int) sregs->fd[rs2 >> 1];
1858 sregs->ftime += T_FdTOi;
1859 sregs->frs1 = 32; /* rs1 ignored */
1860 break;
1861 case FdTOs:
1862 sregs->fs[rd] = (float32) sregs->fd[rs2 >> 1];
1863 sregs->ftime += T_FdTOs;
1864 sregs->frs1 = 32; /* rs1 ignored */
1865 break;
1866 case FiTOs:
1867 sregs->fs[rd] = (float32) sregs->fsi[rs2];
1868 sregs->ftime += T_FiTOs;
1869 sregs->frs1 = 32; /* rs1 ignored */
1870 break;
1871 case FiTOd:
1872 sregs->fd[rd >> 1] = (float64) sregs->fsi[rs2];
1873 sregs->ftime += T_FiTOd;
1874 sregs->frs1 = 32; /* rs1 ignored */
1875 break;
1876 case FsTOi:
1877 sregs->fsi[rd] = (int) sregs->fs[rs2];
1878 sregs->ftime += T_FsTOi;
1879 sregs->frs1 = 32; /* rs1 ignored */
1880 break;
1881 case FsTOd:
1882 sregs->fd[rd >> 1] = sregs->fs[rs2];
1883 sregs->ftime += T_FsTOd;
1884 sregs->frs1 = 32; /* rs1 ignored */
1885 break;
1886
1887 default:
1888 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_UNIMP;
1889 sregs->fpstate = FP_EXC_PE;
1890 }
1891
1892#ifdef ERRINJ
1893 if (errftt) {
1894 sregs->fsr = (sregs->fsr & ~FSR_TT) | (errftt << 14);
1895 sregs->fpstate = FP_EXC_PE;
1896 if (sis_verbose) printf("Inserted fpu error %X\n",errftt);
1897 errftt = 0;
1898 }
1899#endif
1900
1901 accex = get_accex();
1902
9c5f41df 1903#ifdef HOST_LITTLE_ENDIAN
c906108c
SS
1904 switch (opf) {
1905 case FADDd:
1906 case FDIVd:
1907 case FMULd:
1908 case FSQRTd:
1909 case FSUBd:
1910 case FiTOd:
1911 case FsTOd:
1912 sregs->fs[rd & ~1] = sregs->fdp[rd | 1];
1913 sregs->fs[rd | 1] = sregs->fdp[rd & ~1];
1914 default:
d68c23cd 1915 break;
c906108c
SS
1916 }
1917#endif
1918 if (sregs->fpstate == FP_EXC_PE) {
1919 sregs->fpq[0] = sregs->pc;
1920 sregs->fpq[1] = sregs->inst;
1921 sregs->fsr |= FSR_QNE;
1922 } else {
1923 tem = (sregs->fsr >> 23) & 0x1f;
1924 if (tem & accex) {
1925 sregs->fpstate = FP_EXC_PE;
1926 sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
1927 sregs->fsr = ((sregs->fsr & ~0x1f) | accex);
1928 } else {
1929 sregs->fsr = ((((sregs->fsr >> 5) | accex) << 5) | accex);
1930 }
1931 if (sregs->fpstate == FP_EXC_PE) {
1932 sregs->fpq[0] = sregs->pc;
1933 sregs->fpq[1] = sregs->inst;
1934 sregs->fsr |= FSR_QNE;
1935 }
1936 }
1937 clear_accex();
1938
5831e29b 1939 return 0;
c906108c
SS
1940
1941
1942}
1943
1944static int
4a92dedc 1945chk_asi(struct pstate *sregs, uint32_t *asi, uint32_t op3)
c906108c
SS
1946{
1947 if (!(sregs->psr & PSR_S)) {
1948 sregs->trap = TRAP_PRIVI;
5831e29b 1949 return 0;
c906108c
SS
1950 } else if (sregs->inst & INST_I) {
1951 sregs->trap = TRAP_UNIMP;
5831e29b 1952 return 0;
c906108c
SS
1953 } else
1954 *asi = (sregs->inst >> 5) & 0x0ff;
5831e29b 1955 return 1;
c906108c
SS
1956}
1957
1958int
81e6e8ae 1959execute_trap(struct pstate *sregs)
c906108c 1960{
4a92dedc 1961 int32_t cwp;
c906108c
SS
1962
1963 if (sregs->trap == 256) {
1964 sregs->pc = 0;
1965 sregs->npc = 4;
1966 sregs->trap = 0;
1967 } else if (sregs->trap == 257) {
5831e29b 1968 return ERROR;
c906108c
SS
1969 } else {
1970
1971 if ((sregs->psr & PSR_ET) == 0)
5831e29b 1972 return ERROR;
c906108c
SS
1973
1974 sregs->tbr = (sregs->tbr & 0xfffff000) | (sregs->trap << 4);
1975 sregs->trap = 0;
1976 sregs->psr &= ~PSR_ET;
1977 sregs->psr |= ((sregs->psr & PSR_S) >> 1);
1978 sregs->annul = 0;
1979 sregs->psr = (((sregs->psr & PSR_CWP) - 1) & 0x7) | (sregs->psr & ~PSR_CWP);
1980 cwp = ((sregs->psr & PSR_CWP) << 4);
1981 sregs->r[(cwp + 17) & 0x7f] = sregs->pc;
1982 sregs->r[(cwp + 18) & 0x7f] = sregs->npc;
1983 sregs->psr |= PSR_S;
1984 sregs->pc = sregs->tbr;
1985 sregs->npc = sregs->tbr + 4;
1986
1987 if ( 0 != (1 & sregs->asr17) ) {
1988 /* single vector trapping! */
1989 sregs->pc = sregs->tbr & 0xfffff000;
1990 sregs->npc = sregs->pc + 4;
1991 }
1992
1993 /* Increase simulator time */
1994 sregs->icnt = TRAP_C;
1995
1996 }
1997
1998
5831e29b 1999 return 0;
c906108c
SS
2000
2001}
2002
2003extern struct irqcell irqarr[16];
2004
2005int
81e6e8ae 2006check_interrupts(struct pstate *sregs)
c906108c
SS
2007{
2008#ifdef ERRINJ
2009 if (errtt) {
2010 sregs->trap = errtt;
2011 if (sis_verbose) printf("Inserted error trap 0x%02X\n",errtt);
2012 errtt = 0;
2013 }
2014#endif
2015
2016 if ((ext_irl) && (sregs->psr & PSR_ET) &&
2017 ((ext_irl == 15) || (ext_irl > (int) ((sregs->psr & PSR_PIL) >> 8)))) {
2018 if (sregs->trap == 0) {
2019 sregs->trap = 16 + ext_irl;
2020 irqarr[ext_irl & 0x0f].callback(irqarr[ext_irl & 0x0f].arg);
5831e29b 2021 return 1;
c906108c
SS
2022 }
2023 }
5831e29b 2024 return 0;
c906108c
SS
2025}
2026
2027void
81e6e8ae 2028init_regs(struct pstate *sregs)
c906108c
SS
2029{
2030 sregs->pc = 0;
2031 sregs->npc = 4;
2032 sregs->trap = 0;
2033 sregs->psr &= 0x00f03fdf;
df9bc416 2034 sregs->psr |= 0x11000080; /* Set supervisor bit */
c906108c
SS
2035 sregs->breakpoint = 0;
2036 sregs->annul = 0;
2037 sregs->fpstate = FP_EXE_MODE;
2038 sregs->fpqn = 0;
2039 sregs->ftime = 0;
2040 sregs->ltime = 0;
2041 sregs->err_mode = 0;
2042 ext_irl = 0;
2043 sregs->g[0] = 0;
9c5f41df 2044#ifdef HOST_LITTLE_ENDIAN
c906108c 2045 sregs->fdp = (float32 *) sregs->fd;
4a92dedc 2046 sregs->fsi = (int32_t *) sregs->fs;
c906108c
SS
2047#else
2048 sregs->fs = (float32 *) sregs->fd;
4a92dedc 2049 sregs->fsi = (int32_t *) sregs->fd;
c906108c
SS
2050#endif
2051 sregs->fsr = 0;
2052 sregs->fpu_pres = !nfp;
2053 set_fsr(sregs->fsr);
2054 sregs->bphit = 0;
2055 sregs->ildreg = 0;
2056 sregs->ildtime = 0;
2057
2058 sregs->y = 0;
2059 sregs->asr17 = 0;
2060
2061 sregs->rett_err = 0;
2062 sregs->jmpltime = 0;
2063}