📄 exec.c
字号:
/* * This file is part of SIS. * * SIS, SPARC instruction simulator V1.8 Copyright (C) 1995 Jiri Gaisler, * European Space Agency * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 675 * Mass Ave, Cambridge, MA 02139, USA. * */#include "sis.h"#include "end.h"#include <math.h>#include <stdio.h>extern int32 sis_verbose, sparclite;int ext_irl = 0;/* Load/store interlock delay */#define FLSTHOLD 1/* Load delay (delete if unwanted - speeds up simulation) */#define LOAD_DEL 1#define T_LD 2#define T_LDD 3#define T_ST 3#define T_STD 4#define T_LDST 4#define T_JMPL 2#define T_RETT 2#define FSR_QNE 0x2000#define FP_EXE_MODE 0#define FP_EXC_PE 1#define FP_EXC_MODE 2#define FBA 8#define FBN 0#define FBNE 1#define FBLG 2#define FBUL 3#define FBL 4#define FBUG 5#define FBG 6#define FBU 7#define FBA 8#define FBE 9#define FBUE 10#define FBGE 11#define FBUGE 12#define FBLE 13#define FBULE 14#define FBO 15#define FCC_E 0#define FCC_L 1#define FCC_G 2#define FCC_U 3#define PSR_ET 0x20#define PSR_EF 0x1000#define PSR_PS 0x40#define PSR_S 0x80#define PSR_N 0x0800000#define PSR_Z 0x0400000#define PSR_V 0x0200000#define PSR_C 0x0100000#define PSR_CC 0x0F00000#define PSR_CWP 0x7#define PSR_PIL 0x0f00#define ICC_N (icc >> 3)#define ICC_Z (icc >> 2)#define ICC_V (icc >> 1)#define ICC_C (icc)#define FP_PRES (sregs->fpu_pres)#define TRAP_IEXC 1#define TRAP_UNIMP 2#define TRAP_PRIVI 3#define TRAP_FPDIS 4#define TRAP_WOFL 5#define TRAP_WUFL 6#define TRAP_UNALI 7#define TRAP_FPEXC 8#define TRAP_DEXC 9#define TRAP_TAG 10#define TRAP_DIV0 0x2a#define FSR_TT 0x1C000#define FP_IEEE 0x04000#define FP_UNIMP 0x0C000#define FP_SEQ_ERR 0x10000#define BICC_BN 0#define BICC_BE 1#define BICC_BLE 2#define BICC_BL 3#define BICC_BLEU 4#define BICC_BCS 5#define BICC_NEG 6#define BICC_BVS 7#define BICC_BA 8#define BICC_BNE 9#define BICC_BG 10#define BICC_BGE 11#define BICC_BGU 12#define BICC_BCC 13#define BICC_POS 14#define BICC_BVC 15#define INST_SIMM13 0x1fff#define INST_RS2 0x1f#define INST_I 0x2000#define ADD 0x00#define ADDCC 0x10#define ADDX 0x08#define ADDXCC 0x18#define TADDCC 0x20#define TSUBCC 0x21#define TADDCCTV 0x22#define TSUBCCTV 0x23#define IAND 0x01#define IANDCC 0x11#define IANDN 0x05#define IANDNCC 0x15#define MULScc 0x24#define DIVScc 0x1D#define SMUL 0x0B#define SMULCC 0x1B#define UMUL 0x0A#define UMULCC 0x1A#define SDIV 0x0F#define SDIVCC 0x1F#define UDIV 0x0E#define UDIVCC 0x1E#define IOR 0x02#define IORCC 0x12#define IORN 0x06#define IORNCC 0x16#define SLL 0x25#define SRA 0x27#define SRL 0x26#define SUB 0x04#define SUBCC 0x14#define SUBX 0x0C#define SUBXCC 0x1C#define IXNOR 0x07#define IXNORCC 0x17#define IXOR 0x03#define IXORCC 0x13#define SETHI 0x04#define BICC 0x02#define FPBCC 0x06#define RDY 0x28#define RDPSR 0x29#define RDWIM 0x2A#define RDTBR 0x2B#define SCAN 0x2C#define WRY 0x30#define WRPSR 0x31#define WRWIM 0x32#define WRTBR 0x33#define JMPL 0x38#define RETT 0x39#define TICC 0x3A#define SAVE 0x3C#define RESTORE 0x3D#define LDD 0x03#define LDDA 0x13#define LD 0x00#define LDA 0x10#define LDF 0x20#define LDDF 0x23#define LDSTUB 0x0D#define LDSTUBA 0x1D#define LDUB 0x01#define LDUBA 0x11#define LDSB 0x09#define LDSBA 0x19#define LDUH 0x02#define LDUHA 0x12#define LDSH 0x0A#define LDSHA 0x1A#define LDFSR 0x21#define ST 0x04#define STA 0x14#define STB 0x05#define STBA 0x15#define STD 0x07#define STDA 0x17#define STF 0x24#define STDFQ 0x26#define STDF 0x27#define STFSR 0x25#define STH 0x06#define STHA 0x16#define SWAP 0x0F#define SWAPA 0x1F#define FLUSH 0x3B#define SIGN_BIT 0x80000000/* # of cycles overhead when a trap is taken */#define TRAP_C 3/* Forward declarations */static uint32 sub_cc PARAMS ((uint32 psr, int32 operand1, int32 operand2, int32 result));static uint32 add_cc PARAMS ((uint32 psr, int32 operand1, int32 operand2, int32 result));static void log_cc PARAMS ((int32 result, struct pstate *sregs));static int fpexec PARAMS ((uint32 op3, uint32 rd, uint32 rs1, uint32 rs2, struct pstate *sregs));static int chk_asi PARAMS ((struct pstate *sregs, uint32 *asi, uint32 op3));extern struct estate ebase;extern int32 nfp,ift;#ifdef ERRINJextern uint32 errtt, errftt;#endifstatic uint32sub_cc(psr, operand1, operand2, result) uint32 psr; int32 operand1; int32 operand2; int32 result;{ psr = ((psr & ~PSR_N) | ((result >> 8) & PSR_N)); if (result) psr &= ~PSR_Z; else psr |= PSR_Z; psr = (psr & ~PSR_V) | ((((operand1 & ~operand2 & ~result) | (~operand1 & operand2 & result)) >> 10) & PSR_V); psr = (psr & ~PSR_C) | ((((~operand1 & operand2) | ((~operand1 | operand2) & result)) >> 11) & PSR_C); return (psr);}uint32add_cc(psr, operand1, operand2, result) uint32 psr; int32 operand1; int32 operand2; int32 result;{ psr = ((psr & ~PSR_N) | ((result >> 8) & PSR_N)); if (result) psr &= ~PSR_Z; else psr |= PSR_Z; psr = (psr & ~PSR_V) | ((((operand1 & operand2 & ~result) | (~operand1 & ~operand2 & result)) >> 10) & PSR_V); psr = (psr & ~PSR_C) | ((((operand1 & operand2) | ((operand1 | operand2) & ~result)) >> 11) & PSR_C); return(psr);}static voidlog_cc(result, sregs) int32 result; struct pstate *sregs;{ sregs->psr &= ~(PSR_CC); /* Zero CC bits */ sregs->psr = (sregs->psr | ((result >> 8) & PSR_N)); if (result == 0) sregs->psr |= PSR_Z;}/* Add two unsigned 32-bit integers, and calculate the carry out. */static uint32add32 (uint32 n1, uint32 n2, int *carry){ uint32 result = n1 + n2; *carry = result < n1 || result < n1; return(result);}/* Multiply two 32-bit integers. */static voidmul64 (uint32 n1, uint32 n2, uint32 *result_hi, uint32 *result_lo, int msigned){ uint32 lo, mid1, mid2, hi, reg_lo, reg_hi; int carry; int sign = 0; /* If this is a signed multiply, calculate the sign of the result and make the operands positive. */ if (msigned) { sign = (n1 ^ n2) & SIGN_BIT; if (n1 & SIGN_BIT) n1 = -n1; if (n2 & SIGN_BIT) n2 = -n2; } /* We can split the 32x32 into four 16x16 operations. This ensures that we do not lose precision on 32bit only hosts: */ lo = ((n1 & 0xFFFF) * (n2 & 0xFFFF)); mid1 = ((n1 & 0xFFFF) * ((n2 >> 16) & 0xFFFF)); mid2 = (((n1 >> 16) & 0xFFFF) * (n2 & 0xFFFF)); hi = (((n1 >> 16) & 0xFFFF) * ((n2 >> 16) & 0xFFFF)); /* We now need to add all of these results together, taking care to propogate the carries from the additions: */ reg_lo = add32 (lo, (mid1 << 16), &carry); reg_hi = carry; reg_lo = add32 (reg_lo, (mid2 << 16), &carry); reg_hi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi); /* Negate result if necessary. */ if (sign) { reg_hi = ~ reg_hi; reg_lo = - reg_lo; if (reg_lo == 0) reg_hi++; } *result_lo = reg_lo; *result_hi = reg_hi;}/* Divide a 64-bit integer by a 32-bit integer. We cheat and assume that the host compiler supports long long operations. */static voiddiv64 (uint32 n1_hi, uint32 n1_low, uint32 n2, uint32 *result, int msigned){ uint64 n1; n1 = ((uint64) n1_hi) << 32; n1 |= ((uint64) n1_low) & 0xffffffff; if (msigned) { int64 n1_s = (int64) n1; int32 n2_s = (int32) n2; n1_s = n1_s / n2_s; n1 = (uint64) n1_s; } else n1 = n1 / n2; *result = (uint32) (n1 & 0xffffffff);}intdispatch_instruction(sregs) struct pstate *sregs;{ uint32 cwp, op, op2, op3, asi, rd, cond, rs1, rs2; uint32 ldep, icc; int32 operand1, operand2, *rdd, result, eicc, new_cwp; int32 pc, npc, data, address, ws, mexc, fcc; int32 ddata[2]; sregs->ninst++; cwp = ((sregs->psr & PSR_CWP) << 4); op = sregs->inst >> 30; pc = sregs->npc; npc = sregs->npc + 4; op3 = rd = rs1 = operand2 = eicc = 0; rdd = 0; if (op & 2) { op3 = (sregs->inst >> 19) & 0x3f; rs1 = (sregs->inst >> 14) & 0x1f; rd = (sregs->inst >> 25) & 0x1f;#ifdef LOAD_DEL /* Check if load dependecy is possible */ if (ebase.simtime <= sregs->ildtime) ldep = (((op3 & 0x38) != 0x28) && ((op3 & 0x3e) != 0x34) && (sregs->ildreg != 0)); else ldep = 0; if (sregs->inst & INST_I) { if (ldep && (sregs->ildreg == rs1)) sregs->hold++; operand2 = sregs->inst; operand2 = ((operand2 << 19) >> 19); /* sign extend */ } else { rs2 = sregs->inst & INST_RS2; if (rs2 > 7) operand2 = sregs->r[(cwp + rs2) & 0x7f]; else operand2 = sregs->g[rs2]; if (ldep && ((sregs->ildreg == rs1) || (sregs->ildreg == rs2))) sregs->hold++; }#else if (sregs->inst & INST_I) { operand2 = sregs->inst; operand2 = ((operand2 << 19) >> 19); /* sign extend */ } else { rs2 = sregs->inst & INST_RS2; if (rs2 > 7) operand2 = sregs->r[(cwp + rs2) & 0x7f]; else operand2 = sregs->g[rs2]; }#endif if (rd > 7) rdd = &(sregs->r[(cwp + rd) & 0x7f]); else rdd = &(sregs->g[rd]); if (rs1 > 7) rs1 = sregs->r[(cwp + rs1) & 0x7f]; else rs1 = sregs->g[rs1]; } switch (op) { case 0: op2 = (sregs->inst >> 22) & 0x7; switch (op2) { case SETHI: rd = (sregs->inst >> 25) & 0x1f; if (rd > 7) rdd = &(sregs->r[(cwp + rd) & 0x7f]); else rdd = &(sregs->g[rd]); *rdd = sregs->inst << 10; break; case BICC:#ifdef STAT sregs->nbranch++;#endif icc = sregs->psr >> 20; cond = ((sregs->inst >> 25) & 0x0f); switch (cond) { case BICC_BN: eicc = 0; break; case BICC_BE: eicc = ICC_Z; break; case BICC_BLE: eicc = ICC_Z | (ICC_N ^ ICC_V); break; case BICC_BL: eicc = (ICC_N ^ ICC_V); break; case BICC_BLEU: eicc = ICC_C | ICC_Z; break; case BICC_BCS: eicc = ICC_C; break; case BICC_NEG: eicc = ICC_N; break; case BICC_BVS: eicc = ICC_V; break; case BICC_BA: eicc = 1; if (sregs->inst & 0x20000000) sregs->annul = 1; break; case BICC_BNE: eicc = ~(ICC_Z); break; case BICC_BG: eicc = ~(ICC_Z | (ICC_N ^ ICC_V)); break; case BICC_BGE: eicc = ~(ICC_N ^ ICC_V); break; case BICC_BGU: eicc = ~(ICC_C | ICC_Z); break; case BICC_BCC: eicc = ~(ICC_C); break; case BICC_POS: eicc = ~(ICC_N); break; case BICC_BVC: eicc = ~(ICC_V); break; } if (eicc & 1) { operand1 = sregs->inst; operand1 = ((operand1 << 10) >> 8); /* sign extend */ npc = sregs->pc + operand1; } else { if (sregs->inst & 0x20000000) sregs->annul = 1; } break; case FPBCC:#ifdef STAT sregs->nbranch++;#endif if (!((sregs->psr & PSR_EF) && FP_PRES)) { sregs->trap = TRAP_FPDIS; break; } if (ebase.simtime < sregs->ftime) { sregs->ftime = ebase.simtime + sregs->hold; } cond = ((sregs->inst >> 25) & 0x0f); fcc = (sregs->fsr >> 10) & 0x3; switch (cond) { case FBN: eicc = 0; break; case FBNE: eicc = (fcc != FCC_E); break; case FBLG: eicc = (fcc == FCC_L) || (fcc == FCC_G); break; case FBUL: eicc = (fcc == FCC_L) || (fcc == FCC_U); break; case FBL: eicc = (fcc == FCC_L); break; case FBUG: eicc = (fcc == FCC_G) || (fcc == FCC_U); break; case FBG: eicc = (fcc == FCC_G); break; case FBU: eicc = (fcc == FCC_U); break; case FBA: eicc = 1; if (sregs->inst & 0x20000000) sregs->annul = 1; break; case FBE: eicc = !(fcc != FCC_E); break; case FBUE: eicc = !((fcc == FCC_L) || (fcc == FCC_G)); break; case FBGE: eicc = !((fcc == FCC_L) || (fcc == FCC_U)); break; case FBUGE: eicc = !(fcc == FCC_L); break; case FBLE: eicc = !((fcc == FCC_G) || (fcc == FCC_U)); break; case FBULE: eicc = !(fcc == FCC_G); break; case FBO: eicc = !(fcc == FCC_U); break; } if (eicc) { operand1 = sregs->inst; operand1 = ((operand1 << 10) >> 8); /* sign extend */ npc = sregs->pc + operand1; } else { if (sregs->inst & 0x20000000) sregs->annul = 1; } break; default: sregs->trap = TRAP_UNIMP; break; } break; case 1: /* CALL */#ifdef STAT sregs->nbranch++;#endif sregs->r[(cwp + 15) & 0x7f] = sregs->pc; npc = sregs->pc + (sregs->inst << 2); break; case 2: if ((op3 >> 1) == 0x1a) { if (!((sregs->psr & PSR_EF) && FP_PRES)) { sregs->trap = TRAP_FPDIS; } else { rs1 = (sregs->inst >> 14) & 0x1f; rs2 = sregs->inst & 0x1f; sregs->trap = fpexec(op3, rd, rs1, rs2, sregs); } } else { switch (op3) { case TICC: icc = sregs->psr >> 20; cond = ((sregs->inst >> 25) & 0x0f); switch (cond) { case BICC_BN: eicc = 0; break; case BICC_BE: eicc = ICC_Z; break; case BICC_BLE: eicc = ICC_Z | (ICC_N ^ ICC_V); break; case BICC_BL: eicc = (ICC_N ^ ICC_V); break; case BICC_BLEU: eicc = ICC_C | ICC_Z; break; case BICC_BCS: eicc = ICC_C; break; case BICC_NEG: eicc = ICC_N; break; case BICC_BVS: eicc = ICC_V; break; case BICC_BA: eicc = 1; break; case BICC_BNE: eicc = ~(ICC_Z); break; case BICC_BG: eicc = ~(ICC_Z | (ICC_N ^ ICC_V)); break; case BICC_BGE: eicc = ~(ICC_N ^ ICC_V); break; case BICC_BGU: eicc = ~(ICC_C | ICC_Z); break; case BICC_BCC: eicc = ~(ICC_C); break; case BICC_POS: eicc = ~(ICC_N); break; case BICC_BVC: eicc = ~(ICC_V); break; } if (eicc & 1) { sregs->trap = (0x80 | ((rs1 + operand2) & 0x7f)); } break; case MULScc: operand1 = (((sregs->psr & PSR_V) ^ ((sregs->psr & PSR_N) >> 2))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -