GNU Binutils with patches for OS216
Révision | fb20ccaae3ab3e6964b95e8e077d11b31c8f8d8c (tree) |
---|---|
l'heure | 2006-04-02 11:35:32 |
Auteur | Daniel Jacobowitz <drow@fals...> |
Commiter | Daniel Jacobowitz |
Add support for VFP DWARF information and VFP single-precision
pseudo-registers.
@@ -1806,7 +1806,7 @@ arm-tdep.o: arm-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(gdbcmd_h) \ | ||
1806 | 1806 | $(frame_unwind_h) $(frame_base_h) $(trad_frame_h) $(arm_tdep_h) \ |
1807 | 1807 | $(gdb_sim_arm_h) $(elf_bfd_h) $(coff_internal_h) $(elf_arm_h) \ |
1808 | 1808 | $(gdb_assert_h) $(bfd_in2_h) $(libcoff_h) $(objfiles_h) \ |
1809 | - $(dwarf2_frame_h) $(available_h) | |
1809 | + $(dwarf2_frame_h) $(available_h) $(user_regs_h) | |
1810 | 1810 | auxv.o: auxv.c $(defs_h) $(target_h) $(gdbtypes_h) $(command_h) \ |
1811 | 1811 | $(inferior_h) $(valprint_h) $(gdb_assert_h) $(auxv_h) \ |
1812 | 1812 | $(elf_common_h) |
@@ -41,6 +41,7 @@ | ||
41 | 41 | #include "objfiles.h" |
42 | 42 | #include "dwarf2-frame.h" |
43 | 43 | #include "available.h" |
44 | +#include "user-regs.h" | |
44 | 45 | |
45 | 46 | #include "arm-tdep.h" |
46 | 47 | #include "gdb/sim-arm.h" |
@@ -1352,6 +1353,10 @@ arm_register_type (struct gdbarch *gdbarch, int regnum) | ||
1352 | 1353 | if (avail_type) |
1353 | 1354 | return avail_type; |
1354 | 1355 | |
1356 | + if (gdbarch_tdep (current_gdbarch)->have_vfp_pseudos | |
1357 | + && regnum >= NUM_REGS && regnum < NUM_REGS + 32) | |
1358 | + return builtin_type_float; | |
1359 | + | |
1355 | 1360 | if (regnum >= ARM_F0_REGNUM && regnum < ARM_F0_REGNUM + NUM_FREGS) |
1356 | 1361 | { |
1357 | 1362 | if (!gdbarch_tdep (gdbarch)->have_fpa_registers) |
@@ -1366,6 +1371,56 @@ arm_register_type (struct gdbarch *gdbarch, int regnum) | ||
1366 | 1371 | return builtin_type_int32; |
1367 | 1372 | } |
1368 | 1373 | |
1374 | +/* Map DWARF register numbers onto internal GDB register numbers. */ | |
1375 | +static int | |
1376 | +arm_dwarf_reg_to_regnum (int reg) | |
1377 | +{ | |
1378 | + /* Core integer regs. */ | |
1379 | + if (reg >= 0 && reg <= 15) | |
1380 | + return reg; | |
1381 | + | |
1382 | + /* Legacy FPA encoding. These were once used in a way which | |
1383 | + overlapped with VFP register numbering, so their use is | |
1384 | + discouraged, but GDB doesn't support the ARM toolchain | |
1385 | + which did that. */ | |
1386 | + if (reg >= 16 && reg <= 23) | |
1387 | + return ARM_F0_REGNUM + reg - 16; | |
1388 | + | |
1389 | + /* New assignments for the FPA registers. */ | |
1390 | + if (reg >= 96 && reg <= 103) | |
1391 | + return ARM_F0_REGNUM + reg - 96; | |
1392 | + | |
1393 | + /* VFP v2 registers. A double precision value is actually | |
1394 | + in d1 rather than s2, but the ABI only defines numbering | |
1395 | + for the single precision registers. This will "just work" | |
1396 | + in GDB for little endian targets (we'll read eight bytes, | |
1397 | + starting in s0 and then progressing to s1), but will be | |
1398 | + reversed on big endian targets with VFP. This won't | |
1399 | + be a problem for the new Neon quad registers; you're supposed | |
1400 | + to use DW_OP_piece for those. */ | |
1401 | + if (reg >= 64 && reg <= 95) | |
1402 | + { | |
1403 | + char name_buf[4]; | |
1404 | + | |
1405 | + sprintf (name_buf, "s%d", reg - 64); | |
1406 | + return user_reg_map_name_to_regnum (current_gdbarch, name_buf, | |
1407 | + strlen (name_buf)); | |
1408 | + } | |
1409 | + | |
1410 | + /* VFP v3 / Neon registers. This range is also used for VFP v2 | |
1411 | + registers, except that it now describes d0 instead of s0. */ | |
1412 | + if (reg >= 256 && reg <= 287) | |
1413 | + { | |
1414 | + char name_buf[4]; | |
1415 | + | |
1416 | + sprintf (name_buf, "d%d", reg - 256); | |
1417 | + return user_reg_map_name_to_regnum (current_gdbarch, name_buf, | |
1418 | + strlen (name_buf)); | |
1419 | + } | |
1420 | + | |
1421 | + return -1; | |
1422 | +} | |
1423 | + | |
1369 | 1424 | /* Map GDB internal REGNUM onto the Arm simulator register numbers. */ |
1370 | 1425 | static int |
1371 | 1426 | arm_register_sim_regno (int regnum) |
@@ -2475,6 +2530,19 @@ arm_register_name (int i) | ||
2475 | 2530 | return ""; |
2476 | 2531 | } |
2477 | 2532 | |
2533 | + if (gdbarch_tdep (current_gdbarch)->have_vfp_pseudos | |
2534 | + && i >= NUM_REGS && i < NUM_REGS + 32) | |
2535 | + { | |
2536 | + static const char *const vfp_pseudo_names[] = { | |
2537 | + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", | |
2538 | + "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", | |
2539 | + "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", | |
2540 | + "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", | |
2541 | + }; | |
2542 | + | |
2543 | + return vfp_pseudo_names[i - NUM_REGS]; | |
2544 | + } | |
2545 | + | |
2478 | 2546 | /* Check for target-supplied register numbers. */ |
2479 | 2547 | return available_register_name (current_gdbarch, i); |
2480 | 2548 | } |
@@ -2565,6 +2633,57 @@ arm_write_pc (CORE_ADDR pc, ptid_t ptid) | ||
2565 | 2633 | write_register_pid (ARM_PS_REGNUM, val & ~(CORE_ADDR) 0x20, ptid); |
2566 | 2634 | } |
2567 | 2635 | } |
2636 | + | |
2637 | +static void | |
2638 | +arm_pseudo_vfp_read (struct gdbarch *gdbarch, struct regcache *regcache, | |
2639 | + int regnum, gdb_byte *buf) | |
2640 | +{ | |
2641 | + char name_buf[4]; | |
2642 | + gdb_byte reg_buf[8]; | |
2643 | + int offset, double_regnum; | |
2644 | + | |
2645 | + gdb_assert (regnum >= NUM_REGS && regnum <= NUM_REGS + 32); | |
2646 | + regnum -= NUM_REGS; | |
2647 | + | |
2648 | + /* s0 is always the least significant half of d0. */ | |
2649 | + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) | |
2650 | + offset = (regnum & 1) ? 0 : 4; | |
2651 | + else | |
2652 | + offset = (regnum & 1) ? 4 : 0; | |
2653 | + | |
2654 | + sprintf (name_buf, "d%d", regnum >> 1); | |
2655 | + double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf, | |
2656 | + strlen (name_buf)); | |
2657 | + | |
2658 | + regcache_raw_read (regcache, double_regnum, reg_buf); | |
2659 | + memcpy (buf, reg_buf + offset, 4); | |
2660 | +} | |
2661 | + | |
2662 | +static void | |
2663 | +arm_pseudo_vfp_write (struct gdbarch *gdbarch, struct regcache *regcache, | |
2664 | + int regnum, const gdb_byte *buf) | |
2665 | +{ | |
2666 | + char name_buf[4]; | |
2667 | + gdb_byte reg_buf[8]; | |
2668 | + int offset, double_regnum; | |
2669 | + | |
2670 | + gdb_assert (regnum >= NUM_REGS && regnum <= NUM_REGS + 32); | |
2671 | + regnum -= NUM_REGS; | |
2672 | + | |
2673 | + /* s0 is always the least significant half of d0. */ | |
2674 | + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) | |
2675 | + offset = (regnum & 1) ? 0 : 4; | |
2676 | + else | |
2677 | + offset = (regnum & 1) ? 4 : 0; | |
2678 | + | |
2679 | + sprintf (name_buf, "d%d", regnum >> 1); | |
2680 | + double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf, | |
2681 | + strlen (name_buf)); | |
2682 | + | |
2683 | + regcache_raw_read (regcache, double_regnum, reg_buf); | |
2684 | + memcpy (reg_buf + offset, buf, 4); | |
2685 | + regcache_raw_write (regcache, double_regnum, reg_buf); | |
2686 | +} | |
2568 | 2687 | |
2569 | 2688 | static enum gdb_osabi |
2570 | 2689 | arm_elf_osabi_sniffer (bfd *abfd) |
@@ -2628,6 +2747,27 @@ arm_check_feature_set (struct gdbarch *gdbarch, | ||
2628 | 2747 | } |
2629 | 2748 | else |
2630 | 2749 | gdbarch_tdep (gdbarch)->have_fpa_registers = 0; |
2750 | + | |
2751 | + /* If we have a VFP unit, check whether the single precision registers | |
2752 | + are present. If not, then we will synthesize them as pseudo | |
2753 | + registers. */ | |
2754 | + | |
2755 | + if (available_find_named_feature (feature_set, "org.gnu.gdb.arm.vfp")) | |
2756 | + { | |
2757 | + if (available_find_named_register (feature_set, "d0", -1) | |
2758 | + && !available_find_named_register (feature_set, "s0", -1)) | |
2759 | + { | |
2760 | + /* NOTE: This is the only set of pseudo registers used by | |
2761 | + the ARM target at the moment. If more are added, a | |
2762 | + little more care in numbering will be needed. */ | |
2763 | + | |
2764 | + set_gdbarch_num_pseudo_regs (gdbarch, 32); | |
2765 | + set_gdbarch_pseudo_register_read (gdbarch, arm_pseudo_vfp_read); | |
2766 | + set_gdbarch_pseudo_register_write (gdbarch, arm_pseudo_vfp_write); | |
2767 | + gdbarch_tdep (gdbarch)->have_vfp_pseudos = 1; | |
2768 | + } | |
2769 | + gdbarch_tdep (gdbarch)->have_vfp_registers = 1; | |
2770 | + } | |
2631 | 2771 | } |
2632 | 2772 | |
2633 | 2773 |
@@ -2843,6 +2983,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | ||
2843 | 2983 | set_gdbarch_print_float_info (gdbarch, arm_print_float_info); |
2844 | 2984 | |
2845 | 2985 | /* Internal <-> external register number maps. */ |
2986 | + set_gdbarch_dwarf_reg_to_regnum (gdbarch, arm_dwarf_reg_to_regnum); | |
2987 | + set_gdbarch_dwarf2_reg_to_regnum (gdbarch, arm_dwarf_reg_to_regnum); | |
2846 | 2988 | set_gdbarch_register_sim_regno (gdbarch, arm_register_sim_regno); |
2847 | 2989 | |
2848 | 2990 | /* Integer registers are 4 bytes. */ |
@@ -132,6 +132,9 @@ struct gdbarch_tdep | ||
132 | 132 | enum arm_float_model fp_model; /* Floating point calling conventions. */ |
133 | 133 | |
134 | 134 | int have_fpa_registers; /* Does the target report the FPA registers? */ |
135 | + int have_vfp_registers; /* Does the target report the VFP registers? */ | |
136 | + int have_vfp_pseudos; /* Are we synthesizing the single precision | |
137 | + VFP registers? */ | |
135 | 138 | |
136 | 139 | CORE_ADDR lowest_pc; /* Lowest address at which instructions |
137 | 140 | will appear. */ |
@@ -546,9 +546,10 @@ find_register (const struct gdb_feature_set *features, int regnum) | ||
546 | 546 | return NULL; |
547 | 547 | } |
548 | 548 | |
549 | -/* Search FEATURES for a register with target-specified name NAME, | |
550 | - and set its GDB register number to REGNUM. Return 1 if the | |
551 | - register was found, and 0 if it was not. This function should | |
549 | +/* Search FEATURES for a register with target-specified name NAME, and | |
550 | + set its GDB register number to REGNUM. Pass REGNUM == -1 if you do | |
551 | + not need to fix a register number for this register. Return 1 if | |
552 | + the register was found, and 0 if it was not. This function should | |
552 | 553 | only be used while initializing a gdbarch. */ |
553 | 554 | |
554 | 555 | int |
@@ -145,8 +145,8 @@ int features_same_p (const struct gdb_feature_set *, | ||
145 | 145 | void record_available_features (struct gdbarch *, |
146 | 146 | struct gdb_feature_set *); |
147 | 147 | |
148 | -/* Find a register with the given name, and set its internal register | |
149 | - number. */ | |
148 | +/* Find a register with the given name, and optionally set its | |
149 | + internal register number. */ | |
150 | 150 | |
151 | 151 | int available_find_named_register (struct gdb_feature_set *, |
152 | 152 | const char *, int); |
@@ -395,16 +395,26 @@ frame_find_by_id (struct frame_id id) | ||
395 | 395 | { |
396 | 396 | struct frame_info *frame; |
397 | 397 | |
398 | +#if 0 | |
398 | 399 | /* ZERO denotes the null frame, let the caller decide what to do |
399 | 400 | about it. Should it instead return get_current_frame()? */ |
400 | 401 | if (!frame_id_p (id)) |
401 | 402 | return NULL; |
403 | +#endif | |
402 | 404 | |
403 | 405 | for (frame = get_current_frame (); |
404 | 406 | frame != NULL; |
405 | 407 | frame = get_prev_frame (frame)) |
406 | 408 | { |
407 | 409 | struct frame_id this = get_frame_id (frame); |
410 | +#if 1 | |
411 | + /* We use an invalid frame id to mean "could not unwind from | |
412 | + here"! This hack fixes the "value being assigned to is | |
413 | + no longer active" problem. This strongly suggests that | |
414 | + we need to change the representation. */ | |
415 | + if (!frame_id_p (id) && !frame_id_p (this)) | |
416 | + return frame; | |
417 | +#endif | |
408 | 418 | if (frame_id_eq (id, this)) |
409 | 419 | /* An exact match. */ |
410 | 420 | return frame; |