+ /* Save SP and FP. */
+ this_cache->base = sp + sp_offset;
+ this_cache->fp = fp;
+
+ /* Don't forget to free MEMBLOCK if we allocated it. */
+ if (memblock_ptr != NULL)
+ score7_free_memblock (memblock_ptr);
+}
+
+static void
+score3_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc,
+ struct frame_info *this_frame,
+ struct score_frame_cache *this_cache)
+{
+ CORE_ADDR sp;
+ CORE_ADDR fp;
+ CORE_ADDR cur_pc = startaddr;
+ enum bfd_endian byte_order = gdbarch_byte_order (get_frame_arch (this_frame));
+
+ int sp_offset = 0;
+ int ra_offset = 0;
+ int fp_offset = 0;
+ int ra_offset_p = 0;
+ int fp_offset_p = 0;
+ int inst_len = 0;
+
+ CORE_ADDR prev_pc = -1;
+
+ sp = get_frame_register_unsigned (this_frame, SCORE_SP_REGNUM);
+ fp = get_frame_register_unsigned (this_frame, SCORE_FP_REGNUM);
+
+ for (; cur_pc < pc; prev_pc = cur_pc, cur_pc += inst_len)
+ {
+ inst_t *inst = NULL;
+
+ inst = score3_adjust_pc_and_fetch_inst (&cur_pc, &inst_len, byte_order);
+
+ /* FIXME: make a full-power prologue analyzer */
+ if (inst->len == 2)
+ {
+ if (G_FLD (inst->v, 14, 12) == 0x0
+ && G_FLD (inst->v, 11, 7) == 0x0
+ && G_FLD (inst->v, 6, 5) == 0x3)
+ {
+ /* push! */
+ sp_offset += 4;
+
+ if (G_FLD (inst->v, 4, 0) == 0x3
+ && ra_offset_p == 0)
+ {
+ /* push! r3, [r0] */
+ ra_offset = sp_offset;
+ ra_offset_p = 1;
+ }
+ else if (G_FLD (inst->v, 4, 0) == 0x2
+ && fp_offset_p == 0)
+ {
+ /* push! r2, [r0] */
+ fp_offset = sp_offset;
+ fp_offset_p = 1;
+ }
+ }
+ else if (G_FLD (inst->v, 14, 12) == 0x6
+ && G_FLD (inst->v, 11, 10) == 0x3)
+ {
+ /* rpush! */
+ int start_r = G_FLD (inst->v, 9, 5);
+ int cnt = G_FLD (inst->v, 4, 0);
+
+ if ((ra_offset_p == 0)
+ && (start_r <= SCORE_RA_REGNUM)
+ && (SCORE_RA_REGNUM < start_r + cnt))
+ {
+ /* rpush! contains r3 */
+ ra_offset_p = 1;
+ ra_offset = sp_offset + 4 * (SCORE_RA_REGNUM - start_r) + 4;
+ }
+
+ if ((fp_offset_p == 0)
+ && (start_r <= SCORE_FP_REGNUM)
+ && (SCORE_FP_REGNUM < start_r + cnt))
+ {
+ /* rpush! contains r2 */
+ fp_offset_p = 1;
+ fp_offset = sp_offset + 4 * (SCORE_FP_REGNUM - start_r) + 4;
+ }
+
+ sp_offset += 4 * cnt;
+ }
+ else if (G_FLD (inst->v, 14, 12) == 0x0
+ && G_FLD (inst->v, 11, 7) == 0x0
+ && G_FLD (inst->v, 6, 5) == 0x2)
+ {
+ /* pop! */
+ sp_offset -= 4;
+ }
+ else if (G_FLD (inst->v, 14, 12) == 0x6
+ && G_FLD (inst->v, 11, 10) == 0x2)
+ {
+ /* rpop! */
+ sp_offset -= 4 * G_FLD (inst->v, 4, 0);
+ }
+ else if (G_FLD (inst->v, 14, 12) == 0x5
+ && G_FLD (inst->v, 11, 10) == 0x3
+ && G_FLD (inst->v, 9, 6) == 0x0)
+ {
+ /* addi! r0, -offset */
+ int imm = G_FLD (inst->v, 5, 0);
+ if (imm >> 5)
+ imm = -(0x3F - imm + 1);
+ sp_offset -= imm;
+ }
+ else if (G_FLD (inst->v, 14, 12) == 0x5
+ && G_FLD (inst->v, 11, 10) == 0x3
+ && G_FLD (inst->v, 9, 6) == 0x2)
+ {
+ /* addi! r2, offset */
+ if (pc - cur_pc >= 2)
+ {
+ unsigned int save_v = inst->v;
+ inst_t *inst2;
+
+ cur_pc += inst->len;
+ inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL, byte_order);
+
+ if (inst2->len == 2
+ && G_FLD (inst2->v, 14, 10) == 0x10
+ && G_FLD (inst2->v, 9, 5) == 0x0
+ && G_FLD (inst2->v, 4, 0) == 0x2)
+ {
+ /* mv! r0, r2 */
+ int imm = G_FLD (inst->v, 5, 0);
+ if (imm >> 5)
+ imm = -(0x3F - imm + 1);
+ sp_offset -= imm;
+ }
+ }
+ }
+ }
+ else if (inst->len == 4)
+ {
+ if (G_FLD (inst->v, 29, 25) == 0x3
+ && G_FLD (inst->v, 2, 0) == 0x4
+ && G_FLD (inst->v, 24, 20) == 0x3
+ && G_FLD (inst->v, 19, 15) == 0x0)
+ {
+ /* sw r3, [r0, offset]+ */
+ sp_offset += inst->len;
+ if (ra_offset_p == 0)
+ {
+ ra_offset = sp_offset;
+ ra_offset_p = 1;
+ }
+ }
+ else if (G_FLD (inst->v, 29, 25) == 0x3
+ && G_FLD (inst->v, 2, 0) == 0x4
+ && G_FLD (inst->v, 24, 20) == 0x2
+ && G_FLD (inst->v, 19, 15) == 0x0)
+ {
+ /* sw r2, [r0, offset]+ */
+ sp_offset += inst->len;
+ if (fp_offset_p == 0)
+ {
+ fp_offset = sp_offset;
+ fp_offset_p = 1;
+ }
+ }
+ else if (G_FLD (inst->v, 29, 25) == 0x7
+ && G_FLD (inst->v, 2, 0) == 0x0
+ && G_FLD (inst->v, 24, 20) == 0x3
+ && G_FLD (inst->v, 19, 15) == 0x0)
+ {
+ /* lw r3, [r0]+, 4 */
+ sp_offset -= inst->len;
+ ra_offset_p = 1;
+ }
+ else if (G_FLD (inst->v, 29, 25) == 0x7
+ && G_FLD (inst->v, 2, 0) == 0x0
+ && G_FLD (inst->v, 24, 20) == 0x2
+ && G_FLD (inst->v, 19, 15) == 0x0)
+ {
+ /* lw r2, [r0]+, 4 */
+ sp_offset -= inst->len;
+ fp_offset_p = 1;
+ }
+ else if (G_FLD (inst->v, 29, 25) == 0x1
+ && G_FLD (inst->v, 19, 17) == 0x0
+ && G_FLD (inst->v, 24, 20) == 0x0
+ && G_FLD (inst->v, 0, 0) == 0x0)
+ {
+ /* addi r0, -offset */
+ int imm = G_FLD (inst->v, 16, 1);
+ if (imm >> 15)
+ imm = -(0xFFFF - imm + 1);
+ sp_offset -= imm;
+ }
+ else if (G_FLD (inst->v, 29, 25) == 0x1
+ && G_FLD (inst->v, 19, 17) == 0x0
+ && G_FLD (inst->v, 24, 20) == 0x2
+ && G_FLD (inst->v, 0, 0) == 0x0)
+ {
+ /* addi r2, offset */
+ if (pc - cur_pc >= 2)
+ {
+ unsigned int save_v = inst->v;
+ inst_t *inst2;
+
+ cur_pc += inst->len;
+ inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL, byte_order);
+
+ if (inst2->len == 2
+ && G_FLD (inst2->v, 14, 10) == 0x10
+ && G_FLD (inst2->v, 9, 5) == 0x0
+ && G_FLD (inst2->v, 4, 0) == 0x2)
+ {
+ /* mv! r0, r2 */
+ int imm = G_FLD (inst->v, 16, 1);
+ if (imm >> 15)
+ imm = -(0xFFFF - imm + 1);
+ sp_offset -= imm;
+ }
+ }
+ }
+ }
+ }
+
+ /* Save RA. */
+ if (ra_offset_p == 1)
+ {
+ if (this_cache->saved_regs[SCORE_PC_REGNUM].addr == -1)
+ this_cache->saved_regs[SCORE_PC_REGNUM].addr =
+ sp + sp_offset - ra_offset;
+ }
+ else
+ {
+ this_cache->saved_regs[SCORE_PC_REGNUM] =
+ this_cache->saved_regs[SCORE_RA_REGNUM];
+ }
+
+ /* Save FP. */
+ if (fp_offset_p == 1)
+ {
+ if (this_cache->saved_regs[SCORE_FP_REGNUM].addr == -1)
+ this_cache->saved_regs[SCORE_FP_REGNUM].addr =
+ sp + sp_offset - fp_offset;
+ }
+
+ /* Save SP and FP. */
+ this_cache->base = sp + sp_offset;
+ this_cache->fp = fp;