+static CORE_ADDR
+m88k_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,
+ CORE_ADDR struct_addr)
+{
+ /* Set up the function arguments. */
+ sp = m88k_store_arguments (regcache, nargs, args, sp);
+ gdb_assert (sp % 16 == 0);
+
+ /* Store return value address. */
+ if (struct_return)
+ regcache_raw_write_unsigned (regcache, M88K_R12_REGNUM, struct_addr);
+
+ /* Store the stack pointer and return address in the appropriate
+ registers. */
+ regcache_raw_write_unsigned (regcache, M88K_R31_REGNUM, sp);
+ regcache_raw_write_unsigned (regcache, M88K_R1_REGNUM, bp_addr);
+
+ /* Return the stack pointer. */
+ return sp;
+}
+
+static struct frame_id
+m88k_unwind_dummy_id (struct gdbarch *arch, struct frame_info *next_frame)
+{
+ CORE_ADDR sp;
+
+ sp = frame_unwind_register_unsigned (next_frame, M88K_R31_REGNUM);
+ return frame_id_build (sp, frame_pc_unwind (next_frame));
+}
+\f
+
+/* Determine, for architecture GDBARCH, how a return value of TYPE
+ should be returned. If it is supposed to be returned in registers,
+ and READBUF is non-zero, read the appropriate value from REGCACHE,
+ and copy it into READBUF. If WRITEBUF is non-zero, write the value
+ from WRITEBUF into REGCACHE. */
+
+static enum return_value_convention
+m88k_return_value (struct gdbarch *gdbarch, struct type *type,
+ struct regcache *regcache, void *readbuf,
+ const void *writebuf)
+{
+ int len = TYPE_LENGTH (type);
+ char buf[8];
+
+ if (!m88k_integral_or_pointer_p (type) && !m88k_floating_p (type))
+ return RETURN_VALUE_STRUCT_CONVENTION;
+
+ if (readbuf)
+ {
+ /* Read the contents of R2 and (if necessary) R3. */
+ regcache_cooked_read (regcache, M88K_R2_REGNUM, buf);
+ if (len > 4)
+ {
+ regcache_cooked_read (regcache, M88K_R3_REGNUM, buf + 4);
+ gdb_assert (len == 8);
+ memcpy (readbuf, buf, len);
+ }
+ else
+ {
+ /* Just stripping off any unused bytes should preserve the
+ signed-ness just fine. */
+ memcpy (readbuf, buf + 4 - len, len);
+ }
+ }
+
+ if (writebuf)
+ {
+ /* Read the contents to R2 and (if necessary) R3. */
+ if (len > 4)
+ {
+ gdb_assert (len == 8);
+ memcpy (buf, writebuf, 8);
+ regcache_cooked_write (regcache, M88K_R3_REGNUM, buf + 4);
+ }
+ else
+ {
+ /* ??? Do we need to do any sign-extension here? */
+ memcpy (buf + 4 - len, writebuf, len);
+ }
+ regcache_cooked_write (regcache, M88K_R2_REGNUM, buf);
+ }
+
+ return RETURN_VALUE_REGISTER_CONVENTION;
+}
+\f
+/* Default frame unwinder. */
+
+struct m88k_frame_cache
+{
+ /* Base address. */
+ CORE_ADDR base;
+ CORE_ADDR pc;
+
+ int sp_offset;
+ int fp_offset;
+
+ /* Table of saved registers. */
+ struct trad_frame_saved_reg *saved_regs;
+};
+
+/* Prologue analysis. */
+
+/* Macros for extracting fields from instructions. */
+
+#define BITMASK(pos, width) (((0x1 << (width)) - 1) << (pos))
+#define EXTRACT_FIELD(val, pos, width) ((val) >> (pos) & BITMASK (0, width))
+#define SUBU_OFFSET(x) ((unsigned)(x & 0xFFFF))
+#define ST_OFFSET(x) ((unsigned)((x) & 0xFFFF))
+#define ST_SRC(x) EXTRACT_FIELD ((x), 21, 5)
+#define ADDU_OFFSET(x) ((unsigned)(x & 0xFFFF))
+
+/* Possible actions to be taken by the prologue analyzer for the
+ instructions it encounters. */
+
+enum m88k_prologue_insn_action
+{
+ M88K_PIA_SKIP, /* Ignore. */
+ M88K_PIA_NOTE_ST, /* Note register store. */
+ M88K_PIA_NOTE_STD, /* Note register pair store. */
+ M88K_PIA_NOTE_SP_ADJUSTMENT, /* Note stack pointer adjustment. */
+ M88K_PIA_NOTE_FP_ASSIGNMENT, /* Note frame pointer assignment. */
+ M88K_PIA_NOTE_BRANCH, /* Note branch. */
+ M88K_PIA_NOTE_PROLOGUE_END /* Note end of prologue. */
+};
+
+/* Table of instructions that may comprise a function prologue. */
+
+struct m88k_prologue_insn
+{
+ unsigned long insn;
+ unsigned long mask;
+ enum m88k_prologue_insn_action action;
+};
+
+struct m88k_prologue_insn m88k_prologue_insn_table[] =
+{
+ /* Various register move instructions. */
+ { 0x58000000, 0xf800ffff, M88K_PIA_SKIP }, /* or/or.u with immed of 0 */
+ { 0xf4005800, 0xfc1fffe0, M88K_PIA_SKIP }, /* or rd,r0,rs */
+ { 0xf4005800, 0xfc00ffff, M88K_PIA_SKIP }, /* or rd,rs,r0 */
+
+ /* Various other instructions. */
+ { 0x58000000, 0xf8000000, M88K_PIA_SKIP }, /* or/or.u */
+
+ /* Stack pointer setup: "subu sp,sp,n" where n is a multiple of 8. */
+ { 0x67ff0000, 0xffff0007, M88K_PIA_NOTE_SP_ADJUSTMENT },
+
+ /* Frame pointer assignment: "addu r30,r31,n". */
+ { 0x63df0000, 0xffff0000, M88K_PIA_NOTE_FP_ASSIGNMENT },
+
+ /* Store to stack instructions; either "st rx,sp,n" or "st.d rx,sp,n". */
+ { 0x241f0000, 0xfc1f0000, M88K_PIA_NOTE_ST }, /* st rx,sp,n */
+ { 0x201f0000, 0xfc1f0000, M88K_PIA_NOTE_STD }, /* st.d rs,sp,n */
+
+ /* Instructions needed for setting up r25 for pic code. */
+ { 0x5f200000, 0xffff0000, M88K_PIA_SKIP }, /* or.u r25,r0,offset_high */
+ { 0xcc000002, 0xffffffff, M88K_PIA_SKIP }, /* bsr.n Lab */
+ { 0x5b390000, 0xffff0000, M88K_PIA_SKIP }, /* or r25,r25,offset_low */
+ { 0xf7396001, 0xffffffff, M88K_PIA_SKIP }, /* Lab: addu r25,r25,r1 */
+
+ /* Various branch or jump instructions which have a delay slot --
+ these do not form part of the prologue, but the instruction in
+ the delay slot might be a store instruction which should be
+ noted. */
+ { 0xc4000000, 0xe4000000, M88K_PIA_NOTE_BRANCH },
+ /* br.n, bsr.n, bb0.n, or bb1.n */
+ { 0xec000000, 0xfc000000, M88K_PIA_NOTE_BRANCH }, /* bcnd.n */
+ { 0xf400c400, 0xfffff7e0, M88K_PIA_NOTE_BRANCH }, /* jmp.n or jsr.n */
+
+ /* Catch all. Ends prologue analysis. */
+ { 0x00000000, 0x00000000, M88K_PIA_NOTE_PROLOGUE_END }
+};
+
+/* Do a full analysis of the function prologue at PC and update CACHE
+ accordingly. Bail out early if LIMIT is reached. Return the
+ address where the analysis stopped. If LIMIT points beyond the
+ function prologue, the return address should be the end of the