/* SH5 simulator support code Copyright (C) 2000, 2001, 2006, 2008, 2009, 2010, 2011 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. */ } /* Count the number of arguments. */ static int count_argc (cpu) SIM_CPU *cpu; { int i = 0; if (! STATE_PROG_ARGV (CPU_STATE (cpu))) return -1; while (STATE_PROG_ARGV (CPU_STATE (cpu)) [i] != NULL) ++i; return i; } /* 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)); zfree (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); zfree (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)); zfree (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, count_argc (current_cpu)); break; case SYS_argnlen: if (PARM1 < count_argc (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 < count_argc (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 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 MACH_IMP_PROPERTIES sh5_imp_properties = { sizeof (SIM_CPU), #if WITH_SCACHE sizeof (SCACHE) #else 0 #endif }; const MACH sh2_mach = { "sh2", "sh2", MACH_SH5, 16, 16, &sh_models[0], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const MACH sh2e_mach = { "sh2e", "sh2e", MACH_SH5, 16, 16, &sh_models[1], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const MACH sh2a_fpu_mach = { "sh2a", "sh2a", MACH_SH5, 16, 16, &sh_models[2], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const 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 MACH sh3_mach = { "sh3", "sh3", MACH_SH5, 16, 16, &sh_models[4], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const MACH sh3e_mach = { "sh3e", "sh3e", MACH_SH5, 16, 16, &sh_models[5], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const MACH sh4_mach = { "sh4", "sh4", MACH_SH5, 16, 16, &sh_models[6], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const 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 MACH sh4a_mach = { "sh4a", "sh4a", MACH_SH5, 16, 16, &sh_models[8], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const 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 MACH sh4al_mach = { "sh4al", "sh4al", MACH_SH5, 16, 16, &sh_models[10], &sh5_imp_properties, shcompact_init_cpu, sh64_prepare_run }; const MACH sh5_mach = { "sh5", "sh5", MACH_SH5, 32, 32, &sh_models[11], &sh5_imp_properties, shmedia_init_cpu, sh64_prepare_run };