2 * Copyright (c) 1996 Cygnus Support
4 * The authors hereby grant permission to use, copy, modify, distribute,
5 * and license this software and its documentation for any purpose, provided
6 * that existing copyright notices are retained in all copies and that this
7 * notice is included verbatim in any distributions. No written agreement,
8 * license, or royalty fee is required for any of the authorized uses.
9 * Modifications to this software may be copyrighted by their authors
10 * and need not follow the licensing terms described here, provided that
11 * the new terms are clearly indicated on the first page of each file where
21 extern unsigned long rdtbr();
22 extern struct trap_entry fltr_proto
;
23 extern void trap_low();
24 exception_t default_trap_hook
= trap_low
;
27 char *target_read_registers(unsigned long *);
28 char *target_write_registers(unsigned long *);
29 char *target_dump_state(unsigned long *);
33 /* Number of bytes of registers. */
34 #define NUMREGBYTES (NUMREGS * 4)
36 enum regnames
{G0
, G1
, G2
, G3
, G4
, G5
, G6
, G7
,
37 O0
, O1
, O2
, O3
, O4
, O5
, SP
, O7
,
38 L0
, L1
, L2
, L3
, L4
, L5
, L6
, L7
,
39 I0
, I1
, I2
, I3
, I4
, I5
, FP
, I7
,
41 F0
, F1
, F2
, F3
, F4
, F5
, F6
, F7
,
42 F8
, F9
, F10
, F11
, F12
, F13
, F14
, F15
,
43 F16
, F17
, F18
, F19
, F20
, F21
, F22
, F23
,
44 F24
, F25
, F26
, F27
, F28
, F29
, F30
, F31
,
45 Y
, PSR
, WIM
, TBR
, PC
, NPC
, FPSR
, CPSR
};
48 * Each entry in the trap vector occupies four words, typically a jump
49 * to the processing routine.
52 unsigned sethi_filler
:10;
53 unsigned sethi_imm22
:22;
54 unsigned jmpl_filler
:19;
55 unsigned jmpl_simm13
:13;
56 unsigned long filler
[2];
60 * This table contains the mapping between SPARC hardware trap types, and
61 * signals, which are primarily what GDB understands. It also indicates
62 * which hardware traps we need to commandeer when initializing the stub.
64 struct trap_info hard_trap_info
[] = {
65 {1, SIGSEGV
}, /* instruction access error */
66 {2, SIGILL
}, /* privileged instruction */
67 {3, SIGILL
}, /* illegal instruction */
68 {4, SIGEMT
}, /* fp disabled */
69 {36, SIGEMT
}, /* cp disabled */
70 {7, SIGBUS
}, /* mem address not aligned */
71 {9, SIGSEGV
}, /* data access exception */
72 {10, SIGEMT
}, /* tag overflow */
73 {128+1, SIGTRAP
}, /* ta 1 - normal breakpoint instruction */
74 {0, 0} /* Must be last */
77 extern struct trap_entry fltr_proto
;
79 exception_handler (int tt
, unsigned long routine
)
81 struct trap_entry
*tb
; /* Trap vector base address */
83 DEBUG (1, "Entering exception_handler()");
85 tb
= (struct trap_entry
*) (rdtbr() & ~0xfff);
88 tb
= (struct trap_entry
*) 0;
93 tb
[tt
].sethi_imm22
= routine
>> 10;
94 tb
[tt
].jmpl_simm13
= routine
& 0x3ff;
96 DEBUG (1, "Leaving exception_handler()");
100 * This is so we can trap a memory fault when reading or writing
101 * directly to memory.
104 set_mem_fault_trap(enable
)
107 extern void fltr_set_mem_err();
109 DEBUG (1, "Entering set_mem_fault_trap()");
114 exception_handler(9, (unsigned long)fltr_set_mem_err
);
116 exception_handler(9, (unsigned long)trap_low
);
118 DEBUG (1, "Leaving set_mem_fault_trap()");
122 * This function does all command procesing for interfacing to gdb. It
123 * returns 1 if you should skip the instruction at the trap address, 0
126 extern void breakinst();
129 handle_exception (registers
)
130 unsigned long *registers
;
134 /* First, we must force all of the windows to be spilled out */
136 DEBUG (1, "Entering handle_exception()");
138 /* asm("mov %g0, %wim ; nop; nop; nop"); */
139 asm(" save %sp, -64, %sp \n\
140 save %sp, -64, %sp \n\
141 save %sp, -64, %sp \n\
142 save %sp, -64, %sp \n\
143 save %sp, -64, %sp \n\
144 save %sp, -64, %sp \n\
145 save %sp, -64, %sp \n\
146 save %sp, -64, %sp \n\
157 if (registers
[PC
] == (unsigned long)breakinst
) {
158 registers
[PC
] = registers
[NPC
];
162 /* get the last know signal number from the trap register */
163 sigval
= computeSignal((registers
[TBR
] >> 4) & 0xff);
165 /* call the main command processing loop for gdb */
166 gdb_event_loop (sigval
, registers
);
170 * This function will generate a breakpoint exception. It is used at the
171 * beginning of a program to sync up with a debugger and can be used
172 * otherwise as a quick means to stop program execution and "break" into
178 DEBUG (1, "Entering breakpoint()");
183 asm(" .globl " STRINGSYM(breakinst
) " \n\
184 " STRINGSYM(breakinst
) ": ta 128+1 \n\
191 * This is just a test vector for debugging excpetions.
197 print ("Got a bad trap #");
207 * This is just a test vector for debugging excpetions.
213 print ("Got a soft trap #");
223 * Flush the instruction cache. We need to do this for the debugger stub so
224 * that breakpoints, et. al. become visible to the instruction stream after
225 * storing them in memory.
227 * For the sparclite, we need to do something here, but for a standard
228 * sparc (which SIS simulates), we don't.
237 * This will reset the processor, so we never return from here.
247 * g - read registers.
249 * returns a vector of words, size is NUM_REGS.
252 target_read_registers(unsigned long *registers
)
257 DEBUG (1, "In target_read_registers()");
259 ptr
= packet_out_buf
;
260 ptr
= mem2hex((char *)registers
, ptr
, 16 * 4, 0); /* G & O regs */
261 ptr
= mem2hex((unsigned char *)(sp
+ 0), ptr
, 16 * 4, 0); /* L & I regs */
262 memset(ptr
, '0', 32 * 8); /* Floating point */
263 mem2hex((char *)®isters
[Y
],
266 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
271 * G - write registers.
272 * param is a vector of words, size is NUM_REGS.
273 * returns an OK or an error number.
276 target_write_registers(unsigned long *registers
)
280 unsigned long *newsp
, psr
;
282 DEBUG (1, "In target_write_registers()");
284 psr
= registers
[PSR
];
286 ptr
= &packet_in_buf
[1];
288 hex2mem(ptr
, (char *)registers
, 16 * 4, 0); /* G & O regs */
289 hex2mem(ptr
+ 16 * 4 * 2, (unsigned char *)(sp
+ 0), 16 * 4, 0); /* L & I regs */
290 hex2mem(ptr
+ 64 * 4 * 2, (char *)®isters
[Y
],
291 8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
294 * see if the stack pointer has moved. If so, then copy the saved
295 * locals and ins to the new location. This keeps the window
296 * overflow and underflow routines happy.
299 newsp
= (unsigned long *)registers
[SP
];
301 sp
= memcpy(newsp
, sp
, 16 * 4);
303 /* Don't allow CWP to be modified. */
305 if (psr
!= registers
[PSR
])
306 registers
[PSR
] = (psr
& 0x1f) | (registers
[PSR
] & ~0x1f);
312 target_dump_state(unsigned long *registers
)
314 int tt
; /* Trap type */
319 DEBUG (1, "In target_dump_state()");
321 sp
= (unsigned long *)registers
[SP
];
323 tt
= (registers
[TBR
] >> 4) & 0xff;
325 /* reply to host that an exception has occurred */
326 sigval
= computeSignal(tt
);
327 ptr
= packet_out_buf
;
330 *ptr
++ = hexchars
[sigval
>> 4];
331 *ptr
++ = hexchars
[sigval
& 0xf];
333 *ptr
++ = hexchars
[PC
>> 4];
334 *ptr
++ = hexchars
[PC
& 0xf];
336 ptr
= mem2hex((unsigned char *)®isters
[PC
], ptr
, 4, 0);
339 *ptr
++ = hexchars
[FP
>> 4];
340 *ptr
++ = hexchars
[FP
& 0xf];
342 ptr
= mem2hex((unsigned char *)(sp
+ 8 + 6), ptr
, 4, 0); /* FP */
345 *ptr
++ = hexchars
[SP
>> 4];
346 *ptr
++ = hexchars
[SP
& 0xf];
348 ptr
= mem2hex((unsigned char *)&sp
, ptr
, 4, 0);
351 *ptr
++ = hexchars
[NPC
>> 4];
353 return (packet_out_buf
);
357 write_pc(unsigned long *registers
, unsigned long addr
)
359 DEBUG (1, "In write_pc");
361 registers
[PC
] = addr
;
362 registers
[NPC
] = addr
+ 4;