| #include "sim-main.h" |
| #include "targ-vals.h" |
| |
| #ifdef HAVE_UTIME_H |
| #include <utime.h> |
| #endif |
| |
| #ifdef HAVE_TIME_H |
| #include <time.h> |
| #endif |
| |
| #ifdef HAVE_UNISTD_H |
| #include <unistd.h> |
| #endif |
| |
| #ifdef HAVE_STRING_H |
| #include <string.h> |
| #else |
| #ifdef HAVE_STRINGS_H |
| #include <strings.h> |
| #endif |
| #endif |
| #include <sys/stat.h> |
| #include <sys/times.h> |
| #include <sys/time.h> |
| |
| |
| |
| #define REG0(X) ((X) & 0x3) |
| #define REG1(X) (((X) & 0xc) >> 2) |
| #define REG0_4(X) (((X) & 0x30) >> 4) |
| #define REG0_8(X) (((X) & 0x300) >> 8) |
| #define REG1_8(X) (((X) & 0xc00) >> 10) |
| #define REG0_16(X) (((X) & 0x30000) >> 16) |
| #define REG1_16(X) (((X) & 0xc0000) >> 18) |
| |
| |
| INLINE_SIM_MAIN (void) |
| genericAdd(unsigned long source, unsigned long destReg) |
| { |
| int z, c, n, v; |
| unsigned long dest, sum; |
| |
| dest = State.regs[destReg]; |
| sum = source + dest; |
| State.regs[destReg] = sum; |
| |
| z = (sum == 0); |
| n = (sum & 0x80000000); |
| c = (sum < source) || (sum < dest); |
| v = ((dest & 0x80000000) == (source & 0x80000000) |
| && (dest & 0x80000000) != (sum & 0x80000000)); |
| |
| PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V); |
| PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0) |
| | (c ? PSW_C : 0) | (v ? PSW_V : 0)); |
| } |
| |
| |
| |
| |
| INLINE_SIM_MAIN (void) |
| genericSub(unsigned long source, unsigned long destReg) |
| { |
| int z, c, n, v; |
| unsigned long dest, difference; |
| |
| dest = State.regs[destReg]; |
| difference = dest - source; |
| State.regs[destReg] = difference; |
| |
| z = (difference == 0); |
| n = (difference & 0x80000000); |
| c = (source > dest); |
| v = ((dest & 0x80000000) != (source & 0x80000000) |
| && (dest & 0x80000000) != (difference & 0x80000000)); |
| |
| PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V); |
| PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0) |
| | (c ? PSW_C : 0) | (v ? PSW_V : 0)); |
| } |
| |
| INLINE_SIM_MAIN (void) |
| genericCmp(unsigned long leftOpnd, unsigned long rightOpnd) |
| { |
| int z, c, n, v; |
| unsigned long value; |
| |
| value = rightOpnd - leftOpnd; |
| |
| z = (value == 0); |
| n = (value & 0x80000000); |
| c = (leftOpnd > rightOpnd); |
| v = ((rightOpnd & 0x80000000) != (leftOpnd & 0x80000000) |
| && (rightOpnd & 0x80000000) != (value & 0x80000000)); |
| |
| PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V); |
| PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0) |
| | (c ? PSW_C : 0) | (v ? PSW_V : 0)); |
| } |
| |
| |
| INLINE_SIM_MAIN (void) |
| genericOr(unsigned long source, unsigned long destReg) |
| { |
| int n, z; |
| |
| State.regs[destReg] |= source; |
| z = (State.regs[destReg] == 0); |
| n = (State.regs[destReg] & 0x80000000) != 0; |
| PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V); |
| PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0)); |
| } |
| |
| |
| INLINE_SIM_MAIN (void) |
| genericXor(unsigned long source, unsigned long destReg) |
| { |
| int n, z; |
| |
| State.regs[destReg] ^= source; |
| z = (State.regs[destReg] == 0); |
| n = (State.regs[destReg] & 0x80000000) != 0; |
| PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V); |
| PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0)); |
| } |
| |
| |
| INLINE_SIM_MAIN (void) |
| genericBtst(unsigned long leftOpnd, unsigned long rightOpnd) |
| { |
| unsigned long temp; |
| int z, n; |
| |
| temp = rightOpnd; |
| temp &= leftOpnd; |
| n = (temp & 0x80000000) != 0; |
| z = (temp == 0); |
| PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V); |
| PSW |= (z ? PSW_Z : 0) | (n ? PSW_N : 0); |
| } |
| |
| /* Read/write functions for system call interface. */ |
| INLINE_SIM_MAIN (int) |
| syscall_read_mem (host_callback *cb, struct cb_syscall *sc, |
| unsigned long taddr, char *buf, int bytes) |
| { |
| SIM_DESC sd = (SIM_DESC) sc->p1; |
| sim_cpu *cpu = STATE_CPU(sd, 0); |
| |
| return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes); |
| } |
| |
| INLINE_SIM_MAIN (int) |
| syscall_write_mem (host_callback *cb, struct cb_syscall *sc, |
| unsigned long taddr, const char *buf, int bytes) |
| { |
| SIM_DESC sd = (SIM_DESC) sc->p1; |
| sim_cpu *cpu = STATE_CPU(sd, 0); |
| |
| return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes); |
| } |
| |
| |
| /* syscall */ |
| INLINE_SIM_MAIN (void) |
| do_syscall () |
| { |
| |
| /* We use this for simulated system calls; we may need to change |
| it to a reserved instruction if we conflict with uses at |
| Matsushita. */ |
| int save_errno = errno; |
| errno = 0; |
| |
| /* Registers passed to trap 0 */ |
| |
| /* Function number. */ |
| #define FUNC (State.regs[0]) |
| |
| /* Parameters. */ |
| #define PARM1 (State.regs[1]) |
| #define PARM2 (load_word (State.regs[REG_SP] + 12)) |
| #define PARM3 (load_word (State.regs[REG_SP] + 16)) |
| |
| /* Registers set by trap 0 */ |
| |
| #define RETVAL State.regs[0] /* return value */ |
| #define RETERR State.regs[1] /* return error code */ |
| |
| /* Turn a pointer in a register into a pointer into real memory. */ |
| #define MEMPTR(x) (State.mem + x) |
| |
| if ( FUNC == TARGET_SYS_exit ) |
| { |
| /* EXIT - caller can look in PARM1 to work out the reason */ |
| if (PARM1 == 0xdead) |
| State.exception = SIGABRT; |
| else |
| { |
| sim_engine_halt (simulator, STATE_CPU (simulator, 0), NULL, PC, |
| sim_exited, PARM1); |
| State.exception = SIGQUIT; |
| } |
| State.exited = 1; |
| } |
| else |
| { |
| CB_SYSCALL syscall; |
| |
| CB_SYSCALL_INIT (&syscall); |
| syscall.arg1 = PARM1; |
| syscall.arg2 = PARM2; |
| syscall.arg3 = PARM3; |
| syscall.func = FUNC; |
| syscall.p1 = (PTR) simulator; |
| syscall.read_mem = syscall_read_mem; |
| syscall.write_mem = syscall_write_mem; |
| cb_syscall (STATE_CALLBACK (simulator), &syscall); |
| RETERR = syscall.errcode; |
| RETVAL = syscall.result; |
| } |
| |
| |
| errno = save_errno; |
| } |
| |