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