1/* m32r exception, interrupt, and trap (EIT) support 2 Copyright (C) 1998, 2003, 2007 Free Software Foundation, Inc. 3 Contributed by Cygnus Solutions. 4 5 This file is part of GDB, the GNU debugger. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "sim-main.h" 21#include "targ-vals.h" 22 23#define TRAP_FLUSH_CACHE 12 24/* The semantic code invokes this for invalid (unrecognized) instructions. */ 25 26SEM_PC 27sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC pc) 28{ 29 SIM_DESC sd = CPU_STATE (current_cpu); 30 31#if 0 32 if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT) 33 { 34 h_bsm_set (current_cpu, h_sm_get (current_cpu)); 35 h_bie_set (current_cpu, h_ie_get (current_cpu)); 36 h_bcond_set (current_cpu, h_cond_get (current_cpu)); 37 /* sm not changed */ 38 h_ie_set (current_cpu, 0); 39 h_cond_set (current_cpu, 0); 40 41 h_bpc_set (current_cpu, cia); 42 43 sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL, 44 EIT_RSVD_INSN_ADDR); 45 } 46 else 47#endif 48 sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL); 49 50 return pc; 51} 52 53/* Process an address exception. */ 54 55void 56m32r_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia, 57 unsigned int map, int nr_bytes, address_word addr, 58 transfer_type transfer, sim_core_signals sig) 59{ 60 if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT) 61 { 62 m32rbf_h_cr_set (current_cpu, H_CR_BBPC, 63 m32rbf_h_cr_get (current_cpu, H_CR_BPC)); 64 switch (MACH_NUM (CPU_MACH (current_cpu))) 65 { 66 case MACH_M32R: 67 m32rbf_h_bpsw_set (current_cpu, m32rbf_h_psw_get (current_cpu)); 68 /* sm not changed. */ 69 m32rbf_h_psw_set (current_cpu, m32rbf_h_psw_get (current_cpu) & 0x80); 70 break; 71 case MACH_M32RX: 72 m32rxf_h_bpsw_set (current_cpu, m32rxf_h_psw_get (current_cpu)); 73 /* sm not changed. */ 74 m32rxf_h_psw_set (current_cpu, m32rxf_h_psw_get (current_cpu) & 0x80); 75 break; 76 case MACH_M32R2: 77 m32r2f_h_bpsw_set (current_cpu, m32r2f_h_psw_get (current_cpu)); 78 /* sm not changed. */ 79 m32r2f_h_psw_set (current_cpu, m32r2f_h_psw_get (current_cpu) & 0x80); 80 break; 81 default: 82 abort (); 83 } 84 85 m32rbf_h_cr_set (current_cpu, H_CR_BPC, cia); 86 87 sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL, 88 EIT_ADDR_EXCP_ADDR); 89 } 90 else 91 sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr, 92 transfer, sig); 93} 94 95/* Read/write functions for system call interface. */ 96 97static int 98syscall_read_mem (host_callback *cb, struct cb_syscall *sc, 99 unsigned long taddr, char *buf, int bytes) 100{ 101 SIM_DESC sd = (SIM_DESC) sc->p1; 102 SIM_CPU *cpu = (SIM_CPU *) sc->p2; 103 104 return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes); 105} 106 107static int 108syscall_write_mem (host_callback *cb, struct cb_syscall *sc, 109 unsigned long taddr, const char *buf, int bytes) 110{ 111 SIM_DESC sd = (SIM_DESC) sc->p1; 112 SIM_CPU *cpu = (SIM_CPU *) sc->p2; 113 114 return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes); 115} 116 117/* Trap support. 118 The result is the pc address to continue at. 119 Preprocessing like saving the various registers has already been done. */ 120 121USI 122m32r_trap (SIM_CPU *current_cpu, PCADDR pc, int num) 123{ 124 SIM_DESC sd = CPU_STATE (current_cpu); 125 host_callback *cb = STATE_CALLBACK (sd); 126 127#ifdef SIM_HAVE_BREAKPOINTS 128 /* Check for breakpoints "owned" by the simulator first, regardless 129 of --environment. */ 130 if (num == TRAP_BREAKPOINT) 131 { 132 /* First try sim-break.c. If it's a breakpoint the simulator "owns" 133 it doesn't return. Otherwise it returns and let's us try. */ 134 sim_handle_breakpoint (sd, current_cpu, pc); 135 /* Fall through. */ 136 } 137#endif 138 139 if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT) 140 { 141 /* The new pc is the trap vector entry. 142 We assume there's a branch there to some handler. 143 Use cr5 as EVB (EIT Vector Base) register. */ 144 /* USI new_pc = EIT_TRAP_BASE_ADDR + num * 4; */ 145 USI new_pc = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4; 146 return new_pc; 147 } 148 149 switch (num) 150 { 151 case TRAP_SYSCALL : 152 { 153 CB_SYSCALL s; 154 155 CB_SYSCALL_INIT (&s); 156 s.func = m32rbf_h_gr_get (current_cpu, 0); 157 s.arg1 = m32rbf_h_gr_get (current_cpu, 1); 158 s.arg2 = m32rbf_h_gr_get (current_cpu, 2); 159 s.arg3 = m32rbf_h_gr_get (current_cpu, 3); 160 161 if (s.func == TARGET_SYS_exit) 162 { 163 sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, s.arg1); 164 } 165 166 s.p1 = (PTR) sd; 167 s.p2 = (PTR) current_cpu; 168 s.read_mem = syscall_read_mem; 169 s.write_mem = syscall_write_mem; 170 cb_syscall (cb, &s); 171 m32rbf_h_gr_set (current_cpu, 2, s.errcode); 172 m32rbf_h_gr_set (current_cpu, 0, s.result); 173 m32rbf_h_gr_set (current_cpu, 1, s.result2); 174 break; 175 } 176 177 case TRAP_BREAKPOINT: 178 sim_engine_halt (sd, current_cpu, NULL, pc, 179 sim_stopped, SIM_SIGTRAP); 180 break; 181 182 case TRAP_FLUSH_CACHE: 183 /* Do nothing. */ 184 break; 185 186 default : 187 { 188 /* USI new_pc = EIT_TRAP_BASE_ADDR + num * 4; */ 189 /* Use cr5 as EVB (EIT Vector Base) register. */ 190 USI new_pc = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4; 191 return new_pc; 192 } 193 } 194 195 /* Fake an "rte" insn. */ 196 /* FIXME: Should duplicate all of rte processing. */ 197 return (pc & -4) + 4; 198} 199