+\f
+/* Examine an m88k function prologue, recording the addresses at which
+ registers are saved explicitly by the prologue code, and returning
+ the address of the first instruction after the prologue (but not
+ after the instruction at address LIMIT, as explained below).
+
+ LIMIT places an upper bound on addresses of the instructions to be
+ examined. If the prologue code scan reaches LIMIT, the scan is
+ aborted and LIMIT is returned. This is used, when examining the
+ prologue for the current frame, to keep examine_prologue () from
+ claiming that a given register has been saved when in fact the
+ instruction that saves it has not yet been executed. LIMIT is used
+ at other times to stop the scan when we hit code after the true
+ function prologue (e.g. for the first source line) which might
+ otherwise be mistaken for function prologue.
+
+ The format of the function prologue matched by this routine is
+ derived from examination of the source to gcc 1.95, particularly
+ the routine output_prologue () in config/out-m88k.c.
+
+ subu r31,r31,n # stack pointer update
+
+ (st rn,r31,offset)? # save incoming regs
+ (st.d rn,r31,offset)?
+
+ (addu r30,r31,n)? # frame pointer update
+
+ (pic sequence)? # PIC code prologue
+
+ (or rn,rm,0)? # Move parameters to other regs
+ */
+
+/* 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))
+
+/*
+ * prologue_insn_tbl is a table of instructions which may comprise a
+ * function prologue. Associated with each table entry (corresponding
+ * to a single instruction or group of instructions), is an action.
+ * This action is used by examine_prologue (below) to determine
+ * the state of certain machine registers and where the stack frame lives.
+ */
+
+enum prologue_insn_action
+{
+ PIA_SKIP, /* don't care what the instruction does */
+ PIA_NOTE_ST, /* note register stored and where */
+ PIA_NOTE_STD, /* note pair of registers stored and where */
+ PIA_NOTE_SP_ADJUSTMENT, /* note stack pointer adjustment */
+ PIA_NOTE_FP_ASSIGNMENT, /* note frame pointer assignment */
+ PIA_NOTE_PROLOGUE_END, /* no more prologue */
+};
+
+struct prologue_insns
+ {
+ unsigned long insn;
+ unsigned long mask;
+ enum prologue_insn_action action;
+ };
+
+struct prologue_insns prologue_insn_tbl[] =
+{
+ /* Various register move instructions */
+ {0x58000000, 0xf800ffff, PIA_SKIP}, /* or/or.u with immed of 0 */
+ {0xf4005800, 0xfc1fffe0, PIA_SKIP}, /* or rd, r0, rs */
+ {0xf4005800, 0xfc00ffff, PIA_SKIP}, /* or rd, rs, r0 */
+
+ /* Stack pointer setup: "subu sp, sp, n" where n is a multiple of 8 */
+ {0x67ff0000, 0xffff0007, PIA_NOTE_SP_ADJUSTMENT},
+
+ /* Frame pointer assignment: "addu r30, r31, n" */
+ {0x63df0000, 0xffff0000, PIA_NOTE_FP_ASSIGNMENT},
+
+ /* Store to stack instructions; either "st rx, sp, n" or "st.d rx, sp, n" */
+ {0x241f0000, 0xfc1f0000, PIA_NOTE_ST}, /* st rx, sp, n */
+ {0x201f0000, 0xfc1f0000, PIA_NOTE_STD}, /* st.d rs, sp, n */
+
+ /* Instructions needed for setting up r25 for pic code. */
+ {0x5f200000, 0xffff0000, PIA_SKIP}, /* or.u r25, r0, offset_high */
+ {0xcc000002, 0xffffffff, PIA_SKIP}, /* bsr.n Lab */
+ {0x5b390000, 0xffff0000, PIA_SKIP}, /* or r25, r25, offset_low */
+ {0xf7396001, 0xffffffff, PIA_SKIP}, /* Lab: addu r25, r25, r1 */