Commit | Line | Data |
---|---|---|
249abc98 KH |
1 | /* ARC target-dependent stuff. |
2 | Copyright (C) 1995 Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of GDB. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | ||
20 | #include "defs.h" | |
21 | #include "frame.h" | |
22 | #include "inferior.h" | |
23 | #include "gdbcore.h" | |
24 | #include "target.h" | |
25 | #include "floatformat.h" | |
26 | #include "symtab.h" | |
f0d795fa DE |
27 | #include "gdbcmd.h" |
28 | ||
29 | /* Current CPU, set with the "set cpu" command. */ | |
30 | char *arc_cpu_type; | |
31 | char *tmp_arc_cpu_type; | |
32 | ||
33 | /* Table of cpu names. */ | |
34 | struct { | |
35 | char *name; | |
36 | int value; | |
37 | } arc_cpu_type_table[] = { | |
38 | { "base", bfd_mach_arc_base }, | |
39 | { "host", bfd_mach_arc_host }, | |
40 | { "graphics", bfd_mach_arc_graphics }, | |
41 | { "audio", bfd_mach_arc_audio }, | |
42 | { NULL, 0 } | |
43 | }; | |
44 | ||
45 | /* Used by simulator. */ | |
46 | int display_pipeline_p; | |
47 | int cpu_timer; | |
48 | /* This one must have the same type as used in the emulator. | |
49 | It's currently an enum so this should be ok for now. */ | |
50 | int debug_pipeline_p; | |
51 | ||
52 | #define ARC_CALL_SAVED_REG(r) ((r) >= 16 && (r) < 24) | |
249abc98 | 53 | |
f0d795fa DE |
54 | #define OPMASK 0xf8000000 |
55 | ||
56 | /* Instruction field accessor macros. */ | |
57 | #define X_OP(i) (((i) >> 27) & 0x1f) | |
58 | #define X_A(i) (((i) >> 21) & 0x3f) | |
59 | #define X_B(i) (((i) >> 15) & 0x3f) | |
60 | #define X_C(i) (((i) >> 9) & 0x3f) | |
61 | #define X_D(i) ((((i) & 0x1ff) ^ 0x100) - 0x100) | |
62 | #define X_L(i) (((((i) >> 5) & 0x3ffffc) ^ 0x200000) - 0x200000) | |
63 | #define X_N(i) (((i) >> 5) & 3) | |
64 | #define X_Q(i) ((i) & 0x1f) | |
65 | ||
66 | /* Return non-zero if X is a short immediate data indicator. */ | |
67 | #define SHIMM_P(x) ((x) == 61 || (x) == 63) | |
68 | ||
69 | /* Return non-zero if X is a "long" (32 bit) immediate data indicator. */ | |
70 | #define LIMM_P(x) ((x) == 62) | |
71 | ||
72 | /* Build a simple instruction. */ | |
73 | #define BUILD_INSN(op, a, b, c, d) \ | |
74 | ((((op) & 31) << 27) \ | |
75 | | (((a) & 63) << 21) \ | |
76 | | (((b) & 63) << 15) \ | |
77 | | (((c) & 63) << 9) \ | |
78 | | ((d) & 511)) | |
79 | \f | |
80 | /* Codestream stuff. */ | |
249abc98 | 81 | static void codestream_read PARAMS ((unsigned int *, int)); |
f0d795fa | 82 | static void codestream_seek PARAMS ((CORE_ADDR)); |
249abc98 KH |
83 | static unsigned int codestream_fill PARAMS ((int)); |
84 | ||
85 | #define CODESTREAM_BUFSIZ 16 | |
86 | static CORE_ADDR codestream_next_addr; | |
87 | static CORE_ADDR codestream_addr; | |
88 | static unsigned int codestream_buf[CODESTREAM_BUFSIZ]; | |
89 | static int codestream_off; | |
90 | static int codestream_cnt; | |
91 | ||
f0d795fa DE |
92 | #define codestream_tell() \ |
93 | (codestream_addr + codestream_off * sizeof (codestream_buf[0])) | |
94 | #define codestream_peek() \ | |
95 | (codestream_cnt == 0 \ | |
96 | ? codestream_fill (1) \ | |
97 | : codestream_buf[codestream_off]) | |
98 | #define codestream_get() \ | |
99 | (codestream_cnt-- == 0 \ | |
100 | ? codestream_fill (0) \ | |
101 | : codestream_buf[codestream_off++]) | |
249abc98 KH |
102 | |
103 | static unsigned int | |
104 | codestream_fill (peek_flag) | |
105 | int peek_flag; | |
106 | { | |
107 | codestream_addr = codestream_next_addr; | |
f0d795fa | 108 | codestream_next_addr += CODESTREAM_BUFSIZ * sizeof (codestream_buf[0]); |
249abc98 KH |
109 | codestream_off = 0; |
110 | codestream_cnt = CODESTREAM_BUFSIZ; | |
f0d795fa DE |
111 | /* FIXME: need to handle byte order differences. */ |
112 | read_memory (codestream_addr, (char *) codestream_buf, | |
113 | CODESTREAM_BUFSIZ * sizeof (codestream_buf[0])); | |
249abc98 KH |
114 | |
115 | if (peek_flag) | |
116 | return (codestream_peek()); | |
117 | else | |
118 | return (codestream_get()); | |
119 | } | |
120 | ||
121 | static void | |
122 | codestream_seek (place) | |
f0d795fa | 123 | CORE_ADDR place; |
249abc98 KH |
124 | { |
125 | codestream_next_addr = place / CODESTREAM_BUFSIZ; | |
126 | codestream_next_addr *= CODESTREAM_BUFSIZ; | |
127 | codestream_cnt = 0; | |
128 | codestream_fill (1); | |
129 | while (codestream_tell() != place) | |
130 | codestream_get (); | |
131 | } | |
132 | ||
133 | static void | |
134 | codestream_read (buf, count) | |
135 | unsigned int *buf; | |
136 | int count; | |
137 | { | |
138 | unsigned int *p; | |
139 | int i; | |
140 | p = buf; | |
141 | for (i = 0; i < count; i++) | |
142 | *p++ = codestream_get (); | |
143 | } | |
f0d795fa DE |
144 | \f |
145 | /* Set up prologue scanning and return the first insn, | |
146 | not including the "sub sp,sp,32" of a stdarg function. */ | |
147 | ||
148 | static unsigned int | |
149 | setup_prologue_scan (pc) | |
150 | CORE_ADDR pc; | |
151 | { | |
152 | unsigned int insn; | |
153 | ||
154 | codestream_seek (pc); | |
155 | insn = codestream_get (); | |
156 | ||
157 | /* The authority for what appears here is the home-grown ABI. */ | |
158 | ||
159 | /* First insn may be "sub sp,sp,32" if stdarg fn. */ | |
160 | if (insn == BUILD_INSN (10, SP_REGNUM, SP_REGNUM, SHIMM_REGNUM, 32)) | |
161 | insn = codestream_get (); | |
162 | ||
163 | return insn; | |
164 | } | |
249abc98 KH |
165 | |
166 | /* | |
f0d795fa DE |
167 | * Find & return amount a local space allocated, and advance codestream to |
168 | * first register push (if any). | |
169 | * If entry sequence doesn't make sense, return -1, and leave | |
170 | * codestream pointer random. | |
249abc98 KH |
171 | */ |
172 | ||
173 | static long | |
174 | arc_get_frame_setup (pc) | |
f0d795fa | 175 | CORE_ADDR pc; |
249abc98 | 176 | { |
f0d795fa DE |
177 | unsigned int insn; |
178 | /* Size of frame or -1 if unrecognizable prologue. */ | |
179 | int n = -1; | |
249abc98 | 180 | |
f0d795fa | 181 | insn = setup_prologue_scan (pc); |
249abc98 | 182 | |
f0d795fa DE |
183 | if ((insn & BUILD_INSN (-1, 0, -1, -1, -1)) /* st blink,[sp,4] */ |
184 | == BUILD_INSN (2, 0, SP_REGNUM, BLINK_REGNUM, 4)) | |
185 | { | |
186 | insn = codestream_get (); | |
187 | /* Frame may not be necessary, even though blink is saved. | |
188 | At least this is something we recognize. */ | |
189 | n = 0; | |
190 | } | |
191 | ||
192 | if ((insn & BUILD_INSN (-1, 0, -1, -1, -1)) /* st fp,[sp] */ | |
193 | == BUILD_INSN (2, 0, SP_REGNUM, FP_REGNUM, 0)) | |
249abc98 KH |
194 | { |
195 | insn = codestream_get (); | |
f0d795fa DE |
196 | if ((insn & BUILD_INSN (-1, -1, -1, -1, 0)) |
197 | != BUILD_INSN (12, FP_REGNUM, SP_REGNUM, SP_REGNUM, 0)) | |
198 | return -1; | |
249abc98 | 199 | |
f0d795fa | 200 | /* Check for stack adjustment sub sp,sp,nnn. */ |
249abc98 | 201 | insn = codestream_peek (); |
f0d795fa DE |
202 | if ((insn & BUILD_INSN (-1, -1, -1, 0, 0)) |
203 | == BUILD_INSN (10, SP_REGNUM, SP_REGNUM, 0, 0)) | |
249abc98 | 204 | { |
f0d795fa DE |
205 | if (LIMM_P (X_C (insn))) |
206 | n = codestream_get (); | |
207 | else if (SHIMM_P (X_C (insn))) | |
208 | n = X_D (insn); | |
209 | else | |
210 | return -1; | |
211 | if (n < 0) | |
212 | return -1; | |
213 | ||
249abc98 KH |
214 | codestream_get (); |
215 | ||
f0d795fa DE |
216 | /* This sequence is used to get the address of the return |
217 | buffer for a function that returns a structure. */ | |
249abc98 KH |
218 | insn = codestream_peek (); |
219 | if (insn & OPMASK == 0x60000000) | |
220 | codestream_get (); | |
249abc98 | 221 | } |
f0d795fa | 222 | /* Frameless fn. */ |
249abc98 KH |
223 | else |
224 | { | |
f0d795fa | 225 | n = 0; |
249abc98 KH |
226 | } |
227 | } | |
f0d795fa DE |
228 | |
229 | return n; | |
249abc98 KH |
230 | } |
231 | ||
f0d795fa DE |
232 | /* Given a pc value, skip it forward past the function prologue by |
233 | disassembling instructions that appear to be a prologue. | |
234 | ||
235 | If FRAMELESS_P is set, we are only testing to see if the function | |
236 | is frameless. If it is a frameless function, return PC unchanged. | |
237 | This allows a quicker answer. */ | |
238 | ||
249abc98 | 239 | CORE_ADDR |
f0d795fa DE |
240 | skip_prologue (pc, frameless_p) |
241 | CORE_ADDR pc; | |
242 | int frameless_p; | |
249abc98 KH |
243 | { |
244 | unsigned int insn; | |
f0d795fa DE |
245 | int i, frame_size; |
246 | ||
247 | if ((frame_size = arc_get_frame_setup (pc)) < 0) | |
249abc98 | 248 | return (pc); |
f0d795fa DE |
249 | |
250 | if (frameless_p) | |
251 | return frame_size == 0 ? pc : codestream_tell (); | |
252 | ||
253 | /* Skip over register saves. */ | |
254 | for (i = 0; i < 8; i++) | |
249abc98 KH |
255 | { |
256 | insn = codestream_peek (); | |
f0d795fa DE |
257 | if ((insn & BUILD_INSN (-1, 0, -1, 0, 0)) |
258 | != BUILD_INSN (2, 0, SP_REGNUM, 0, 0)) | |
259 | break; /* not st insn */ | |
260 | if (! ARC_CALL_SAVED_REG (X_C (insn))) | |
249abc98 KH |
261 | break; |
262 | codestream_get (); | |
263 | } | |
f0d795fa DE |
264 | |
265 | return codestream_tell (); | |
249abc98 KH |
266 | } |
267 | ||
f0d795fa DE |
268 | /* Return the return address for a frame. |
269 | This is used to implement FRAME_SAVED_PC. | |
270 | This is taken from frameless_look_for_prologue. */ | |
271 | ||
272 | CORE_ADDR | |
273 | arc_frame_saved_pc (frame) | |
274 | struct frame_info *frame; | |
249abc98 | 275 | { |
f0d795fa DE |
276 | CORE_ADDR func_start; |
277 | unsigned int insn; | |
278 | ||
279 | func_start = get_pc_function_start (frame->pc) + FUNCTION_START_OFFSET; | |
280 | if (func_start == 0) | |
249abc98 | 281 | { |
f0d795fa DE |
282 | /* Best guess. */ |
283 | return ARC_PC_TO_REAL_ADDRESS (read_memory_integer (FRAME_FP (frame) + 4, 4)); | |
249abc98 | 284 | } |
f0d795fa DE |
285 | |
286 | /* If the first insn is "st blink,[sp,4]" we can get blink from there. | |
287 | Otherwise this is a leaf function and we can use blink. Note that | |
288 | this still allows for the case where a leaf function saves/clobbers/ | |
289 | restores blink. */ | |
290 | ||
291 | insn = setup_prologue_scan (func_start); | |
292 | ||
293 | if ((insn & BUILD_INSN (-1, 0, -1, -1, -1)) /* st blink,[sp,4] */ | |
294 | != BUILD_INSN (2, 0, SP_REGNUM, BLINK_REGNUM, 4)) | |
295 | return ARC_PC_TO_REAL_ADDRESS (read_register (BLINK_REGNUM)); | |
249abc98 | 296 | else |
f0d795fa | 297 | return ARC_PC_TO_REAL_ADDRESS (read_memory_integer (FRAME_FP (frame) + 4, 4)); |
249abc98 KH |
298 | } |
299 | ||
300 | /* | |
f0d795fa | 301 | * Parse the first few instructions of the function to see |
249abc98 KH |
302 | * what registers were stored. |
303 | * | |
304 | * The startup sequence can be at the start of the function. | |
f0d795fa | 305 | * 'st blink,[sp+4], st fp,[sp], mov fp,sp' |
249abc98 | 306 | * |
f0d795fa DE |
307 | * Local space is allocated just below by sub sp,sp,nnn. |
308 | * Next, the registers used by this function are stored (as offsets from sp). | |
249abc98 KH |
309 | */ |
310 | ||
311 | void | |
312 | frame_find_saved_regs (fip, fsrp) | |
313 | struct frame_info *fip; | |
314 | struct frame_saved_regs *fsrp; | |
315 | { | |
316 | long locals; | |
317 | unsigned int insn; | |
318 | CORE_ADDR dummy_bottom; | |
319 | CORE_ADDR adr; | |
320 | int i, regnum, offset; | |
f0d795fa | 321 | |
249abc98 | 322 | memset (fsrp, 0, sizeof *fsrp); |
f0d795fa DE |
323 | |
324 | /* If frame is the end of a dummy, compute where the beginning would be. */ | |
249abc98 | 325 | dummy_bottom = fip->frame - 4 - REGISTER_BYTES - CALL_DUMMY_LENGTH; |
f0d795fa DE |
326 | |
327 | /* Check if the PC is in the stack, in a dummy frame. */ | |
249abc98 KH |
328 | if (dummy_bottom <= fip->pc && fip->pc <= fip->frame) |
329 | { | |
330 | /* all regs were saved by push_call_dummy () */ | |
331 | adr = fip->frame; | |
332 | for (i = 0; i < NUM_REGS; i++) | |
333 | { | |
334 | adr -= REGISTER_RAW_SIZE (i); | |
335 | fsrp->regs[i] = adr; | |
336 | } | |
337 | return; | |
338 | } | |
f0d795fa | 339 | |
249abc98 | 340 | locals = arc_get_frame_setup (get_pc_function_start (fip->pc)); |
f0d795fa | 341 | |
249abc98 KH |
342 | if (locals >= 0) |
343 | { | |
f0d795fa | 344 | /* Set `adr' to the value of `sp'. */ |
249abc98 | 345 | adr = fip->frame - locals; |
f0d795fa | 346 | for (i = 0; i < 8; i++) |
249abc98 KH |
347 | { |
348 | insn = codestream_get (); | |
f0d795fa DE |
349 | if ((insn & BUILD_INSN (-1, 0, -1, 0, 0)) |
350 | != BUILD_INSN (2, 0, SP_REGNUM, 0, 0)) | |
249abc98 | 351 | break; |
f0d795fa DE |
352 | regnum = X_C (insn); |
353 | offset = X_D (insn); | |
249abc98 KH |
354 | fsrp->regs[regnum] = adr + offset; |
355 | } | |
356 | } | |
f0d795fa | 357 | |
249abc98 KH |
358 | fsrp->regs[PC_REGNUM] = fip->frame + 4; |
359 | fsrp->regs[FP_REGNUM] = fip->frame; | |
360 | } | |
361 | ||
362 | void | |
363 | push_dummy_frame () | |
364 | { | |
365 | CORE_ADDR sp = read_register (SP_REGNUM); | |
366 | int regnum; | |
367 | char regbuf[MAX_REGISTER_RAW_SIZE]; | |
368 | ||
369 | read_register_gen (PC_REGNUM, regbuf); | |
370 | write_memory (sp+4, regbuf, REGISTER_SIZE); | |
371 | read_register_gen (FP_REGNUM, regbuf); | |
372 | write_memory (sp, regbuf, REGISTER_SIZE); | |
373 | write_register (FP_REGNUM, sp); | |
374 | for (regnum = 0; regnum < NUM_REGS; regnum++) | |
375 | { | |
376 | read_register_gen (regnum, regbuf); | |
377 | sp = push_bytes (sp, regbuf, REGISTER_RAW_SIZE (regnum)); | |
378 | } | |
379 | sp += (2*REGISTER_SIZE); | |
380 | write_register (SP_REGNUM, sp); | |
381 | } | |
382 | ||
383 | void | |
384 | pop_frame () | |
385 | { | |
386 | struct frame_info *frame = get_current_frame (); | |
387 | CORE_ADDR fp; | |
388 | int regnum; | |
389 | struct frame_saved_regs fsr; | |
390 | char regbuf[MAX_REGISTER_RAW_SIZE]; | |
391 | ||
392 | fp = FRAME_FP (frame); | |
393 | get_frame_saved_regs (frame, &fsr); | |
394 | for (regnum = 0; regnum < NUM_REGS; regnum++) | |
395 | { | |
396 | CORE_ADDR adr; | |
397 | adr = fsr.regs[regnum]; | |
398 | if (adr) | |
399 | { | |
400 | read_memory (adr, regbuf, REGISTER_RAW_SIZE (regnum)); | |
401 | write_register_bytes (REGISTER_BYTE (regnum), regbuf, | |
402 | REGISTER_RAW_SIZE (regnum)); | |
403 | } | |
404 | } | |
405 | write_register (FP_REGNUM, read_memory_integer (fp, 4)); | |
406 | write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); | |
407 | write_register (SP_REGNUM, fp + 8); | |
408 | flush_cached_frames (); | |
409 | } | |
f0d795fa DE |
410 | \f |
411 | /* Simulate single-step. */ | |
412 | ||
413 | typedef enum | |
414 | { | |
415 | NORMAL4, /* a normal 4 byte insn */ | |
416 | NORMAL8, /* a normal 8 byte insn */ | |
417 | BRANCH4, /* a 4 byte branch insn, including ones without delay slots */ | |
418 | BRANCH8, /* an 8 byte branch insn, including ones with delay slots */ | |
419 | } insn_type; | |
420 | ||
421 | /* Return the type of INSN and store in TARGET the destination address of a | |
422 | branch if this is one. */ | |
423 | /* ??? Need to verify all cases are properly handled. */ | |
424 | ||
425 | static insn_type | |
426 | get_insn_type (insn, pc, target) | |
427 | unsigned long insn; | |
428 | CORE_ADDR pc, *target; | |
429 | { | |
430 | unsigned long limm; | |
431 | ||
432 | switch (insn >> 27) | |
433 | { | |
434 | case 0 : case 1 : case 2 : /* load/store insns */ | |
435 | if (LIMM_P (X_A (insn)) | |
436 | || LIMM_P (X_B (insn)) | |
437 | || LIMM_P (X_C (insn))) | |
438 | return NORMAL8; | |
439 | return NORMAL4; | |
440 | case 4 : case 5 : case 6 : /* branch insns */ | |
441 | *target = pc + 4 + X_L (insn); | |
442 | /* ??? It isn't clear that this is always the right answer. | |
443 | The problem occurs when the next insn is an 8 byte insn. If the | |
444 | branch is conditional there's no worry as there shouldn't be an 8 | |
445 | byte insn following. The programmer may be cheating if s/he knows | |
446 | the branch will never be taken, but we don't deal with that. | |
447 | Note that the programmer is also allowed to play games by putting | |
448 | an insn with long immediate data in the delay slot and then duplicate | |
449 | the long immediate data at the branch target. Ugh! */ | |
450 | if (X_N (insn) == 0) | |
451 | return BRANCH4; | |
452 | return BRANCH8; | |
453 | case 7 : /* jump insns */ | |
454 | if (LIMM_P (X_B (insn))) | |
455 | { | |
456 | limm = read_memory_integer (pc + 4, 4); | |
457 | *target = ARC_PC_TO_REAL_ADDRESS (limm); | |
458 | return BRANCH8; | |
459 | } | |
460 | if (SHIMM_P (X_B (insn))) | |
461 | *target = ARC_PC_TO_REAL_ADDRESS (X_D (insn)); | |
462 | else | |
463 | *target = ARC_PC_TO_REAL_ADDRESS (read_register (X_B (insn))); | |
464 | if (X_Q (insn) == 0 && X_N (insn) == 0) | |
465 | return BRANCH4; | |
466 | return BRANCH8; | |
467 | default : /* arithmetic insns, etc. */ | |
468 | if (LIMM_P (X_A (insn)) | |
469 | || LIMM_P (X_B (insn)) | |
470 | || LIMM_P (X_C (insn))) | |
471 | return NORMAL8; | |
472 | return NORMAL4; | |
473 | } | |
474 | } | |
475 | ||
476 | /* Non-zero if we just simulated a single-step. This is needed because we | |
477 | cannot remove the breakpoints in the inferior process until after the | |
478 | `wait' in `wait_for_inferior'. */ | |
479 | ||
480 | int one_stepped; | |
481 | ||
482 | /* single_step() is called just before we want to resume the inferior, if we | |
483 | want to single-step it but there is no hardware or kernel single-step | |
484 | support. We find all the possible targets of the coming instruction and | |
485 | breakpoint them. | |
486 | ||
487 | single_step is also called just after the inferior stops. If we had | |
488 | set up a simulated single-step, we undo our damage. */ | |
249abc98 | 489 | |
f0d795fa DE |
490 | void |
491 | single_step (ignore) | |
492 | int ignore; /* sig, but we don't need it */ | |
493 | { | |
494 | static CORE_ADDR next_pc, target; | |
495 | static int brktrg_p; | |
496 | typedef char binsn_quantum[BREAKPOINT_MAX]; | |
497 | static binsn_quantum break_mem[2]; | |
498 | ||
499 | if (!one_stepped) | |
500 | { | |
501 | insn_type type; | |
502 | CORE_ADDR pc; | |
503 | unsigned long insn; | |
504 | ||
505 | pc = read_register (PC_REGNUM); | |
506 | insn = read_memory_integer (pc, 4); | |
507 | type = get_insn_type (insn, pc, &target); | |
508 | ||
509 | /* Always set a breakpoint for the insn after the branch. */ | |
510 | next_pc = pc + ((type == NORMAL8 || type == BRANCH8) ? 8 : 4); | |
511 | target_insert_breakpoint (next_pc, break_mem[0]); | |
512 | ||
513 | brktrg_p = 0; | |
514 | ||
515 | if ((type == BRANCH4 || type == BRANCH8) | |
516 | /* Watch out for branches to the following location. | |
517 | We just stored a breakpoint there and another call to | |
518 | target_insert_breakpoint will think the real insn is the | |
519 | breakpoint we just stored there. */ | |
520 | && target != next_pc) | |
521 | { | |
522 | brktrg_p = 1; | |
523 | target_insert_breakpoint (target, break_mem[1]); | |
524 | } | |
525 | ||
526 | /* We are ready to let it go. */ | |
527 | one_stepped = 1; | |
528 | } | |
529 | else | |
530 | { | |
531 | /* Remove breakpoints. */ | |
532 | target_remove_breakpoint (next_pc, break_mem[0]); | |
533 | ||
534 | if (brktrg_p) | |
535 | target_remove_breakpoint (target, break_mem[1]); | |
536 | ||
537 | /* Fix the pc. */ | |
538 | stop_pc -= DECR_PC_AFTER_BREAK; | |
539 | write_pc (stop_pc); | |
540 | ||
541 | one_stepped = 0; | |
542 | } | |
543 | } | |
544 | \f | |
249abc98 KH |
545 | #ifdef GET_LONGJMP_TARGET |
546 | /* Figure out where the longjmp will land. Slurp the args out of the stack. | |
547 | We expect the first arg to be a pointer to the jmp_buf structure from which | |
548 | we extract the pc (JB_PC) that we will land at. The pc is copied into PC. | |
549 | This routine returns true on success. */ | |
550 | ||
551 | int | |
552 | get_longjmp_target(pc) | |
553 | CORE_ADDR *pc; | |
554 | { | |
555 | char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT]; | |
556 | CORE_ADDR sp, jb_addr; | |
557 | ||
558 | sp = read_register (SP_REGNUM); | |
559 | ||
560 | if (target_read_memory (sp + SP_ARG0, /* Offset of first arg on stack */ | |
561 | buf, | |
562 | TARGET_PTR_BIT / TARGET_CHAR_BIT)) | |
563 | return 0; | |
564 | ||
565 | jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT); | |
566 | ||
567 | if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf, | |
568 | TARGET_PTR_BIT / TARGET_CHAR_BIT)) | |
569 | return 0; | |
570 | ||
571 | *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT); | |
572 | ||
573 | return 1; | |
574 | } | |
575 | #endif /* GET_LONGJMP_TARGET */ | |
f0d795fa DE |
576 | \f |
577 | /* Command to set cpu type. */ | |
249abc98 | 578 | |
f0d795fa DE |
579 | void |
580 | arc_set_cpu_type_command (args, from_tty) | |
581 | char *args; | |
582 | int from_tty; | |
583 | { | |
584 | int i; | |
585 | ||
586 | if (tmp_arc_cpu_type == NULL || *tmp_arc_cpu_type == '\0') | |
587 | { | |
588 | printf_unfiltered ("The known ARC cpu types are as follows:\n"); | |
589 | for (i = 0; arc_cpu_type_table[i].name != NULL; ++i) | |
590 | printf_unfiltered ("%s\n", arc_cpu_type_table[i].name); | |
591 | ||
592 | /* Restore the value. */ | |
593 | tmp_arc_cpu_type = strsave (arc_cpu_type); | |
594 | ||
595 | return; | |
596 | } | |
597 | ||
598 | if (!arc_set_cpu_type (tmp_arc_cpu_type)) | |
599 | { | |
600 | error ("Unknown cpu type `%s'.", tmp_arc_cpu_type); | |
601 | /* Restore its value. */ | |
602 | tmp_arc_cpu_type = strsave (arc_cpu_type); | |
603 | } | |
604 | } | |
605 | ||
606 | static void | |
607 | arc_show_cpu_type_command (args, from_tty) | |
608 | char *args; | |
609 | int from_tty; | |
610 | { | |
611 | } | |
612 | ||
613 | /* Modify the actual cpu type. | |
614 | Result is a boolean indicating success. */ | |
615 | ||
616 | int | |
617 | arc_set_cpu_type (str) | |
618 | char *str; | |
619 | { | |
620 | int i, j; | |
621 | ||
622 | if (str == NULL) | |
623 | return 0; | |
624 | ||
625 | for (i = 0; arc_cpu_type_table[i].name != NULL; ++i) | |
626 | { | |
627 | if (strcasecmp (str, arc_cpu_type_table[i].name) == 0) | |
628 | { | |
629 | arc_cpu_type = str; | |
630 | tm_print_insn = arc_get_disassembler (arc_cpu_type_table[i].value, | |
631 | TARGET_BYTE_ORDER == BIG_ENDIAN); | |
632 | return 1; | |
633 | } | |
634 | } | |
635 | ||
636 | return 0; | |
637 | } | |
638 | \f | |
9c4ecee6 SS |
639 | void |
640 | _initialize_arc_tdep () | |
249abc98 | 641 | { |
f0d795fa DE |
642 | struct cmd_list_element *c; |
643 | ||
644 | c = add_set_cmd ("cpu", class_support, var_string_noescape, | |
645 | (char *) &tmp_arc_cpu_type, | |
646 | "Set the type of ARC cpu in use.\n\ | |
647 | This command has two purposes. In a multi-cpu system it lets one\n\ | |
648 | change the cpu being debugged. It also gives one access to\n\ | |
649 | cpu-type-specific registers and recognize cpu-type-specific instructions.\ | |
650 | ", | |
651 | &setlist); | |
652 | c->function.cfunc = arc_set_cpu_type_command; | |
653 | c = add_show_from_set (c, &showlist); | |
654 | c->function.cfunc = arc_show_cpu_type_command; | |
655 | ||
656 | /* We have to use strsave here because the `set' command frees it before | |
657 | setting a new value. */ | |
658 | tmp_arc_cpu_type = strsave (DEFAULT_ARC_CPU_TYPE); | |
659 | arc_set_cpu_type (tmp_arc_cpu_type); | |
660 | ||
661 | c = add_set_cmd ("displaypipeline", class_support, var_zinteger, | |
662 | (char *) &display_pipeline_p, | |
663 | "Set pipeline display (simulator only).\n\ | |
664 | When enabled, the state of the pipeline after each cycle is displayed.", | |
665 | &setlist); | |
666 | c = add_show_from_set (c, &showlist); | |
667 | ||
668 | c = add_set_cmd ("debugpipeline", class_support, var_zinteger, | |
669 | (char *) &debug_pipeline_p, | |
670 | "Set pipeline debug display (simulator only).\n\ | |
671 | When enabled, debugging information about the pipeline is displayed.", | |
672 | &setlist); | |
673 | c = add_show_from_set (c, &showlist); | |
674 | ||
675 | c = add_set_cmd ("cputimer", class_support, var_zinteger, | |
676 | (char *) &cpu_timer, | |
677 | "Set maximum cycle count (simulator only).\n\ | |
678 | Control will return to gdb if the timer expires.\n\ | |
679 | A negative value disables the timer.", | |
680 | &setlist); | |
681 | c = add_show_from_set (c, &showlist); | |
682 | ||
683 | /* FIXME: must be done after for now. */ | |
684 | tm_print_insn = arc_get_disassembler (bfd_mach_arc_base, 1 /*FIXME*/); | |
249abc98 | 685 | } |