/* SH5 simulator support code Copyright (C) 2000-2020 Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of the GNU simulators. 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 . */ #define WANT_CPU #define WANT_CPU_SH64 #include "sim-main.h" #include "sim-fpu.h" #include "cgen-mem.h" #include "cgen-ops.h" #include "gdb/callback.h" #include "defs-compact.h" #include "bfd.h" /* From include/gdb/. */ #include "gdb/sim-sh.h" #define SYS_exit 1 #define SYS_read 3 #define SYS_write 4 #define SYS_open 5 #define SYS_close 6 #define SYS_lseek 19 #define SYS_time 23 #define SYS_argc 172 #define SYS_argnlen 173 #define SYS_argn 174 IDESC * sh64_idesc_media; IDESC * sh64_idesc_compact; BI sh64_endian (SIM_CPU *current_cpu) { return (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN); } SF sh64_fldi0 (SIM_CPU *current_cpu) { SF result; sim_fpu_to32 (&result, &sim_fpu_zero); return result; } SF sh64_fldi1 (SIM_CPU *current_cpu) { SF result; sim_fpu_to32 (&result, &sim_fpu_one); return result; } DF sh64_fabsd(SIM_CPU *current_cpu, DF drgh) { DF result; sim_fpu f, fres; sim_fpu_64to (&f, drgh); sim_fpu_abs (&fres, &f); sim_fpu_to64 (&result, &fres); return result; } SF sh64_fabss(SIM_CPU *current_cpu, SF frgh) { SF result; sim_fpu f, fres; sim_fpu_32to (&f, frgh); sim_fpu_abs (&fres, &f); sim_fpu_to32 (&result, &fres); return result; } DF sh64_faddd(SIM_CPU *current_cpu, DF drg, DF drh) { DF result; sim_fpu f1, f2, fres; sim_fpu_64to (&f1, drg); sim_fpu_64to (&f2, drh); sim_fpu_add (&fres, &f1, &f2); sim_fpu_to64 (&result, &fres); return result; } SF sh64_fadds(SIM_CPU *current_cpu, SF frg, SF frh) { SF result; sim_fpu f1, f2, fres; sim_fpu_32to (&f1, frg); sim_fpu_32to (&f2, frh); sim_fpu_add (&fres, &f1, &f2); sim_fpu_to32 (&result, &fres); return result; } BI sh64_fcmpeqd(SIM_CPU *current_cpu, DF drg, DF drh) { sim_fpu f1, f2; sim_fpu_64to (&f1, drg); sim_fpu_64to (&f2, drh); return sim_fpu_is_eq (&f1, &f2); } BI sh64_fcmpeqs(SIM_CPU *current_cpu, SF frg, SF frh) { sim_fpu f1, f2; sim_fpu_32to (&f1, frg); sim_fpu_32to (&f2, frh); return sim_fpu_is_eq (&f1, &f2); } BI sh64_fcmpged(SIM_CPU *current_cpu, DF drg, DF drh) { sim_fpu f1, f2; sim_fpu_64to (&f1, drg); sim_fpu_64to (&f2, drh); return sim_fpu_is_ge (&f1, &f2); } BI sh64_fcmpges(SIM_CPU *current_cpu, SF frg, SF frh) { sim_fpu f1, f2; sim_fpu_32to (&f1, frg); sim_fpu_32to (&f2, frh); return sim_fpu_is_ge (&f1, &f2); } BI sh64_fcmpgtd(SIM_CPU *current_cpu, DF drg, DF drh) { sim_fpu f1, f2; sim_fpu_64to (&f1, drg); sim_fpu_64to (&f2, drh); return sim_fpu_is_gt (&f1, &f2); } BI sh64_fcmpgts(SIM_CPU *current_cpu, SF frg, SF frh) { sim_fpu f1, f2; sim_fpu_32to (&f1, frg); sim_fpu_32to (&f2, frh); return sim_fpu_is_gt (&f1, &f2); } BI sh64_fcmpund(SIM_CPU *current_cpu, DF drg, DF drh) { sim_fpu f1, f2; sim_fpu_64to (&f1, drg); sim_fpu_64to (&f2, drh); return (sim_fpu_is_nan (&f1) || sim_fpu_is_nan (&f2)); } BI sh64_fcmpuns(SIM_CPU *current_cpu, SF frg, SF frh) { sim_fpu f1, f2; sim_fpu_32to (&f1, frg); sim_fpu_32to (&f2, frh); return (sim_fpu_is_nan (&f1) || sim_fpu_is_nan (&f2)); } SF sh64_fcnvds(SIM_CPU *current_cpu, DF drgh) { union { unsigned long long ll; double d; } f1; union { unsigned long l; float f; } f2; f1.ll = drgh; f2.f = (float) f1.d; return (SF) f2.l; } DF sh64_fcnvsd(SIM_CPU *current_cpu, SF frgh) { DF result; sim_fpu f; sim_fpu_32to (&f, frgh); sim_fpu_to64 (&result, &f); return result; } DF sh64_fdivd(SIM_CPU *current_cpu, DF drg, DF drh) { DF result; sim_fpu f1, f2, fres; sim_fpu_64to (&f1, drg); sim_fpu_64to (&f2, drh); sim_fpu_div (&fres, &f1, &f2); sim_fpu_to64 (&result, &fres); return result; } SF sh64_fdivs(SIM_CPU *current_cpu, SF frg, SF frh) { SF result; sim_fpu f1, f2, fres; sim_fpu_32to (&f1, frg); sim_fpu_32to (&f2, frh); sim_fpu_div (&fres, &f1, &f2); sim_fpu_to32 (&result, &fres); return result; } DF sh64_floatld(SIM_CPU *current_cpu, SF frgh) { DF result; sim_fpu f; sim_fpu_i32to (&f, frgh, sim_fpu_round_default); sim_fpu_to64 (&result, &f); return result; } SF sh64_floatls(SIM_CPU *current_cpu, SF frgh) { SF result; sim_fpu f; sim_fpu_i32to (&f, frgh, sim_fpu_round_default); sim_fpu_to32 (&result, &f); return result; } DF sh64_floatqd(SIM_CPU *current_cpu, DF drgh) { DF result; sim_fpu f; sim_fpu_i64to (&f, drgh, sim_fpu_round_default); sim_fpu_to64 (&result, &f); return result; } SF sh64_floatqs(SIM_CPU *current_cpu, DF drgh) { SF result; sim_fpu f; sim_fpu_i64to (&f, drgh, sim_fpu_round_default); sim_fpu_to32 (&result, &f); return result; } SF sh64_fmacs(SIM_CPU *current_cpu, SF fr0, SF frm, SF frn) { SF result; sim_fpu m1, m2, a1, fres; sim_fpu_32to (&m1, fr0); sim_fpu_32to (&m2, frm); sim_fpu_32to (&a1, frn); sim_fpu_mul (&fres, &m1, &m2); sim_fpu_add (&fres, &fres, &a1); sim_fpu_to32 (&result, &fres); return result; } DF sh64_fmuld(SIM_CPU *current_cpu, DF drg, DF drh) { DF result; sim_fpu f1, f2, fres; sim_fpu_64to (&f1, drg); sim_fpu_64to (&f2, drh); sim_fpu_mul (&fres, &f1, &f2); sim_fpu_to64 (&result, &fres); return result; } SF sh64_fmuls(SIM_CPU *current_cpu, SF frg, SF frh) { SF result; sim_fpu f1, f2, fres; sim_fpu_32to (&f1, frg); sim_fpu_32to (&f2, frh); sim_fpu_mul (&fres, &f1, &f2); sim_fpu_to32 (&result, &fres); return result; } DF sh64_fnegd(SIM_CPU *current_cpu, DF drgh) { DF result; sim_fpu f1, f2; sim_fpu_64to (&f1, drgh); sim_fpu_neg (&f2, &f1); sim_fpu_to64 (&result, &f2); return result; } SF sh64_fnegs(SIM_CPU *current_cpu, SF frgh) { SF result; sim_fpu f, fres; sim_fpu_32to (&f, frgh); sim_fpu_neg (&fres, &f); sim_fpu_to32 (&result, &fres); return result; } DF sh64_fsqrtd(SIM_CPU *current_cpu, DF drgh) { DF result; sim_fpu f, fres; sim_fpu_64to (&f, drgh); sim_fpu_sqrt (&fres, &f); sim_fpu_to64 (&result, &fres); return result; } SF sh64_fsqrts(SIM_CPU *current_cpu, SF frgh) { SF result; sim_fpu f, fres; sim_fpu_32to (&f, frgh); sim_fpu_sqrt (&fres, &f); sim_fpu_to32 (&result, &fres); return result; } DF sh64_fsubd(SIM_CPU *current_cpu, DF drg, DF drh) { DF result; sim_fpu f1, f2, fres; sim_fpu_64to (&f1, drg); sim_fpu_64to (&f2, drh); sim_fpu_sub (&fres, &f1, &f2); sim_fpu_to64 (&result, &fres); return result; } SF sh64_fsubs(SIM_CPU *current_cpu, SF frg, SF frh) { SF result; sim_fpu f1, f2, fres; sim_fpu_32to (&f1, frg); sim_fpu_32to (&f2, frh); sim_fpu_sub (&fres, &f1, &f2); sim_fpu_to32 (&result, &fres); return result; } SF sh64_ftrcdl(SIM_CPU *current_cpu, DF drgh) { SI result; sim_fpu f; sim_fpu_64to (&f, drgh); sim_fpu_to32i (&result, &f, sim_fpu_round_zero); return (SF) result; } SF sh64_ftrcsl(SIM_CPU *current_cpu, SF frgh) { SI result; sim_fpu f; sim_fpu_32to (&f, frgh); sim_fpu_to32i (&result, &f, sim_fpu_round_zero); return (SF) result; } DF sh64_ftrcdq(SIM_CPU *current_cpu, DF drgh) { DI result; sim_fpu f; sim_fpu_64to (&f, drgh); sim_fpu_to64i (&result, &f, sim_fpu_round_zero); return (DF) result; } DF sh64_ftrcsq(SIM_CPU *current_cpu, SF frgh) { DI result; sim_fpu f; sim_fpu_32to (&f, frgh); sim_fpu_to64i (&result, &f, sim_fpu_round_zero); return (DF) result; } VOID sh64_ftrvs(SIM_CPU *cpu, unsigned g, unsigned h, unsigned f) { int i, j; for (i = 0; i < 4; i++) { SF result; sim_fpu sum; sim_fpu_32to (&sum, 0); for (j = 0; j < 4; j++) { sim_fpu f1, f2, temp; sim_fpu_32to (&f1, sh64_h_fr_get (cpu, (g + i) + (j * 4))); sim_fpu_32to (&f2, sh64_h_fr_get (cpu, h + j)); sim_fpu_mul (&temp, &f1, &f2); sim_fpu_add (&sum, &sum, &temp); } sim_fpu_to32 (&result, &sum); sh64_h_fr_set (cpu, f + i, result); } } VOID sh64_fipr (SIM_CPU *cpu, unsigned m, unsigned n) { SF result = sh64_fmuls (cpu, sh64_h_fvc_get (cpu, m), sh64_h_fvc_get (cpu, n)); result = sh64_fadds (cpu, result, sh64_fmuls (cpu, sh64_h_frc_get (cpu, m + 1), sh64_h_frc_get (cpu, n + 1))); result = sh64_fadds (cpu, result, sh64_fmuls (cpu, sh64_h_frc_get (cpu, m + 2), sh64_h_frc_get (cpu, n + 2))); result = sh64_fadds (cpu, result, sh64_fmuls (cpu, sh64_h_frc_get (cpu, m + 3), sh64_h_frc_get (cpu, n + 3))); sh64_h_frc_set (cpu, n + 3, result); } SF sh64_fiprs (SIM_CPU *cpu, unsigned g, unsigned h) { SF temp = sh64_fmuls (cpu, sh64_h_fr_get (cpu, g), sh64_h_fr_get (cpu, h)); temp = sh64_fadds (cpu, temp, sh64_fmuls (cpu, sh64_h_fr_get (cpu, g + 1), sh64_h_fr_get (cpu, h + 1))); temp = sh64_fadds (cpu, temp, sh64_fmuls (cpu, sh64_h_fr_get (cpu, g + 2), sh64_h_fr_get (cpu, h + 2))); temp = sh64_fadds (cpu, temp, sh64_fmuls (cpu, sh64_h_fr_get (cpu, g + 3), sh64_h_fr_get (cpu, h + 3))); return temp; } VOID sh64_fldp (SIM_CPU *cpu, PCADDR pc, DI rm, DI rn, unsigned f) { sh64_h_fr_set (cpu, f, GETMEMSF (cpu, pc, rm + rn)); sh64_h_fr_set (cpu, f + 1, GETMEMSF (cpu, pc, rm + rn + 4)); } VOID sh64_fstp (SIM_CPU *cpu, PCADDR pc, DI rm, DI rn, unsigned f) { SETMEMSF (cpu, pc, rm + rn, sh64_h_fr_get (cpu, f)); SETMEMSF (cpu, pc, rm + rn + 4, sh64_h_fr_get (cpu, f + 1)); } VOID sh64_ftrv (SIM_CPU *cpu, UINT ignored) { /* TODO: Unimplemented. */ } VOID sh64_pref (SIM_CPU *cpu, SI addr) { /* TODO: Unimplemented. */ } /* Read a null terminated string from memory, return in a buffer */ static char * fetch_str (current_cpu, pc, addr) SIM_CPU *current_cpu; PCADDR pc; DI addr; { char *buf; int nr = 0; while (sim_core_read_1 (current_cpu, pc, read_map, addr + nr) != 0) nr++; buf = NZALLOC (char, nr + 1); sim_read (CPU_STATE (current_cpu), addr, buf, nr); return buf; } static void trap_handler (SIM_CPU *current_cpu, int shmedia_abi_p, UQI trapnum, PCADDR pc) { char ch; switch (trapnum) { case 1: ch = GET_H_GRC (0); sim_io_write_stdout (CPU_STATE (current_cpu), &ch, 1); fflush (stdout); break; case 2: sim_engine_halt (CPU_STATE (current_cpu), current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP); break; case 34: { int i; int ret_reg = (shmedia_abi_p) ? 2 : 0; char *buf; DI PARM1 = GET_H_GR ((shmedia_abi_p) ? 3 : 5); DI PARM2 = GET_H_GR ((shmedia_abi_p) ? 4 : 6); DI PARM3 = GET_H_GR ((shmedia_abi_p) ? 5 : 7); switch (GET_H_GR ((shmedia_abi_p) ? 2 : 4)) { case SYS_write: buf = zalloc (PARM3); sim_read (CPU_STATE (current_cpu), PARM2, buf, PARM3); SET_H_GR (ret_reg, sim_io_write (CPU_STATE (current_cpu), PARM1, buf, PARM3)); free (buf); break; case SYS_lseek: SET_H_GR (ret_reg, sim_io_lseek (CPU_STATE (current_cpu), PARM1, PARM2, PARM3)); break; case SYS_exit: sim_engine_halt (CPU_STATE (current_cpu), current_cpu, NULL, pc, sim_exited, PARM1); break; case SYS_read: buf = zalloc (PARM3); SET_H_GR (ret_reg, sim_io_read (CPU_STATE (current_cpu), PARM1, buf, PARM3)); sim_write (CPU_STATE (current_cpu), PARM2, buf, PARM3); free (buf); break; case SYS_open: buf = fetch_str (current_cpu, pc, PARM1); SET_H_GR (ret_reg, sim_io_open (CPU_STATE (current_cpu), buf, PARM2)); free (buf); break; case SYS_close: SET_H_GR (ret_reg, sim_io_close (CPU_STATE (current_cpu), PARM1)); break; case SYS_time: SET_H_GR (ret_reg, time (0)); break; case SYS_argc: SET_H_GR (ret_reg, countargv (STATE_PROG_ARGV (CPU_STATE (current_cpu)))); break; case SYS_argnlen: if (PARM1 < countargv (STATE_PROG_ARGV (CPU_STATE (current_cpu)))) SET_H_GR (ret_reg, strlen (STATE_PROG_ARGV (CPU_STATE (current_cpu)) [PARM1])); else SET_H_GR (ret_reg, -1); break; case SYS_argn: if (PARM1 < countargv (STATE_PROG_ARGV (CPU_STATE (current_cpu)))) { /* Include the NULL byte. */ i = strlen (STATE_PROG_ARGV (CPU_STATE (current_cpu)) [PARM1]) + 1; sim_write (CPU_STATE (current_cpu), PARM2, STATE_PROG_ARGV (CPU_STATE (current_cpu)) [PARM1], i); /* Just for good measure. */ SET_H_GR (ret_reg, i); break; } else SET_H_GR (ret_reg, -1); break; default: SET_H_GR (ret_reg, -1); } } break; case 253: puts ("pass"); exit (0); case 254: puts ("fail"); exit (1); case 0xc3: /* fall through. */ case 255: sim_engine_halt (CPU_STATE (current_cpu), current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP); break; } } void sh64_trapa (SIM_CPU *current_cpu, DI rm, PCADDR pc) { trap_handler (current_cpu, 1, (UQI) rm & 0xff, pc); } void sh64_compact_trapa (SIM_CPU *current_cpu, UQI trapnum, PCADDR pc) { int mach_sh5_p; /* If this is an SH5 executable, this is SHcompact code running in the SHmedia ABI. */ mach_sh5_p = (bfd_get_mach (STATE_PROG_BFD (CPU_STATE (current_cpu))) == bfd_mach_sh5); trap_handler (current_cpu, mach_sh5_p, trapnum, pc); } DI sh64_nsb (SIM_CPU *current_cpu, DI rm) { int result = 0, count; UDI source = (UDI) rm; if ((source >> 63)) source = ~source; source <<= 1; for (count = 32; count; count >>= 1) { UDI newval = source << count; if ((newval >> count) == source) { result |= count; source = newval; } } return result; } void sh64_break (SIM_CPU *current_cpu, PCADDR pc) { SIM_DESC sd = CPU_STATE (current_cpu); sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP); } SI sh64_movua (SIM_CPU *current_cpu, PCADDR pc, SI rn) { SI v; int i; /* Move the data one byte at a time to avoid alignment problems. Be aware of endianness. */ v = 0; for (i = 0; i < 4; ++i) v = (v << 8) | (GETMEMQI (current_cpu, pc, rn + i) & 0xff); v = T2H_4 (v); return v; } void set_isa (SIM_CPU *current_cpu, int mode) { /* Do nothing. */ } /* The semantic code invokes this for invalid (unrecognized) instructions. */ SEM_PC sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc) { SIM_DESC sd = CPU_STATE (current_cpu); sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL); return vpc; } /* Process an address exception. */ void sh64_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia, unsigned int map, int nr_bytes, address_word addr, transfer_type transfer, sim_core_signals sig) { sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr, transfer, sig); } /* Initialize cycle counting for an insn. FIRST_P is non-zero if this is the first insn in a set of parallel insns. */ void sh64_compact_model_insn_before (SIM_CPU *cpu, int first_p) { /* Do nothing. */ } void sh64_media_model_insn_before (SIM_CPU *cpu, int first_p) { /* Do nothing. */ } /* Record the cycles computed for an insn. LAST_P is non-zero if this is the last insn in a set of parallel insns, and we update the total cycle count. CYCLES is the cycle count of the insn. */ void sh64_compact_model_insn_after(SIM_CPU *cpu, int last_p, int cycles) { /* Do nothing. */ } void sh64_media_model_insn_after(SIM_CPU *cpu, int last_p, int cycles) { /* Do nothing. */ } int sh64_fetch_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len) { /* Fetch general purpose registers. */ if (nr >= SIM_SH64_R0_REGNUM && nr < (SIM_SH64_R0_REGNUM + SIM_SH64_NR_R_REGS) && len == 8) { *((unsigned64*) buf) = H2T_8 (sh64_h_gr_get (cpu, nr - SIM_SH64_R0_REGNUM)); return len; } /* Fetch PC. */ if (nr == SIM_SH64_PC_REGNUM && len == 8) { *((unsigned64*) buf) = H2T_8 (sh64_h_pc_get (cpu) | sh64_h_ism_get (cpu)); return len; } /* Fetch status register (SR). */ if (nr == SIM_SH64_SR_REGNUM && len == 8) { *((unsigned64*) buf) = H2T_8 (sh64_h_sr_get (cpu)); return len; } /* Fetch saved status register (SSR) and PC (SPC). */ if ((nr == SIM_SH64_SSR_REGNUM || nr == SIM_SH64_SPC_REGNUM) && len == 8) { *((unsigned64*) buf) = 0; return len; } /* Fetch target registers. */ if (nr >= SIM_SH64_TR0_REGNUM && nr < (SIM_SH64_TR0_REGNUM + SIM_SH64_NR_TR_REGS) && len == 8) { *((unsigned64*) buf) = H2T_8 (sh64_h_tr_get (cpu, nr - SIM_SH64_TR0_REGNUM)); return len; } /* Fetch floating point registers. */ if (nr >= SIM_SH64_FR0_REGNUM && nr < (SIM_SH64_FR0_REGNUM + SIM_SH64_NR_FP_REGS) && len == 4) { *((unsigned32*) buf) = H2T_4 (sh64_h_fr_get (cpu, nr - SIM_SH64_FR0_REGNUM)); return len; } /* We should never get here. */ return 0; } int sh64_store_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len) { /* Store general purpose registers. */ if (nr >= SIM_SH64_R0_REGNUM && nr < (SIM_SH64_R0_REGNUM + SIM_SH64_NR_R_REGS) && len == 8) { sh64_h_gr_set (cpu, nr - SIM_SH64_R0_REGNUM, T2H_8 (*((unsigned64*)buf))); return len; } /* Store PC. */ if (nr == SIM_SH64_PC_REGNUM && len == 8) { unsigned64 new_pc = T2H_8 (*((unsigned64*)buf)); sh64_h_pc_set (cpu, new_pc); return len; } /* Store status register (SR). */ if (nr == SIM_SH64_SR_REGNUM && len == 8) { sh64_h_sr_set (cpu, T2H_8 (*((unsigned64*)buf))); return len; } /* Store saved status register (SSR) and PC (SPC). */ if (nr == SIM_SH64_SSR_REGNUM || nr == SIM_SH64_SPC_REGNUM) { /* Do nothing. */ return len; } /* Store target registers. */ if (nr >= SIM_SH64_TR0_REGNUM && nr < (SIM_SH64_TR0_REGNUM + SIM_SH64_NR_TR_REGS) && len == 8) { sh64_h_tr_set (cpu, nr - SIM_SH64_TR0_REGNUM, T2H_8 (*((unsigned64*)buf))); return len; } /* Store floating point registers. */ if (nr >= SIM_SH64_FR0_REGNUM && nr < (SIM_SH64_FR0_REGNUM + SIM_SH64_NR_FP_REGS) && len == 4) { sh64_h_fr_set (cpu, nr - SIM_SH64_FR0_REGNUM, T2H_4 (*((unsigned32*)buf))); return len; } /* We should never get here. */ return 0; } void sh64_engine_run_full(SIM_CPU *cpu) { if (sh64_h_ism_get (cpu) == ISM_MEDIA) { if (!sh64_idesc_media) { sh64_media_init_idesc_table (cpu); sh64_idesc_media = CPU_IDESC (cpu); } else CPU_IDESC (cpu) = sh64_idesc_media; sh64_media_engine_run_full (cpu); } else { if (!sh64_idesc_compact) { sh64_compact_init_idesc_table (cpu); sh64_idesc_compact = CPU_IDESC (cpu); } else CPU_IDESC (cpu) = sh64_idesc_compact; sh64_compact_engine_run_full (cpu); } } void sh64_engine_run_fast (SIM_CPU *cpu) { if (sh64_h_ism_get (cpu) == ISM_MEDIA) { if (!sh64_idesc_media) { sh64_media_init_idesc_table (cpu); sh64_idesc_media = CPU_IDESC (cpu); } else CPU_IDESC (cpu) = sh64_idesc_media; sh64_media_engine_run_fast (cpu); } else { if (!sh64_idesc_compact) { sh64_compact_init_idesc_table (cpu); sh64_idesc_compact = CPU_IDESC (cpu); } else CPU_IDESC (cpu) = sh64_idesc_compact; sh64_compact_engine_run_fast (cpu); } } static void sh64_prepare_run (SIM_CPU *cpu) { /* Nothing. */ } static const CGEN_INSN * sh64_get_idata (SIM_CPU *cpu, int inum) { return CPU_IDESC (cpu) [inum].idata; } static void sh64_init_cpu (SIM_CPU *cpu) { CPU_REG_FETCH (cpu) = sh64_fetch_register; CPU_REG_STORE (cpu) = sh64_store_register; CPU_PC_FETCH (cpu) = sh64_h_pc_get; CPU_PC_STORE (cpu) = sh64_h_pc_set; CPU_GET_IDATA (cpu) = sh64_get_idata; /* Only used by profiling. 0 disables it. */ CPU_MAX_INSNS (cpu) = 0; CPU_INSN_NAME (cpu) = cgen_insn_name; CPU_FULL_ENGINE_FN (cpu) = sh64_engine_run_full; #if WITH_FAST CPU_FAST_ENGINE_FN (cpu) = sh64_engine_run_fast; #else CPU_FAST_ENGINE_FN (cpu) = sh64_engine_run_full; #endif } static void shmedia_init_cpu (SIM_CPU *cpu) { sh64_init_cpu (cpu); } static void shcompact_init_cpu (SIM_CPU *cpu) { sh64_init_cpu (cpu); } static void sh64_model_init() { /* Do nothing. */ } static const SIM_MODEL sh_models [] = { { "sh2", & sh2_mach, MODEL_SH5, NULL, sh64_model_init }, { "sh2e", & sh2e_mach, MODEL_SH5, NULL, sh64_model_init }, { "sh2a", & sh2a_fpu_mach, MODEL_SH5, NULL, sh64_model_init }, { "sh2a_nofpu", & sh2a_nofpu_mach, MODEL_SH5, NULL, sh64_model_init }, { "sh3", & sh3_mach, MODEL_SH5, NULL, sh64_model_init }, { "sh3e", & sh3_mach, MODEL_SH5, NULL, sh64_model_init }, { "sh4", & sh4_mach, MODEL_SH5, NULL, sh64_model_init }, { "sh4_nofpu", & sh4_nofpu_mach, MODEL_SH5, NULL, sh64_model_init }, { "sh4a", & sh4a_mach, MODEL_SH5, NULL, sh64_model_init }, { "sh4a_nofpu", & sh4a_nofpu_mach, MODEL_SH5, NULL, sh64_model_init }, { "sh4al", & sh4al_mach, MODEL_SH5, NULL, sh64_model_init }, { "sh5", & sh5_mach, MODEL_SH5, NULL, sh64_model_init }, { 0 } }; static const SIM_MACH_IMP_PROPERTIES sh5_imp_properties = { sizeof (SIM_CPU), #if WITH_SCACHE sizeof (SCACHE) #else 0 #endif }; const SIM_MACH sh2_mach = { "sh2", "sh2", MACH_SH5, 16, 16, &sh_models[0], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const SIM_MACH sh2e_mach = { "sh2e", "sh2e", MACH_SH5, 16, 16, &sh_models[1], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const SIM_MACH sh2a_fpu_mach = { "sh2a", "sh2a", MACH_SH5, 16, 16, &sh_models[2], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const SIM_MACH sh2a_nofpu_mach = { "sh2a_nofpu", "sh2a_nofpu", MACH_SH5, 16, 16, &sh_models[3], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const SIM_MACH sh3_mach = { "sh3", "sh3", MACH_SH5, 16, 16, &sh_models[4], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const SIM_MACH sh3e_mach = { "sh3e", "sh3e", MACH_SH5, 16, 16, &sh_models[5], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const SIM_MACH sh4_mach = { "sh4", "sh4", MACH_SH5, 16, 16, &sh_models[6], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const SIM_MACH sh4_nofpu_mach = { "sh4_nofpu", "sh4_nofpu", MACH_SH5, 16, 16, &sh_models[7], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const SIM_MACH sh4a_mach = { "sh4a", "sh4a", MACH_SH5, 16, 16, &sh_models[8], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const SIM_MACH sh4a_nofpu_mach = { "sh4a_nofpu", "sh4a_nofpu", MACH_SH5, 16, 16, &sh_models[9], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const SIM_MACH sh4al_mach = { "sh4al", "sh4al", MACH_SH5, 16, 16, &sh_models[10], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const SIM_MACH sh5_mach = { "sh5", "sh5", MACH_SH5, 32, 32, &sh_models[11], &sh5_imp_properties, shmedia_init_cpu, sh64_prepare_run };