* stabs.c (_bfd_link_section_stabs): If the output_section field
[deliverable/binutils-gdb.git] / gdb / arm-tdep.c
CommitLineData
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
5This file is part of GDB.
6
54af8e6e 7This program is free software; you can redistribute it and/or modify
bd5635a1 8it under the terms of the GNU General Public License as published by
54af8e6e
SC
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
bd5635a1 11
54af8e6e 12This program is distributed in the hope that it will be useful,
bd5635a1
RP
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
54af8e6e 18along with this program; if not, write to the Free Software
72c9954b 19Foundation, 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 28int arm_apcs_32 = 1;
bd5635a1 29
72c9954b
SS
30CORE_ADDR
31arm_addr_bits_remove (val)
32CORE_ADDR val;
bd5635a1 33{
72c9954b 34 return (val & (arm_apcs_32 ? 0xfffffffc : 0x03fffffc));
bd5635a1 35}
bd5635a1 36
72c9954b
SS
37CORE_ADDR
38arm_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
56CORE_ADDR
72c9954b 57arm_skip_prologue (pc)
bd5635a1
RP
58CORE_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
107void
108arm_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
155void
156arm_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
174void
175arm_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 199static void
72c9954b 200print_fpu_flags (flags)
bd5635a1
RP
201int 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
211void
72c9954b 212arm_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
227static void
228arm_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
241void
242convert_from_extended (ptr, dbl)
243void *ptr;
244double *dbl;
245{
246 *dbl = *(double*)ptr;
247}
248
54af8e6e
SC
249void
250convert_to_extended (dbl, ptr)
251void *ptr;
252double *dbl;
253{
254 *(double*)ptr = *dbl;
255}
256
72c9954b
SS
257int
258arm_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
315static unsigned long
316shifted_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
367CORE_ADDR
368arm_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
580void
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}
This page took 0.406429 seconds and 4 git commands to generate.