]> Git Repo - binutils.git/blob - sim/lm32/traps.c
Automatic date update in version.in
[binutils.git] / sim / lm32 / traps.c
1 /* Lattice Mico32 exception and system call support.
2    Contributed by Jon Beniston <[email protected]>
3
4    Copyright (C) 2009-2022 Free Software Foundation, Inc.
5
6    This file is part of GDB.
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 /* This must come before any other includes.  */
22 #include "defs.h"
23
24 #define WANT_CPU lm32bf
25 #define WANT_CPU_LM32BF
26
27 #include "sim-main.h"
28 #include "sim-signal.h"
29 #include "sim-syscall.h"
30 #include "lm32-sim.h"
31 #include "target-newlib-syscall.h"
32
33 /* Handle invalid instructions.  */
34
35 SEM_PC
36 sim_engine_invalid_insn (SIM_CPU * current_cpu, IADDR cia, SEM_PC pc)
37 {
38   SIM_DESC sd = CPU_STATE (current_cpu);
39
40   sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
41
42   return pc;
43 }
44
45 /* Handle divide instructions. */
46
47 USI
48 lm32bf_divu_insn (SIM_CPU * current_cpu, IADDR pc, USI r0, USI r1, USI r2)
49 {
50   SIM_DESC sd = CPU_STATE (current_cpu);
51   host_callback *cb = STATE_CALLBACK (sd);
52
53   /* Check for divide by zero */
54   if (GET_H_GR (r1) == 0)
55     {
56       if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
57         sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGFPE);
58       else
59         {
60           /* Save PC in exception address register.  */
61           SET_H_GR (30, pc);
62           /* Save and clear interrupt enable.  */
63           SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
64           /* Branch to divide by zero exception handler.  */
65           return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DIVIDE_BY_ZERO * 32;
66         }
67     }
68   else
69     {
70       SET_H_GR (r2, (USI) GET_H_GR (r0) / (USI) GET_H_GR (r1));
71       return pc + 4;
72     }
73 }
74
75 USI
76 lm32bf_modu_insn (SIM_CPU * current_cpu, IADDR pc, USI r0, USI r1, USI r2)
77 {
78   SIM_DESC sd = CPU_STATE (current_cpu);
79   host_callback *cb = STATE_CALLBACK (sd);
80
81   /* Check for divide by zero.  */
82   if (GET_H_GR (r1) == 0)
83     {
84       if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
85         sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGFPE);
86       else
87         {
88           /* Save PC in exception address register.  */
89           SET_H_GR (30, pc);
90           /* Save and clear interrupt enable.  */
91           SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
92           /* Branch to divide by zero exception handler.  */
93           return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DIVIDE_BY_ZERO * 32;
94         }
95     }
96   else
97     {
98       SET_H_GR (r2, (USI) GET_H_GR (r0) % (USI) GET_H_GR (r1));
99       return pc + 4;
100     }
101 }
102
103 /* Handle break instructions.  */
104
105 USI
106 lm32bf_break_insn (SIM_CPU * current_cpu, IADDR pc)
107 {
108   SIM_DESC sd = CPU_STATE (current_cpu);
109   host_callback *cb = STATE_CALLBACK (sd);
110   /* Breakpoint.  */
111   if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
112     {
113       sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
114       return pc;
115     }
116   else
117     {
118       /* Save PC in breakpoint address register.  */
119       SET_H_GR (31, pc);
120       /* Save and clear interrupt enable.  */
121       SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 2);
122       /* Branch to breakpoint exception handler.  */
123       return GET_H_CSR (LM32_CSR_DEBA) + LM32_EID_BREAKPOINT * 32;
124     }
125 }
126
127 /* Handle scall instructions.  */
128
129 USI
130 lm32bf_scall_insn (SIM_CPU * current_cpu, IADDR pc)
131 {
132   SIM_DESC sd = CPU_STATE (current_cpu);
133   host_callback *cb = STATE_CALLBACK (sd);
134
135   if ((STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
136       || (GET_H_GR (8) == TARGET_NEWLIB_SYS_exit))
137     {
138       /* Delegate system call to host O/S.  */
139       long result, result2;
140       int errcode;
141
142       /* Perform the system call.  */
143       sim_syscall_multi (current_cpu, GET_H_GR (8), GET_H_GR (1), GET_H_GR (2),
144                          GET_H_GR (3), GET_H_GR (4), &result, &result2,
145                          &errcode);
146       /* Store the return value in the CPU's registers.  */
147       SET_H_GR (1, result);
148       SET_H_GR (2, result2);
149       SET_H_GR (3, errcode);
150
151       /* Skip over scall instruction.  */
152       return pc + 4;
153     }
154   else
155     {
156       /* Save PC in exception address register.  */
157       SET_H_GR (30, pc);
158       /* Save and clear interrupt enable */
159       SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
160       /* Branch to system call exception handler.  */
161       return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_SYSTEM_CALL * 32;
162     }
163 }
164
165 /* Handle b instructions.  */
166
167 USI
168 lm32bf_b_insn (SIM_CPU * current_cpu, USI r0, USI f_r0)
169 {
170   SIM_DESC sd = CPU_STATE (current_cpu);
171   host_callback *cb = STATE_CALLBACK (sd);
172
173   /* Restore interrupt enable.  */
174   if (f_r0 == 30)
175     SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 2) >> 1);
176   else if (f_r0 == 31)
177     SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 4) >> 2);
178   return r0;
179 }
180
181 /* Handle wcsr instructions.  */
182
183 void
184 lm32bf_wcsr_insn (SIM_CPU * current_cpu, USI f_csr, USI r1)
185 {
186   SIM_DESC sd = CPU_STATE (current_cpu);
187   host_callback *cb = STATE_CALLBACK (sd);
188
189   /* Writing a 1 to IP CSR clears a bit, writing 0 has no effect.  */
190   if (f_csr == LM32_CSR_IP)
191     SET_H_CSR (f_csr, GET_H_CSR (f_csr) & ~r1);
192   else
193     SET_H_CSR (f_csr, r1);
194 }
195
196 /* Handle signals.  */
197
198 void
199 lm32_core_signal (SIM_DESC sd,
200                   sim_cpu * cpu,
201                   sim_cia cia,
202                   unsigned map,
203                   int nr_bytes,
204                   address_word addr,
205                   transfer_type transfer, sim_core_signals sig)
206 {
207   const char *copy = (transfer == read_transfer ? "read" : "write");
208   address_word ip = CIA_ADDR (cia);
209   SIM_CPU *current_cpu = cpu;
210
211   switch (sig)
212     {
213     case sim_core_unmapped_signal:
214       sim_io_eprintf (sd,
215                       "core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
216                       nr_bytes, copy, (unsigned long) addr,
217                       (unsigned long) ip);
218       SET_H_GR (30, ip);
219       /* Save and clear interrupt enable.  */
220       SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
221       CPU_PC_SET (cpu, GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DATA_BUS_ERROR * 32);
222       sim_engine_halt (sd, cpu, NULL, LM32_EID_DATA_BUS_ERROR * 32,
223                        sim_stopped, SIM_SIGSEGV);
224       break;
225     case sim_core_unaligned_signal:
226       sim_io_eprintf (sd,
227                       "core: %d byte misaligned %s to address 0x%lx at 0x%lx\n",
228                       nr_bytes, copy, (unsigned long) addr,
229                       (unsigned long) ip);
230       SET_H_GR (30, ip);
231       /* Save and clear interrupt enable.  */
232       SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
233       CPU_PC_SET (cpu, GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DATA_BUS_ERROR * 32);
234       sim_engine_halt (sd, cpu, NULL, LM32_EID_DATA_BUS_ERROR * 32,
235                        sim_stopped, SIM_SIGBUS);
236       break;
237     default:
238       sim_engine_abort (sd, cpu, cia,
239                         "sim_core_signal - internal error - bad switch");
240     }
241 }
This page took 0.036824 seconds and 4 git commands to generate.