int deferred_stores = 0; /* Cumulates stores we want to do eventually. */
+/* Some machines, such as Fujitsu SPARClite 86x, have a bi-endian mode
+ where instructions are big-endian and data are little-endian.
+ This flag is set when we detect that the target is of this type. */
+
+int bi_endian = 0;
+
+
/* Fetch a single instruction. Even on bi-endian machines
such as sparc86x, instructions are always big-endian. */
typedef char binsn_quantum[BREAKPOINT_MAX];
static binsn_quantum break_mem[3];
-/* Non-zero if we just simulated a single-step ptrace call. This is
- needed because we cannot remove the breakpoints in the inferior
- process until after the `wait' in `wait_for_inferior'. Used for
- sun4. */
-
-int one_stepped;
-
static branch_type isbranch PARAMS ((long, CORE_ADDR, CORE_ADDR *));
/* single_step() is called just before we want to resume the inferior,
set up a simulated single-step, we undo our damage. */
void
-single_step (ignore)
+sparc_software_single_step (ignore, insert_breakpoints_p)
enum target_signal ignore; /* pid, but we don't need it */
+ int insert_breakpoints_p;
{
branch_type br;
CORE_ADDR pc;
long pc_instruction;
- if (!one_stepped)
+ if (insert_breakpoints_p)
{
/* Always set breakpoint for NPC. */
next_pc = read_register (NPC_REGNUM);
target_insert_breakpoint (target, break_mem[2]);
}
#endif
-
- /* We are ready to let it go */
- one_stepped = 1;
- return;
}
else
{
if (brktrg)
target_remove_breakpoint (target, break_mem[2]);
-
- one_stepped = 0;
}
}
\f
struct frame_info *fi;
{
char *name;
- CORE_ADDR addr;
+ CORE_ADDR prologue_start, prologue_end;
int insn;
fi->bottom =
/* Decide whether this is a function with a ``flat register window''
frame. For such functions, the frame pointer is actually in %i7. */
fi->flat = 0;
- if (find_pc_partial_function (fi->pc, &name, &addr, NULL))
+ fi->in_prologue = 0;
+ if (find_pc_partial_function (fi->pc, &name, &prologue_start, &prologue_end))
{
/* See if the function starts with an add (which will be of a
negative number if a flat frame) to the sp. FIXME: Does not
handle large frames which will need more than one instruction
to adjust the sp. */
- insn = fetch_instruction (addr);
+ insn = fetch_instruction (prologue_start, 4);
if (X_OP (insn) == 2 && X_RD (insn) == 14 && X_OP3 (insn) == 0
&& X_I (insn) && X_SIMM13 (insn) < 0)
{
int offset = X_SIMM13 (insn);
/* Then look for a save of %i7 into the frame. */
- insn = fetch_instruction (addr + 4);
+ insn = fetch_instruction (prologue_start + 4);
if (X_OP (insn) == 3
&& X_RD (insn) == 31
&& X_OP3 (insn) == 4
/* Also try to collect where the pc got saved to. */
fi->pc_addr = 0;
- insn = fetch_instruction (addr + 12);
+ insn = fetch_instruction (prologue_start + 12);
if (X_OP (insn) == 3
&& X_RD (insn) == 15
&& X_OP3 (insn) == 4
fi->pc_addr = fi->frame + fi->sp_offset + X_SIMM13 (insn);
}
}
+ else
+ {
+ /* Check if the PC is in the function prologue before a SAVE
+ instruction has been executed yet. If so, set the frame
+ to the current value of the stack pointer and set
+ the in_prologue flag. */
+ CORE_ADDR addr;
+ struct symtab_and_line sal;
+
+ sal = find_pc_line (prologue_start, 0);
+ if (sal.line == 0) /* no line info, use PC */
+ prologue_end = fi->pc;
+ else if (sal.end < prologue_end)
+ prologue_end = sal.end;
+ if (fi->pc < prologue_end)
+ {
+ for (addr = prologue_start; addr < fi->pc; addr += 4)
+ {
+ insn = read_memory_integer (addr, 4);
+ if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3c)
+ break; /* SAVE seen, stop searching */
+ }
+ if (addr >= fi->pc)
+ {
+ fi->in_prologue = 1;
+ fi->frame = read_register (SP_REGNUM);
+ }
+ }
+ }
}
if (fi->next && fi->frame == 0)
{
sparc_extract_struct_value_address (regbuf)
char regbuf[REGISTER_BYTES];
{
-#ifdef GDB_TARGET_IS_SPARC64
return extract_address (regbuf + REGISTER_BYTE (O0_REGNUM),
REGISTER_RAW_SIZE (O0_REGNUM));
-#else
- CORE_ADDR sp = extract_address (®buf [REGISTER_BYTE (SP_REGNUM)],
- REGISTER_RAW_SIZE (SP_REGNUM));
- return read_memory_integer (sp + (16 * SPARC_INTREG_SIZE),
- TARGET_PTR_BIT / TARGET_CHAR_BIT);
-#endif
}
/* Find the pc saved in frame FRAME. */
scbuf, sizeof (scbuf));
return extract_address (scbuf, sizeof (scbuf));
}
- else if (frame->next != NULL
- && (frame->next->signal_handler_caller
- || frame_in_dummy (frame->next))
- && frameless_look_for_prologue (frame))
+ else if (frame->in_prologue ||
+ (frame->next != NULL
+ && (frame->next->signal_handler_caller
+ || frame_in_dummy (frame->next))
+ && frameless_look_for_prologue (frame)))
{
/* A frameless function interrupted by a signal did not save
the PC, it is still in %o7. */
}
CORE_ADDR
-skip_prologue (start_pc, frameless_p)
+sparc_skip_prologue (start_pc, frameless_p)
CORE_ADDR start_pc;
int frameless_p;
{
The argument RAW_BUFFER must point to aligned memory. */
void
-get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+sparc_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
char *raw_buffer;
int *optimized;
CORE_ADDR *addrp;
else
memcpy (valbuf,
®buf [O0_REGNUM * regsize +
- (typelen >= regsize ? 0 : regsize - typelen)],
+ (typelen >= regsize
+ || TARGET_BYTE_ORDER == LITTLE_ENDIAN ? 0
+ : regsize - typelen)],
typelen);
}
}
-/* Insert the function address into a call dummy instsruction sequence
+/* Insert the function address into a call dummy instruction sequence
stored at DUMMY.
For structs and unions, if the function was compiled with Sun cc,
store_unsigned_integer (dummy + (i * 4), 4, 0x01000000);
}
#endif
+
+ /* If this is a bi-endian target, GDB has written the call dummy
+ in little-endian order. We must byte-swap it back to big-endian. */
+ if (bi_endian)
+ {
+ for (i = 0; i < CALL_DUMMY_LENGTH; i += 4)
+ {
+ char tmp = dummy [i];
+ dummy [i] = dummy [i+3];
+ dummy [i+3] = tmp;
+ tmp = dummy [i+1];
+ dummy [i+1] = dummy [i+2];
+ dummy [i+2] = tmp;
+ }
+ }
}
int i, j;
if (ap->mach == bfd_mach_sparc_sparclite_le)
- target_byte_order = LITTLE_ENDIAN;
+ {
+ if (TARGET_BYTE_ORDER_SELECTABLE_P)
+ {
+ target_byte_order = LITTLE_ENDIAN;
+ bi_endian = 1;
+ }
+ else
+ {
+ warning ("This GDB does not support little endian sparclite.");
+ }
+ }
+ else
+ bi_endian = 0;
return 1;
}