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