diff options
Diffstat (limited to 'sim/sh64/sh64.c')
-rw-r--r-- | sim/sh64/sh64.c | 1030 |
1 files changed, 1030 insertions, 0 deletions
diff --git a/sim/sh64/sh64.c b/sim/sh64/sh64.c new file mode 100644 index 0000000..55c90e6 --- /dev/null +++ b/sim/sh64/sh64.c @@ -0,0 +1,1030 @@ +/* SH5 simulator support code + Copyright (C) 2000, 2001 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 2, 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., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#define WANT_CPU +#define WANT_CPU_SH64 + +#include "sim-main.h" +#include "sim-fpu.h" +#include "cgen-mem.h" +#include "cgen-ops.h" + +#include "callback.h" +#include "defs-compact.h" + +#include "bfd.h" +/* From include/. */ +#include "sim-sh64.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); + } +} + +/* 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); +} + +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 }, + { "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 }, + { "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 sh3_mach = +{ + "sh3", "sh3", MACH_SH5, + 16, 16, &sh_models[1], &sh5_imp_properties, + shcompact_init_cpu, + sh64_prepare_run +}; + +const MACH sh3e_mach = +{ + "sh3e", "sh3e", MACH_SH5, + 16, 16, &sh_models[2], &sh5_imp_properties, + shcompact_init_cpu, + sh64_prepare_run +}; + +const MACH sh4_mach = +{ + "sh4", "sh4", MACH_SH5, + 16, 16, &sh_models[3], &sh5_imp_properties, + shcompact_init_cpu, + sh64_prepare_run +}; + +const MACH sh5_mach = +{ + "sh5", "sh5", MACH_SH5, + 32, 32, &sh_models[4], &sh5_imp_properties, + shmedia_init_cpu, + sh64_prepare_run +}; |