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