-static CORE_ADDR
-h8300_skip_prologue (CORE_ADDR start_pc)
-{
- short int w;
- int adjust = 0;
-
- /* Skip past all push and stm insns. */
- while (1)
- {
- w = read_memory_unsigned_integer (start_pc, 2);
- /* First look for push insns. */
- if (w == 0x0100 || w == 0x0110 || w == 0x0120 || w == 0x0130)
- {
- w = read_memory_unsigned_integer (start_pc + 2, 2);
- adjust = 2;
- }
-
- if (IS_PUSH (w))
- {
- start_pc += 2 + adjust;
- w = read_memory_unsigned_integer (start_pc, 2);
- continue;
- }
- adjust = 0;
- break;
- }
-
- /* Skip past a move to FP, either word or long sized */
- w = read_memory_unsigned_integer (start_pc, 2);
- if (w == 0x0100)
- {
- w = read_memory_unsigned_integer (start_pc + 2, 2);
- adjust += 2;
- }
-
- if (IS_MOVE_FP (w))
- {
- start_pc += 2 + adjust;
- w = read_memory_unsigned_integer (start_pc, 2);
- }
-
- /* Check for loading either a word constant into r5;
- long versions are handled by the SUBL_SP below. */
- if (IS_MOVK_R5 (w))
- {
- start_pc += 2;
- w = read_memory_unsigned_integer (start_pc, 2);
- }
-
- /* Now check for subtracting r5 from sp, word sized only. */
- if (IS_SUB_R5SP (w))
- {
- start_pc += 2 + adjust;
- w = read_memory_unsigned_integer (start_pc, 2);
- }
-
- /* Check for subs #2 and subs #4. */
- while (IS_SUB2_SP (w) || IS_SUB4_SP (w))
- {
- start_pc += 2 + adjust;
- w = read_memory_unsigned_integer (start_pc, 2);
- }
-
- /* Check for a 32bit subtract. */
- if (IS_SUBL_SP (w))
- start_pc += 6 + adjust;
-
- /* Skip past another possible stm insn for registers R3 to R5 (possibly used
- for register qualified arguments. */
- w = read_memory_unsigned_integer (start_pc, 2);
- /* First look for push insns. */
- if (w == 0x0110 || w == 0x0120 || w == 0x0130)
- {
- w = read_memory_unsigned_integer (start_pc + 2, 2);
- if (IS_PUSH (w) && (w & 0xf) >= 0x3 && (w & 0xf) <= 0x5)
- start_pc += 4;
- }
-
- /* Check for spilling an argument register to the stack frame.
- This could also be an initializing store from non-prologue code,
- but I don't think there's any harm in skipping that. */
- for (;;)
- {
- int spill_size = h8300_is_argument_spill (start_pc);
- if (spill_size == 0)
- break;
- start_pc += spill_size;
- }
-
- return start_pc;
-}
-
-static CORE_ADDR
-h8300_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
- char buf[8];
-
- frame_unwind_register (next_frame, E_PC_REGNUM, buf);
- return extract_typed_address (buf, builtin_type_void_func_ptr);
-}
-
-static struct frame_id
-h8300_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
- char buf[4];
- CORE_ADDR fp;
-
- frame_unwind_register (next_frame, E_FP_REGNUM, buf);
- fp = extract_unsigned_integer (buf, 4);
-
- return frame_id_build (fp, frame_pc_unwind (next_frame));
-}
-
-struct h8300_frame_cache
-{
- /* Base address. */
- CORE_ADDR base;
- CORE_ADDR sp_offset;
- CORE_ADDR pc;
-
- /* Saved registers. */
- CORE_ADDR saved_regs[H8300_MAX_NUM_REGS];
- CORE_ADDR saved_sp;
-
- /* Stack space reserved for local variables. */
- long locals;
-};
-
-/* Normal frames. */
-
-/* Allocate and initialize a frame cache. */
-
-static struct h8300_frame_cache *
-h8300_alloc_frame_cache (void)
-{
- struct h8300_frame_cache *cache;
- int i;
-
- cache = FRAME_OBSTACK_ZALLOC (struct h8300_frame_cache);
-
- /* Base address. */
- cache->base = 0;
- cache->sp_offset = -4;
- cache->pc = 0;
-
- /* Saved registers. We initialize these to -1 since zero is a valid
- offset (that's where %fp is supposed to be stored). */
- for (i = 0; i < NUM_REGS; i++)
- cache->saved_regs[i] = -1;
-
- /* Frameless until proven otherwise. */
- cache->locals = -1;
-
- return cache;
-}
-
-/* Check whether PC points at a code that sets up a new stack frame.
- If so, it updates CACHE and returns the address of the first
- instruction after the sequence that sets removes the "hidden"
- argument from the stack or CURRENT_PC, whichever is smaller.
- Otherwise, return PC. */
-
-static CORE_ADDR
-h8300_analyze_frame_setup (CORE_ADDR pc, CORE_ADDR current_pc,
- struct h8300_frame_cache *cache)
-{
- unsigned int op;
- int subs_count;
-
- if (pc >= current_pc)
- return current_pc;
-
- op = read_memory_unsigned_integer (pc, 4);
-
- if (op == 0x6df60d76)
- {
- /* mov.w r6,@-sp; mov.w sp,r6 */
- cache->saved_regs[E_FP_REGNUM] = 0;
- cache->sp_offset += 2;
- op = read_memory_unsigned_integer (pc + 4, 4);
- if (((op >> 16) & 0xfff0) == 0x7900)
- {
- /* mov.w #imm,rN */
- cache->locals = -(short) (op & 0xffff);
- return pc + 8;
- }
- else if ((op >> 16) == 0x1b87)
- {
- /* subs #2,sp */
- for (cache->locals = 0, pc += 4;
- read_memory_unsigned_integer (pc, 2) == 0x1b87;
- pc += 2, cache->locals += 2);
- return pc;
- }
- }
- else if (op == 0x01006df6)
- {
- /* mov.l er6,@-sp */
- op = read_memory_unsigned_integer (pc + 4, 2);
- if (op == 0x0ff6)
- {
- /* mov.l sp,er6 */
- op = read_memory_unsigned_integer (pc + 6, 2);
- if (op == 0x7a17)
- {
- /* add.l #-n,sp */
- cache->locals = -read_memory_unsigned_integer (pc + 8, 4);
- return pc + 12;
- }
- else if (op == 0x1b97)
- {
- /* subs #4,sp */
- for (cache->locals = 0, pc += 6;
- read_memory_unsigned_integer (pc, 2) == 0x1b97;
- pc += 2, cache->locals += 2);
- return pc;
- }
- }
- }
-
- return pc;
-}
-
-/* Check whether PC points at code that saves registers on the stack.
- If so, it updates CACHE and returns the address of the first
- instruction after the register saves or CURRENT_PC, whichever is
- smaller. Otherwise, return PC. */
-
-static CORE_ADDR
-h8300_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
- struct h8300_frame_cache *cache)
-{
- if (cache->locals >= 0)
- {
- CORE_ADDR offset;
- int op;
- int i, regno;
-
- offset = -cache->locals;
- while (pc < current_pc)
- {
- op = read_memory_unsigned_integer (pc, 2);
- if ((op & 0xfff0) == 0x6df0)
- {
- /* mov.w rN,@-sp */
- regno = op & 0x000f;
- cache->saved_regs[regno] = offset;
- offset -= 2;
- pc += 2;
- }
- else if (op == 0x0100)
- {
- op = read_memory_unsigned_integer (pc + 2, 2);
- if ((op & 0xfff0) == 0x6df0)
- {
- /* mov.l erN,@-sp */
- regno = op & 0x000f;
- cache->saved_regs[regno] = offset;
- offset -= 4;
- pc += 4;
- }
- else
- break;
- }
- else if ((op & 0xffcf) == 0x0100)
- {
- int op1;
- op1 = read_memory_unsigned_integer (pc + 2, 2);
- if ((op1 & 0xfff0) == 0x6df0)
- {
- /* stm.l reglist,@-sp */
- i = ((op & 0x0030) >> 4) + 1;
- regno = op1 & 0x000f;
- for (; i > 0; regno++, --i)
- {
- cache->saved_regs[regno] = offset;
- offset -= 4;
- }
- pc += 4;
- }
- else
- break;
- }
- else
- break;
- }
- }
- return pc;
-}
-
-