X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fm68k-tdep.c;h=5b2a29a350e53d2a7d366dcfcd95213d57b63897;hb=911e1e795e2496e1a5315601ab89e56afcd10fb0;hp=1a18d36eb9a79c56664e2630a20d2f2336123a98;hpb=0fde2c536bc483baa4baa2990ebebfb3a7c00415;p=binutils-gdb.git diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c index 1a18d36eb9a..5b2a29a350e 100644 --- a/gdb/m68k-tdep.c +++ b/gdb/m68k-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for the Motorola 68000 series. - Copyright (C) 1990-2015 Free Software Foundation, Inc. + Copyright (C) 1990-2023 Free Software Foundation, Inc. This file is part of GDB. @@ -18,7 +18,7 @@ along with this program. If not, see . */ #include "defs.h" -#include "dwarf2-frame.h" +#include "dwarf2/frame.h" #include "frame.h" #include "frame-base.h" #include "frame-unwind.h" @@ -32,6 +32,10 @@ #include "osabi.h" #include "dis-asm.h" #include "target-descriptions.h" +#include "floatformat.h" +#include "target-float.h" +#include "elf-bfd.h" +#include "elf/m68k.h" #include "m68k-tdep.h" @@ -57,27 +61,22 @@ #define BPT_VECTOR 0xf #endif -static const gdb_byte * -m68k_local_breakpoint_from_pc (struct gdbarch *gdbarch, - CORE_ADDR *pcptr, int *lenptr) -{ - static gdb_byte break_insn[] = {0x4e, (0x40 | BPT_VECTOR)}; - *lenptr = sizeof (break_insn); - return break_insn; -} +constexpr gdb_byte m68k_break_insn[] = {0x4e, (0x40 | BPT_VECTOR)}; + +typedef BP_MANIPULATION (m68k_break_insn) m68k_breakpoint; /* Construct types for ISA-specific registers. */ static struct type * m68k_ps_type (struct gdbarch *gdbarch) { - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); if (!tdep->m68k_ps_type) { struct type *type; - type = arch_flags_type (gdbarch, "builtin_type_m68k_ps", 4); + type = arch_flags_type (gdbarch, "builtin_type_m68k_ps", 32); append_flags_type_flag (type, 0, "C"); append_flags_type_flag (type, 1, "V"); append_flags_type_flag (type, 2, "Z"); @@ -100,12 +99,15 @@ m68k_ps_type (struct gdbarch *gdbarch) static struct type * m68881_ext_type (struct gdbarch *gdbarch) { - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); if (!tdep->m68881_ext_type) - tdep->m68881_ext_type - = arch_float_type (gdbarch, -1, "builtin_type_m68881_ext", - floatformats_m68881_ext); + { + type_allocator alloc (gdbarch); + tdep->m68881_ext_type + = init_float_type (alloc, -1, "builtin_type_m68881_ext", + floatformats_m68881_ext); + } return tdep->m68881_ext_type; } @@ -121,7 +123,7 @@ m68881_ext_type (struct gdbarch *gdbarch) static struct type * m68k_register_type (struct gdbarch *gdbarch, int regnum) { - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); if (tdep->fpregs_present) { @@ -158,7 +160,7 @@ m68k_register_type (struct gdbarch *gdbarch, int regnum) return builtin_type (gdbarch)->builtin_int32; } -static const char *m68k_register_names[] = { +static const char * const m68k_register_names[] = { "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", "ps", "pc", @@ -172,12 +174,11 @@ static const char *m68k_register_names[] = { static const char * m68k_register_name (struct gdbarch *gdbarch, int regnum) { - if (regnum < 0 || regnum >= ARRAY_SIZE (m68k_register_names)) - internal_error (__FILE__, __LINE__, - _("m68k_register_name: illegal register number %d"), - regnum); - else if (regnum >= M68K_FP0_REGNUM && regnum <= M68K_FPI_REGNUM - && gdbarch_tdep (gdbarch)->fpregs_present == 0) + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + gdb_static_assert (ARRAY_SIZE (m68k_register_names) == M68K_NUM_REGS); + if (regnum >= M68K_FP0_REGNUM && regnum <= M68K_FPI_REGNUM + && tdep->fpregs_present == 0) return ""; else return m68k_register_names[regnum]; @@ -190,9 +191,13 @@ static int m68k_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type) { - if (!gdbarch_tdep (gdbarch)->fpregs_present) + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (!tdep->fpregs_present) return 0; return (regnum >= M68K_FP0_REGNUM && regnum <= M68K_FP0_REGNUM + 7 + /* We only support floating-point values. */ + && type->code () == TYPE_CODE_FLT && type != register_type (gdbarch, M68K_FP0_REGNUM)); } @@ -200,31 +205,25 @@ m68k_convert_register_p (struct gdbarch *gdbarch, return its contents in TO. */ static int -m68k_register_to_value (struct frame_info *frame, int regnum, +m68k_register_to_value (frame_info_ptr frame, int regnum, struct type *type, gdb_byte *to, int *optimizedp, int *unavailablep) { + struct gdbarch *gdbarch = get_frame_arch (frame); gdb_byte from[M68K_MAX_REGISTER_SIZE]; - struct type *fpreg_type = register_type (get_frame_arch (frame), - M68K_FP0_REGNUM); + struct type *fpreg_type = register_type (gdbarch, M68K_FP0_REGNUM); - /* We only support floating-point values. */ - if (TYPE_CODE (type) != TYPE_CODE_FLT) - { - warning (_("Cannot convert floating-point register value " - "to non-floating-point type.")); - *optimizedp = *unavailablep = 0; - return 0; - } - - /* Convert to TYPE. */ + gdb_assert (type->code () == TYPE_CODE_FLT); /* Convert to TYPE. */ - if (!get_frame_register_bytes (frame, regnum, 0, TYPE_LENGTH (type), - from, optimizedp, unavailablep)) + if (!get_frame_register_bytes (frame, regnum, 0, + gdb::make_array_view (from, + register_size (gdbarch, + regnum)), + optimizedp, unavailablep)) return 0; - convert_typed_floating (from, fpreg_type, to, type); + target_float_convert (from, fpreg_type, to, type); *optimizedp = *unavailablep = 0; return 1; } @@ -233,7 +232,7 @@ m68k_register_to_value (struct frame_info *frame, int regnum, REGNUM in frame FRAME. */ static void -m68k_value_to_register (struct frame_info *frame, int regnum, +m68k_value_to_register (frame_info_ptr frame, int regnum, struct type *type, const gdb_byte *from) { gdb_byte to[M68K_MAX_REGISTER_SIZE]; @@ -241,7 +240,7 @@ m68k_value_to_register (struct frame_info *frame, int regnum, M68K_FP0_REGNUM); /* We only support floating-point values. */ - if (TYPE_CODE (type) != TYPE_CODE_FLT) + if (type->code () != TYPE_CODE_FLT) { warning (_("Cannot convert non-floating-point type " "to floating-point register value.")); @@ -249,7 +248,7 @@ m68k_value_to_register (struct frame_info *frame, int regnum, } /* Convert from TYPE. */ - convert_typed_floating (from, type, to, fpreg_type); + target_float_convert (from, type, to, fpreg_type); put_frame_register (frame, regnum, to); } @@ -266,7 +265,7 @@ m68k_value_to_register (struct frame_info *frame, int regnum, The 68020/030/040/060 do support an FPU, either as a coprocessor (68881/2) or built-in (68040/68060). That's why System V release 4 - (SVR4) instroduces a new calling convention specified by the SVR4 + (SVR4) introduces a new calling convention specified by the SVR4 psABI. Integer values are returned in %d0/%d1, pointer return values in %a0 and floating values in %fp0. When calling functions returning a structure the caller should pass a pointer to a buffer @@ -281,7 +280,12 @@ m68k_value_to_register (struct frame_info *frame, int regnum, %d0/%d1 instead of in memory by using -freg-struct-return. This is the default on NetBSD a.out, OpenBSD and GNU/Linux and several embedded systems. This convention is implemented by setting the - struct_return member of `struct gdbarch_tdep' to reg_struct_return. */ + struct_return member of `struct gdbarch_tdep' to reg_struct_return. + + GCC also has an "embedded" ABI. This works like the SVR4 ABI, + except that pointers are returned in %D0. This is implemented by + setting the pointer_result_regnum member of `struct gdbarch_tdep' + as appropriate. */ /* Read a function return value of TYPE from REGCACHE, and copy that into VALBUF. */ @@ -290,23 +294,28 @@ static void m68k_extract_return_value (struct type *type, struct regcache *regcache, gdb_byte *valbuf) { - int len = TYPE_LENGTH (type); + int len = type->length (); gdb_byte buf[M68K_MAX_REGISTER_SIZE]; - if (len <= 4) + if (type->code () == TYPE_CODE_PTR && len == 4) + { + struct gdbarch *gdbarch = regcache->arch (); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + regcache->raw_read (tdep->pointer_result_regnum, valbuf); + } + else if (len <= 4) { - regcache_raw_read (regcache, M68K_D0_REGNUM, buf); + regcache->raw_read (M68K_D0_REGNUM, buf); memcpy (valbuf, buf + (4 - len), len); } else if (len <= 8) { - regcache_raw_read (regcache, M68K_D0_REGNUM, buf); + regcache->raw_read (M68K_D0_REGNUM, buf); memcpy (valbuf, buf + (8 - len), len - 4); - regcache_raw_read (regcache, M68K_D1_REGNUM, valbuf + (len - 4)); + regcache->raw_read (M68K_D1_REGNUM, valbuf + (len - 4)); } else - internal_error (__FILE__, __LINE__, - _("Cannot extract return value of %d bytes long."), len); + internal_error (_("Cannot extract return value of %d bytes long."), len); } static void @@ -314,17 +323,15 @@ m68k_svr4_extract_return_value (struct type *type, struct regcache *regcache, gdb_byte *valbuf) { gdb_byte buf[M68K_MAX_REGISTER_SIZE]; - struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + struct gdbarch *gdbarch = regcache->arch (); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - if (tdep->float_return && TYPE_CODE (type) == TYPE_CODE_FLT) + if (tdep->float_return && type->code () == TYPE_CODE_FLT) { struct type *fpreg_type = register_type (gdbarch, M68K_FP0_REGNUM); - regcache_raw_read (regcache, M68K_FP0_REGNUM, buf); - convert_typed_floating (buf, fpreg_type, valbuf, type); + regcache->raw_read (M68K_FP0_REGNUM, buf); + target_float_convert (buf, fpreg_type, valbuf, type); } - else if (TYPE_CODE (type) == TYPE_CODE_PTR && TYPE_LENGTH (type) == 4) - regcache_raw_read (regcache, M68K_A0_REGNUM, valbuf); else m68k_extract_return_value (type, regcache, valbuf); } @@ -335,39 +342,41 @@ static void m68k_store_return_value (struct type *type, struct regcache *regcache, const gdb_byte *valbuf) { - int len = TYPE_LENGTH (type); + int len = type->length (); - if (len <= 4) - regcache_raw_write_part (regcache, M68K_D0_REGNUM, 4 - len, len, valbuf); + if (type->code () == TYPE_CODE_PTR && len == 4) + { + struct gdbarch *gdbarch = regcache->arch (); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + regcache->raw_write (tdep->pointer_result_regnum, valbuf); + /* gdb historically also set D0 in the SVR4 case. */ + if (tdep->pointer_result_regnum != M68K_D0_REGNUM) + regcache->raw_write (M68K_D0_REGNUM, valbuf); + } + else if (len <= 4) + regcache->raw_write_part (M68K_D0_REGNUM, 4 - len, len, valbuf); else if (len <= 8) { - regcache_raw_write_part (regcache, M68K_D0_REGNUM, 8 - len, - len - 4, valbuf); - regcache_raw_write (regcache, M68K_D1_REGNUM, valbuf + (len - 4)); + regcache->raw_write_part (M68K_D0_REGNUM, 8 - len, len - 4, valbuf); + regcache->raw_write (M68K_D1_REGNUM, valbuf + (len - 4)); } else - internal_error (__FILE__, __LINE__, - _("Cannot store return value of %d bytes long."), len); + internal_error (_("Cannot store return value of %d bytes long."), len); } static void m68k_svr4_store_return_value (struct type *type, struct regcache *regcache, const gdb_byte *valbuf) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + struct gdbarch *gdbarch = regcache->arch (); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - if (tdep->float_return && TYPE_CODE (type) == TYPE_CODE_FLT) + if (tdep->float_return && type->code () == TYPE_CODE_FLT) { struct type *fpreg_type = register_type (gdbarch, M68K_FP0_REGNUM); gdb_byte buf[M68K_MAX_REGISTER_SIZE]; - convert_typed_floating (valbuf, type, buf, fpreg_type); - regcache_raw_write (regcache, M68K_FP0_REGNUM, buf); - } - else if (TYPE_CODE (type) == TYPE_CODE_PTR && TYPE_LENGTH (type) == 4) - { - regcache_raw_write (regcache, M68K_A0_REGNUM, valbuf); - regcache_raw_write (regcache, M68K_D0_REGNUM, valbuf); + target_float_convert (valbuf, type, buf, fpreg_type); + regcache->raw_write (M68K_FP0_REGNUM, buf); } else m68k_store_return_value (type, regcache, valbuf); @@ -380,16 +389,33 @@ m68k_svr4_store_return_value (struct type *type, struct regcache *regcache, static int m68k_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type) { - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - enum type_code code = TYPE_CODE (type); - int len = TYPE_LENGTH (type); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + enum type_code code = type->code (); + int len = type->length (); gdb_assert (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION - || code == TYPE_CODE_COMPLEX); + || code == TYPE_CODE_COMPLEX || code == TYPE_CODE_ARRAY); if (tdep->struct_return == pcc_struct_return) return 0; + const bool is_vector = code == TYPE_CODE_ARRAY && type->is_vector (); + + if (is_vector + && check_typedef (type->target_type ())->code () == TYPE_CODE_FLT) + return 0; + + /* According to m68k_return_in_memory in the m68k GCC back-end, + strange things happen for small aggregate types. Aggregate types + with only one component are always returned like the type of the + component. Aggregate types whose size is 2, 4, or 8 are returned + in registers if their natural alignment is at least 16 bits. + + We reject vectors here, as experimentally this gives the correct + answer. */ + if (!is_vector && (len == 2 || len == 4 || len == 8)) + return type_align (type) >= 2; + return (len == 1 || len == 2 || len == 4 || len == 8); } @@ -404,24 +430,24 @@ m68k_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { - enum type_code code = TYPE_CODE (type); + enum type_code code = type->code (); /* GCC returns a `long double' in memory too. */ if (((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION - || code == TYPE_CODE_COMPLEX) + || code == TYPE_CODE_COMPLEX || code == TYPE_CODE_ARRAY) && !m68k_reg_struct_return_p (gdbarch, type)) - || (code == TYPE_CODE_FLT && TYPE_LENGTH (type) == 12)) + || (code == TYPE_CODE_FLT && type->length () == 12)) { /* The default on m68k is to return structures in static memory. - Consequently a function must return the address where we can - find the return value. */ + Consequently a function must return the address where we can + find the return value. */ if (readbuf) { ULONGEST addr; regcache_raw_read_unsigned (regcache, M68K_D0_REGNUM, &addr); - read_memory (addr, readbuf, TYPE_LENGTH (type)); + read_memory (addr, readbuf, type->length ()); } return RETURN_VALUE_ABI_RETURNS_ADDRESS; @@ -440,11 +466,26 @@ m68k_svr4_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { - enum type_code code = TYPE_CODE (type); + enum type_code code = type->code (); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Aggregates with a single member are always returned like their + sole element. */ + if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION) + && type->num_fields () == 1) + { + type = check_typedef (type->field (0).type ()); + return m68k_svr4_return_value (gdbarch, function, type, regcache, + readbuf, writebuf); + } - if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION - || code == TYPE_CODE_COMPLEX) - && !m68k_reg_struct_return_p (gdbarch, type)) + if (((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION + || code == TYPE_CODE_COMPLEX || code == TYPE_CODE_ARRAY) + && !m68k_reg_struct_return_p (gdbarch, type)) + /* GCC may return a `long double' in memory too. */ + || (!tdep->float_return + && code == TYPE_CODE_FLT + && type->length () == 12)) { /* The System V ABI says that: @@ -454,32 +495,24 @@ m68k_svr4_return_value (struct gdbarch *gdbarch, struct value *function, register %a0." So the ABI guarantees that we can always find the return - value just after the function has returned. */ + value just after the function has returned. + + However, GCC also implements the "embedded" ABI. That ABI + does not preserve %a0 across calls, but does write the value + back to %d0. */ if (readbuf) { ULONGEST addr; - regcache_raw_read_unsigned (regcache, M68K_A0_REGNUM, &addr); - read_memory (addr, readbuf, TYPE_LENGTH (type)); + regcache_raw_read_unsigned (regcache, tdep->pointer_result_regnum, + &addr); + read_memory (addr, readbuf, type->length ()); } return RETURN_VALUE_ABI_RETURNS_ADDRESS; } - /* This special case is for structures consisting of a single - `float' or `double' member. These structures are returned in - %fp0. For these structures, we call ourselves recursively, - changing TYPE into the type of the first member of the structure. - Since that should work for all structures that have only one - member, we don't bother to check the member's type here. */ - if (code == TYPE_CODE_STRUCT && TYPE_NFIELDS (type) == 1) - { - type = check_typedef (TYPE_FIELD_TYPE (type, 0)); - return m68k_svr4_return_value (gdbarch, function, type, regcache, - readbuf, writebuf); - } - if (readbuf) m68k_svr4_extract_return_value (type, regcache, readbuf); if (writebuf) @@ -502,10 +535,11 @@ m68k_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp) static CORE_ADDR m68k_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct regcache *regcache, CORE_ADDR bp_addr, int nargs, - struct value **args, CORE_ADDR sp, int struct_return, + struct value **args, CORE_ADDR sp, + function_call_return_method return_method, CORE_ADDR struct_addr) { - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); gdb_byte buf[4]; int i; @@ -513,29 +547,29 @@ m68k_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* Push arguments in reverse order. */ for (i = nargs - 1; i >= 0; i--) { - struct type *value_type = value_enclosing_type (args[i]); - int len = TYPE_LENGTH (value_type); + struct type *value_type = args[i]->enclosing_type (); + int len = value_type->length (); int container_len = (len + 3) & ~3; int offset; /* Non-scalars bigger than 4 bytes are left aligned, others are right aligned. */ - if ((TYPE_CODE (value_type) == TYPE_CODE_STRUCT - || TYPE_CODE (value_type) == TYPE_CODE_UNION - || TYPE_CODE (value_type) == TYPE_CODE_ARRAY) + if ((value_type->code () == TYPE_CODE_STRUCT + || value_type->code () == TYPE_CODE_UNION + || value_type->code () == TYPE_CODE_ARRAY) && len > 4) offset = 0; else offset = container_len - len; sp -= container_len; - write_memory (sp + offset, value_contents_all (args[i]), len); + write_memory (sp + offset, args[i]->contents_all ().data (), len); } /* Store struct value address. */ - if (struct_return) + if (return_method == return_method_struct) { store_unsigned_integer (buf, 4, byte_order, struct_addr); - regcache_cooked_write (regcache, tdep->struct_value_regnum, buf); + regcache->cooked_write (tdep->struct_value_regnum, buf); } /* Store return address. */ @@ -545,10 +579,10 @@ m68k_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* Finally, update the stack pointer... */ store_unsigned_integer (buf, 4, byte_order, sp); - regcache_cooked_write (regcache, M68K_SP_REGNUM, buf); + regcache->cooked_write (M68K_SP_REGNUM, buf); /* ...and fake a frame pointer. */ - regcache_cooked_write (regcache, M68K_FP_REGNUM, buf); + regcache->cooked_write (M68K_FP_REGNUM, buf); /* DWARF2/GCC uses the stack address *before* the function call as a frame's CFA. */ @@ -560,13 +594,15 @@ m68k_push_dummy_call (struct gdbarch *gdbarch, struct value *function, static int m68k_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int num) { + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + if (num < 8) /* d0..7 */ return (num - 0) + M68K_D0_REGNUM; else if (num < 16) /* a0..7 */ return (num - 8) + M68K_A0_REGNUM; - else if (num < 24 && gdbarch_tdep (gdbarch)->fpregs_present) + else if (num < 24 && tdep->fpregs_present) /* fp0..7 */ return (num - 16) + M68K_FP0_REGNUM; else if (num == 25) @@ -728,6 +764,7 @@ m68k_analyze_register_saves (struct gdbarch *gdbarch, CORE_ADDR pc, struct m68k_frame_cache *cache) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); if (cache->locals >= 0) { @@ -740,7 +777,7 @@ m68k_analyze_register_saves (struct gdbarch *gdbarch, CORE_ADDR pc, { op = read_memory_unsigned_integer (pc, 2, byte_order); if (op == P_FMOVEMX_SP - && gdbarch_tdep (gdbarch)->fpregs_present) + && tdep->fpregs_present) { /* fmovem.x REGS,-(%sp) */ op = read_memory_unsigned_integer (pc + 2, 2, byte_order); @@ -862,7 +899,7 @@ m68k_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) } static CORE_ADDR -m68k_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) +m68k_unwind_pc (struct gdbarch *gdbarch, frame_info_ptr next_frame) { gdb_byte buf[8]; @@ -873,7 +910,7 @@ m68k_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) /* Normal frames. */ static struct m68k_frame_cache * -m68k_frame_cache (struct frame_info *this_frame, void **this_cache) +m68k_frame_cache (frame_info_ptr this_frame, void **this_cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); @@ -938,7 +975,7 @@ m68k_frame_cache (struct frame_info *this_frame, void **this_cache) } static void -m68k_frame_this_id (struct frame_info *this_frame, void **this_cache, +m68k_frame_this_id (frame_info_ptr this_frame, void **this_cache, struct frame_id *this_id) { struct m68k_frame_cache *cache = m68k_frame_cache (this_frame, this_cache); @@ -952,7 +989,7 @@ m68k_frame_this_id (struct frame_info *this_frame, void **this_cache, } static struct value * -m68k_frame_prev_register (struct frame_info *this_frame, void **this_cache, +m68k_frame_prev_register (frame_info_ptr this_frame, void **this_cache, int regnum) { struct m68k_frame_cache *cache = m68k_frame_cache (this_frame, this_cache); @@ -971,6 +1008,7 @@ m68k_frame_prev_register (struct frame_info *this_frame, void **this_cache, static const struct frame_unwind m68k_frame_unwind = { + "m68k prologue", NORMAL_FRAME, default_frame_unwind_stop_reason, m68k_frame_this_id, @@ -980,7 +1018,7 @@ static const struct frame_unwind m68k_frame_unwind = }; static CORE_ADDR -m68k_frame_base_address (struct frame_info *this_frame, void **this_cache) +m68k_frame_base_address (frame_info_ptr this_frame, void **this_cache) { struct m68k_frame_cache *cache = m68k_frame_cache (this_frame, this_cache); @@ -996,7 +1034,7 @@ static const struct frame_base m68k_frame_base = }; static struct frame_id -m68k_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) +m68k_dummy_id (struct gdbarch *gdbarch, frame_info_ptr this_frame) { CORE_ADDR fp; @@ -1013,18 +1051,17 @@ m68k_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) This routine returns true on success. */ static int -m68k_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) +m68k_get_longjmp_target (frame_info_ptr frame, CORE_ADDR *pc) { gdb_byte *buf; CORE_ADDR sp, jb_addr; struct gdbarch *gdbarch = get_frame_arch (frame); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); if (tdep->jb_pc < 0) { - internal_error (__FILE__, __LINE__, - _("m68k_get_longjmp_target: not implemented")); + internal_error (_("m68k_get_longjmp_target: not implemented")); return 0; } @@ -1064,14 +1101,30 @@ m68k_return_in_first_hidden_param_p (struct gdbarch *gdbarch, void m68k_svr4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); /* SVR4 uses a different calling convention. */ set_gdbarch_return_value (gdbarch, m68k_svr4_return_value); /* SVR4 uses %a0 instead of %a1. */ tdep->struct_value_regnum = M68K_A0_REGNUM; + + /* SVR4 returns pointers in %a0. */ + tdep->pointer_result_regnum = M68K_A0_REGNUM; } + +/* GCC's m68k "embedded" ABI. This is like the SVR4 ABI, but pointer + values are returned in %d0, not %a0. */ + +static void +m68k_embedded_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + m68k_svr4_init_abi (info, gdbarch); + tdep->pointer_result_regnum = M68K_D0_REGNUM; +} + /* Function: m68k_gdbarch_init @@ -1081,10 +1134,8 @@ m68k_svr4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) static struct gdbarch * m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { - struct gdbarch_tdep *tdep = NULL; - struct gdbarch *gdbarch; struct gdbarch_list *best_arch; - struct tdesc_arch_data *tdesc_data = NULL; + tdesc_arch_data_up tdesc_data; int i; enum m68k_flavour flavour = m68k_no_flavour; int has_fp = 1; @@ -1122,14 +1173,11 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) valid_p = 1; for (i = 0; i <= M68K_PC_REGNUM; i++) - valid_p &= tdesc_numbered_register (feature, tdesc_data, i, + valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), i, m68k_register_names[i]); if (!valid_p) - { - tdesc_data_cleanup (tdesc_data); - return NULL; - } + return NULL; feature = tdesc_find_feature (info.target_desc, "org.gnu.gdb.coldfire.fp"); @@ -1137,13 +1185,10 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { valid_p = 1; for (i = M68K_FP0_REGNUM; i <= M68K_FPI_REGNUM; i++) - valid_p &= tdesc_numbered_register (feature, tdesc_data, i, + valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), i, m68k_register_names[i]); if (!valid_p) - { - tdesc_data_cleanup (tdesc_data); - return NULL; - } + return NULL; } else has_fp = 0; @@ -1164,30 +1209,53 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) flavour = m68k_coldfire_flavour; } + /* Try to figure out if the arch uses floating registers to return + floating point values from functions. On ColdFire, floating + point values are returned in D0. */ + int float_return = 0; + if (has_fp && flavour != m68k_coldfire_flavour) + float_return = 1; +#ifdef HAVE_ELF + if (info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour) + { + int fp_abi = bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU, + Tag_GNU_M68K_ABI_FP); + if (fp_abi == 1) + float_return = 1; + else if (fp_abi == 2) + float_return = 0; + } +#endif /* HAVE_ELF */ + /* If there is already a candidate, use it. */ for (best_arch = gdbarch_list_lookup_by_info (arches, &info); best_arch != NULL; best_arch = gdbarch_list_lookup_by_info (best_arch->next, &info)) { - if (flavour != gdbarch_tdep (best_arch->gdbarch)->flavour) + m68k_gdbarch_tdep *tdep + = gdbarch_tdep (best_arch->gdbarch); + + if (flavour != tdep->flavour) + continue; + + if (has_fp != tdep->fpregs_present) continue; - if (has_fp != gdbarch_tdep (best_arch->gdbarch)->fpregs_present) + if (float_return != tdep->float_return) continue; break; } if (best_arch != NULL) - { - if (tdesc_data != NULL) - tdesc_data_cleanup (tdesc_data); - return best_arch->gdbarch; - } + return best_arch->gdbarch; + + gdbarch *gdbarch + = gdbarch_alloc (&info, gdbarch_tdep_up (new m68k_gdbarch_tdep)); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - tdep = XCNEW (struct gdbarch_tdep); - gdbarch = gdbarch_alloc (&info, tdep); tdep->fpregs_present = has_fp; + tdep->float_return = float_return; tdep->flavour = flavour; if (flavour == m68k_coldfire_flavour || flavour == m68k_fido_flavour) @@ -1196,7 +1264,8 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_long_double_bit (gdbarch, long_double_format[0]->totalsize); set_gdbarch_skip_prologue (gdbarch, m68k_skip_prologue); - set_gdbarch_breakpoint_from_pc (gdbarch, m68k_local_breakpoint_from_pc); + set_gdbarch_breakpoint_kind_from_pc (gdbarch, m68k_breakpoint::kind_from_pc); + set_gdbarch_sw_breakpoint_from_kind (gdbarch, m68k_breakpoint::bp_from_kind); /* Stack grows down. */ set_gdbarch_inner_than (gdbarch, core_addr_lessthan); @@ -1222,38 +1291,19 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) if (has_fp) set_gdbarch_fp0_regnum (gdbarch, M68K_FP0_REGNUM); - /* Try to figure out if the arch uses floating registers to return - floating point values from functions. */ - if (has_fp) - { - /* On ColdFire, floating point values are returned in D0. */ - if (flavour == m68k_coldfire_flavour) - tdep->float_return = 0; - else - tdep->float_return = 1; - } - else - { - /* No floating registers, so can't use them for returning values. */ - tdep->float_return = 0; - } - /* Function call & return. */ set_gdbarch_push_dummy_call (gdbarch, m68k_push_dummy_call); set_gdbarch_return_value (gdbarch, m68k_return_value); set_gdbarch_return_in_first_hidden_param_p (gdbarch, m68k_return_in_first_hidden_param_p); - - /* Disassembler. */ - set_gdbarch_print_insn (gdbarch, print_insn_m68k); - #if defined JB_PC && defined JB_ELEMENT_SIZE tdep->jb_pc = JB_PC; tdep->jb_elt_size = JB_ELEMENT_SIZE; #else tdep->jb_pc = -1; #endif + tdep->pointer_result_regnum = M68K_D0_REGNUM; tdep->struct_value_regnum = M68K_A1_REGNUM; tdep->struct_return = reg_struct_return; @@ -1277,8 +1327,8 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) frame_unwind_append_unwinder (gdbarch, &m68k_frame_unwind); - if (tdesc_data) - tdesc_use_registers (gdbarch, info.target_desc, tdesc_data); + if (tdesc_data != nullptr) + tdesc_use_registers (gdbarch, info.target_desc, std::move (tdesc_data)); return gdbarch; } @@ -1287,16 +1337,33 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) static void m68k_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file) { - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + m68k_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); if (tdep == NULL) return; } -extern initialize_file_ftype _initialize_m68k_tdep; /* -Wmissing-prototypes */ +/* OSABI sniffer for m68k. */ + +static enum gdb_osabi +m68k_osabi_sniffer (bfd *abfd) +{ + unsigned int elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI]; + + if (elfosabi == ELFOSABI_NONE) + return GDB_OSABI_SVR4; + return GDB_OSABI_UNKNOWN; +} + +void _initialize_m68k_tdep (); void -_initialize_m68k_tdep (void) +_initialize_m68k_tdep () { gdbarch_register (bfd_arch_m68k, m68k_gdbarch_init, m68k_dump_tdep); + + gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_elf_flavour, + m68k_osabi_sniffer); + gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_SVR4, + m68k_embedded_init_abi); }