]>
Commit | Line | Data |
---|---|---|
54af8e6e | 1 | /* Target-dependent code for the Acorn Risc Machine, for GDB, the GNU Debugger. |
72c9954b SS |
2 | Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995, 1996 |
3 | Free Software Foundation, Inc. | |
bd5635a1 RP |
4 | |
5 | This file is part of GDB. | |
6 | ||
54af8e6e | 7 | This program is free software; you can redistribute it and/or modify |
bd5635a1 | 8 | it under the terms of the GNU General Public License as published by |
54af8e6e SC |
9 | the Free Software Foundation; either version 2 of the License, or |
10 | (at your option) any later version. | |
bd5635a1 | 11 | |
54af8e6e | 12 | This program is distributed in the hope that it will be useful, |
bd5635a1 RP |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
54af8e6e | 18 | along with this program; if not, write to the Free Software |
72c9954b | 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
bd5635a1 RP |
20 | |
21 | #include "defs.h" | |
bd5635a1 RP |
22 | #include "frame.h" |
23 | #include "inferior.h" | |
72c9954b | 24 | #include "gdbcmd.h" |
bd5635a1 | 25 | |
72c9954b | 26 | /* Set to true if the 32-bit mode is in use. */ |
bd5635a1 | 27 | |
72c9954b | 28 | int arm_apcs_32 = 1; |
bd5635a1 | 29 | |
72c9954b SS |
30 | CORE_ADDR |
31 | arm_addr_bits_remove (val) | |
32 | CORE_ADDR val; | |
bd5635a1 | 33 | { |
72c9954b | 34 | return (val & (arm_apcs_32 ? 0xfffffffc : 0x03fffffc)); |
bd5635a1 | 35 | } |
bd5635a1 | 36 | |
72c9954b SS |
37 | CORE_ADDR |
38 | arm_saved_pc_after_call (frame) | |
39 | struct frame_info *frame; | |
bd5635a1 | 40 | { |
72c9954b | 41 | return ADDR_BITS_REMOVE (read_register (LR_REGNUM)); |
bd5635a1 | 42 | } |
72c9954b | 43 | |
bd5635a1 RP |
44 | /* APCS (ARM procedure call standard) defines the following prologue: |
45 | ||
46 | mov ip, sp | |
47 | [stmfd sp!, {a1,a2,a3,a4}] | |
48 | stmfd sp!, {...,fp,ip,lr,pc} | |
49 | [stfe f7, [sp, #-12]!] | |
50 | [stfe f6, [sp, #-12]!] | |
51 | [stfe f5, [sp, #-12]!] | |
52 | [stfe f4, [sp, #-12]!] | |
53 | sub fp, ip, #nn // nn == 20 or 4 depending on second ins | |
54 | */ | |
55 | ||
56 | CORE_ADDR | |
72c9954b | 57 | arm_skip_prologue (pc) |
bd5635a1 RP |
58 | CORE_ADDR pc; |
59 | { | |
72c9954b SS |
60 | unsigned long inst; |
61 | CORE_ADDR skip_pc = pc; | |
62 | ||
63 | inst = read_memory_integer (skip_pc, 4); | |
64 | if (inst != 0xe1a0c00d) /* mov ip, sp */ | |
65 | return pc; | |
66 | ||
67 | skip_pc += 4; | |
68 | inst = read_memory_integer (skip_pc, 4); | |
69 | if ((inst & 0xfffffff0) == 0xe92d0000) /* stmfd sp!,{a1,a2,a3,a4} */ | |
70 | { | |
71 | skip_pc += 4; | |
72 | inst = read_memory_integer (skip_pc, 4); | |
73 | } | |
74 | ||
75 | if ((inst & 0xfffff800) != 0xe92dd800) /* stmfd sp!,{...,fp,ip,lr,pc} */ | |
76 | return pc; | |
77 | ||
78 | skip_pc += 4; | |
79 | inst = read_memory_integer (skip_pc, 4); | |
80 | ||
81 | /* Any insns after this point may float into the code, if it makes | |
82 | for better instruction scheduling, so we skip them only if | |
83 | we find them, but still consdier the function to be frame-ful */ | |
84 | ||
85 | /* We may have either one sfmfd instruction here, or several stfe insns, | |
86 | depending on the version of floating point code we support. */ | |
87 | if ((inst & 0xffbf0fff) == 0xec2d0200) /* sfmfd fn, <cnt>, [sp]! */ | |
88 | { | |
89 | skip_pc += 4; | |
90 | inst = read_memory_integer (skip_pc, 4); | |
91 | } | |
92 | else | |
93 | { | |
94 | while ((inst & 0xffff8fff) == 0xed6d0103) /* stfe fn, [sp, #-12]! */ | |
95 | { | |
96 | skip_pc += 4; | |
97 | inst = read_memory_integer (skip_pc, 4); | |
98 | } | |
99 | } | |
100 | ||
101 | if ((inst & 0xfffff000) == 0xe24cb000) /* sub fp, ip, #nn */ | |
bd5635a1 | 102 | skip_pc += 4; |
72c9954b SS |
103 | |
104 | return skip_pc; | |
bd5635a1 RP |
105 | } |
106 | ||
54af8e6e SC |
107 | void |
108 | arm_frame_find_saved_regs (frame_info, saved_regs_addr) | |
109 | struct frame_info *frame_info; | |
110 | struct frame_saved_regs *saved_regs_addr; | |
111 | { | |
112 | register int regnum; | |
113 | register int frame; | |
114 | register int next_addr; | |
115 | register int return_data_save; | |
116 | register int saved_register_mask; | |
117 | ||
118 | memset (saved_regs_addr, '\0', sizeof (*saved_regs_addr)); | |
119 | frame = frame_info->frame; | |
120 | return_data_save = read_memory_integer (frame, 4) & 0x03fffffc - 12; | |
121 | saved_register_mask = read_memory_integer (return_data_save, 4); | |
122 | next_addr = frame - 12; | |
123 | for (regnum = 4; regnum < 10; regnum++) | |
124 | if (saved_register_mask & (1 << regnum)) | |
125 | { | |
126 | next_addr -= 4; | |
127 | saved_regs_addr->regs[regnum] = next_addr; | |
128 | } | |
129 | if (read_memory_integer (return_data_save + 4, 4) == 0xed6d7103) | |
130 | { | |
131 | next_addr -= 12; | |
132 | saved_regs_addr->regs[F0_REGNUM + 7] = next_addr; | |
133 | } | |
134 | if (read_memory_integer (return_data_save + 8, 4) == 0xed6d6103) | |
135 | { | |
136 | next_addr -= 12; | |
137 | saved_regs_addr->regs[F0_REGNUM + 6] = next_addr; | |
138 | } | |
139 | if (read_memory_integer (return_data_save + 12, 4) == 0xed6d5103) | |
140 | { | |
141 | next_addr -= 12; | |
142 | saved_regs_addr->regs[F0_REGNUM + 5] = next_addr; | |
143 | } | |
144 | if (read_memory_integer(return_data_save + 16, 4) == 0xed6d4103) | |
145 | { | |
146 | next_addr -= 12; | |
147 | saved_regs_addr->regs[F0_REGNUM + 4] = next_addr; | |
148 | } | |
149 | saved_regs_addr->regs[SP_REGNUM] = next_addr; | |
150 | saved_regs_addr->regs[PC_REGNUM] = frame - 4; | |
151 | saved_regs_addr->regs[PS_REGNUM] = frame - 4; | |
152 | saved_regs_addr->regs[FP_REGNUM] = frame - 12; | |
153 | } | |
154 | ||
72c9954b SS |
155 | void |
156 | arm_push_dummy_frame () | |
157 | { | |
158 | register CORE_ADDR sp = read_register (SP_REGNUM); | |
159 | register int regnum; | |
160 | ||
161 | /* opcode for ldmdb fp,{v1-v6,fp,ip,lr,pc}^ */ | |
162 | sp = push_word (sp, 0xe92dbf0); /* dummy return_data_save ins */ | |
163 | /* push a pointer to the dummy instruction minus 12 */ | |
164 | sp = push_word (sp, read_register (SP_REGNUM) - 16); | |
165 | sp = push_word (sp, read_register (PS_REGNUM)); | |
166 | sp = push_word (sp, read_register (SP_REGNUM)); | |
167 | sp = push_word (sp, read_register (FP_REGNUM)); | |
168 | for (regnum = 9; regnum >= 4; regnum --) | |
169 | sp = push_word (sp, read_register (regnum)); | |
170 | write_register (FP_REGNUM, read_register (SP_REGNUM) - 8); | |
171 | write_register (SP_REGNUM, sp); | |
172 | } | |
173 | ||
174 | void | |
175 | arm_pop_frame () | |
176 | { | |
177 | register CORE_ADDR fp = read_register (FP_REGNUM); | |
178 | register unsigned long return_data_save = | |
179 | read_memory_integer (ADDR_BITS_REMOVE (read_memory_integer (fp, 4)) - 12, | |
180 | 4); | |
181 | register int regnum; | |
182 | ||
183 | write_register (PS_REGNUM, read_memory_integer (fp - 4, 4)); | |
184 | write_register (PC_REGNUM, ADDR_BITS_REMOVE (read_register (PS_REGNUM))); | |
185 | write_register (SP_REGNUM, read_memory_integer (fp - 8, 4)); | |
186 | write_register (FP_REGNUM, read_memory_integer (fp - 12, 4)); | |
187 | fp -= 12; | |
188 | for (regnum = 9; regnum >= 4; regnum--) | |
189 | { | |
190 | if (return_data_save & (1 << regnum)) | |
191 | { | |
192 | fp -= 4; | |
193 | write_register (regnum, read_memory_integer (fp, 4)); | |
194 | } | |
195 | } | |
196 | flush_cached_frames (); | |
197 | } | |
198 | ||
bd5635a1 | 199 | static void |
72c9954b | 200 | print_fpu_flags (flags) |
bd5635a1 RP |
201 | int flags; |
202 | { | |
72c9954b SS |
203 | if (flags & (1 << 0)) fputs ("IVO ", stdout); |
204 | if (flags & (1 << 1)) fputs ("DVZ ", stdout); | |
205 | if (flags & (1 << 2)) fputs ("OFL ", stdout); | |
206 | if (flags & (1 << 3)) fputs ("UFL ", stdout); | |
207 | if (flags & (1 << 4)) fputs ("INX ", stdout); | |
208 | putchar ('\n'); | |
bd5635a1 RP |
209 | } |
210 | ||
211 | void | |
72c9954b | 212 | arm_float_info () |
bd5635a1 | 213 | { |
72c9954b | 214 | register unsigned long status = read_register (FPS_REGNUM); |
bd5635a1 RP |
215 | int type; |
216 | ||
217 | type = (status >> 24) & 127; | |
72c9954b SS |
218 | printf ("%s FPU type %d\n", |
219 | (status & (1<<31)) ? "Hardware" : "Software", | |
220 | type); | |
221 | fputs ("mask: ", stdout); | |
222 | print_fpu_flags (status >> 16); | |
223 | fputs ("flags: ", stdout); | |
224 | print_fpu_flags (status); | |
bd5635a1 | 225 | } |
54af8e6e | 226 | |
72c9954b SS |
227 | static void |
228 | arm_othernames () | |
54af8e6e | 229 | { |
72c9954b SS |
230 | static int toggle; |
231 | static char *original[] = ORIGINAL_REGISTER_NAMES; | |
232 | static char *extra_crispy[] = ADDITIONAL_REGISTER_NAMES; | |
54af8e6e | 233 | |
72c9954b SS |
234 | memcpy (reg_names, toggle ? extra_crispy : original, sizeof(original)); |
235 | toggle = !toggle; | |
236 | } | |
54af8e6e SC |
237 | |
238 | /* FIXME: Fill in with the 'right thing', see asm | |
239 | template in arm-convert.s */ | |
240 | ||
241 | void | |
242 | convert_from_extended (ptr, dbl) | |
243 | void *ptr; | |
244 | double *dbl; | |
245 | { | |
246 | *dbl = *(double*)ptr; | |
247 | } | |
248 | ||
54af8e6e SC |
249 | void |
250 | convert_to_extended (dbl, ptr) | |
251 | void *ptr; | |
252 | double *dbl; | |
253 | { | |
254 | *(double*)ptr = *dbl; | |
255 | } | |
256 | ||
72c9954b SS |
257 | int |
258 | arm_nullified_insn (inst) | |
259 | unsigned long inst; | |
260 | { | |
261 | unsigned long cond = inst & 0xf0000000; | |
262 | unsigned long status_reg; | |
263 | ||
264 | if (cond == INST_AL || cond == INST_NV) | |
265 | return 0; | |
266 | ||
267 | status_reg = read_register (PS_REGNUM); | |
268 | ||
269 | switch (cond) | |
270 | { | |
271 | case INST_EQ: | |
272 | return ((status_reg & FLAG_Z) == 0); | |
273 | case INST_NE: | |
274 | return ((status_reg & FLAG_Z) != 0); | |
275 | case INST_CS: | |
276 | return ((status_reg & FLAG_C) == 0); | |
277 | case INST_CC: | |
278 | return ((status_reg & FLAG_C) != 0); | |
279 | case INST_MI: | |
280 | return ((status_reg & FLAG_N) == 0); | |
281 | case INST_PL: | |
282 | return ((status_reg & FLAG_N) != 0); | |
283 | case INST_VS: | |
284 | return ((status_reg & FLAG_V) == 0); | |
285 | case INST_VC: | |
286 | return ((status_reg & FLAG_V) != 0); | |
287 | case INST_HI: | |
288 | return ((status_reg & (FLAG_C | FLAG_Z)) != FLAG_C); | |
289 | case INST_LS: | |
290 | return (((status_reg & (FLAG_C | FLAG_Z)) ^ FLAG_C) == 0); | |
291 | case INST_GE: | |
292 | return (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0)); | |
293 | case INST_LT: | |
294 | return (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0)); | |
295 | case INST_GT: | |
296 | return (((status_reg & FLAG_Z) != 0) || | |
297 | (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0))); | |
298 | case INST_LE: | |
299 | return (((status_reg & FLAG_Z) == 0) && | |
300 | (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0))); | |
301 | } | |
302 | return 0; | |
303 | } | |
304 | ||
305 | #define submask(x) ((1L << ((x) + 1)) - 1) | |
306 | #define bit(obj,st) (((obj) & (1L << (st))) >> st) | |
307 | #define bits(obj,st,fn) \ | |
308 | (((obj) & submask (fn) & ~ submask ((st) - 1)) >> (st)) | |
309 | #define sbits(obj,st,fn) \ | |
310 | ((long) (bits(obj,st,fn) | ((long) bit(obj,fn) * ~ submask (fn - st)))) | |
311 | #define BranchDest(addr,instr) \ | |
312 | ((CORE_ADDR) (((long) (addr)) + 8 + (sbits (instr, 0, 23) << 2))) | |
313 | #define ARM_PC_32 1 | |
314 | ||
315 | static unsigned long | |
316 | shifted_reg_val (inst, carry, pc_val) | |
317 | unsigned long inst; | |
318 | int carry; | |
319 | unsigned long pc_val; | |
320 | { | |
321 | unsigned long res, shift; | |
322 | int rm = bits (inst, 0, 3); | |
323 | unsigned long shifttype = bits (inst, 5, 6); | |
324 | ||
325 | if (bit(inst, 4)) | |
326 | { | |
327 | int rs = bits (inst, 8, 11); | |
328 | shift = (rs == 15 ? pc_val + 8 : read_register (rs)) & 0xFF; | |
329 | } | |
330 | else | |
331 | shift = bits (inst, 7, 11); | |
332 | ||
333 | res = (rm == 15 | |
334 | ? ((pc_val | (ARM_PC_32 ? 0 : read_register (PS_REGNUM))) | |
335 | + (bit (inst, 4) ? 12 : 8)) | |
336 | : read_register (rm)); | |
337 | ||
338 | switch (shifttype) | |
339 | { | |
340 | case 0: /* LSL */ | |
341 | res = shift >= 32 ? 0 : res << shift; | |
342 | break; | |
343 | ||
344 | case 1: /* LSR */ | |
345 | res = shift >= 32 ? 0 : res >> shift; | |
346 | break; | |
347 | ||
348 | case 2: /* ASR */ | |
349 | if (shift >= 32) shift = 31; | |
350 | res = ((res & 0x80000000L) | |
351 | ? ~((~res) >> shift) : res >> shift); | |
352 | break; | |
353 | ||
354 | case 3: /* ROR/RRX */ | |
355 | shift &= 31; | |
356 | if (shift == 0) | |
357 | res = (res >> 1) | (carry ? 0x80000000L : 0); | |
358 | else | |
359 | res = (res >> shift) | (res << (32-shift)); | |
360 | break; | |
361 | } | |
362 | ||
363 | return res & 0xffffffff; | |
364 | } | |
365 | ||
366 | ||
367 | CORE_ADDR | |
368 | arm_get_next_pc (pc) | |
369 | CORE_ADDR pc; | |
370 | { | |
371 | unsigned long pc_val = (unsigned long) pc; | |
372 | unsigned long this_instr = read_memory_integer (pc, 4); | |
373 | unsigned long status = read_register (PS_REGNUM); | |
374 | CORE_ADDR nextpc = (CORE_ADDR) (pc_val + 4); /* Default case */ | |
375 | ||
376 | if (! arm_nullified_insn (this_instr)) | |
377 | { | |
378 | switch (bits(this_instr, 24, 27)) | |
379 | { | |
380 | case 0x0: case 0x1: /* data processing */ | |
381 | case 0x2: case 0x3: | |
382 | { | |
383 | unsigned long operand1, operand2, result = 0; | |
384 | unsigned long rn; | |
385 | int c; | |
386 | ||
387 | if (bits(this_instr, 12, 15) != 15) | |
388 | break; | |
389 | ||
390 | if (bits (this_instr, 22, 25) == 0 | |
391 | && bits (this_instr, 4, 7) == 9) /* multiply */ | |
392 | error ("Illegal update to pc in instruction"); | |
393 | ||
394 | /* Multiply into PC */ | |
395 | c = (status & FLAG_C) ? 1 : 0; | |
396 | rn = bits (this_instr, 16, 19); | |
397 | operand1 = (rn == 15) ? pc_val + 8 : read_register (rn); | |
398 | ||
399 | if (bit (this_instr, 25)) | |
400 | { | |
401 | unsigned long immval = bits (this_instr, 0, 7); | |
402 | unsigned long rotate = 2 * bits (this_instr, 8, 11); | |
403 | operand2 = ((immval >> rotate) | (immval << (32-rotate)) | |
404 | & 0xffffffff); | |
405 | } | |
406 | else /* operand 2 is a shifted register */ | |
407 | operand2 = shifted_reg_val (this_instr, c, pc_val); | |
408 | ||
409 | switch (bits (this_instr, 21, 24)) | |
410 | { | |
411 | case 0x0: /*and*/ | |
412 | result = operand1 & operand2; | |
413 | break; | |
414 | ||
415 | case 0x1: /*eor*/ | |
416 | result = operand1 ^ operand2; | |
417 | break; | |
418 | ||
419 | case 0x2: /*sub*/ | |
420 | result = operand1 - operand2; | |
421 | break; | |
422 | ||
423 | case 0x3: /*rsb*/ | |
424 | result = operand2 - operand1; | |
425 | break; | |
426 | ||
427 | case 0x4: /*add*/ | |
428 | result = operand1 + operand2; | |
429 | break; | |
430 | ||
431 | case 0x5: /*adc*/ | |
432 | result = operand1 + operand2 + c; | |
433 | break; | |
434 | ||
435 | case 0x6: /*sbc*/ | |
436 | result = operand1 - operand2 + c; | |
437 | break; | |
438 | ||
439 | case 0x7: /*rsc*/ | |
440 | result = operand2 - operand1 + c; | |
441 | break; | |
442 | ||
443 | case 0x8: case 0x9: case 0xa: case 0xb: /* tst, teq, cmp, cmn */ | |
444 | result = (unsigned long) nextpc; | |
445 | break; | |
446 | ||
447 | case 0xc: /*orr*/ | |
448 | result = operand1 | operand2; | |
449 | break; | |
450 | ||
451 | case 0xd: /*mov*/ | |
452 | /* Always step into a function. */ | |
453 | result = operand2; | |
454 | break; | |
455 | ||
456 | case 0xe: /*bic*/ | |
457 | result = operand1 & ~operand2; | |
458 | break; | |
459 | ||
460 | case 0xf: /*mvn*/ | |
461 | result = ~operand2; | |
462 | break; | |
463 | } | |
464 | nextpc = (CORE_ADDR) ADDR_BITS_REMOVE (result); | |
465 | ||
466 | if (nextpc == pc) | |
467 | error ("Infinite loop detected"); | |
468 | break; | |
469 | } | |
470 | ||
471 | case 0x4: case 0x5: /* data transfer */ | |
472 | case 0x6: case 0x7: | |
473 | if (bit (this_instr, 20)) | |
474 | { | |
475 | /* load */ | |
476 | if (bits (this_instr, 12, 15) == 15) | |
477 | { | |
478 | /* rd == pc */ | |
479 | unsigned long rn; | |
480 | unsigned long base; | |
481 | ||
482 | if (bit (this_instr, 22)) | |
483 | error ("Illegal update to pc in instruction"); | |
484 | ||
485 | /* byte write to PC */ | |
486 | rn = bits (this_instr, 16, 19); | |
487 | base = (rn == 15) ? pc_val + 8 : read_register (rn); | |
488 | if (bit (this_instr, 24)) | |
489 | { | |
490 | /* pre-indexed */ | |
491 | int c = (status & FLAG_C) ? 1 : 0; | |
492 | unsigned long offset = | |
493 | (bit (this_instr, 25) | |
494 | ? shifted_reg_val (this_instr, c, pc_val) | |
495 | : bits (this_instr, 0, 11)); | |
496 | ||
497 | if (bit (this_instr, 23)) | |
498 | base += offset; | |
499 | else | |
500 | base -= offset; | |
501 | } | |
502 | nextpc = (CORE_ADDR) read_memory_integer ((CORE_ADDR) base, | |
503 | 4); | |
504 | ||
505 | nextpc = ADDR_BITS_REMOVE (nextpc); | |
506 | ||
507 | if (nextpc == pc) | |
508 | error ("Infinite loop detected"); | |
509 | } | |
510 | } | |
511 | break; | |
512 | ||
513 | case 0x8: case 0x9: /* block transfer */ | |
514 | if (bit (this_instr, 20)) | |
515 | { | |
516 | /* LDM */ | |
517 | if (bit (this_instr, 15)) | |
518 | { | |
519 | /* loading pc */ | |
520 | int offset = 0; | |
521 | ||
522 | if (bit (this_instr, 23)) | |
523 | { | |
524 | /* up */ | |
525 | unsigned long reglist = bits (this_instr, 0, 14); | |
526 | unsigned long regbit; | |
527 | ||
528 | for (; reglist != 0; reglist &= ~regbit) | |
529 | { | |
530 | regbit = reglist & (-reglist); | |
531 | offset += 4; | |
532 | } | |
533 | ||
534 | if (bit (this_instr, 24)) /* pre */ | |
535 | offset += 4; | |
536 | } | |
537 | else if (bit (this_instr, 24)) | |
538 | offset = -4; | |
539 | ||
540 | { | |
541 | unsigned long rn_val = | |
542 | read_register (bits (this_instr, 16, 19)); | |
543 | nextpc = | |
544 | (CORE_ADDR) read_memory_integer ((CORE_ADDR) (rn_val | |
545 | + offset), | |
546 | 4); | |
547 | } | |
548 | nextpc = ADDR_BITS_REMOVE (nextpc); | |
549 | if (nextpc == pc) | |
550 | error ("Infinite loop detected"); | |
551 | } | |
552 | } | |
553 | break; | |
554 | ||
555 | case 0xb: /* branch & link */ | |
556 | case 0xa: /* branch */ | |
557 | { | |
558 | nextpc = BranchDest (pc, this_instr); | |
559 | ||
560 | nextpc = ADDR_BITS_REMOVE (nextpc); | |
561 | if (nextpc == pc) | |
562 | error ("Infinite loop detected"); | |
563 | break; | |
564 | } | |
565 | ||
566 | case 0xc: case 0xd: | |
567 | case 0xe: /* coproc ops */ | |
568 | case 0xf: /* SWI */ | |
569 | break; | |
570 | ||
571 | default: | |
572 | fprintf (stderr, "Bad bit-field extraction\n"); | |
573 | return (pc); | |
574 | } | |
575 | } | |
576 | ||
577 | return nextpc; | |
578 | } | |
579 | ||
580 | void | |
581 | _initialize_arm_tdep () | |
582 | { | |
583 | tm_print_insn = print_insn_little_arm; | |
584 | ||
585 | add_com ("othernames", class_obscure, arm_othernames, | |
586 | "Switch to the other set of register names."); | |
587 | ||
588 | add_show_from_set (add_set_cmd ("apcs32", no_class, | |
589 | var_integer, (char *)&arm_apcs_32, | |
590 | "Set usage of ARM 32-bit mode.\n", &setlist), | |
591 | &showlist); | |
592 | ||
593 | } |