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