1 /* Target-dependent code for the Acorn Risc Machine, for GDB, the GNU Debugger.
2 Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995, 1996
3 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
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.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
26 /* Set to true if the 32-bit mode is in use. */
31 arm_addr_bits_remove (val)
34 return (val & (arm_apcs_32 ? 0xfffffffc : 0x03fffffc));
38 arm_saved_pc_after_call (frame)
39 struct frame_info *frame;
41 return ADDR_BITS_REMOVE (read_register (LR_REGNUM));
44 /* APCS (ARM procedure call standard) defines the following prologue:
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
57 arm_skip_prologue (pc)
61 CORE_ADDR skip_pc = pc;
63 inst = read_memory_integer (skip_pc, 4);
64 if (inst != 0xe1a0c00d) /* mov ip, sp */
68 inst = read_memory_integer (skip_pc, 4);
69 if ((inst & 0xfffffff0) == 0xe92d0000) /* stmfd sp!,{a1,a2,a3,a4} */
72 inst = read_memory_integer (skip_pc, 4);
75 if ((inst & 0xfffff800) != 0xe92dd800) /* stmfd sp!,{...,fp,ip,lr,pc} */
79 inst = read_memory_integer (skip_pc, 4);
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 */
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]! */
90 inst = read_memory_integer (skip_pc, 4);
94 while ((inst & 0xffff8fff) == 0xed6d0103) /* stfe fn, [sp, #-12]! */
97 inst = read_memory_integer (skip_pc, 4);
101 if ((inst & 0xfffff000) == 0xe24cb000) /* sub fp, ip, #nn */
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;
114 register int next_addr;
115 register int return_data_save;
116 register int saved_register_mask;
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))
127 saved_regs_addr->regs[regnum] = next_addr;
129 if (read_memory_integer (return_data_save + 4, 4) == 0xed6d7103)
132 saved_regs_addr->regs[F0_REGNUM + 7] = next_addr;
134 if (read_memory_integer (return_data_save + 8, 4) == 0xed6d6103)
137 saved_regs_addr->regs[F0_REGNUM + 6] = next_addr;
139 if (read_memory_integer (return_data_save + 12, 4) == 0xed6d5103)
142 saved_regs_addr->regs[F0_REGNUM + 5] = next_addr;
144 if (read_memory_integer(return_data_save + 16, 4) == 0xed6d4103)
147 saved_regs_addr->regs[F0_REGNUM + 4] = next_addr;
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;
156 arm_push_dummy_frame ()
158 register CORE_ADDR sp = read_register (SP_REGNUM);
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);
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,
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));
188 for (regnum = 9; regnum >= 4; regnum--)
190 if (return_data_save & (1 << regnum))
193 write_register (regnum, read_memory_integer (fp, 4));
196 flush_cached_frames ();
200 print_fpu_flags (flags)
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);
214 register unsigned long status = read_register (FPS_REGNUM);
217 type = (status >> 24) & 127;
218 printf ("%s FPU type %d\n",
219 (status & (1<<31)) ? "Hardware" : "Software",
221 fputs ("mask: ", stdout);
222 print_fpu_flags (status >> 16);
223 fputs ("flags: ", stdout);
224 print_fpu_flags (status);
231 static char *original[] = ORIGINAL_REGISTER_NAMES;
232 static char *extra_crispy[] = ADDITIONAL_REGISTER_NAMES;
234 memcpy (reg_names, toggle ? extra_crispy : original, sizeof(original));
238 /* FIXME: Fill in with the 'right thing', see asm
239 template in arm-convert.s */
242 convert_from_extended (ptr, dbl)
246 *dbl = *(double*)ptr;
250 convert_to_extended (dbl, ptr)
254 *(double*)ptr = *dbl;
258 arm_nullified_insn (inst)
261 unsigned long cond = inst & 0xf0000000;
262 unsigned long status_reg;
264 if (cond == INST_AL || cond == INST_NV)
267 status_reg = read_register (PS_REGNUM);
272 return ((status_reg & FLAG_Z) == 0);
274 return ((status_reg & FLAG_Z) != 0);
276 return ((status_reg & FLAG_C) == 0);
278 return ((status_reg & FLAG_C) != 0);
280 return ((status_reg & FLAG_N) == 0);
282 return ((status_reg & FLAG_N) != 0);
284 return ((status_reg & FLAG_V) == 0);
286 return ((status_reg & FLAG_V) != 0);
288 return ((status_reg & (FLAG_C | FLAG_Z)) != FLAG_C);
290 return (((status_reg & (FLAG_C | FLAG_Z)) ^ FLAG_C) == 0);
292 return (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0));
294 return (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0));
296 return (((status_reg & FLAG_Z) != 0) ||
297 (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0)));
299 return (((status_reg & FLAG_Z) == 0) &&
300 (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0)));
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)))
316 shifted_reg_val (inst, carry, pc_val)
319 unsigned long pc_val;
321 unsigned long res, shift;
322 int rm = bits (inst, 0, 3);
323 unsigned long shifttype = bits (inst, 5, 6);
327 int rs = bits (inst, 8, 11);
328 shift = (rs == 15 ? pc_val + 8 : read_register (rs)) & 0xFF;
331 shift = bits (inst, 7, 11);
334 ? ((pc_val | (ARM_PC_32 ? 0 : read_register (PS_REGNUM)))
335 + (bit (inst, 4) ? 12 : 8))
336 : read_register (rm));
341 res = shift >= 32 ? 0 : res << shift;
345 res = shift >= 32 ? 0 : res >> shift;
349 if (shift >= 32) shift = 31;
350 res = ((res & 0x80000000L)
351 ? ~((~res) >> shift) : res >> shift);
354 case 3: /* ROR/RRX */
357 res = (res >> 1) | (carry ? 0x80000000L : 0);
359 res = (res >> shift) | (res << (32-shift));
363 return res & 0xffffffff;
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 */
376 if (! arm_nullified_insn (this_instr))
378 switch (bits(this_instr, 24, 27))
380 case 0x0: case 0x1: /* data processing */
383 unsigned long operand1, operand2, result = 0;
387 if (bits(this_instr, 12, 15) != 15)
390 if (bits (this_instr, 22, 25) == 0
391 && bits (this_instr, 4, 7) == 9) /* multiply */
392 error ("Illegal update to pc in instruction");
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);
399 if (bit (this_instr, 25))
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))
406 else /* operand 2 is a shifted register */
407 operand2 = shifted_reg_val (this_instr, c, pc_val);
409 switch (bits (this_instr, 21, 24))
412 result = operand1 & operand2;
416 result = operand1 ^ operand2;
420 result = operand1 - operand2;
424 result = operand2 - operand1;
428 result = operand1 + operand2;
432 result = operand1 + operand2 + c;
436 result = operand1 - operand2 + c;
440 result = operand2 - operand1 + c;
443 case 0x8: case 0x9: case 0xa: case 0xb: /* tst, teq, cmp, cmn */
444 result = (unsigned long) nextpc;
448 result = operand1 | operand2;
452 /* Always step into a function. */
457 result = operand1 & ~operand2;
464 nextpc = (CORE_ADDR) ADDR_BITS_REMOVE (result);
467 error ("Infinite loop detected");
471 case 0x4: case 0x5: /* data transfer */
473 if (bit (this_instr, 20))
476 if (bits (this_instr, 12, 15) == 15)
482 if (bit (this_instr, 22))
483 error ("Illegal update to pc in instruction");
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))
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));
497 if (bit (this_instr, 23))
502 nextpc = (CORE_ADDR) read_memory_integer ((CORE_ADDR) base,
505 nextpc = ADDR_BITS_REMOVE (nextpc);
508 error ("Infinite loop detected");
513 case 0x8: case 0x9: /* block transfer */
514 if (bit (this_instr, 20))
517 if (bit (this_instr, 15))
522 if (bit (this_instr, 23))
525 unsigned long reglist = bits (this_instr, 0, 14);
526 unsigned long regbit;
528 for (; reglist != 0; reglist &= ~regbit)
530 regbit = reglist & (-reglist);
534 if (bit (this_instr, 24)) /* pre */
537 else if (bit (this_instr, 24))
541 unsigned long rn_val =
542 read_register (bits (this_instr, 16, 19));
544 (CORE_ADDR) read_memory_integer ((CORE_ADDR) (rn_val
548 nextpc = ADDR_BITS_REMOVE (nextpc);
550 error ("Infinite loop detected");
555 case 0xb: /* branch & link */
556 case 0xa: /* branch */
558 nextpc = BranchDest (pc, this_instr);
560 nextpc = ADDR_BITS_REMOVE (nextpc);
562 error ("Infinite loop detected");
567 case 0xe: /* coproc ops */
572 fprintf (stderr, "Bad bit-field extraction\n");
581 _initialize_arm_tdep ()
583 tm_print_insn = print_insn_little_arm;
585 add_com ("othernames", class_obscure, arm_othernames,
586 "Switch to the other set of register names.");
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),