* nlm/Makefile.in: install gdbserve.nlm.
[binutils-gdb.git] / gdb / nlm / ppc.c
1 #include <nwdfs.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <time.h>
6 #include <nwconio.h>
7 #include <nwadv.h>
8 #include <nwdbgapi.h>
9 #include <errno.h>
10 #include <nwthread.h>
11 #include "ppc.h"
12
13 extern char *mem2hex (void *mem, char *buf, int count, int may_fault);
14 extern char *hex2mem (char *buf, void *mem, int count, int may_fault);
15 extern int computeSignal (int exceptionVector);
16
17 void
18 flush_i_cache (void)
19 {
20 }
21
22 /* Get the registers out of the frame information. */
23
24 void
25 frame_to_registers (frame, regs)
26 struct StackFrame *frame;
27 char *regs;
28 {
29 mem2hex (&frame->ExceptionState.CsavedRegs, &regs[GP0_REGNUM * 4 * 2], 4 * 32, 0);
30
31 mem2hex (&frame->ExceptionState.CSavedFPRegs, &regs[FP0_REGNUM * 4 * 2], 4 * 32, 0);
32
33 mem2hex (&frame->ExceptionPC, &regs[PC_REGNUM * 4 * 2], 4 * 1, 0);
34
35 mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedSRR1, &regs[CR_REGNUM * 4 * 2], 4 * 1, 0);
36 mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR, &regs[LR_REGNUM * 4 * 2], 4 * 1, 0);
37 mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR, &regs[CTR_REGNUM * 4 * 2], 4 * 1, 0);
38 mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedXER, &regs[XER_REGNUM * 4 * 2], 4 * 1, 0);
39 mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedMQ, &regs[MQ_REGNUM * 4 * 2], 4 * 1, 0);
40 }
41
42 /* Put the registers back into the frame information. */
43
44 void
45 registers_to_frame (regs, frame)
46 char *regs;
47 struct StackFrame *frame;
48 {
49 hex2mem (&regs[GP0_REGNUM * 4 * 2], &frame->ExceptionState.CsavedRegs, 4 * 32, 0);
50
51 hex2mem (&regs[FP0_REGNUM * 4 * 2], &frame->ExceptionState.CSavedFPRegs, 4 * 32, 0);
52
53 hex2mem (&regs[PC_REGNUM * 4 * 2], &frame->ExceptionPC, 4 * 1, 0);
54
55 hex2mem (&regs[CR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedSRR1, 4 * 1, 0);
56 hex2mem (&regs[LR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR, 4 * 1, 0);
57 hex2mem (&regs[CTR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR, 4 * 1, 0);
58 hex2mem (&regs[XER_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedXER, 4 * 1, 0);
59 hex2mem (&regs[MQ_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedMQ, 4 * 1, 0);
60 }
61
62 extern int ReadByteAltDebugger (char* addr, char *theByte);
63
64 extern int WriteByteAltDebugger (char* addr, char theByte);
65
66 extern volatile int mem_err;
67
68 int
69 get_char (addr)
70 char *addr;
71 {
72 char c;
73
74 if (!ReadByteAltDebugger (addr, &c))
75 mem_err = 1;
76
77 return c;
78 }
79
80 void
81 set_char (addr, val)
82 char *addr;
83 int val;
84 {
85 if (!WriteByteAltDebugger (addr, val))
86 mem_err = 1;
87 }
88
89 int
90 mem_write (dst, src, len)
91 char *dst, *src;
92 int len;
93 {
94 while (len-- && !mem_err)
95 set_char (dst++, *src++);
96
97 return mem_err;
98 }
99
100 union inst
101 {
102 LONG l;
103
104 struct
105 {
106 union
107 {
108 struct /* Unconditional branch */
109 {
110 unsigned opcode : 6; /* 18 */
111 signed li : 24;
112 unsigned aa : 1;
113 unsigned lk : 1;
114 } b;
115 struct /* Conditional branch */
116 {
117 unsigned opcode : 6; /* 16 */
118 unsigned bo : 5;
119 unsigned bi : 5;
120 signed bd : 14;
121 unsigned aa : 1;
122 unsigned lk : 1;
123 } bc;
124 struct /* Conditional branch to ctr or lr reg */
125 {
126 unsigned opcode : 6; /* 19 */
127 unsigned bo : 5;
128 unsigned bi : 5;
129 unsigned type : 15; /* 528 = ctr, 16 = lr */
130 unsigned lk : 1;
131 } bclr;
132 } variant;
133 } inst;
134 };
135
136 static LONG saved_inst;
137 static LONG *saved_inst_pc = 0;
138 static LONG saved_target_inst;
139 static LONG *saved_target_inst_pc = 0;
140
141 void
142 set_step_traps (frame)
143 struct StackFrame *frame;
144 {
145 union inst inst;
146 LONG *target;
147 int opcode;
148 int ra, rb;
149 LONG *pc = (LONG *)frame->ExceptionPC;
150
151 inst.l = *pc++;
152
153 opcode = inst.inst.variant.b.opcode;
154
155 target = pc;
156
157 switch (opcode)
158 {
159 case 18: /* Unconditional branch */
160
161 if (inst.inst.variant.b.aa) /* Absolute? */
162 target = 0;
163 target += inst.inst.variant.b.li;
164
165 break;
166 case 16: /* Conditional branch */
167
168 if (!inst.inst.variant.bc.aa) /* Absolute? */
169 target = 0;
170 target += inst.inst.variant.bc.bd;
171
172 break;
173 case 19: /* Cond. branch via ctr or lr reg */
174 switch (inst.inst.variant.bclr.type)
175 {
176 case 528: /* ctr */
177 target = (LONG *)frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR;
178 break;
179 case 16: /* lr */
180 target = (LONG *)frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR;
181 break;
182 }
183 break;
184 }
185
186 saved_inst = *pc;
187 mem_write (pc, breakpoint_insn, BREAKPOINT_SIZE);
188 saved_inst_pc = pc;
189
190 if (target != pc)
191 {
192 saved_target_inst = *target;
193 mem_write (target, breakpoint_insn, BREAKPOINT_SIZE);
194 saved_target_inst_pc = target;
195 }
196 }
197
198 /* Remove step breakpoints. Returns non-zero if pc was at a step breakpoint,
199 zero otherwise. This routine works even if there were no step breakpoints
200 set. */
201
202 int
203 clear_step_traps (frame)
204 struct StackFrame *frame;
205 {
206 int retcode;
207 LONG *pc = (LONG *)frame->ExceptionPC;
208
209 if (saved_inst_pc == pc || saved_target_inst_pc == pc)
210 retcode = 1;
211 else
212 retcode = 0;
213
214 if (saved_inst_pc)
215 {
216 mem_write (saved_inst_pc, saved_inst, BREAKPOINT_SIZE);
217 saved_inst_pc = 0;
218 }
219
220 if (saved_target_inst_pc)
221 {
222 mem_write (saved_target_inst_pc, saved_target_inst, BREAKPOINT_SIZE);
223 saved_target_inst_pc = 0;
224 }
225
226 return retcode;
227 }
228
229 void
230 do_status (ptr, frame)
231 char *ptr;
232 struct StackFrame *frame;
233 {
234 int sigval;
235
236 sigval = computeSignal (frame->ExceptionNumber);
237
238 sprintf (ptr, "T%02x", sigval);
239 ptr += 3;
240
241 sprintf (ptr, "%02x:", PC_REGNUM);
242 ptr = mem2hex (&frame->ExceptionPC, ptr + 3, 4, 0);
243 *ptr++ = ';';
244
245 sprintf (ptr, "%02x:", SP_REGNUM);
246 ptr = mem2hex (&frame->ExceptionState.CsavedRegs[SP_REGNUM], ptr + 3, 4, 0);
247 *ptr++ = ';';
248
249 sprintf (ptr, "%02x:", LR_REGNUM);
250 ptr = mem2hex (&frame->ExceptionState.CsavedRegs[LR_REGNUM], ptr + 3, 4, 0);
251 *ptr++ = ';';
252
253 *ptr = '\000';
254 }
255
256 #if 0
257 /*
258 * strtol : convert a string to long.
259 *
260 * Andy Wilson, 2-Oct-89.
261 */
262
263 /* FIXME: It'd be nice to configure around these, but the include files are too
264 painful. These macros should at least be more portable than hardwired hex
265 constants. */
266
267 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
268 #define LONG_MAX ((long)(ULONG_MAX >> 1)) /* 0x7FFFFFFF */
269 #define LONG_MIN ((long)(~LONG_MAX)) /* 0x80000000 */
270
271 extern int errno;
272
273 unsigned long strtoul(const char *s, char **ptr, int base);
274
275 long
276 strtol(s, ptr, base)
277 const char *s; char **ptr; int base;
278 {
279 int minus=0;
280 unsigned long tmp;
281 const char *start=s;
282 char *eptr;
283
284 if (s==NULL)
285 {
286 errno = ERANGE;
287 if (!ptr)
288 *ptr = (char *)start;
289 return 0L;
290 }
291 while (isspace(*s))
292 s++;
293 if (*s == '-') {
294 s++;
295 minus = 1;
296 }
297 else if (*s == '+')
298 s++;
299
300 /*
301 * let strtoul do the hard work.
302 */
303 tmp = strtoul(s, &eptr, base);
304 if (ptr != NULL)
305 *ptr = (char *)((eptr==s) ? (char *)start : eptr);
306 if (tmp > (minus ? - (unsigned long) LONG_MIN : (unsigned long) LONG_MAX))
307 {
308 errno = ERANGE;
309 return (minus ? LONG_MIN : LONG_MAX);
310 }
311 return (minus ? (long) -tmp : (long) tmp);
312 }
313
314 /*
315 * strtol : convert a string to long.
316 *
317 * Andy Wilson, 2-Oct-89.
318 */
319
320 #ifndef ULONG_MAX
321 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
322 #endif
323
324 extern int errno;
325
326 unsigned long
327 strtoul(s, ptr, base)
328 const char *s; char **ptr; int base;
329 {
330 unsigned long total = 0;
331 unsigned digit;
332 const char *start=s;
333 int did_conversion=0;
334 int overflow = 0;
335 int negate = 0;
336 unsigned long maxdiv, maxrem;
337
338 if (s==NULL)
339 {
340 errno = ERANGE;
341 if (!ptr)
342 *ptr = (char *)start;
343 return 0L;
344 }
345
346 while (isspace(*s))
347 s++;
348 if (*s == '+')
349 s++;
350 else if (*s == '-')
351 s++, negate = 1;
352 if (base==0 || base==16) /* the 'base==16' is for handling 0x */
353 {
354 int tmp;
355
356 /*
357 * try to infer base from the string
358 */
359 if (*s != '0')
360 tmp = 10; /* doesn't start with 0 - assume decimal */
361 else if (s[1] == 'X' || s[1] == 'x')
362 tmp = 16, s += 2; /* starts with 0x or 0X - hence hex */
363 else
364 tmp = 8; /* starts with 0 - hence octal */
365 if (base==0)
366 base = (int)tmp;
367 }
368
369 maxdiv = ULONG_MAX / base;
370 maxrem = ULONG_MAX % base;
371
372 while ((digit = *s) != '\0')
373 {
374 if (digit >= '0' && digit < ('0'+base))
375 digit -= '0';
376 else
377 if (base > 10)
378 {
379 if (digit >= 'a' && digit < ('a'+(base-10)))
380 digit = digit - 'a' + 10;
381 else if (digit >= 'A' && digit < ('A'+(base-10)))
382 digit = digit - 'A' + 10;
383 else
384 break;
385 }
386 else
387 break;
388 did_conversion = 1;
389 if (total > maxdiv
390 || (total == maxdiv && digit > maxrem))
391 overflow = 1;
392 total = (total * base) + digit;
393 s++;
394 }
395 if (overflow)
396 {
397 errno = ERANGE;
398 if (ptr != NULL)
399 *ptr = (char *)s;
400 return (ULONG_MAX);
401 }
402 if (ptr != NULL)
403 *ptr = (char *) ((did_conversion) ? (char *)s : (char *)start);
404 return negate ? -total : total;
405 }
406 #endif
407
408 void _exit (int foo) __attribute__ ((noreturn));
409
410 void
411 exit (int foo)
412 {
413 _exit (foo);
414 }