/* Target-dependent code for Morpho mt processor, for GDB.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Contributed by Michael Snyder, msnyder@redhat.com. */
#include "dis-asm.h"
#include "arch-utils.h"
#include "gdbtypes.h"
-#include "gdb_string.h"
#include "regcache.h"
#include "reggroups.h"
#include "gdbcore.h"
#include "inferior.h"
#include "dwarf2-frame.h"
#include "infcall.h"
-#include "gdb_assert.h"
+#include "language.h"
+#include "valprint.h"
enum mt_arch_constants
{
MT_OUT_REGNUM, /* 16 bits. */
MT_EXMAC_REGNUM, /* 32 bits (8 used). */
MT_QCHANNEL_REGNUM, /* 32 bits. */
+ MT_ZI2_REGNUM, /* 16 bits. */
+ MT_ZQ2_REGNUM, /* 16 bits. */
+ MT_CHANNEL2_REGNUM, /* 32 bits. */
+ MT_ISCRAMB2_REGNUM, /* 32 bits. */
+ MT_QSCRAMB2_REGNUM, /* 32 bits. */
+ MT_QCHANNEL2_REGNUM, /* 32 bits. */
/* Number of real registers. */
MT_NUM_REGS,
/* Pseudo-registers. */
MT_COPRO_PSEUDOREG_REGNUM = MT_NUM_REGS,
MT_MAC_PSEUDOREG_REGNUM,
+ MT_COPRO_PSEUDOREG_ARRAY,
+
+ MT_COPRO_PSEUDOREG_DIM_1 = 2,
+ MT_COPRO_PSEUDOREG_DIM_2 = 8,
+ /* The number of pseudo-registers for each coprocessor. These
+ include the real coprocessor registers, the pseudo-registe for
+ the coprocessor number, and the pseudo-register for the MAC. */
+ MT_COPRO_PSEUDOREG_REGS = MT_NUM_REGS - MT_NUM_CPU_REGS + 2,
+ /* The register number of the MAC, relative to a given coprocessor. */
+ MT_COPRO_PSEUDOREG_MAC_REGNUM = MT_COPRO_PSEUDOREG_REGS - 1,
/* Two pseudo-regs ('coprocessor' and 'mac'). */
- MT_NUM_PSEUDO_REGS = 2
+ MT_NUM_PSEUDO_REGS = 2 + (MT_COPRO_PSEUDOREG_REGS
+ * MT_COPRO_PSEUDOREG_DIM_1
+ * MT_COPRO_PSEUDOREG_DIM_2)
+};
+
+/* The tdep structure. */
+struct gdbarch_tdep
+{
+ /* ISA-specific types. */
+ struct type *copro_type;
};
+
/* Return name of register number specified by REGNUM. */
static const char *
-mt_register_name (int regnum)
+mt_register_name (struct gdbarch *gdbarch, int regnum)
{
static const char *const register_names[] = {
/* CPU regs. */
"cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15",
"bypa", "bypb", "bypc", "flag", "context", "" /* mac. */ , "z1", "z2",
"Ichannel", "Iscramb", "Qscramb", "out", "" /* ex-mac. */ , "Qchannel",
+ "zi2", "zq2", "Ichannel2", "Iscramb2", "Qscramb2", "Qchannel2",
/* Pseudo-registers. */
"coprocessor", "MAC"
};
+ static const char *array_names[MT_COPRO_PSEUDOREG_REGS
+ * MT_COPRO_PSEUDOREG_DIM_1
+ * MT_COPRO_PSEUDOREG_DIM_2];
+
+ if (regnum < 0)
+ return "";
+ if (regnum < ARRAY_SIZE (register_names))
+ return register_names[regnum];
+ if (array_names[regnum - MT_COPRO_PSEUDOREG_ARRAY])
+ return array_names[regnum - MT_COPRO_PSEUDOREG_ARRAY];
+
+ {
+ char *name;
+ const char *stub;
+ unsigned dim_1;
+ unsigned dim_2;
+ unsigned index;
+
+ regnum -= MT_COPRO_PSEUDOREG_ARRAY;
+ index = regnum % MT_COPRO_PSEUDOREG_REGS;
+ dim_2 = (regnum / MT_COPRO_PSEUDOREG_REGS) % MT_COPRO_PSEUDOREG_DIM_2;
+ dim_1 = ((regnum / MT_COPRO_PSEUDOREG_REGS / MT_COPRO_PSEUDOREG_DIM_2)
+ % MT_COPRO_PSEUDOREG_DIM_1);
+
+ if (index == MT_COPRO_PSEUDOREG_MAC_REGNUM)
+ stub = register_names[MT_MAC_PSEUDOREG_REGNUM];
+ else if (index >= MT_NUM_REGS - MT_CPR0_REGNUM)
+ stub = "";
+ else
+ stub = register_names[index + MT_CPR0_REGNUM];
+ if (!*stub)
+ {
+ array_names[regnum] = stub;
+ return stub;
+ }
+ name = (char *) xmalloc (30);
+ sprintf (name, "copro_%d_%d_%s", dim_1, dim_2, stub);
+ array_names[regnum] = name;
+ return name;
+ }
+}
+
+/* Return the type of a coprocessor register. */
- gdb_assert (regnum >= 0 && regnum < ARRAY_SIZE (register_names));
- return register_names[regnum];
+static struct type *
+mt_copro_register_type (struct gdbarch *arch, int regnum)
+{
+ switch (regnum)
+ {
+ case MT_INT_ENABLE_REGNUM:
+ case MT_ICHANNEL_REGNUM:
+ case MT_QCHANNEL_REGNUM:
+ case MT_ISCRAMB_REGNUM:
+ case MT_QSCRAMB_REGNUM:
+ return builtin_type (arch)->builtin_int32;
+ case MT_BYPA_REGNUM:
+ case MT_BYPB_REGNUM:
+ case MT_BYPC_REGNUM:
+ case MT_Z1_REGNUM:
+ case MT_Z2_REGNUM:
+ case MT_OUT_REGNUM:
+ case MT_ZI2_REGNUM:
+ case MT_ZQ2_REGNUM:
+ return builtin_type (arch)->builtin_int16;
+ case MT_EXMAC_REGNUM:
+ case MT_MAC_REGNUM:
+ return builtin_type (arch)->builtin_uint32;
+ case MT_CONTEXT_REGNUM:
+ return builtin_type (arch)->builtin_long_long;
+ case MT_FLAG_REGNUM:
+ return builtin_type (arch)->builtin_unsigned_char;
+ default:
+ if (regnum >= MT_CPR0_REGNUM && regnum <= MT_CPR15_REGNUM)
+ return builtin_type (arch)->builtin_int16;
+ else if (regnum == MT_CPR0_REGNUM + MT_COPRO_PSEUDOREG_MAC_REGNUM)
+ {
+ if (gdbarch_bfd_arch_info (arch)->mach == bfd_mach_mrisc2
+ || gdbarch_bfd_arch_info (arch)->mach == bfd_mach_ms2)
+ return builtin_type (arch)->builtin_uint64;
+ else
+ return builtin_type (arch)->builtin_uint32;
+ }
+ else
+ return builtin_type (arch)->builtin_uint32;
+ }
}
/* Given ARCH and a register number specified by REGNUM, return the
static struct type *
mt_register_type (struct gdbarch *arch, int regnum)
{
- static struct type *void_func_ptr = NULL;
- static struct type *void_ptr = NULL;
- static struct type *copro_type;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
if (regnum >= 0 && regnum < MT_NUM_REGS + MT_NUM_PSEUDO_REGS)
{
- if (void_func_ptr == NULL)
- {
- struct type *temp;
-
- void_ptr = lookup_pointer_type (builtin_type_void);
- void_func_ptr =
- lookup_pointer_type (lookup_function_type (builtin_type_void));
- temp = create_range_type (NULL, builtin_type_unsigned_int, 0, 1);
- copro_type = create_array_type (NULL, builtin_type_int16, temp);
- }
switch (regnum)
{
case MT_PC_REGNUM:
case MT_RA_REGNUM:
case MT_IRA_REGNUM:
- return void_func_ptr;
+ return builtin_type (arch)->builtin_func_ptr;
case MT_SP_REGNUM:
case MT_FP_REGNUM:
- return void_ptr;
- case MT_INT_ENABLE_REGNUM:
- case MT_ICHANNEL_REGNUM:
- case MT_QCHANNEL_REGNUM:
- case MT_ISCRAMB_REGNUM:
- case MT_QSCRAMB_REGNUM:
- return builtin_type_int32;
- case MT_EXMAC_REGNUM:
- case MT_MAC_REGNUM:
- return builtin_type_uint32;
- case MT_BYPA_REGNUM:
- case MT_BYPB_REGNUM:
- case MT_BYPC_REGNUM:
- case MT_Z1_REGNUM:
- case MT_Z2_REGNUM:
- case MT_OUT_REGNUM:
- return builtin_type_int16;
- case MT_CONTEXT_REGNUM:
- return builtin_type_long_long;
+ return builtin_type (arch)->builtin_data_ptr;
case MT_COPRO_REGNUM:
case MT_COPRO_PSEUDOREG_REGNUM:
- return copro_type;
+ if (tdep->copro_type == NULL)
+ {
+ struct type *elt = builtin_type (arch)->builtin_int16;
+ tdep->copro_type = lookup_array_range_type (elt, 0, 1);
+ }
+ return tdep->copro_type;
case MT_MAC_PSEUDOREG_REGNUM:
- if (gdbarch_bfd_arch_info (arch)->mach == bfd_mach_mrisc2
- || gdbarch_bfd_arch_info (arch)->mach == bfd_mach_ms2)
- return builtin_type_uint64;
- else
- return builtin_type_uint32;
- case MT_FLAG_REGNUM:
- return builtin_type_unsigned_char;
+ return mt_copro_register_type (arch,
+ MT_CPR0_REGNUM
+ + MT_COPRO_PSEUDOREG_MAC_REGNUM);
default:
if (regnum >= MT_R0_REGNUM && regnum <= MT_R15_REGNUM)
- return builtin_type_int32;
- else if (regnum >= MT_CPR0_REGNUM && regnum <= MT_CPR15_REGNUM)
- return builtin_type_int16;
+ return builtin_type (arch)->builtin_int32;
+ else if (regnum < MT_COPRO_PSEUDOREG_ARRAY)
+ return mt_copro_register_type (arch, regnum);
+ else
+ {
+ regnum -= MT_COPRO_PSEUDOREG_ARRAY;
+ regnum %= MT_COPRO_PSEUDOREG_REGS;
+ regnum += MT_CPR0_REGNUM;
+ return mt_copro_register_type (arch, regnum);
+ }
}
}
internal_error (__FILE__, __LINE__,
if (group == all_reggroup)
return (regnum >= 0
&& regnum < MT_NUM_REGS + MT_NUM_PSEUDO_REGS
- && mt_register_name (regnum)[0] != '\0');
+ && mt_register_name (gdbarch, regnum)[0] != '\0');
if (group == general_reggroup)
return (regnum >= MT_R0_REGNUM && regnum <= MT_R15_REGNUM);
values. */
static enum return_value_convention
-mt_return_value (struct gdbarch *gdbarch, struct type *type,
- struct regcache *regcache, gdb_byte *readbuf,
- const gdb_byte *writebuf)
+mt_return_value (struct gdbarch *gdbarch, struct value *function,
+ struct type *type, struct regcache *regcache,
+ gdb_byte *readbuf, const gdb_byte *writebuf)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
if (TYPE_LENGTH (type) > 4)
{
/* Return values > 4 bytes are returned in memory,
/* Return values of <= 4 bytes are returned in R11. */
regcache_cooked_read_unsigned (regcache, MT_R11_REGNUM, &temp);
- store_unsigned_integer (readbuf, TYPE_LENGTH (type), temp);
+ store_unsigned_integer (readbuf, TYPE_LENGTH (type),
+ byte_order, temp);
}
if (writebuf)
call. */
static CORE_ADDR
-mt_skip_prologue (CORE_ADDR pc)
+mt_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR func_addr = 0, func_end = 0;
- char *func_name;
+ const char *func_name;
unsigned long instr;
if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
struct symbol *sym;
/* Found a function. */
- sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL, NULL);
+ sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL).symbol;
if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
{
/* Don't use this trick for assembly source files. */
/* No function symbol, or no line symbol. Use prologue scanning method. */
for (;; pc += 4)
{
- instr = read_memory_unsigned_integer (pc, 4);
+ instr = read_memory_unsigned_integer (pc, 4, byte_order);
if (instr == 0x12000000) /* nop */
continue;
if (instr == 0x12ddc000) /* copy sp into fp */
instruction in the instruction set.
The BP for ms1 is defined as 0x68000000 (BREAK).
- The BP for ms2 is defined as 0x69000000 (illegal) */
+ The BP for ms2 is defined as 0x69000000 (illegal). */
static const gdb_byte *
-mt_breakpoint_from_pc (CORE_ADDR *bp_addr, int *bp_size)
+mt_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
+ int *bp_size)
{
static gdb_byte ms1_breakpoint[] = { 0x68, 0, 0, 0 };
static gdb_byte ms2_breakpoint[] = { 0x69, 0, 0, 0 };
*bp_size = 4;
- if (gdbarch_bfd_arch_info (current_gdbarch)->mach == bfd_mach_ms2)
+ if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_ms2)
return ms2_breakpoint;
return ms1_breakpoint;
}
+/* Select the correct coprocessor register bank. Return the pseudo
+ regnum we really want to read. */
+
+static int
+mt_select_coprocessor (struct gdbarch *gdbarch,
+ struct regcache *regcache, int regno)
+{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ unsigned index, base;
+ gdb_byte copro[4];
+
+ /* Get the copro pseudo regnum. */
+ regcache_raw_read (regcache, MT_COPRO_REGNUM, copro);
+ base = ((extract_signed_integer (&copro[0], 2, byte_order)
+ * MT_COPRO_PSEUDOREG_DIM_2)
+ + extract_signed_integer (&copro[2], 2, byte_order));
+
+ regno -= MT_COPRO_PSEUDOREG_ARRAY;
+ index = regno % MT_COPRO_PSEUDOREG_REGS;
+ regno /= MT_COPRO_PSEUDOREG_REGS;
+ if (base != regno)
+ {
+ /* Select the correct coprocessor register bank. Invalidate the
+ coprocessor register cache. */
+ unsigned ix;
+
+ store_signed_integer (&copro[0], 2, byte_order,
+ regno / MT_COPRO_PSEUDOREG_DIM_2);
+ store_signed_integer (&copro[2], 2, byte_order,
+ regno % MT_COPRO_PSEUDOREG_DIM_2);
+ regcache_raw_write (regcache, MT_COPRO_REGNUM, copro);
+
+ /* We must flush the cache, as it is now invalid. */
+ for (ix = MT_NUM_CPU_REGS; ix != MT_NUM_REGS; ix++)
+ regcache_invalidate (regcache, ix);
+ }
+
+ return index;
+}
+
/* Fetch the pseudo registers:
- There are two pseudo-registers:
+ There are two regular pseudo-registers:
1) The 'coprocessor' pseudo-register (which mirrors the
"real" coprocessor register sent by the target), and
2) The 'MAC' pseudo-register (which represents the union
of the original 32 bit target MAC register and the new
- 8-bit extended-MAC register). */
+ 8-bit extended-MAC register).
-static void
+ Additionally there is an array of coprocessor registers which track
+ the coprocessor registers for each coprocessor. */
+
+static enum register_status
mt_pseudo_register_read (struct gdbarch *gdbarch,
- struct regcache *regcache, int regno, gdb_byte *buf)
+ struct regcache *regcache, int regno, gdb_byte *buf)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
switch (regno)
{
case MT_COPRO_REGNUM:
case MT_COPRO_PSEUDOREG_REGNUM:
- regcache_raw_read (regcache, MT_COPRO_REGNUM, buf);
- break;
+ return regcache_raw_read (regcache, MT_COPRO_REGNUM, buf);
case MT_MAC_REGNUM:
case MT_MAC_PSEUDOREG_REGNUM:
if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_mrisc2
|| gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_ms2)
{
+ enum register_status status;
ULONGEST oldmac = 0, ext_mac = 0;
ULONGEST newmac;
- regcache_cooked_read_unsigned (regcache, MT_MAC_REGNUM, &oldmac);
+ status = regcache_cooked_read_unsigned (regcache, MT_MAC_REGNUM, &oldmac);
+ if (status != REG_VALID)
+ return status;
+
regcache_cooked_read_unsigned (regcache, MT_EXMAC_REGNUM, &ext_mac);
+ if (status != REG_VALID)
+ return status;
+
newmac =
(oldmac & 0xffffffff) | ((long long) (ext_mac & 0xff) << 32);
- store_signed_integer (buf, 8, newmac);
+ store_signed_integer (buf, 8, byte_order, newmac);
+
+ return REG_VALID;
}
else
- regcache_raw_read (regcache, MT_MAC_REGNUM, buf);
+ return regcache_raw_read (regcache, MT_MAC_REGNUM, buf);
break;
default:
- internal_error (__FILE__, __LINE__,
- _("mt_pseudo_register_read: bad reg # (%d)"), regno);
+ {
+ unsigned index = mt_select_coprocessor (gdbarch, regcache, regno);
+
+ if (index == MT_COPRO_PSEUDOREG_MAC_REGNUM)
+ return mt_pseudo_register_read (gdbarch, regcache,
+ MT_MAC_PSEUDOREG_REGNUM, buf);
+ else if (index < MT_NUM_REGS - MT_CPR0_REGNUM)
+ return regcache_raw_read (regcache, index + MT_CPR0_REGNUM, buf);
+ else
+ /* ??? */
+ return REG_VALID;
+ }
break;
}
}
struct regcache *regcache,
int regno, const gdb_byte *buf)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int i;
switch (regno)
case MT_COPRO_PSEUDOREG_REGNUM:
regcache_raw_write (regcache, MT_COPRO_REGNUM, buf);
for (i = MT_NUM_CPU_REGS; i < MT_NUM_REGS; i++)
- set_register_cached (i, 0);
+ regcache_invalidate (regcache, i);
break;
case MT_MAC_REGNUM:
case MT_MAC_PSEUDOREG_REGNUM:
unsigned int oldmac, ext_mac;
ULONGEST newmac;
- newmac = extract_unsigned_integer (buf, 8);
+ newmac = extract_unsigned_integer (buf, 8, byte_order);
oldmac = newmac & 0xffffffff;
ext_mac = (newmac >> 32) & 0xff;
regcache_cooked_write_unsigned (regcache, MT_MAC_REGNUM, oldmac);
regcache_raw_write (regcache, MT_MAC_REGNUM, buf);
break;
default:
- internal_error (__FILE__, __LINE__,
- _("mt_pseudo_register_write: bad reg # (%d)"), regno);
+ {
+ unsigned index = mt_select_coprocessor (gdbarch, regcache, regno);
+
+ if (index == MT_COPRO_PSEUDOREG_MAC_REGNUM)
+ mt_pseudo_register_write (gdbarch, regcache,
+ MT_MAC_PSEUDOREG_REGNUM, buf);
+ else if (index < MT_NUM_REGS - MT_CPR0_REGNUM)
+ regcache_raw_write (regcache, index + MT_CPR0_REGNUM, buf);
+ }
break;
}
}
static void
mt_registers_info (struct gdbarch *gdbarch,
- struct ui_file *file,
- struct frame_info *frame, int regnum, int all)
+ struct ui_file *file,
+ struct frame_info *frame, int regnum, int all)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
if (regnum == -1)
{
int lim;
regsize = register_size (gdbarch, regnum);
- buff = alloca (regsize);
- bytes = alloca (regsize * sizeof (*bytes));
+ buff = (unsigned char *) alloca (regsize);
+ bytes = XALLOCAVEC (unsigned int, regsize);
- frame_register_read (frame, regnum, buff);
+ deprecated_frame_register_read (frame, regnum, buff);
- fputs_filtered (REGISTER_NAME (regnum), file);
- print_spaces_filtered (15 - strlen (REGISTER_NAME (regnum)), file);
+ fputs_filtered (gdbarch_register_name
+ (gdbarch, regnum), file);
+ print_spaces_filtered (15 - strlen (gdbarch_register_name
+ (gdbarch, regnum)),
+ file);
fputs_filtered ("0x", file);
for (i = 0; i < regsize; i++)
fprintf_filtered (file, "%02x", (unsigned int)
- extract_unsigned_integer (buff + i, 1));
+ extract_unsigned_integer (buff + i, 1, byte_order));
fputs_filtered ("\t", file);
print_longest (file, 'd', 0,
- extract_unsigned_integer (buff, regsize));
+ extract_unsigned_integer (buff, regsize, byte_order));
fputs_filtered ("\n", file);
}
else if (regnum == MT_COPRO_REGNUM
{
/* Special output handling for the 'coprocessor' register. */
gdb_byte *buf;
+ struct value_print_options opts;
- buf = alloca (register_size (gdbarch, MT_COPRO_REGNUM));
- frame_register_read (frame, MT_COPRO_REGNUM, buf);
+ buf = (gdb_byte *) alloca (register_size (gdbarch, MT_COPRO_REGNUM));
+ deprecated_frame_register_read (frame, MT_COPRO_REGNUM, buf);
/* And print. */
regnum = MT_COPRO_PSEUDOREG_REGNUM;
- fputs_filtered (REGISTER_NAME (regnum), file);
- print_spaces_filtered (15 - strlen (REGISTER_NAME (regnum)), file);
+ fputs_filtered (gdbarch_register_name (gdbarch, regnum),
+ file);
+ print_spaces_filtered (15 - strlen (gdbarch_register_name
+ (gdbarch, regnum)),
+ file);
+ get_no_prettyformat_print_options (&opts);
+ opts.deref_ref = 1;
val_print (register_type (gdbarch, regnum), buf,
- 0, 0, file, 0, 1, 0, Val_no_prettyprint);
+ 0, 0, file, 0, NULL,
+ &opts, current_language);
fputs_filtered ("\n", file);
}
else if (regnum == MT_MAC_REGNUM || regnum == MT_MAC_PSEUDOREG_REGNUM)
gdb_byte buf[3 * sizeof (LONGEST)];
/* Get the two "real" mac registers. */
- frame_register_read (frame, MT_MAC_REGNUM, buf);
+ deprecated_frame_register_read (frame, MT_MAC_REGNUM, buf);
oldmac = extract_unsigned_integer
- (buf, register_size (gdbarch, MT_MAC_REGNUM));
+ (buf, register_size (gdbarch, MT_MAC_REGNUM), byte_order);
if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_mrisc2
|| gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_ms2)
{
- frame_register_read (frame, MT_EXMAC_REGNUM, buf);
+ deprecated_frame_register_read (frame, MT_EXMAC_REGNUM, buf);
ext_mac = extract_unsigned_integer
- (buf, register_size (gdbarch, MT_EXMAC_REGNUM));
+ (buf, register_size (gdbarch, MT_EXMAC_REGNUM), byte_order);
}
else
ext_mac = 0;
/* And print. */
regnum = MT_MAC_PSEUDOREG_REGNUM;
- fputs_filtered (REGISTER_NAME (regnum), file);
- print_spaces_filtered (15 - strlen (REGISTER_NAME (regnum)), file);
+ fputs_filtered (gdbarch_register_name (gdbarch, regnum),
+ file);
+ print_spaces_filtered (15 - strlen (gdbarch_register_name
+ (gdbarch, regnum)),
+ file);
fputs_filtered ("0x", file);
print_longest (file, 'x', 0, newmac);
fputs_filtered ("\t", file);
int struct_return, CORE_ADDR struct_addr)
{
#define wordsize 4
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[MT_MAX_STRUCT_SIZE];
int argreg = MT_1ST_ARGREG;
int split_param_len = 0;
regcache_cooked_write_unsigned (regcache, argreg++,
extract_unsigned_integer
(value_contents (args[i]),
- wordsize));
+ wordsize, byte_order));
break;
case 8:
case 12:
/* This word of the argument is passed in a register. */
regcache_cooked_write_unsigned (regcache, argreg++,
extract_unsigned_integer
- (val, wordsize));
+ (val, wordsize, byte_order));
typelen -= wordsize;
val += wordsize;
}
for (j = nargs - 1; j >= i; j--)
{
gdb_byte *val;
+ struct cleanup *back_to;
+ const gdb_byte *contents = value_contents (args[j]);
/* Right-justify the value in an aligned-length buffer. */
typelen = TYPE_LENGTH (value_type (args[j]));
slacklen = (wordsize - (typelen % wordsize)) % wordsize;
- val = alloca (typelen + slacklen);
- memcpy (val, value_contents (args[j]), typelen);
+ val = (gdb_byte *) xmalloc (typelen + slacklen);
+ back_to = make_cleanup (xfree, val);
+ memcpy (val, contents, typelen);
memset (val + typelen, 0, slacklen);
/* Now write this data to the stack. */
stack_dest -= typelen + slacklen;
write_memory (stack_dest, val, typelen + slacklen);
+ do_cleanups (back_to);
}
/* Finally, if a param needs to be split between registers and stack,
struct mt_unwind_cache
{
- /* The previous frame's inner most stack address.
+ /* The previous frame's inner most stack address.
Used as this frame ID's stack_addr. */
CORE_ADDR prev_sp;
CORE_ADDR frame_base;
the frame. */
static struct mt_unwind_cache *
-mt_frame_unwind_cache (struct frame_info *next_frame,
+mt_frame_unwind_cache (struct frame_info *this_frame,
void **this_prologue_cache)
{
struct gdbarch *gdbarch;
ULONGEST sp, fp;
if ((*this_prologue_cache))
- return (*this_prologue_cache);
+ return (struct mt_unwind_cache *) (*this_prologue_cache);
- gdbarch = get_frame_arch (next_frame);
+ gdbarch = get_frame_arch (this_frame);
info = FRAME_OBSTACK_ZALLOC (struct mt_unwind_cache);
(*this_prologue_cache) = info;
info->framesize = 0;
info->frame_base = 0;
info->frameless_p = 1;
- info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+ info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
- /* Grab the frame-relative values of SP and FP, needed below.
+ /* Grab the frame-relative values of SP and FP, needed below.
The frame_saved_register function will find them on the
stack or in the registers as appropriate. */
- frame_unwind_unsigned_register (next_frame, MT_SP_REGNUM, &sp);
- frame_unwind_unsigned_register (next_frame, MT_FP_REGNUM, &fp);
+ sp = get_frame_register_unsigned (this_frame, MT_SP_REGNUM);
+ fp = get_frame_register_unsigned (this_frame, MT_FP_REGNUM);
- start_addr = frame_func_unwind (next_frame);
+ start_addr = get_frame_func (this_frame);
/* Return early if GDB couldn't find the function. */
if (start_addr == 0)
return info;
- end_addr = frame_pc_unwind (next_frame);
- prologue_end_addr = skip_prologue_using_sal (start_addr);
+ end_addr = get_frame_pc (this_frame);
+ prologue_end_addr = skip_prologue_using_sal (gdbarch, start_addr);
if (end_addr == 0)
for (next_addr = start_addr; next_addr < end_addr; next_addr += 4)
{
- instr = get_frame_memory_unsigned (next_frame, next_addr, 4);
- if (delayed_store) /* previous instr was a push */
+ instr = get_frame_memory_unsigned (this_frame, next_addr, 4);
+ if (delayed_store) /* Previous instr was a push. */
{
upper_half = delayed_store >> 16;
regnum = upper_half & 0xf;
offset = delayed_store & 0xffff;
switch (upper_half & 0xfff0)
{
- case 0x43c0: /* push using frame pointer */
+ case 0x43c0: /* push using frame pointer. */
info->saved_regs[regnum].addr = offset;
break;
- case 0x43d0: /* push using stack pointer */
+ case 0x43d0: /* push using stack pointer. */
info->saved_regs[regnum].addr = offset;
break;
default: /* lint */
case 0x12000000: /* NO-OP */
continue;
case 0x12ddc000: /* copy sp into fp */
- info->frameless_p = 0; /* Record that the frame pointer is in use. */
+ info->frameless_p = 0; /* Record that the frame
+ pointer is in use. */
continue;
default:
upper_half = instr >> 16;
keep scanning until we reach it (or we reach end_addr). */
if (prologue_end_addr && (prologue_end_addr > (next_addr + 4)))
- continue; /* Keep scanning, recording saved_regs etc. */
+ continue; /* Keep scanning, recording saved_regs etc. */
else
- break; /* Quit scanning: breakpoint can be set here. */
+ break; /* Quit scanning: breakpoint can be set here. */
}
}
{
ULONGEST pc;
- frame_unwind_unsigned_register (next_frame, MT_PC_REGNUM, &pc);
+ pc = frame_unwind_register_unsigned (next_frame, MT_PC_REGNUM);
return pc;
}
{
ULONGEST sp;
- frame_unwind_unsigned_register (next_frame, MT_SP_REGNUM, &sp);
+ sp = frame_unwind_register_unsigned (next_frame, MT_SP_REGNUM);
return sp;
}
-/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
- dummy frame. The frame ID's base needs to match the TOS value
- saved by save_dummy_frame_tos(), and the PC match the dummy frame's
- breakpoint. */
+/* Assuming THIS_FRAME is a dummy, return the frame ID of that dummy
+ frame. The frame ID's base needs to match the TOS value saved by
+ save_dummy_frame_tos(), and the PC match the dummy frame's breakpoint. */
static struct frame_id
-mt_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+mt_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
- return frame_id_build (mt_unwind_sp (gdbarch, next_frame),
- frame_pc_unwind (next_frame));
+ CORE_ADDR sp = get_frame_register_unsigned (this_frame, MT_SP_REGNUM);
+ return frame_id_build (sp, get_frame_pc (this_frame));
}
/* Given a GDB frame, determine the address of the calling function's
frame. This will be used to create a new GDB frame struct. */
static void
-mt_frame_this_id (struct frame_info *next_frame,
+mt_frame_this_id (struct frame_info *this_frame,
void **this_prologue_cache, struct frame_id *this_id)
{
struct mt_unwind_cache *info =
- mt_frame_unwind_cache (next_frame, this_prologue_cache);
+ mt_frame_unwind_cache (this_frame, this_prologue_cache);
if (!(info == NULL || info->prev_sp == 0))
- {
- (*this_id) = frame_id_build (info->prev_sp,
- frame_func_unwind (next_frame));
- }
+ (*this_id) = frame_id_build (info->prev_sp, get_frame_func (this_frame));
+
return;
}
-static void
-mt_frame_prev_register (struct frame_info *next_frame,
- void **this_prologue_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, gdb_byte *bufferp)
+static struct value *
+mt_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
{
struct mt_unwind_cache *info =
- mt_frame_unwind_cache (next_frame, this_prologue_cache);
+ mt_frame_unwind_cache (this_frame, this_prologue_cache);
- trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
- optimizedp, lvalp, addrp, realnump, bufferp);
+ return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
}
static CORE_ADDR
-mt_frame_base_address (struct frame_info *next_frame,
+mt_frame_base_address (struct frame_info *this_frame,
void **this_prologue_cache)
{
struct mt_unwind_cache *info =
- mt_frame_unwind_cache (next_frame, this_prologue_cache);
+ mt_frame_unwind_cache (this_frame, this_prologue_cache);
return info->frame_base;
}
static const struct frame_unwind mt_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
mt_frame_this_id,
- mt_frame_prev_register
+ mt_frame_prev_register,
+ NULL,
+ default_frame_sniffer
};
-/* The sniffer is a registered function that identifies our family of
- frame unwind functions (this_id and prev_register). */
-
-static const struct frame_unwind *
-mt_frame_sniffer (struct frame_info *next_frame)
-{
- return &mt_frame_unwind;
-}
-
/* Another shared interface: the 'frame_base' object specifies how to
unwind a frame and secure the base addresses for frame objects
(locals, args). */
mt_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
struct gdbarch *gdbarch;
+ struct gdbarch_tdep *tdep;
/* Find a candidate among the list of pre-declared architectures. */
arches = gdbarch_list_lookup_by_info (arches, &info);
/* None found, create a new architecture from the information
provided. */
- gdbarch = gdbarch_alloc (&info, NULL);
+ tdep = XCNEW (struct gdbarch_tdep);
+ gdbarch = gdbarch_alloc (&info, tdep);
- switch (info.byte_order)
- {
- case BFD_ENDIAN_BIG:
- set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_big);
- set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_big);
- set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
- break;
- case BFD_ENDIAN_LITTLE:
- set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little);
- set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_little);
- set_gdbarch_long_double_format (gdbarch,
- &floatformat_ieee_double_little);
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("mt_gdbarch_init: bad byte order for float format"));
- }
+ set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
+ set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
+ set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
set_gdbarch_register_name (gdbarch, mt_register_name);
set_gdbarch_num_regs (gdbarch, MT_NUM_REGS);
/* Register the DWARF 2 sniffer first, and then the traditional prologue
based sniffer. */
- frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
- frame_unwind_append_sniffer (gdbarch, mt_frame_sniffer);
+ dwarf2_append_unwinders (gdbarch);
+ frame_unwind_append_unwinder (gdbarch, &mt_frame_unwind);
frame_base_set_default (gdbarch, &mt_frame_base);
/* Register the 'unwind_pc' method. */
set_gdbarch_unwind_pc (gdbarch, mt_unwind_pc);
set_gdbarch_unwind_sp (gdbarch, mt_unwind_sp);
- /* Methods for saving / extracting a dummy frame's ID.
+ /* Methods for saving / extracting a dummy frame's ID.
The ID's stack address must match the SP value returned by
PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos. */
- set_gdbarch_unwind_dummy_id (gdbarch, mt_unwind_dummy_id);
+ set_gdbarch_dummy_id (gdbarch, mt_dummy_id);
return gdbarch;
}
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern initialize_file_ftype _initialize_mt_tdep;
+
void
_initialize_mt_tdep (void)
{