1 /* sparc64 trap support
2 Copyright (C) 1999 Cygnus Solutions. */
4 #define WANT_CPU sparc64
5 #define WANT_CPU_SPARC64
10 /* Indicate a window overflow has occured. */
13 sparc64_window_overflow (SIM_CPU *cpu, IADDR pc)
15 SIM_DESC sd = CPU_STATE (cpu);
17 if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
18 sparc64_hw_trap (cpu, pc, TRAP32_WINDOW_OVERFLOW);
20 sparc64_hw_trap (cpu, pc, TRAP32_SIM_SPILL);
23 /* Indicate a window underflow has occured. */
26 sparc64_window_underflow (SIM_CPU *cpu, IADDR pc)
28 SIM_DESC sd = CPU_STATE (cpu);
30 if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
31 sparc64_hw_trap (cpu, pc, TRAP32_WINDOW_UNDERFLOW);
33 sparc64_hw_trap (cpu, pc, TRAP32_SIM_FILL);
37 sparc64_invalid_insn (SIM_CPU * cpu, IADDR pc)
39 sparc64_hw_trap (cpu, pc, TRAP32_ILLEGAL_INSN);
43 sparc64_core_signal (SIM_DESC sd, SIM_CPU *cpu, sim_cia pc,
44 unsigned int map, int nr_bytes, address_word addr,
45 transfer_type transfer, sim_core_signals sig)
47 sparc64_hw_trap (cpu, pc,
49 ? TRAP32_INSTRUCTION_ACCESS
50 : TRAP32_DATA_ACCESS);
53 /* Handle hardware generated traps when --environment=operating. */
56 sparc64_hw_trap_oper (SIM_CPU *current_cpu, IADDR pc, TRAP32_TYPE trap)
58 SIM_DESC sd = CPU_STATE (current_cpu);
59 IADDR new_pc = (GET_H_TBR () & 0xfffff000) | (trap << 4);
60 USI psr = GET_H_PSR ();
63 psr = (psr & ~PSR_PS) | (psr & PSR_S ? PSR_PS : 0);
65 psr = (psr & ~PSR_CWP) | NEXT_WIN (psr & PSR_CWP);
67 SET_H_GR (H_GR__L1, GET_H_PC ());
68 SET_H_GR (H_GR__L2, GET_H_NPC ());
72 /* The wrtbr insn doesn't affect the tt part so SET_H_TBR doesn't either
73 (??? doesn't *have* to be this way though).
74 Therefore we can't use SET_H_TBR here. */
77 SET_H_NPC (new_pc + 4);
79 sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL, new_pc);
82 /* Handle hardware generated traps when --environment=user. */
85 sparc64_hw_trap_user (SIM_CPU *current_cpu, IADDR pc, TRAP32_TYPE trap)
87 SIM_DESC sd = CPU_STATE (current_cpu);
91 case TRAP32_SIM_SPILL :
92 /* The CWP-1 window is invalid. */
94 int win = NEXT_WIN (GET_H_CWP ());
95 int next_win = NEXT_WIN (win);
96 int nwindows = GET_NWINDOWS ();
97 unsigned int mask = (1 << nwindows) - 1;
98 unsigned int wim = GET_H_WIM ();
100 /* There's no need to flush `current_regs' here, `next_win' can't
102 sparc64_flush_regwin (current_cpu, pc, next_win, 0 /* error ok (?) */);
103 /* Rotate WIM right one. */
104 wim = ((wim & mask) >> 1) | (wim << (nwindows - 1));
105 SET_H_WIM (wim & mask);
109 case TRAP32_SIM_FILL :
110 /* The CWP+1 window is invalid. */
112 int win = PREV_WIN (GET_H_CWP ());
113 int nwindows = GET_NWINDOWS ();
114 unsigned int mask = (1 << nwindows) - 1;
115 unsigned int wim = GET_H_WIM ();
117 /* Load caller's caller's window.
118 There's no need to flush `current_regs' as `win' can't
120 sparc64_load_regwin (current_cpu, pc, win);
121 /* Rotate WIM left one. */
122 wim = (wim << 1) | ((wim & mask) >> (nwindows - 1));
123 SET_H_WIM (wim & mask);
128 sim_io_eprintf (sd, "Received trap %d\n", trap);
129 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGABRT);
132 /* Handle hardware generated traps. */
135 sparc64_hw_trap (SIM_CPU *current_cpu, IADDR pc, TRAP32_TYPE trap)
137 SIM_DESC sd = CPU_STATE (current_cpu);
139 if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
140 sparc64_hw_trap_oper (current_cpu, pc, trap);
142 sparc64_hw_trap_user (current_cpu, pc, trap);
145 /* Handle the trap insn when --environment=operating. */
148 sparc64_sw_trap_oper (SIM_CPU *current_cpu, IADDR pc, SI rs1, SI rs2_simm13)
150 SIM_DESC sd = CPU_STATE (current_cpu);
151 int trap = 128 + ((rs1 + rs2_simm13) & 127);
154 /* ??? Quick hack to have breakpoints work with gdb+"target sim" until
155 other things are working. */
156 if (trap == TRAP32_BREAKPOINT)
157 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
162 ??? wip, need to remain compatible with erc32 for now. */
163 int i0 = GET_H_GR (H_GR__I0);
164 int i1 = GET_H_GR (H_GR__I1);
166 if (i1 == LIBGLOSS_EXIT_MAGIC)
167 sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, i0);
170 sim_io_eprintf (sd, "Unexpected program termination, pc=0x%x\n",
172 sim_engine_halt (sd, current_cpu, NULL, pc,
173 sim_signalled, SIM_SIGABRT);
178 SET_H_PSR ((GET_H_PSR () & ~(PSR_CWP | PSR_PS))
180 | (GET_H_S () ? PSR_PS : 0)
181 | (NEXT_WIN (GET_H_CWP ())));
182 SET_H_GR (H_GR__L1, GET_H_PC ());
183 SET_H_GR (H_GR__L2, GET_H_NPC ());
184 /* The wrtbr insn doesn't affect the tt part so SET_H_TBR doesn't either
185 (??? doesn't *have* to be this way though).
186 Therefore we can't use SET_H_TBR here. */
187 CPU (h_tbr) = new_pc = ((GET_H_TBR () & 0xfffff000)
192 /* Subroutine of sparc64_do_trap to read target memory. */
195 syscall_read_mem (host_callback *cb, CB_SYSCALL *sc,
196 unsigned long taddr, char *buf, int bytes)
198 SIM_DESC sd = (SIM_DESC) sc->p1;
199 SIM_CPU *cpu = (SIM_CPU *) sc->p2;
201 return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
204 /* Subroutine of sparc64_do_trap to write target memory. */
207 syscall_write_mem (host_callback *cb, CB_SYSCALL *sc,
208 unsigned long taddr, const char *buf, int bytes)
210 SIM_DESC sd = (SIM_DESC) sc->p1;
211 SIM_CPU *cpu = (SIM_CPU *) sc->p2;
213 return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
216 /* Handle the trap insn when --environment=user. */
219 sparc64_sw_trap_user (SIM_CPU *current_cpu, IADDR pc, SI rs1, SI rs2_simm13)
221 SIM_DESC sd = CPU_STATE (current_cpu);
222 int trap = 128 + ((rs1 + rs2_simm13) & 127);
223 IADDR new_pc = pc + 4;
227 case TRAP32_SYSCALL :
228 /* FIXME: Later make trap number runtime selectable. */
232 CB_SYSCALL_INIT (&s);
233 s.func = a_sparc_h_gr_get (current_cpu, 8);
234 s.arg1 = a_sparc_h_gr_get (current_cpu, 9);
235 s.arg2 = a_sparc_h_gr_get (current_cpu, 10);
236 s.arg3 = a_sparc_h_gr_get (current_cpu, 11);
237 if (s.func == TARGET_SYS_exit)
239 /* Tell sim_resume program called exit(). */
240 sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, s.arg1);
243 s.p2 = (PTR) current_cpu;
244 s.read_mem = syscall_read_mem;
245 s.write_mem = syscall_write_mem;
246 cb_syscall (STATE_CALLBACK (CPU_STATE (current_cpu)), &s);
247 a_sparc_h_gr_set (current_cpu, 10, s.errcode);
248 a_sparc_h_gr_set (current_cpu, 8, s.result);
249 a_sparc_h_gr_set (current_cpu, 9, s.result2);
253 case TRAP32_BREAKPOINT :
254 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
256 case TRAP32_DIVIDE_0 :
257 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGFPE);
259 case TRAP32_FLUSH_REGWIN :
260 sparc64_flush_regwins (current_cpu, pc, 0 /* error ok */);
264 sim_io_eprintf (sd, "Unsupported trap %d\n", trap);
265 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
271 /* Called from the semantic code to handle the trap instruction. */
274 sparc64_sw_trap (SIM_CPU *current_cpu, IADDR pc, SI rs1, SI rs2_simm13)
276 SIM_DESC sd = CPU_STATE (current_cpu);
279 if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
280 new_pc = sparc64_sw_trap_oper (current_cpu, pc, rs1, rs2_simm13);
282 new_pc = sparc64_sw_trap_user (current_cpu, pc, rs1, rs2_simm13);
286 /* Handle the rett insn. */
289 sparc64_do_rett (SIM_CPU *current_cpu, IADDR pc, SI rs1, SI rs2_simm13)
291 int psr = GET_H_PSR ();
293 /* FIXME: check for trap conditions. */
295 SET_H_PSR ((psr & ~(PSR_S + PSR_CWP))
296 | ((psr & PSR_PS) ? PSR_S : 0)
298 | PREV_WIN (psr & PSR_CWP));
300 if (TRACE_INSN_P (current_cpu)) /* FIXME */
302 trace_result (current_cpu, "sp", 'x', GET_H_GR (H_GR__SP));
303 trace_result (current_cpu, "fp", 'x', GET_H_GR (H_GR__FP));
304 trace_result (current_cpu, "cwp", 'x', GET_H_CWP ());
307 return rs1 + rs2_simm13;