Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Theodore A. Roth, troth@verinet.com */
+/* Contributed by Theodore A. Roth, troth@openavr.org */
/* Portions of this file were taken from the original gdb-4.18 patch developed
by Denis Chertykov, denisc@overta.ru */
return register_names[regnum];
}
-/* Index within `registers' of the first byte of the space for
- register REGNUM. */
-
-static int
-avr_register_byte (int regnum)
-{
- if (regnum < AVR_PC_REGNUM)
- return regnum;
- else
- return AVR_PC_REG_INDEX;
-}
-
-/* Number of bytes of storage in the actual machine representation for
- register REGNUM. */
-
-static int
-avr_register_raw_size (int regnum)
-{
- switch (regnum)
- {
- case AVR_PC_REGNUM:
- return 4;
- case AVR_SP_REGNUM:
- case AVR_FP_REGNUM:
- return 2;
- default:
- return 1;
- }
-}
-
-/* Number of bytes of storage in the program's representation
- for register N. */
-
-static int
-avr_register_virtual_size (int regnum)
-{
- return TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (regnum));
-}
-
/* Return the GDB type object for the "standard" data type
of data in register N. */
static struct type *
-avr_register_virtual_type (int regnum)
+avr_register_type (struct gdbarch *gdbarch, int reg_nr)
{
- switch (regnum)
- {
- case AVR_PC_REGNUM:
- return builtin_type_unsigned_long;
- case AVR_SP_REGNUM:
- return builtin_type_unsigned_short;
- default:
- return builtin_type_unsigned_char;
- }
+ if (reg_nr == AVR_PC_REGNUM)
+ return builtin_type_uint32;
+ if (reg_nr == AVR_SP_REGNUM)
+ return builtin_type_void_data_ptr;
+ else
+ return builtin_type_uint8;
}
/* Instruction address checks and convertions. */
|| TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD)
{
store_unsigned_integer (buf, TYPE_LENGTH (type),
- avr_convert_iaddr_to_raw (addr));
+ avr_convert_iaddr_to_raw (addr >> 1));
}
else
{
static CORE_ADDR
avr_pointer_to_address (struct type *type, const void *buf)
{
- CORE_ADDR addr = extract_address (buf, TYPE_LENGTH (type));
-
- if (TYPE_CODE_SPACE (TYPE_TARGET_TYPE (type)))
- {
- fprintf_unfiltered (gdb_stderr, "CODE_SPACE ---->> ptr->addr: 0x%lx\n",
- addr);
- fprintf_unfiltered (gdb_stderr,
- "+++ If you see this, please send me an email <troth@verinet.com>\n");
- }
+ CORE_ADDR addr = extract_unsigned_integer (buf, TYPE_LENGTH (type));
/* Is it a code address? */
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
|| TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD
|| TYPE_CODE_SPACE (TYPE_TARGET_TYPE (type)))
- return avr_make_iaddr (addr);
+ return avr_make_iaddr (addr << 1);
else
return avr_make_saddr (addr);
}
static CORE_ADDR
avr_read_fp (void)
{
- return (avr_make_saddr (read_register (AVR_FP_REGNUM)));
-}
-
-/* Translate a GDB virtual ADDR/LEN into a format the remote target
- understands. Returns number of bytes that can be transfered
- starting at TARG_ADDR. Return ZERO if no bytes can be transfered
- (segmentation fault).
-
- TRoth/2002-04-08: Could this be used to check for dereferencing an invalid
- pointer? */
-
-static void
-avr_remote_translate_xfer_address (CORE_ADDR memaddr, int nr_bytes,
- CORE_ADDR *targ_addr, int *targ_len)
-{
- long out_addr;
- long out_len;
+ CORE_ADDR fp;
- /* FIXME: TRoth: Do nothing for now. Will need to examine memaddr at this
- point and see if the high bit are set with the masks that we want. */
+ fp = read_register (AVR_FP_REGNUM);
+ fp += (read_register (AVR_FP_REGNUM+1) << 8);
- *targ_addr = memaddr;
- *targ_len = nr_bytes;
+ return (avr_make_saddr (fp));
}
-/* Function pointers obtained from the target are half of what gdb expects so
- multiply by 2. */
-
-static CORE_ADDR
-avr_convert_from_func_ptr_addr (CORE_ADDR addr)
-{
- return addr * 2;
-}
-
-/* avr_scan_prologue is also used as the frame_init_saved_regs().
+/* avr_scan_prologue is also used as the
+ deprecated_frame_init_saved_regs().
Put here the code to store, into fi->saved_regs, the addresses of
the saved registers of frame described by FRAME_INFO. This
3) the offsets of saved regs
This information is stored in the "extra_info" field of the frame_info.
- A typical AVR function prologue might look like this:
- push rXX
- push r28
- push r29
- in r28,__SP_L__
- in r29,__SP_H__
- sbiw r28,<LOCALS_SIZE>
- in __tmp_reg__,__SREG__
+ Some devices lack the sbiw instruction, so on those replace this:
+ sbiw r28, XX
+ with this:
+ subi r28,lo8(XX)
+ sbci r29,hi8(XX)
+
+ A typical AVR function prologue with a frame pointer might look like this:
+ push rXX ; saved regs
+ ...
+ push r28
+ push r29
+ in r28,__SP_L__
+ in r29,__SP_H__
+ sbiw r28,<LOCALS_SIZE>
+ in __tmp_reg__,__SREG__
+ cli
+ out __SP_H__,r29
+ out __SREG__,__tmp_reg__
+ out __SP_L__,r28
+
+ A typical AVR function prologue without a frame pointer might look like
+ this:
+ push rXX ; saved regs
+ ...
+
+ A main function prologue looks like this:
+ ldi r28,lo8(<RAM_ADDR> - <LOCALS_SIZE>)
+ ldi r29,hi8(<RAM_ADDR> - <LOCALS_SIZE>)
+ out __SP_H__,r29
+ out __SP_L__,r28
+
+ A signal handler prologue looks like this:
+ push __zero_reg__
+ push __tmp_reg__
+ in __tmp_reg__, __SREG__
+ push __tmp_reg__
+ clr __zero_reg__
+ push rXX ; save registers r18:r27, r30:r31
+ ...
+ push r28 ; save frame pointer
+ push r29
+ in r28, __SP_L__
+ in r29, __SP_H__
+ sbiw r28, <LOCALS_SIZE>
+ out __SP_H__, r29
+ out __SP_L__, r28
+
+ A interrupt handler prologue looks like this:
+ sei
+ push __zero_reg__
+ push __tmp_reg__
+ in __tmp_reg__, __SREG__
+ push __tmp_reg__
+ clr __zero_reg__
+ push rXX ; save registers r18:r27, r30:r31
+ ...
+ push r28 ; save frame pointer
+ push r29
+ in r28, __SP_L__
+ in r29, __SP_H__
+ sbiw r28, <LOCALS_SIZE>
cli
- out __SP_L__,r28
- out __SREG__,__tmp_reg__
- out __SP_H__,r29
-
- A `-mcall-prologues' prologue look like this:
- ldi r26,<LOCALS_SIZE>
- ldi r27,<LOCALS_SIZE>/265
- ldi r30,pm_lo8(.L_foo_body)
- ldi r31,pm_hi8(.L_foo_body)
- rjmp __prologue_saves__+RRR
- .L_foo_body: */
+ out __SP_H__, r29
+ sei
+ out __SP_L__, r28
+
+ A `-mcall-prologues' prologue looks like this (Note that the megas use a
+ jmp instead of a rjmp, thus the prologue is one word larger since jmp is a
+ 32 bit insn and rjmp is a 16 bit insn):
+ ldi r26,lo8(<LOCALS_SIZE>)
+ ldi r27,hi8(<LOCALS_SIZE>)
+ ldi r30,pm_lo8(.L_foo_body)
+ ldi r31,pm_hi8(.L_foo_body)
+ rjmp __prologue_saves__+RRR
+ .L_foo_body: */
static void
avr_scan_prologue (struct frame_info *fi)
unsigned char prologue[AVR_MAX_PROLOGUE_SIZE];
int vpc = 0;
- fi->extra_info->framereg = AVR_SP_REGNUM;
+ get_frame_extra_info (fi)->framereg = AVR_SP_REGNUM;
if (find_pc_partial_function
(get_frame_pc (fi), &name, &prologue_start, &prologue_end))
/* Search the prologue looking for instructions that set up the
frame pointer, adjust the stack pointer, and save registers. */
- fi->extra_info->framesize = 0;
- prologue_len = prologue_end - prologue_start;
+ get_frame_extra_info (fi)->framesize = 0;
+ prologue_len = min (prologue_end - prologue_start, AVR_MAX_PROLOGUE_SIZE);
read_memory (prologue_start, prologue, prologue_len);
/* Scanning main()'s prologue
0xcd, 0xbf /* out __SP_L__,r28 */
};
- fi->extra_info->framereg = AVR_FP_REGNUM;
+ get_frame_extra_info (fi)->framereg = AVR_FP_REGNUM;
insn = EXTRACT_INSN (&prologue[vpc]);
/* ldi r28,lo8(<RAM_ADDR> - <LOCALS_SIZE>) */
if ((insn & 0xf0f0) == 0xe0c0)
{
deprecated_update_frame_base_hack (fi, locals);
- fi->extra_info->is_main = 1;
+ get_frame_extra_info (fi)->is_main = 1;
return;
}
}
}
}
- /* Scanning `-mcall-prologues' prologue
- FIXME: mega prologue have a 12 bytes long */
+ /* Scanning `-mcall-prologues' prologue */
- while (prologue_len <= 12) /* I'm use while to avoit many goto's */
+ while (1) /* Using a while to avoid many goto's */
{
int loc_size;
int body_addr;
break;
body_addr |= ((insn & 0xf) | ((insn & 0x0f00) >> 4)) << 8;
- if (body_addr != (prologue_start + 10) / 2)
- break;
-
msymbol = lookup_minimal_symbol ("__prologue_saves__", NULL, NULL);
if (!msymbol)
break;
/* FIXME: prologue for mega have a JMP instead of RJMP */
insn = EXTRACT_INSN (&prologue[vpc + 8]);
/* rjmp __prologue_saves__+RRR */
- if ((insn & 0xf000) != 0xc000)
- break;
+ if ((insn & 0xf000) == 0xc000)
+ {
+ /* Extract PC relative offset from RJMP */
+ i = (insn & 0xfff) | (insn & 0x800 ? (-1 ^ 0xfff) : 0);
+ /* Convert offset to byte addressable mode */
+ i *= 2;
+ /* Destination address */
+ i += prologue_start + 10;
+
+ if (body_addr != (prologue_start + 10) / 2)
+ break;
+ }
+ /* jmp __prologue_saves__+RRR */
+ else if ((insn & 0xfe0e) == 0x940c)
+ {
+ /* Extract absolute PC address from JMP */
+ i = (((insn & 0x1) | ((insn & 0x1f0) >> 3) << 16)
+ | (EXTRACT_INSN (&prologue[vpc + 10]) & 0xffff));
+ /* Convert address to byte addressable mode */
+ i *= 2;
+
+ if (body_addr != (prologue_start + 12)/2)
+ break;
+ }
+ else
+ break;
- /* Extract PC relative offset from RJMP */
- i = (insn & 0xfff) | (insn & 0x800 ? (-1 ^ 0xfff) : 0);
- /* Convert offset to byte addressable mode */
- i *= 2;
- /* Destination address */
- i += vpc + prologue_start + 10;
/* Resovle offset (in words) from __prologue_saves__ symbol.
Which is a pushes count in `-mcall-prologues' mode */
num_pushes = AVR_MAX_PUSHES - (i - SYMBOL_VALUE_ADDRESS (msymbol)) / 2;
from <= AVR_LAST_PUSHED_REGNUM; ++from)
get_frame_saved_regs (fi)[from] = ++i;
}
- fi->extra_info->locals_size = loc_size;
- fi->extra_info->framesize = loc_size + num_pushes;
- fi->extra_info->framereg = AVR_FP_REGNUM;
+ get_frame_extra_info (fi)->locals_size = loc_size;
+ get_frame_extra_info (fi)->framesize = loc_size + num_pushes;
+ get_frame_extra_info (fi)->framereg = AVR_FP_REGNUM;
return;
}
vpc += sizeof (img);
get_frame_saved_regs (fi)[0] = 2;
get_frame_saved_regs (fi)[1] = 1;
- fi->extra_info->framesize += 3;
+ get_frame_extra_info (fi)->framesize += 3;
}
else if (memcmp (img + 1, prologue, sizeof (img) - 1) == 0)
{
vpc += sizeof (img) - 1;
get_frame_saved_regs (fi)[0] = 2;
get_frame_saved_regs (fi)[1] = 1;
- fi->extra_info->framesize += 3;
+ get_frame_extra_info (fi)->framesize += 3;
}
}
{
/* Bits 4-9 contain a mask for registers R0-R32. */
regno = (insn & 0x1f0) >> 4;
- ++fi->extra_info->framesize;
- get_frame_saved_regs (fi)[regno] = fi->extra_info->framesize;
+ ++get_frame_extra_info (fi)->framesize;
+ get_frame_saved_regs (fi)[regno] = get_frame_extra_info (fi)->framesize;
scan_stage = 1;
}
else
if (memcmp (prologue + vpc, img, sizeof (img)) == 0)
{
vpc += 4;
- fi->extra_info->framereg = AVR_FP_REGNUM;
+ get_frame_extra_info (fi)->framereg = AVR_FP_REGNUM;
scan_stage = 2;
}
}
/* Third stage of the prologue scanning. (Really two stages)
Scan for:
sbiw r28,XX or subi r28,lo8(XX)
- sbci r29,hi8(XX)
+ sbci r29,hi8(XX)
in __tmp_reg__,__SREG__
cli
- out __SP_L__,r28
+ out __SP_H__,r29
out __SREG__,__tmp_reg__
- out __SP_H__,r29 */
+ out __SP_L__,r28 */
if (scan_stage == 2 && vpc + 12 <= prologue_len)
{
unsigned char img[] = {
0x0f, 0xb6, /* in r0,0x3f */
0xf8, 0x94, /* cli */
- 0xcd, 0xbf, /* out 0x3d,r28 ; SPL */
+ 0xde, 0xbf, /* out 0x3e,r29 ; SPH */
0x0f, 0xbe, /* out 0x3f,r0 ; SREG */
- 0xde, 0xbf /* out 0x3e,r29 ; SPH */
+ 0xcd, 0xbf /* out 0x3d,r28 ; SPL */
};
unsigned char img_sig[] = {
- 0xcd, 0xbf, /* out 0x3d,r28 ; SPL */
- 0xde, 0xbf /* out 0x3e,r29 ; SPH */
+ 0xde, 0xbf, /* out 0x3e,r29 ; SPH */
+ 0xcd, 0xbf /* out 0x3d,r28 ; SPL */
};
unsigned char img_int[] = {
0xf8, 0x94, /* cli */
- 0xcd, 0xbf, /* out 0x3d,r28 ; SPL */
+ 0xde, 0xbf, /* out 0x3e,r29 ; SPH */
0x78, 0x94, /* sei */
- 0xde, 0xbf /* out 0x3e,r29 ; SPH */
+ 0xcd, 0xbf /* out 0x3d,r28 ; SPL */
};
insn = EXTRACT_INSN (&prologue[vpc]);
}
else
return;
- fi->extra_info->locals_size = locals_size;
- fi->extra_info->framesize += locals_size;
+ get_frame_extra_info (fi)->locals_size = locals_size;
+ get_frame_extra_info (fi)->framesize += locals_size;
}
}
{
int reg;
- if (fi->next)
- deprecated_update_frame_pc_hack (fi, FRAME_SAVED_PC (fi->next));
+ if (get_next_frame (fi))
+ deprecated_update_frame_pc_hack (fi, DEPRECATED_FRAME_SAVED_PC (get_next_frame (fi)));
frame_extra_info_zalloc (fi, sizeof (struct frame_extra_info));
frame_saved_regs_zalloc (fi);
- fi->extra_info->return_pc = 0;
- fi->extra_info->args_pointer = 0;
- fi->extra_info->locals_size = 0;
- fi->extra_info->framereg = 0;
- fi->extra_info->framesize = 0;
- fi->extra_info->is_main = 0;
+ get_frame_extra_info (fi)->return_pc = 0;
+ get_frame_extra_info (fi)->args_pointer = 0;
+ get_frame_extra_info (fi)->locals_size = 0;
+ get_frame_extra_info (fi)->framereg = 0;
+ get_frame_extra_info (fi)->framesize = 0;
+ get_frame_extra_info (fi)->is_main = 0;
avr_scan_prologue (fi);
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), get_frame_base (fi),
get_frame_base (fi)))
{
- /* We need to setup fi->frame here because run_stack_dummy gets it wrong
- by assuming it's always FP. */
+ /* We need to setup fi->frame here because call_function_by_hand
+ gets it wrong by assuming it's always FP. */
deprecated_update_frame_base_hack (fi, deprecated_read_register_dummy (get_frame_pc (fi), get_frame_base (fi),
AVR_PC_REGNUM));
}
- else if (!fi->next) /* this is the innermost frame? */
- deprecated_update_frame_base_hack (fi, read_register (fi->extra_info->framereg));
- else if (fi->extra_info->is_main != 1) /* not the innermost frame, not `main' */
+ else if (!get_next_frame (fi))
+ /* this is the innermost frame? */
+ deprecated_update_frame_base_hack (fi, read_register (get_frame_extra_info (fi)->framereg));
+ else if (get_frame_extra_info (fi)->is_main != 1)
+ /* not the innermost frame, not `main' */
/* If we have an next frame, the callee saved it. */
{
- struct frame_info *next_fi = fi->next;
- if (fi->extra_info->framereg == AVR_SP_REGNUM)
- deprecated_update_frame_base_hack (fi, get_frame_base (next_fi) + 2 /* ret addr */ + next_fi->extra_info->framesize);
+ struct frame_info *next_fi = get_next_frame (fi);
+ if (get_frame_extra_info (fi)->framereg == AVR_SP_REGNUM)
+ deprecated_update_frame_base_hack (fi, (get_frame_base (next_fi)
+ + 2 /* ret addr */
+ + get_frame_extra_info (next_fi)->framesize));
/* FIXME: I don't analyse va_args functions */
else
{
unsigned int fp_low, fp_high;
/* Scan all frames */
- for (; next_fi; next_fi = next_fi->next)
+ for (; next_fi; next_fi = get_next_frame (next_fi))
{
/* look for saved AVR_FP_REGNUM */
if (get_frame_saved_regs (next_fi)[AVR_FP_REGNUM] && !fp)
/* TRoth: Do we want to do this if we are in main? I don't think we should
since return_pc makes no sense when we are in main. */
- if ((get_frame_pc (fi)) && (fi->extra_info->is_main == 0)) /* We are not in CALL_DUMMY */
+ if ((get_frame_pc (fi)) && (get_frame_extra_info (fi)->is_main == 0))
+ /* We are not in CALL_DUMMY */
{
CORE_ADDR addr;
int i;
- addr = get_frame_base (fi) + fi->extra_info->framesize + 1;
+ addr = get_frame_base (fi) + get_frame_extra_info (fi)->framesize + 1;
/* Return address in stack in different endianness */
- fi->extra_info->return_pc =
+ get_frame_extra_info (fi)->return_pc =
read_memory_unsigned_integer (avr_make_saddr (addr), 1) << 8;
- fi->extra_info->return_pc |=
+ get_frame_extra_info (fi)->return_pc |=
read_memory_unsigned_integer (avr_make_saddr (addr + 1), 1);
/* This return address in words,
must be converted to the bytes address */
- fi->extra_info->return_pc *= 2;
+ get_frame_extra_info (fi)->return_pc *= 2;
/* Resolve a pushed registers addresses */
for (i = 0; i < NUM_REGS; i++)
}
/* Don't forget the update the PC too! */
- write_pc (frame->extra_info->return_pc);
+ write_pc (get_frame_extra_info (frame)->return_pc);
}
flush_cached_frames ();
}
get_frame_base (frame),
AVR_PC_REGNUM);
else
- return frame->extra_info->return_pc;
+ return get_frame_extra_info (frame)->return_pc;
}
static CORE_ADDR
return (m2 | (m1 << 8)) * 2;
}
-/* Figure out where in REGBUF the called function has left its return value.
- Copy that into VALBUF. */
-
-static void
-avr_extract_return_value (struct type *type, char *regbuf, char *valbuf)
-{
- int wordsize, len;
-
- wordsize = 2;
-
- len = TYPE_LENGTH (type);
-
- switch (len)
- {
- case 1: /* (char) */
- case 2: /* (short), (int) */
- memcpy (valbuf, regbuf + REGISTER_BYTE (24), 2);
- break;
- case 4: /* (long), (float) */
- memcpy (valbuf, regbuf + REGISTER_BYTE (22), 4);
- break;
- case 8: /* (double) (doesn't seem to happen, which is good,
- because this almost certainly isn't right. */
- error ("I don't know how a double is returned.");
- break;
- }
-}
-
/* Returns the return address for a dummy. */
static CORE_ADDR
return entry_point_address ();
}
-/* Place the appropriate value in the appropriate registers.
- Primarily used by the RETURN command. */
-
-static void
-avr_store_return_value (struct type *type, char *valbuf)
-{
- int wordsize, len, regval;
-
- wordsize = 2;
-
- len = TYPE_LENGTH (type);
- switch (len)
- {
- case 1: /* char */
- case 2: /* short, int */
- regval = extract_address (valbuf, len);
- write_register (0, regval);
- break;
- case 4: /* long, float */
- regval = extract_address (valbuf, len);
- write_register (0, regval >> 16);
- write_register (1, regval & 0xffff);
- break;
- case 8: /* presumeably double, but doesn't seem to happen */
- error ("I don't know how to return a double.");
- break;
- }
-}
-
/* Setup the return address for a dummy frame, as called by
call_function_by_hand. Only necessary when you are using an empty
CALL_DUMMY. */
/* Given a GDB frame, determine the address of the calling function's
frame. This will be used to create a new GDB frame struct, and
- then INIT_EXTRA_FRAME_INFO and DEPRECATED_INIT_FRAME_PC will be
- called for the new frame.
+ then DEPRECATED_INIT_EXTRA_FRAME_INFO and DEPRECATED_INIT_FRAME_PC
+ will be called for the new frame.
For us, the frame address is its stack pointer value, so we look up
the function prologue to determine the caller's sp value, and return it. */
get_frame_base (frame)))
{
/* initialize the return_pc now */
- frame->extra_info->return_pc
+ get_frame_extra_info (frame)->return_pc
= deprecated_read_register_dummy (get_frame_pc (frame),
get_frame_base (frame),
AVR_PC_REGNUM);
return get_frame_base (frame);
}
- return (frame->extra_info->is_main ? 0
- : get_frame_base (frame) + frame->extra_info->framesize + 2 /* ret addr */ );
+ return (get_frame_extra_info (frame)->is_main ? 0
+ : get_frame_base (frame) + get_frame_extra_info (frame)->framesize + 2 /* ret addr */ );
}
/* Store the address of the place in which to copy the structure the
write_register (0, addr);
}
-/* Extract from an array REGBUF containing the (raw) register state
- the address in which a function should return its structure value,
- as a CORE_ADDR (or an expression that can be used as one). */
-
-static CORE_ADDR
-avr_extract_struct_value_address (char *regbuf)
-{
- return (extract_address ((regbuf) + REGISTER_BYTE (0),
- REGISTER_RAW_SIZE (0)) | AVR_SMEM_START);
-}
-
/* Setup the function arguments for calling a function in the inferior.
On the AVR architecture, there are 18 registers (R25 to R8) which are
while (len > 0)
{ /* there's room in registers */
len -= wordsize;
- regval = extract_address (val + len, wordsize);
+ regval = extract_unsigned_integer (val + len, wordsize);
write_register (argreg--, regval);
}
}
return sp;
}
+/* Not all avr devices support the BREAK insn. Those that don't should treat
+ it as a NOP. Thus, it should be ok. Since the avr is currently a remote
+ only target, this shouldn't be a problem (I hope). TRoth/2003-05-14 */
+
+static const unsigned char *
+avr_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
+{
+ static unsigned char avr_break_insn [] = { 0x98, 0x95 };
+ *lenptr = sizeof (avr_break_insn);
+ return avr_break_insn;
+}
+
+/* Given a return value in `regbuf' with a type `valtype',
+ extract and copy its value into `valbuf'.
+
+ Return values are always passed via registers r25:r24:... */
+
+static void
+avr_extract_return_value (struct type *type, struct regcache *regcache,
+ void *valbuf)
+{
+ if (TYPE_LENGTH (type) == 1)
+ {
+ ULONGEST c;
+
+ /* For single byte return values, r25 is always cleared, so we can
+ ignore it. */
+ regcache_cooked_read_unsigned (regcache, 24, &c);
+ store_unsigned_integer (valbuf, 1, c);
+ }
+ else
+ {
+ int i;
+ /* The MSB of the return value is always in r25, calculate which
+ register holds the LSB. */
+ int lsb_reg = 25 - TYPE_LENGTH (type) + 1;
+
+ for (i=0; i< TYPE_LENGTH (type); i++)
+ {
+ regcache_cooked_read (regcache, lsb_reg + i,
+ (bfd_byte *) valbuf + i);
+ }
+ }
+}
+
/* Initialize the gdbarch structure for the AVR's. */
static struct gdbarch *
avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
- /* FIXME: TRoth/2002-02-18: I have no idea if avr_call_dummy_words[] should
- be bigger or not. Initial testing seems to show that `call my_func()`
- works and backtrace from a breakpoint within the call looks correct.
- Admittedly, I haven't tested with more than a very simple program. */
- static LONGEST avr_call_dummy_words[] = { 0 };
-
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
set_gdbarch_read_pc (gdbarch, avr_read_pc);
set_gdbarch_write_pc (gdbarch, avr_write_pc);
- set_gdbarch_read_fp (gdbarch, avr_read_fp);
+ set_gdbarch_deprecated_target_read_fp (gdbarch, avr_read_fp);
set_gdbarch_read_sp (gdbarch, avr_read_sp);
- set_gdbarch_write_sp (gdbarch, avr_write_sp);
+ set_gdbarch_deprecated_dummy_write_sp (gdbarch, avr_write_sp);
set_gdbarch_num_regs (gdbarch, AVR_NUM_REGS);
set_gdbarch_sp_regnum (gdbarch, AVR_SP_REGNUM);
- set_gdbarch_fp_regnum (gdbarch, AVR_FP_REGNUM);
+ set_gdbarch_deprecated_fp_regnum (gdbarch, AVR_FP_REGNUM);
set_gdbarch_pc_regnum (gdbarch, AVR_PC_REGNUM);
set_gdbarch_register_name (gdbarch, avr_register_name);
- set_gdbarch_register_size (gdbarch, 1);
- set_gdbarch_register_bytes (gdbarch, AVR_NUM_REG_BYTES);
- set_gdbarch_register_byte (gdbarch, avr_register_byte);
- set_gdbarch_register_raw_size (gdbarch, avr_register_raw_size);
- set_gdbarch_max_register_raw_size (gdbarch, 4);
- set_gdbarch_register_virtual_size (gdbarch, avr_register_virtual_size);
- set_gdbarch_max_register_virtual_size (gdbarch, 4);
- set_gdbarch_register_virtual_type (gdbarch, avr_register_virtual_type);
+ set_gdbarch_register_type (gdbarch, avr_register_type);
+ set_gdbarch_extract_return_value (gdbarch, avr_extract_return_value);
set_gdbarch_print_insn (gdbarch, print_insn_avr);
set_gdbarch_call_dummy_address (gdbarch, avr_call_dummy_address);
- set_gdbarch_call_dummy_start_offset (gdbarch, 0);
- set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
- set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
- set_gdbarch_call_dummy_length (gdbarch, 0);
- set_gdbarch_call_dummy_p (gdbarch, 1);
- set_gdbarch_call_dummy_words (gdbarch, avr_call_dummy_words);
- set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
- set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
-
-/* set_gdbarch_believe_pcc_promotion (gdbarch, 1); // TRoth: should this be set? */
set_gdbarch_address_to_pointer (gdbarch, avr_address_to_pointer);
set_gdbarch_pointer_to_address (gdbarch, avr_pointer_to_address);
- set_gdbarch_deprecated_extract_return_value (gdbarch, avr_extract_return_value);
- set_gdbarch_push_arguments (gdbarch, avr_push_arguments);
- set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
- set_gdbarch_push_return_address (gdbarch, avr_push_return_address);
- set_gdbarch_pop_frame (gdbarch, avr_pop_frame);
-
- set_gdbarch_deprecated_store_return_value (gdbarch, avr_store_return_value);
+ set_gdbarch_deprecated_push_arguments (gdbarch, avr_push_arguments);
+ set_gdbarch_deprecated_push_return_address (gdbarch, avr_push_return_address);
+ set_gdbarch_deprecated_pop_frame (gdbarch, avr_pop_frame);
set_gdbarch_use_struct_convention (gdbarch, generic_use_struct_convention);
- set_gdbarch_store_struct_return (gdbarch, avr_store_struct_return);
- set_gdbarch_deprecated_extract_struct_value_address
- (gdbarch, avr_extract_struct_value_address);
+ set_gdbarch_deprecated_store_struct_return (gdbarch, avr_store_struct_return);
- set_gdbarch_frame_init_saved_regs (gdbarch, avr_scan_prologue);
- set_gdbarch_init_extra_frame_info (gdbarch, avr_init_extra_frame_info);
+ set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, avr_scan_prologue);
+ set_gdbarch_deprecated_init_extra_frame_info (gdbarch, avr_init_extra_frame_info);
set_gdbarch_skip_prologue (gdbarch, avr_skip_prologue);
-/* set_gdbarch_prologue_frameless_p (gdbarch, avr_prologue_frameless_p); */
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
set_gdbarch_decr_pc_after_break (gdbarch, 0);
+ set_gdbarch_breakpoint_from_pc (gdbarch, avr_breakpoint_from_pc);
set_gdbarch_function_start_offset (gdbarch, 0);
- set_gdbarch_remote_translate_xfer_address (gdbarch,
- avr_remote_translate_xfer_address);
+
set_gdbarch_frame_args_skip (gdbarch, 0);
set_gdbarch_frameless_function_invocation (gdbarch, frameless_look_for_prologue); /* ??? */
- set_gdbarch_frame_chain (gdbarch, avr_frame_chain);
- set_gdbarch_frame_saved_pc (gdbarch, avr_frame_saved_pc);
+ set_gdbarch_deprecated_frame_chain (gdbarch, avr_frame_chain);
+ set_gdbarch_deprecated_frame_saved_pc (gdbarch, avr_frame_saved_pc);
set_gdbarch_frame_args_address (gdbarch, avr_frame_address);
set_gdbarch_frame_locals_address (gdbarch, avr_frame_address);
- set_gdbarch_saved_pc_after_call (gdbarch, avr_saved_pc_after_call);
- set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
-
- set_gdbarch_convert_from_func_ptr_addr (gdbarch,
- avr_convert_from_func_ptr_addr);
+ set_gdbarch_deprecated_saved_pc_after_call (gdbarch, avr_saved_pc_after_call);
return gdbarch;
}
unsigned int val;
int i, j, k, step;
-/* fprintf_unfiltered (gdb_stderr, "DEBUG: avr_io_reg_read_command (\"%s\", %d)\n", */
-/* args, from_tty); */
-
if (!current_target.to_query)
{
fprintf_unfiltered (gdb_stderr,
- "ERR: info io_registers NOT supported by current target\n");
+ "ERR: info io_registers NOT supported by current "
+ "target\n");
return;
}
for (i = 0; i < nreg; i += step)
{
- j = step - (nreg % step); /* how many registers this round? */
+ /* how many registers this round? */
+ j = step;
+ if ((i+j) >= nreg)
+ j = nreg - i; /* last block is less than 8 registers */
snprintf (query, sizeof (query) - 1, "avr.io_reg:%x,%x", i, j);
target_query ((int) 'R', query, buf, &bufsiz);
}
}
+extern initialize_file_ftype _initialize_avr_tdep; /* -Wmissing-prototypes */
+
void
_initialize_avr_tdep (void)
{