X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fm32r%2Fm32rx.c;h=774eacb95c31470ff045d10e270fa56748153320;hb=17fc27167f678285d2f64040837b8cc41b6a664a;hp=1710428ed8ea8bf29607213fc8ceceb55e03c698;hpb=e98fe4f7b54cbdf29aef9287bbb1bea8801dd05a;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/m32r/m32rx.c b/sim/m32r/m32rx.c index 1710428ed8..774eacb95c 100644 --- a/sim/m32r/m32rx.c +++ b/sim/m32r/m32rx.c @@ -1,112 +1,310 @@ /* m32rx simulator support code - Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1997-2020 Free Software Foundation, Inc. Contributed by Cygnus Support. This file is part of GDB, the GNU debugger. 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. +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, write to the Free Software Foundation, Inc., -59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +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_M32RX +#define WANT_CPU m32rxf +#define WANT_CPU_M32RXF #include "sim-main.h" -#include -#include "libiberty.h" -#include "bfd.h" -/* FIXME: need to provide general mechanism for accessing target files - these. For now this is a hack to avoid getting the host version. */ -#include "../../libgloss/m32r/sys/syscall.h" -#include "targ-vals.h" - +#include "cgen-mem.h" +#include "cgen-ops.h" + +/* The contents of BUF are in target byte order. */ + +int +m32rxf_fetch_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len) +{ + return m32rbf_fetch_register (current_cpu, rn, buf, len); +} + /* The contents of BUF are in target byte order. */ +int +m32rxf_store_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len) +{ + return m32rbf_store_register (current_cpu, rn, buf, len); +} + +/* Cover fns to get/set the control registers. + FIXME: Duplicated from m32r.c. The issue is structure offsets. */ + +USI +m32rxf_h_cr_get_handler (SIM_CPU *current_cpu, UINT cr) +{ + switch (cr) + { + case H_CR_PSW : /* psw */ + return (((CPU (h_bpsw) & 0xc1) << 8) + | ((CPU (h_psw) & 0xc0) << 0) + | GET_H_COND ()); + case H_CR_BBPSW : /* backup backup psw */ + return CPU (h_bbpsw) & 0xc1; + case H_CR_CBR : /* condition bit */ + return GET_H_COND (); + case H_CR_SPI : /* interrupt stack pointer */ + if (! GET_H_SM ()) + return CPU (h_gr[H_GR_SP]); + else + return CPU (h_cr[H_CR_SPI]); + case H_CR_SPU : /* user stack pointer */ + if (GET_H_SM ()) + return CPU (h_gr[H_GR_SP]); + else + return CPU (h_cr[H_CR_SPU]); + case H_CR_BPC : /* backup pc */ + return CPU (h_cr[H_CR_BPC]) & 0xfffffffe; + case H_CR_BBPC : /* backup backup pc */ + return CPU (h_cr[H_CR_BBPC]) & 0xfffffffe; + case 4 : /* ??? unspecified, but apparently available */ + case 5 : /* ??? unspecified, but apparently available */ + return CPU (h_cr[cr]); + default : + return 0; + } +} + void -m32rx_fetch_register (sd, rn, buf) - SIM_DESC sd; - int rn; - unsigned char *buf; -{ - SIM_CPU *current_cpu = STATE_CPU (sd, 0); - - if (rn < 16) - SETTWI (buf, GET_H_GR (rn)); - else if (rn < 21) - SETTWI (buf, GET_H_CR (rn - 16)); - else switch (rn) { - case PC_REGNUM: - SETTWI (buf, GET_H_PC ()); +m32rxf_h_cr_set_handler (SIM_CPU *current_cpu, UINT cr, USI newval) +{ + switch (cr) + { + case H_CR_PSW : /* psw */ + { + int old_sm = (CPU (h_psw) & 0x80) != 0; + int new_sm = (newval & 0x80) != 0; + CPU (h_bpsw) = (newval >> 8) & 0xff; + CPU (h_psw) = newval & 0xff; + SET_H_COND (newval & 1); + /* When switching stack modes, update the registers. */ + if (old_sm != new_sm) + { + if (old_sm) + { + /* Switching user -> system. */ + CPU (h_cr[H_CR_SPU]) = CPU (h_gr[H_GR_SP]); + CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPI]); + } + else + { + /* Switching system -> user. */ + CPU (h_cr[H_CR_SPI]) = CPU (h_gr[H_GR_SP]); + CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPU]); + } + } + break; + } + case H_CR_BBPSW : /* backup backup psw */ + CPU (h_bbpsw) = newval & 0xff; break; - case ACCL_REGNUM: - SETTWI (buf, GETLODI (GET_H_ACCUM ())); + case H_CR_CBR : /* condition bit */ + SET_H_COND (newval & 1); break; - case ACCH_REGNUM: - SETTWI (buf, GETHIDI (GET_H_ACCUM ())); + case H_CR_SPI : /* interrupt stack pointer */ + if (! GET_H_SM ()) + CPU (h_gr[H_GR_SP]) = newval; + else + CPU (h_cr[H_CR_SPI]) = newval; break; -#if 0 - case 23: *reg = STATE_CPU_CPU (sd, 0)->h_cond; break; - case 24: *reg = STATE_CPU_CPU (sd, 0)->h_sm; break; - case 25: *reg = STATE_CPU_CPU (sd, 0)->h_bsm; break; - case 26: *reg = STATE_CPU_CPU (sd, 0)->h_ie; break; - case 27: *reg = STATE_CPU_CPU (sd, 0)->h_bie; break; - case 28: *reg = STATE_CPU_CPU (sd, 0)->h_bcarry; break; /* rename: bc */ - case 29: memcpy (buf, &STATE_CPU_CPU (sd, 0)->h_bpc, sizeof(WI)); break; /* duplicate */ -#endif - default: abort (); - } -} - -/* The contents of BUF are in target byte order. */ - -void -m32rx_store_register (sd, rn, buf) - SIM_DESC sd; - int rn; - unsigned char *buf; -{ - SIM_CPU *current_cpu = STATE_CPU (sd, 0); - - if (rn < 16) - SET_H_GR (rn, GETTWI (buf)); - else if (rn < 21) - SET_H_CR (rn - 16, GETTWI (buf)); - else switch (rn) { - case PC_REGNUM: - SET_H_PC (GETTWI (buf)); + case H_CR_SPU : /* user stack pointer */ + if (GET_H_SM ()) + CPU (h_gr[H_GR_SP]) = newval; + else + CPU (h_cr[H_CR_SPU]) = newval; + break; + case H_CR_BPC : /* backup pc */ + CPU (h_cr[H_CR_BPC]) = newval; break; - case ACCL_REGNUM: - SETLODI (CPU (h_accum), GETTWI (buf)); + case H_CR_BBPC : /* backup backup pc */ + CPU (h_cr[H_CR_BBPC]) = newval; break; - case ACCH_REGNUM: - SETHIDI (CPU (h_accum), GETTWI (buf)); + case 4 : /* ??? unspecified, but apparently available */ + case 5 : /* ??? unspecified, but apparently available */ + CPU (h_cr[cr]) = newval; break; -#if 0 - case 23: STATE_CPU_CPU (sd, 0)->h_cond = *reg; break; - case 24: STATE_CPU_CPU (sd, 0)->h_sm = *reg; break; - case 25: STATE_CPU_CPU (sd, 0)->h_bsm = *reg; break; - case 26: STATE_CPU_CPU (sd, 0)->h_ie = *reg; break; - case 27: STATE_CPU_CPU (sd, 0)->h_bie = *reg; break; - case 28: STATE_CPU_CPU (sd, 0)->h_bcarry = *reg; break; /* rename: bc */ - case 29: memcpy (&STATE_CPU_CPU (sd, 0)->h_bpc, buf, sizeof(DI)); break; /* duplicate */ -#endif - } + default : + /* ignore */ + break; + } +} + +/* Cover fns to access h-psw. */ + +UQI +m32rxf_h_psw_get_handler (SIM_CPU *current_cpu) +{ + return (CPU (h_psw) & 0xfe) | (CPU (h_cond) & 1); } -/* Cover fn to access h-accums. */ +void +m32rxf_h_psw_set_handler (SIM_CPU *current_cpu, UQI newval) +{ + CPU (h_psw) = newval; + CPU (h_cond) = newval & 1; +} -UDI -m32rx_h_accums_get (SIM_CPU *current_cpu, UINT accum) +/* Cover fns to access h-accum. */ + +DI +m32rxf_h_accum_get_handler (SIM_CPU *current_cpu) { - return 0; + /* Sign extend the top 8 bits. */ + DI r; + r = ANDDI (CPU (h_accum), MAKEDI (0xffffff, 0xffffffff)); + r = XORDI (r, MAKEDI (0x800000, 0)); + r = SUBDI (r, MAKEDI (0x800000, 0)); + return r; } + +void +m32rxf_h_accum_set_handler (SIM_CPU *current_cpu, DI newval) +{ + CPU (h_accum) = newval; +} + +/* Cover fns to access h-accums. */ + +DI +m32rxf_h_accums_get_handler (SIM_CPU *current_cpu, UINT regno) +{ + /* FIXME: Yes, this is just a quick hack. */ + DI r; + if (regno == 0) + r = CPU (h_accum); + else + r = CPU (h_accums[1]); + /* Sign extend the top 8 bits. */ + r = ANDDI (r, MAKEDI (0xffffff, 0xffffffff)); + r = XORDI (r, MAKEDI (0x800000, 0)); + r = SUBDI (r, MAKEDI (0x800000, 0)); + return r; +} + +void +m32rxf_h_accums_set_handler (SIM_CPU *current_cpu, UINT regno, DI newval) +{ + /* FIXME: Yes, this is just a quick hack. */ + if (regno == 0) + CPU (h_accum) = newval; + else + CPU (h_accums[1]) = newval; +} + +#if WITH_PROFILE_MODEL_P + +/* Initialize cycle counting for an insn. + FIRST_P is non-zero if this is the first insn in a set of parallel + insns. */ + +void +m32rxf_model_insn_before (SIM_CPU *cpu, int first_p) +{ + m32rbf_model_insn_before (cpu, first_p); +} + +/* 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 +m32rxf_model_insn_after (SIM_CPU *cpu, int last_p, int cycles) +{ + m32rbf_model_insn_after (cpu, last_p, cycles); +} + +static INLINE void +check_load_stall (SIM_CPU *cpu, int regno) +{ + UINT h_gr = CPU_M32R_MISC_PROFILE (cpu)->load_regs; + + if (regno != -1 + && (h_gr & (1 << regno)) != 0) + { + CPU_M32R_MISC_PROFILE (cpu)->load_stall += 2; + if (TRACE_INSN_P (cpu)) + cgen_trace_printf (cpu, " ; Load stall of 2 cycles."); + } +} + +int +m32rxf_model_m32rx_u_exec (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT sr, INT sr2, INT dr) +{ + check_load_stall (cpu, sr); + check_load_stall (cpu, sr2); + return idesc->timing->units[unit_num].done; +} + +int +m32rxf_model_m32rx_u_cmp (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT src1, INT src2) +{ + check_load_stall (cpu, src1); + check_load_stall (cpu, src2); + return idesc->timing->units[unit_num].done; +} + +int +m32rxf_model_m32rx_u_mac (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT src1, INT src2) +{ + check_load_stall (cpu, src1); + check_load_stall (cpu, src2); + return idesc->timing->units[unit_num].done; +} + +int +m32rxf_model_m32rx_u_cti (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT sr) +{ + PROFILE_DATA *profile = CPU_PROFILE_DATA (cpu); + int taken_p = (referenced & (1 << 1)) != 0; + + check_load_stall (cpu, sr); + if (taken_p) + { + CPU_M32R_MISC_PROFILE (cpu)->cti_stall += 2; + PROFILE_MODEL_TAKEN_COUNT (profile) += 1; + } + else + PROFILE_MODEL_UNTAKEN_COUNT (profile) += 1; + return idesc->timing->units[unit_num].done; +} + +int +m32rxf_model_m32rx_u_load (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT sr, INT dr) +{ + CPU_M32R_MISC_PROFILE (cpu)->load_regs_pending |= (1 << dr); + return idesc->timing->units[unit_num].done; +} + +int +m32rxf_model_m32rx_u_store (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT src1, INT src2) +{ + return idesc->timing->units[unit_num].done; +} + +#endif /* WITH_PROFILE_MODEL_P */