diff options
author | Jiri Gaisler <jiri@gaisler.se> | 2019-03-22 10:00:07 +0100 |
---|---|---|
committer | Jiri Gaisler <jiri@gaisler.se> | 2019-05-14 22:26:21 +0200 |
commit | 865b177d0e2fd534270ef158030e7c3056a930e3 (patch) | |
tree | 4edbf27496977adaed90287d11eaffbe357ac757 /exec.c |
Standalone sis - initial commit
Diffstat (limited to 'exec.c')
-rw-r--r-- | exec.c | 177 |
1 files changed, 177 insertions, 0 deletions
@@ -0,0 +1,177 @@ +/* This file is part of SIS (SPARC instruction simulator) + + Copyright (C) 1995-2017 Free Software Foundation, Inc. + Contributed by 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 3 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, see <http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "sis.h" +#include <inttypes.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> + +int ext_irl[NCPU]; + +#define SIGN_BIT 0x80000000 + +/* Add two unsigned 32-bit integers, and calculate the carry out. */ + +static uint32 +add32 (uint32 n1, uint32 n2, int *carry) +{ + uint32 result = n1 + n2; + + *carry = result < n1 || result < n2; + return result; +} + +/* Multiply two 32-bit integers. */ + +void +mul64 (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. */ + +void +div64 (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); +} + +void +init_regs(sregs) + struct pstate *sregs; +{ + int i; + + ebase.wphit = 0; + + for (i=0; i<NCPU; i++) { + sregs[i].pc = 0; + sregs[i].npc = 4; + sregs[i].trap = 0; + sregs[i].psr &= 0x00f03fdf; + if (cputype == CPU_LEON3) + sregs[i].psr |= 0xF3000080; /* Set supervisor bit */ + else + if (cputype == CPU_LEON2) + sregs[i].psr |= 0x00000080; /* Set supervisor bit */ + else + sregs[i].psr |= 0x11000080; /* Set supervisor bit */ + sregs[i].breakpoint = 0; + sregs[i].fpstate = 0; + sregs[i].fpqn = 0; + sregs[i].ftime = 0; + sregs[i].ltime = 0; + sregs[i].err_mode = 0; + ext_irl[i] = 0; + sregs[i].g[0] = 0; + sregs[i].fs = (float32 *) sregs[i].fd; + sregs[i].fsi = (int32 *) sregs[i].fd; + sregs[i].fsr = 0; + sregs[i].fpu_pres = !nfp; + set_fsr(sregs[i].fsr); + sregs[i].ildreg = 0; + sregs[i].ildtime = 0; + + sregs[i].y = 0; + sregs[i].asr17 = 0; + + sregs[i].rett_err = 0; + sregs[i].jmpltime = 0; + if (cputype == CPU_LEON3) { + sregs[i].asr17 = 0x04000107 | (i << 28); + if (!nfp) sregs[i].asr17 |= (3 << 10); /* Meiko FPU */ + } + sregs[i].cpu = i; + sregs[i].simtime = 0; + sregs[i].pwdtime = 0; + sregs[i].pwdstart = 0; + if (i == 0) + sregs[i].pwd_mode = 0; + else + sregs[i].pwd_mode = 1; + sregs[i].mip = 0; + sregs[i].mstatus = 0; + sregs[i].mie = 0; + sregs[i].mpp = 0; + sregs[i].mode = 1; + sregs[i].lrq = 0; + sregs[i].bphit = 0; + } +} |