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