Obsolete tic80.

This commit is contained in:
Andrew Cagney 2001-04-03 21:14:37 +00:00
parent 5854c6337e
commit 52071915c8
7 changed files with 744 additions and 733 deletions

View File

@ -1,3 +1,13 @@
2001-04-03 Andrew Cagney <ac131313@redhat.com>
Obsolete tic80-*-* target.
* configure.tgt (tic80-*-*): Obsolete.
* config/tic80/tic80.mt: Obsolete.
* config/tic80/tm-tic80.h: Obsolete.
* tic80-tdep.c: Obsolete.
* TODO: Update
* NEWS: Update.
2001-04-02 J.T. Conklin <jtc@redback.com>
* remote-mips.c (S_IROTH): Moved definition from here.

View File

@ -18,6 +18,7 @@ x86 FreeBSD before 2.2 i[3456]86*-freebsd{1,2.[01]}*,
Harris/CXUX m88k m88*-harris-cxux*
Most ns32k hosts and targets ns32k-*-mach3* ns32k-umax-*
ns32k-utek-sysv* ns32k-utek-*
TiC80 32 Bit DSP target tic80-*-*
stuff.c (Program to stuff files into a specially prepared space in kdb)
kdb-start.c (Main loop for the standalone kernel debugger)

View File

@ -185,7 +185,7 @@ Steps:
ns32k-umax-* ns32k umax - yes
ns32k-utek-sysv* ns32k merlin merlin yes
ns32k-utek-* ns32k - umax yes
tic80-* tic80 - tic80
tic80-* tic80 - tic80 yes
m68*-isi-* m68k isi isi
m68*-sony-* m68k news news
m68030-sony-* m68k news1000 -

View File

@ -1,7 +1,7 @@
# Target: TI TMS320C80 (MVP) processor
TDEPFILES= tic80-tdep.o
TM_FILE= tm-tic80.h
SIM_OBS = remote-sim.o
SIM = ../sim/tic80/libsim.a
GDBSERVER_DEPFILES= low-sim.o
GDBSERVER_LIBS = ../../sim/tic80/libsim.a ../../bfd/libbfd.a ../../libiberty/libiberty.a -lm ../../intl/libintl.a
# OBSOLETE # Target: TI TMS320C80 (MVP) processor
# OBSOLETE TDEPFILES= tic80-tdep.o
# OBSOLETE TM_FILE= tm-tic80.h
# OBSOLETE SIM_OBS = remote-sim.o
# OBSOLETE SIM = ../sim/tic80/libsim.a
# OBSOLETE GDBSERVER_DEPFILES= low-sim.o
# OBSOLETE GDBSERVER_LIBS = ../../sim/tic80/libsim.a ../../bfd/libbfd.a ../../libiberty/libiberty.a -lm ../../intl/libintl.a

View File

@ -1,255 +1,255 @@
/* Parameters for execution on a TI TMS320C80 (MVP) processor.
Copyright 1997, 1999, 2000
Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef TM_TIC80_H
#define TM_TIC80_H
#include "regcache.h"
/* Forward declare structs used in prototypes */
struct frame_info;
struct type;
struct value;
struct symbol;
struct frame_saved_regs;
#define TARGET_BYTE_ORDER LITTLE_ENDIAN
#define NUM_REGS 38
#define REGISTER_NAMES \
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \
"pc", "npc", \
"a0", "a1", "a2", "a3", \
}
/* Various dedicated register numbers
FIXME: Shadow updates in sim/tic80/sim-calls.c */
#define SP_REGNUM 1 /* Contains address of top of stack */
#define ARG0_REGNUM 2 /* Contains argument 1 (r3 has high word) */
#define RET_REGNUM 2 /* Contains function return value */
#define ARGLAST_REGNUM 12 /* Contains argument 6 (r13 has high word) */
#define FP_REGNUM 30 /* Contains address of executing stack frame */
#define LR_REGNUM 31 /* Contains address of caller (link register) */
#define PC_REGNUM 32 /* Contains program counter (FIXME?) */
#define NPC_REGNUM 33 /* Contains the next program counter (FIXME?) */
#define A0_REGNUM 34 /* Accumulator register 0 */
#define A3_REGNUM 37 /* Accumulator register 1 */
#define R0_REGNUM 0 /* General Purpose Register 0 - for sim */
#define Rn_REGNUM 31 /* Last General Purpose Register - for sim */
#define An_REGNUM A3_REGNUM /* Last Accumulator register - for sim */
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (((NUM_REGS - 4) * 4) + (4 * 8))
/* Index within `registers' of the first byte of the space for
register N. */
#define REGISTER_BYTE(N) \
(((N) >= A0_REGNUM) ? (((N) - A0_REGNUM) * 8 + A0_REGNUM * 4) : ((N) * 4))
/* Most registers are 4 bytes */
#define REGISTER_SIZE 4
/* Some registers are 8 bytes. */
#define REGISTER_RAW_SIZE(N) \
(((N) >= A0_REGNUM) ? 8 : 4)
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE (8)
/* All regs are 4 bytes. */
#define REGISTER_VIRTUAL_SIZE(N) (REGISTER_RAW_SIZE(N))
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE (MAX_REGISTER_RAW_SIZE)
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) /* FIXME? */ \
(((N) >= A0_REGNUM) ? builtin_type_float : builtin_type_int)
/* Offset from address of function to start of its code.
Zero on most machines. */
#define FUNCTION_START_OFFSET 0
/* Stack grows downward. */
#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
/* Sequence of bytes for breakpoint instruction.
This is padded out to the size of a machine word. */
#define BREAKPOINT {0x49, 0x80, 0x00, 0x00} /* FIXME! */
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#define DECR_PC_AFTER_BREAK 0 /* FIXME! */
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME tic80_pop_frame(get_current_frame ())
extern struct frame_info *tic80_pop_frame (struct frame_info *frame);
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 0
/* Set VAL to the number of args passed to frame described by FI.
Can set VAL to -1, meaning no way to tell. */
/* We can't tell how many args there are */
#define FRAME_NUM_ARGS(fi) (-1)
#define FRAME_ARGS_SKIP 0
#define FRAME_ARGS_ADDRESS(fi) (fi)->frame
#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
/* Define other aspects of the stack frame.
We keep the offsets of all saved registers, 'cause we need 'em a lot!
We also keep the current size of the stack frame, and the offset of
the frame pointer from the stack pointer (for frameless functions, and
when we're still in the prologue of a function with a frame) */
#define EXTRA_FRAME_INFO \
struct frame_saved_regs fsr; \
int framesize; \
int frameoffset; \
int framereg;
extern void tic80_init_extra_frame_info (struct frame_info *fi);
#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) tic80_init_extra_frame_info (fi)
#define INIT_FRAME_PC /* Not necessary */
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
tic80_frame_find_saved_regs(frame_info, &(frame_saved_regs))
extern void tic80_frame_find_saved_regs (struct frame_info *,
struct frame_saved_regs *);
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
#define SKIP_PROLOGUE(pc) (tic80_skip_prologue (pc))
extern CORE_ADDR tic80_skip_prologue (CORE_ADDR pc);
/* Immediately after a function call, return the saved pc.
Can't always go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
#define SAVED_PC_AFTER_CALL(frame) read_register (LR_REGNUM)
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* FRAME_CHAIN takes a frame's nominal address
and produces the frame's chain-pointer. */
#define FRAME_CHAIN(thisframe) (CORE_ADDR) tic80_frame_chain (thisframe)
extern CORE_ADDR tic80_frame_chain (struct frame_info *);
#define FRAME_SAVED_PC(FRAME) tic80_frame_saved_pc (FRAME)
extern CORE_ADDR tic80_frame_saved_pc (struct frame_info *);
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function.
We store structs through a pointer passed in R2 */
#define STORE_STRUCT_RETURN(STRUCT_ADDR, SP) \
write_register (ARG0_REGNUM, STRUCT_ADDR)
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
memcpy ((VALBUF), \
(char *)(REGBUF) + REGISTER_BYTE (RET_REGNUM) + \
((TYPE_LENGTH (TYPE) > 4 ? 8 : 4) - TYPE_LENGTH (TYPE)), \
TYPE_LENGTH (TYPE))
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
write_register_bytes(REGISTER_BYTE (RET_REGNUM) + \
((TYPE_LENGTH (TYPE) > 4 ? 8:4) - TYPE_LENGTH (TYPE)),\
(VALBUF), TYPE_LENGTH (TYPE));
/* PUSH_ARGUMENTS */
extern CORE_ADDR tic80_push_arguments (int nargs,
struct value **args,
CORE_ADDR sp,
unsigned char struct_return,
CORE_ADDR struct_addr);
#define PUSH_ARGUMENTS(NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) \
(tic80_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR))
/* PUSH_RETURN_ADDRESS */
extern CORE_ADDR tic80_push_return_address (CORE_ADDR, CORE_ADDR);
#define PUSH_RETURN_ADDRESS(PC, SP) tic80_push_return_address (PC, SP)
/* override the standard get_saved_register function with
one that takes account of generic CALL_DUMMY frames */
#define GET_SAVED_REGISTER(raw_buffer, optimized, addrp, frame, regnum, lval) \
generic_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
#define USE_GENERIC_DUMMY_FRAMES 1
#define CALL_DUMMY {0}
#define CALL_DUMMY_LENGTH (0)
#define CALL_DUMMY_START_OFFSET (0)
#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
#define FIX_CALL_DUMMY(DUMMY1, STARTADDR, FUNADDR, NARGS, ARGS, TYPE, GCCP)
#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
#define CALL_DUMMY_ADDRESS() entry_point_address ()
/* generic dummy frame stuff */
#define PUSH_DUMMY_FRAME generic_push_dummy_frame ()
#define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP, FP)
#endif /* TM_TIC80_H */
/* OBSOLETE /* Parameters for execution on a TI TMS320C80 (MVP) processor. */
/* OBSOLETE Copyright 1997, 1999, 2000 */
/* OBSOLETE Free Software Foundation, Inc. */
/* OBSOLETE */
/* OBSOLETE This file is part of GDB. */
/* OBSOLETE */
/* OBSOLETE This program is free software; you can redistribute it and/or modify */
/* OBSOLETE it under the terms of the GNU General Public License as published by */
/* OBSOLETE the Free Software Foundation; either version 2 of the License, or */
/* OBSOLETE (at your option) any later version. */
/* OBSOLETE */
/* OBSOLETE This program is distributed in the hope that it will be useful, */
/* OBSOLETE but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* OBSOLETE MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* OBSOLETE GNU General Public License for more details. */
/* OBSOLETE */
/* OBSOLETE You should have received a copy of the GNU General Public License */
/* OBSOLETE along with this program; if not, write to the Free Software */
/* OBSOLETE Foundation, Inc., 59 Temple Place - Suite 330, */
/* OBSOLETE Boston, MA 02111-1307, USA. */ */
/* OBSOLETE */
/* OBSOLETE #ifndef TM_TIC80_H */
/* OBSOLETE #define TM_TIC80_H */
/* OBSOLETE */
/* OBSOLETE #include "regcache.h" */
/* OBSOLETE */
/* OBSOLETE /* Forward declare structs used in prototypes */ */
/* OBSOLETE struct frame_info; */
/* OBSOLETE struct type; */
/* OBSOLETE struct value; */
/* OBSOLETE struct symbol; */
/* OBSOLETE struct frame_saved_regs; */
/* OBSOLETE */
/* OBSOLETE #define TARGET_BYTE_ORDER LITTLE_ENDIAN */
/* OBSOLETE */
/* OBSOLETE #define NUM_REGS 38 */
/* OBSOLETE */
/* OBSOLETE #define REGISTER_NAMES \ */
/* OBSOLETE { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ */
/* OBSOLETE "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ */
/* OBSOLETE "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ */
/* OBSOLETE "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \ */
/* OBSOLETE "pc", "npc", \ */
/* OBSOLETE "a0", "a1", "a2", "a3", \ */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE /* Various dedicated register numbers */
/* OBSOLETE FIXME: Shadow updates in sim/tic80/sim-calls.c */ */
/* OBSOLETE */
/* OBSOLETE #define SP_REGNUM 1 /* Contains address of top of stack */ */
/* OBSOLETE #define ARG0_REGNUM 2 /* Contains argument 1 (r3 has high word) */ */
/* OBSOLETE #define RET_REGNUM 2 /* Contains function return value */ */
/* OBSOLETE #define ARGLAST_REGNUM 12 /* Contains argument 6 (r13 has high word) */ */
/* OBSOLETE #define FP_REGNUM 30 /* Contains address of executing stack frame */ */
/* OBSOLETE #define LR_REGNUM 31 /* Contains address of caller (link register) */ */
/* OBSOLETE #define PC_REGNUM 32 /* Contains program counter (FIXME?) */ */
/* OBSOLETE #define NPC_REGNUM 33 /* Contains the next program counter (FIXME?) */ */
/* OBSOLETE #define A0_REGNUM 34 /* Accumulator register 0 */ */
/* OBSOLETE #define A3_REGNUM 37 /* Accumulator register 1 */ */
/* OBSOLETE */
/* OBSOLETE #define R0_REGNUM 0 /* General Purpose Register 0 - for sim */ */
/* OBSOLETE #define Rn_REGNUM 31 /* Last General Purpose Register - for sim */ */
/* OBSOLETE #define An_REGNUM A3_REGNUM /* Last Accumulator register - for sim */ */
/* OBSOLETE */
/* OBSOLETE /* Total amount of space needed to store our copies of the machine's */
/* OBSOLETE register state, the array `registers'. */ */
/* OBSOLETE */
/* OBSOLETE #define REGISTER_BYTES (((NUM_REGS - 4) * 4) + (4 * 8)) */
/* OBSOLETE */
/* OBSOLETE /* Index within `registers' of the first byte of the space for */
/* OBSOLETE register N. */ */
/* OBSOLETE */
/* OBSOLETE #define REGISTER_BYTE(N) \ */
/* OBSOLETE (((N) >= A0_REGNUM) ? (((N) - A0_REGNUM) * 8 + A0_REGNUM * 4) : ((N) * 4)) */
/* OBSOLETE */
/* OBSOLETE /* Most registers are 4 bytes */ */
/* OBSOLETE */
/* OBSOLETE #define REGISTER_SIZE 4 */
/* OBSOLETE */
/* OBSOLETE /* Some registers are 8 bytes. */ */
/* OBSOLETE */
/* OBSOLETE #define REGISTER_RAW_SIZE(N) \ */
/* OBSOLETE (((N) >= A0_REGNUM) ? 8 : 4) */
/* OBSOLETE */
/* OBSOLETE /* Largest value REGISTER_RAW_SIZE can have. */ */
/* OBSOLETE */
/* OBSOLETE #define MAX_REGISTER_RAW_SIZE (8) */
/* OBSOLETE */
/* OBSOLETE /* All regs are 4 bytes. */ */
/* OBSOLETE */
/* OBSOLETE #define REGISTER_VIRTUAL_SIZE(N) (REGISTER_RAW_SIZE(N)) */
/* OBSOLETE */
/* OBSOLETE /* Largest value REGISTER_VIRTUAL_SIZE can have. */ */
/* OBSOLETE */
/* OBSOLETE #define MAX_REGISTER_VIRTUAL_SIZE (MAX_REGISTER_RAW_SIZE) */
/* OBSOLETE */
/* OBSOLETE /* Return the GDB type object for the "standard" data type */
/* OBSOLETE of data in register N. */ */
/* OBSOLETE */
/* OBSOLETE #define REGISTER_VIRTUAL_TYPE(N) /* FIXME? */ \ */
/* OBSOLETE (((N) >= A0_REGNUM) ? builtin_type_float : builtin_type_int) */
/* OBSOLETE */
/* OBSOLETE /* Offset from address of function to start of its code. */
/* OBSOLETE Zero on most machines. */ */
/* OBSOLETE */
/* OBSOLETE #define FUNCTION_START_OFFSET 0 */
/* OBSOLETE */
/* OBSOLETE /* Stack grows downward. */ */
/* OBSOLETE */
/* OBSOLETE #define INNER_THAN(lhs,rhs) ((lhs) < (rhs)) */
/* OBSOLETE */
/* OBSOLETE /* Sequence of bytes for breakpoint instruction. */
/* OBSOLETE This is padded out to the size of a machine word. */ */
/* OBSOLETE */
/* OBSOLETE #define BREAKPOINT {0x49, 0x80, 0x00, 0x00} /* FIXME! */ */
/* OBSOLETE */
/* OBSOLETE /* Amount PC must be decremented by after a breakpoint. */
/* OBSOLETE This is often the number of bytes in BREAKPOINT */
/* OBSOLETE but not always. */ */
/* OBSOLETE */
/* OBSOLETE #define DECR_PC_AFTER_BREAK 0 /* FIXME! */ */
/* OBSOLETE */
/* OBSOLETE /* Discard from the stack the innermost frame, restoring all registers. */ */
/* OBSOLETE */
/* OBSOLETE #define POP_FRAME tic80_pop_frame(get_current_frame ()) */
/* OBSOLETE extern struct frame_info *tic80_pop_frame (struct frame_info *frame); */
/* OBSOLETE */
/* OBSOLETE /* Return number of bytes at start of arglist that are not really args. */ */
/* OBSOLETE */
/* OBSOLETE #define FRAME_ARGS_SKIP 0 */
/* OBSOLETE */
/* OBSOLETE /* Set VAL to the number of args passed to frame described by FI. */
/* OBSOLETE Can set VAL to -1, meaning no way to tell. */ */
/* OBSOLETE /* We can't tell how many args there are */ */
/* OBSOLETE */
/* OBSOLETE #define FRAME_NUM_ARGS(fi) (-1) */
/* OBSOLETE */
/* OBSOLETE #define FRAME_ARGS_SKIP 0 */
/* OBSOLETE #define FRAME_ARGS_ADDRESS(fi) (fi)->frame */
/* OBSOLETE #define FRAME_LOCALS_ADDRESS(fi) (fi)->frame */
/* OBSOLETE */
/* OBSOLETE /* Define other aspects of the stack frame. */
/* OBSOLETE We keep the offsets of all saved registers, 'cause we need 'em a lot! */
/* OBSOLETE We also keep the current size of the stack frame, and the offset of */
/* OBSOLETE the frame pointer from the stack pointer (for frameless functions, and */
/* OBSOLETE when we're still in the prologue of a function with a frame) */ */
/* OBSOLETE */
/* OBSOLETE #define EXTRA_FRAME_INFO \ */
/* OBSOLETE struct frame_saved_regs fsr; \ */
/* OBSOLETE int framesize; \ */
/* OBSOLETE int frameoffset; \ */
/* OBSOLETE int framereg; */
/* OBSOLETE */
/* OBSOLETE extern void tic80_init_extra_frame_info (struct frame_info *fi); */
/* OBSOLETE #define INIT_EXTRA_FRAME_INFO(fromleaf, fi) tic80_init_extra_frame_info (fi) */
/* OBSOLETE #define INIT_FRAME_PC /* Not necessary */ */
/* OBSOLETE */
/* OBSOLETE /* Put here the code to store, into a struct frame_saved_regs, */
/* OBSOLETE the addresses of the saved registers of frame described by FRAME_INFO. */
/* OBSOLETE This includes special registers such as pc and fp saved in special */
/* OBSOLETE ways in the stack frame. sp is even more special: */
/* OBSOLETE the address we return for it IS the sp for the next frame. */ */
/* OBSOLETE */
/* OBSOLETE #define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \ */
/* OBSOLETE tic80_frame_find_saved_regs(frame_info, &(frame_saved_regs)) */
/* OBSOLETE extern void tic80_frame_find_saved_regs (struct frame_info *, */
/* OBSOLETE struct frame_saved_regs *); */
/* OBSOLETE */
/* OBSOLETE /* Advance PC across any function entry prologue instructions */
/* OBSOLETE to reach some "real" code. */ */
/* OBSOLETE */
/* OBSOLETE #define SKIP_PROLOGUE(pc) (tic80_skip_prologue (pc)) */
/* OBSOLETE extern CORE_ADDR tic80_skip_prologue (CORE_ADDR pc); */
/* OBSOLETE */
/* OBSOLETE /* Immediately after a function call, return the saved pc. */
/* OBSOLETE Can't always go through the frames for this because on some machines */
/* OBSOLETE the new frame is not set up until the new function executes */
/* OBSOLETE some instructions. */ */
/* OBSOLETE */
/* OBSOLETE #define SAVED_PC_AFTER_CALL(frame) read_register (LR_REGNUM) */
/* OBSOLETE */
/* OBSOLETE /* Describe the pointer in each stack frame to the previous stack frame */
/* OBSOLETE (its caller). */ */
/* OBSOLETE */
/* OBSOLETE /* FRAME_CHAIN takes a frame's nominal address */
/* OBSOLETE and produces the frame's chain-pointer. */ */
/* OBSOLETE */
/* OBSOLETE #define FRAME_CHAIN(thisframe) (CORE_ADDR) tic80_frame_chain (thisframe) */
/* OBSOLETE extern CORE_ADDR tic80_frame_chain (struct frame_info *); */
/* OBSOLETE */
/* OBSOLETE #define FRAME_SAVED_PC(FRAME) tic80_frame_saved_pc (FRAME) */
/* OBSOLETE extern CORE_ADDR tic80_frame_saved_pc (struct frame_info *); */
/* OBSOLETE */
/* OBSOLETE /* Store the address of the place in which to copy the structure the */
/* OBSOLETE subroutine will return. This is called from call_function. */
/* OBSOLETE */
/* OBSOLETE We store structs through a pointer passed in R2 */ */
/* OBSOLETE */
/* OBSOLETE #define STORE_STRUCT_RETURN(STRUCT_ADDR, SP) \ */
/* OBSOLETE write_register (ARG0_REGNUM, STRUCT_ADDR) */
/* OBSOLETE */
/* OBSOLETE /* Extract from an array REGBUF containing the (raw) register state */
/* OBSOLETE a function return value of type TYPE, and copy that, in virtual format, */
/* OBSOLETE into VALBUF. */ */
/* OBSOLETE */
/* OBSOLETE #define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \ */
/* OBSOLETE memcpy ((VALBUF), \ */
/* OBSOLETE (char *)(REGBUF) + REGISTER_BYTE (RET_REGNUM) + \ */
/* OBSOLETE ((TYPE_LENGTH (TYPE) > 4 ? 8 : 4) - TYPE_LENGTH (TYPE)), \ */
/* OBSOLETE TYPE_LENGTH (TYPE)) */
/* OBSOLETE */
/* OBSOLETE /* Write into appropriate registers a function return value */
/* OBSOLETE of type TYPE, given in virtual format. */ */
/* OBSOLETE */
/* OBSOLETE #define STORE_RETURN_VALUE(TYPE,VALBUF) \ */
/* OBSOLETE write_register_bytes(REGISTER_BYTE (RET_REGNUM) + \ */
/* OBSOLETE ((TYPE_LENGTH (TYPE) > 4 ? 8:4) - TYPE_LENGTH (TYPE)),\ */
/* OBSOLETE (VALBUF), TYPE_LENGTH (TYPE)); */
/* OBSOLETE */
/* OBSOLETE */
/* OBSOLETE */
/* OBSOLETE /* PUSH_ARGUMENTS */ */
/* OBSOLETE extern CORE_ADDR tic80_push_arguments (int nargs, */
/* OBSOLETE struct value **args, */
/* OBSOLETE CORE_ADDR sp, */
/* OBSOLETE unsigned char struct_return, */
/* OBSOLETE CORE_ADDR struct_addr); */
/* OBSOLETE */
/* OBSOLETE #define PUSH_ARGUMENTS(NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) \ */
/* OBSOLETE (tic80_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR)) */
/* OBSOLETE */
/* OBSOLETE /* PUSH_RETURN_ADDRESS */ */
/* OBSOLETE extern CORE_ADDR tic80_push_return_address (CORE_ADDR, CORE_ADDR); */
/* OBSOLETE #define PUSH_RETURN_ADDRESS(PC, SP) tic80_push_return_address (PC, SP) */
/* OBSOLETE */
/* OBSOLETE /* override the standard get_saved_register function with */
/* OBSOLETE one that takes account of generic CALL_DUMMY frames */ */
/* OBSOLETE #define GET_SAVED_REGISTER(raw_buffer, optimized, addrp, frame, regnum, lval) \ */
/* OBSOLETE generic_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) */
/* OBSOLETE */
/* OBSOLETE #define USE_GENERIC_DUMMY_FRAMES 1 */
/* OBSOLETE #define CALL_DUMMY {0} */
/* OBSOLETE #define CALL_DUMMY_LENGTH (0) */
/* OBSOLETE #define CALL_DUMMY_START_OFFSET (0) */
/* OBSOLETE #define CALL_DUMMY_BREAKPOINT_OFFSET (0) */
/* OBSOLETE #define FIX_CALL_DUMMY(DUMMY1, STARTADDR, FUNADDR, NARGS, ARGS, TYPE, GCCP) */
/* OBSOLETE #define CALL_DUMMY_LOCATION AT_ENTRY_POINT */
/* OBSOLETE #define CALL_DUMMY_ADDRESS() entry_point_address () */
/* OBSOLETE */
/* OBSOLETE /* generic dummy frame stuff */ */
/* OBSOLETE */
/* OBSOLETE #define PUSH_DUMMY_FRAME generic_push_dummy_frame () */
/* OBSOLETE #define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP, FP) */
/* OBSOLETE */
/* OBSOLETE #endif /* TM_TIC80_H */ */

View File

@ -287,8 +287,8 @@ sparc86x-*-*) gdb_target=sparclite ;;
sparc64-*-linux*) gdb_target=sp64linux ;;
sparc64-*-*) gdb_target=sp64 ;;
tic80-*-*) gdb_target=tic80
configdirs="${configdirs} gdbserver" ;;
# OBSOLETE tic80-*-*) gdb_target=tic80
# OBSOLETE configdirs="${configdirs} gdbserver" ;;
vax-*-*) gdb_target=vax ;;

View File

@ -1,468 +1,468 @@
/* Target-dependent code for the TI TMS320C80 (MVP) for GDB, the GNU debugger.
Copyright 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "value.h"
#include "frame.h"
#include "inferior.h"
#include "obstack.h"
#include "target.h"
#include "bfd.h"
#include "gdb_string.h"
#include "gdbcore.h"
#include "symfile.h"
#include "regcache.h"
/* Function: frame_find_saved_regs
Return the frame_saved_regs structure for the frame.
Doesn't really work for dummy frames, but it does pass back
an empty frame_saved_regs, so I guess that's better than total failure */
void
tic80_frame_find_saved_regs (struct frame_info *fi,
struct frame_saved_regs *regaddr)
{
memcpy (regaddr, &fi->fsr, sizeof (struct frame_saved_regs));
}
/* Function: skip_prologue
Find end of function prologue. */
CORE_ADDR
tic80_skip_prologue (CORE_ADDR pc)
{
CORE_ADDR func_addr, func_end;
struct symtab_and_line sal;
/* See what the symbol table says */
if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
{
sal = find_pc_line (func_addr, 0);
if (sal.line != 0 && sal.end < func_end)
return sal.end;
else
/* Either there's no line info, or the line after the prologue is after
the end of the function. In this case, there probably isn't a
prologue. */
return pc;
}
/* We can't find the start of this function, so there's nothing we can do. */
return pc;
}
/* Function: tic80_scan_prologue
This function decodes the target function prologue to determine:
1) the size of the stack frame
2) which registers are saved on it
3) the offsets of saved regs
4) the frame size
This information is stored in the "extra" fields of the frame_info. */
static void
tic80_scan_prologue (struct frame_info *fi)
{
struct symtab_and_line sal;
CORE_ADDR prologue_start, prologue_end, current_pc;
/* Assume there is no frame until proven otherwise. */
fi->framereg = SP_REGNUM;
fi->framesize = 0;
fi->frameoffset = 0;
/* this code essentially duplicates skip_prologue,
but we need the start address below. */
if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
{
sal = find_pc_line (prologue_start, 0);
if (sal.line == 0) /* no line info, use current PC */
if (prologue_start != entry_point_address ())
prologue_end = fi->pc;
else
return; /* _start has no frame or prologue */
else if (sal.end < prologue_end) /* next line begins after fn end */
prologue_end = sal.end; /* (probably means no prologue) */
}
else
/* FIXME */
prologue_end = prologue_start + 40; /* We're in the boondocks: allow for */
/* 16 pushes, an add, and "mv fp,sp" */
prologue_end = min (prologue_end, fi->pc);
/* Now search the prologue looking for instructions that set up the
frame pointer, adjust the stack pointer, and save registers. */
for (current_pc = prologue_start; current_pc < prologue_end; current_pc += 4)
{
unsigned int insn;
int regno;
int offset = 0;
insn = read_memory_unsigned_integer (current_pc, 4);
if ((insn & 0x301000) == 0x301000) /* Long immediate? */
/* FIXME - set offset for long immediate instructions */
current_pc += 4;
else
{
offset = insn & 0x7fff; /* extract 15-bit offset */
if (offset & 0x4000) /* if negative, sign-extend */
offset = -(0x8000 - offset);
}
if ((insn & 0x7fd0000) == 0x590000) /* st.{w,d} reg, xx(r1) */
{
regno = ((insn >> 27) & 0x1f);
fi->fsr.regs[regno] = offset;
if (insn & 0x8000) /* 64-bit store (st.d)? */
fi->fsr.regs[regno + 1] = offset + 4;
}
else if ((insn & 0xffff8000) == 0x086c8000) /* addu xx, r1, r1 */
fi->framesize = -offset;
else if ((insn & 0xffff8000) == 0xf06c8000) /* addu xx, r1, r30 */
{
fi->framereg = FP_REGNUM; /* fp is now valid */
fi->frameoffset = offset;
break; /* end of stack adjustments */
}
else if (insn == 0xf03b2001) /* addu r1, r0, r30 */
{
fi->framereg = FP_REGNUM; /* fp is now valid */
fi->frameoffset = 0;
break; /* end of stack adjustments */
}
else
/* FIXME - handle long immediate instructions */
break; /* anything else isn't prologue */
}
}
/* Function: init_extra_frame_info
This function actually figures out the frame address for a given pc and
sp. This is tricky on the c80 because we sometimes don't use an explicit
frame pointer, and the previous stack pointer isn't necessarily recorded
on the stack. The only reliable way to get this info is to
examine the prologue. */
void
tic80_init_extra_frame_info (struct frame_info *fi)
{
int reg;
if (fi->next)
fi->pc = FRAME_SAVED_PC (fi->next);
/* Because zero is a valid register offset relative to SP, we initialize
the offsets to -1 to indicate unused entries. */
for (reg = 0; reg < NUM_REGS; reg++)
fi->fsr.regs[reg] = -1;
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
{
/* We need to setup fi->frame here because run_stack_dummy gets it wrong
by assuming it's always FP. */
fi->frame = generic_read_register_dummy (fi->pc, fi->frame, SP_REGNUM);
fi->framesize = 0;
fi->frameoffset = 0;
return;
}
else
{
tic80_scan_prologue (fi);
if (!fi->next) /* this is the innermost frame? */
fi->frame = read_register (fi->framereg);
else
/* not the innermost frame */
/* If this function uses FP as the frame register, and the function
it called saved the FP, get the saved FP. */ if (fi->framereg == FP_REGNUM &&
fi->next->fsr.regs[FP_REGNUM] != (unsigned) -1)
fi->frame = read_memory_integer (fi->next->fsr.regs[FP_REGNUM], 4);
/* Convert SP-relative offsets of saved registers to real addresses. */
for (reg = 0; reg < NUM_REGS; reg++)
if (fi->fsr.regs[reg] == (unsigned) -1)
fi->fsr.regs[reg] = 0; /* unused entry */
else
fi->fsr.regs[reg] += fi->frame - fi->frameoffset;
}
}
/* Function: find_callers_reg
Find REGNUM on the stack. Otherwise, it's in an active register. One thing
we might want to do here is to check REGNUM against the clobber mask, and
somehow flag it as invalid if it isn't saved on the stack somewhere. This
would provide a graceful failure mode when trying to get the value of
caller-saves registers for an inner frame. */
CORE_ADDR
tic80_find_callers_reg (struct frame_info *fi, int regnum)
{
for (; fi; fi = fi->next)
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
return generic_read_register_dummy (fi->pc, fi->frame, regnum);
else if (fi->fsr.regs[regnum] != 0)
return read_memory_integer (fi->fsr.regs[regnum],
REGISTER_RAW_SIZE (regnum));
return read_register (regnum);
}
/* Function: frame_chain
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 INIT_FRAME_PC will be called for the new frame.
For c80, we save the frame size when we initialize the frame_info. */
CORE_ADDR
tic80_frame_chain (struct frame_info *fi)
{
CORE_ADDR fn_start, callers_pc, fp;
/* is this a dummy frame? */
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
return fi->frame; /* dummy frame same as caller's frame */
/* is caller-of-this a dummy frame? */
callers_pc = FRAME_SAVED_PC (fi); /* find out who called us: */
fp = tic80_find_callers_reg (fi, FP_REGNUM);
if (PC_IN_CALL_DUMMY (callers_pc, fp, fp))
return fp; /* dummy frame's frame may bear no relation to ours */
if (find_pc_partial_function (fi->pc, 0, &fn_start, 0))
if (fn_start == entry_point_address ())
return 0; /* in _start fn, don't chain further */
if (fi->framereg == FP_REGNUM)
return tic80_find_callers_reg (fi, FP_REGNUM);
else
return fi->frame + fi->framesize;
}
/* Function: pop_frame
Discard from the stack the innermost frame,
restoring all saved registers. */
struct frame_info *
tic80_pop_frame (struct frame_info *frame)
{
int regnum;
if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
generic_pop_dummy_frame ();
else
{
for (regnum = 0; regnum < NUM_REGS; regnum++)
if (frame->fsr.regs[regnum] != 0)
write_register (regnum,
read_memory_integer (frame->fsr.regs[regnum], 4));
write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
write_register (SP_REGNUM, read_register (FP_REGNUM));
#if 0
if (read_register (PSW_REGNUM) & 0x80)
write_register (SPU_REGNUM, read_register (SP_REGNUM));
else
write_register (SPI_REGNUM, read_register (SP_REGNUM));
#endif
}
flush_cached_frames ();
return NULL;
}
/* Function: frame_saved_pc
Find the caller of this frame. We do this by seeing if LR_REGNUM is saved
in the stack anywhere, otherwise we get it from the registers. */
CORE_ADDR
tic80_frame_saved_pc (struct frame_info *fi)
{
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
return generic_read_register_dummy (fi->pc, fi->frame, PC_REGNUM);
else
return tic80_find_callers_reg (fi, LR_REGNUM);
}
/* Function: tic80_push_return_address (pc, sp)
Set up the return address for the inferior function call.
Necessary for targets that don't actually execute a JSR/BSR instruction
(ie. when using an empty CALL_DUMMY) */
CORE_ADDR
tic80_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
{
write_register (LR_REGNUM, CALL_DUMMY_ADDRESS ());
return sp;
}
/* Function: push_arguments
Setup the function arguments for calling a function in the inferior.
On the TI C80 architecture, there are six register pairs (R2/R3 to R12/13)
which are dedicated for passing function arguments. Up to the first six
arguments (depending on size) may go into these registers.
The rest go on the stack.
Arguments that are smaller than 4 bytes will still take up a whole
register or a whole 32-bit word on the stack, and will be
right-justified in the register or the stack word. This includes
chars, shorts, and small aggregate types.
Arguments that are four bytes or less in size are placed in the
even-numbered register of a register pair, and the odd-numbered
register is not used.
Arguments of 8 bytes size (such as floating point doubles) are placed
in a register pair. The least significant 32-bit word is placed in
the even-numbered register, and the most significant word in the
odd-numbered register.
Aggregate types with sizes between 4 and 8 bytes are passed
entirely on the stack, and are left-justified within the
double-word (as opposed to aggregates smaller than 4 bytes
which are right-justified).
Aggregates of greater than 8 bytes are first copied onto the stack,
and then a pointer to the copy is passed in the place of the normal
argument (either in a register if available, or on the stack).
Functions that must return an aggregate type can return it in the
normal return value registers (R2 and R3) if its size is 8 bytes or
less. For larger return values, the caller must allocate space for
the callee to copy the return value to. A pointer to this space is
passed as an implicit first argument, always in R0. */
CORE_ADDR
tic80_push_arguments (int nargs, value_ptr *args, CORE_ADDR sp,
unsigned char struct_return, CORE_ADDR struct_addr)
{
int stack_offset, stack_alloc;
int argreg;
int argnum;
struct type *type;
CORE_ADDR regval;
char *val;
char valbuf[4];
int len;
int odd_sized_struct;
int is_struct;
/* first force sp to a 4-byte alignment */
sp = sp & ~3;
argreg = ARG0_REGNUM;
/* The "struct return pointer" pseudo-argument goes in R0 */
if (struct_return)
write_register (argreg++, struct_addr);
/* Now make sure there's space on the stack */
for (argnum = 0, stack_alloc = 0;
argnum < nargs; argnum++)
stack_alloc += ((TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 3) & ~3);
sp -= stack_alloc; /* make room on stack for args */
/* Now load as many as possible of the first arguments into
registers, and push the rest onto the stack. There are 16 bytes
in four registers available. Loop thru args from first to last. */
argreg = ARG0_REGNUM;
for (argnum = 0, stack_offset = 0; argnum < nargs; argnum++)
{
type = VALUE_TYPE (args[argnum]);
len = TYPE_LENGTH (type);
memset (valbuf, 0, sizeof (valbuf));
val = (char *) VALUE_CONTENTS (args[argnum]);
/* FIXME -- tic80 can take doubleword arguments in register pairs */
is_struct = (type->code == TYPE_CODE_STRUCT);
odd_sized_struct = 0;
if (!is_struct)
{
if (len < 4)
{ /* value gets right-justified in the register or stack word */
memcpy (valbuf + (4 - len), val, len);
val = valbuf;
}
if (len > 4 && (len & 3) != 0)
odd_sized_struct = 1; /* such structs go entirely on stack */
}
else
{
/* Structs are always passed by reference. */
write_register (argreg, sp + stack_offset);
argreg++;
}
while (len > 0)
{
if (is_struct || argreg > ARGLAST_REGNUM || odd_sized_struct)
{ /* must go on the stack */
write_memory (sp + stack_offset, val, 4);
stack_offset += 4;
}
/* NOTE WELL!!!!! This is not an "else if" clause!!!
That's because some things get passed on the stack
AND in the registers! */
if (!is_struct && argreg <= ARGLAST_REGNUM)
{ /* there's room in a register */
regval = extract_address (val, REGISTER_RAW_SIZE (argreg));
write_register (argreg, regval);
argreg += 2; /* FIXME -- what about doubleword args? */
}
/* Store the value 4 bytes at a time. This means that things
larger than 4 bytes may go partly in registers and partly
on the stack. */
len -= REGISTER_RAW_SIZE (argreg);
val += REGISTER_RAW_SIZE (argreg);
}
}
return sp;
}
/* Function: tic80_write_sp
Because SP is really a read-only register that mirrors either SPU or SPI,
we must actually write one of those two as well, depending on PSW. */
void
tic80_write_sp (CORE_ADDR val)
{
#if 0
unsigned long psw = read_register (PSW_REGNUM);
if (psw & 0x80) /* stack mode: user or interrupt */
write_register (SPU_REGNUM, val);
else
write_register (SPI_REGNUM, val);
#endif
write_register (SP_REGNUM, val);
}
void
_initialize_tic80_tdep (void)
{
tm_print_insn = print_insn_tic80;
}
/* OBSOLETE /* Target-dependent code for the TI TMS320C80 (MVP) for GDB, the GNU debugger. */
/* OBSOLETE Copyright 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. */
/* OBSOLETE */
/* OBSOLETE This file is part of GDB. */
/* OBSOLETE */
/* OBSOLETE This program is free software; you can redistribute it and/or modify */
/* OBSOLETE it under the terms of the GNU General Public License as published by */
/* OBSOLETE the Free Software Foundation; either version 2 of the License, or */
/* OBSOLETE (at your option) any later version. */
/* OBSOLETE */
/* OBSOLETE This program is distributed in the hope that it will be useful, */
/* OBSOLETE but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* OBSOLETE MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* OBSOLETE GNU General Public License for more details. */
/* OBSOLETE */
/* OBSOLETE You should have received a copy of the GNU General Public License */
/* OBSOLETE along with this program; if not, write to the Free Software */
/* OBSOLETE Foundation, Inc., 59 Temple Place - Suite 330, */
/* OBSOLETE Boston, MA 02111-1307, USA. */ */
/* OBSOLETE */
/* OBSOLETE #include "defs.h" */
/* OBSOLETE #include "value.h" */
/* OBSOLETE #include "frame.h" */
/* OBSOLETE #include "inferior.h" */
/* OBSOLETE #include "obstack.h" */
/* OBSOLETE #include "target.h" */
/* OBSOLETE #include "bfd.h" */
/* OBSOLETE #include "gdb_string.h" */
/* OBSOLETE #include "gdbcore.h" */
/* OBSOLETE #include "symfile.h" */
/* OBSOLETE #include "regcache.h" */
/* OBSOLETE */
/* OBSOLETE /* Function: frame_find_saved_regs */
/* OBSOLETE Return the frame_saved_regs structure for the frame. */
/* OBSOLETE Doesn't really work for dummy frames, but it does pass back */
/* OBSOLETE an empty frame_saved_regs, so I guess that's better than total failure */ */
/* OBSOLETE */
/* OBSOLETE void */
/* OBSOLETE tic80_frame_find_saved_regs (struct frame_info *fi, */
/* OBSOLETE struct frame_saved_regs *regaddr) */
/* OBSOLETE { */
/* OBSOLETE memcpy (regaddr, &fi->fsr, sizeof (struct frame_saved_regs)); */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE /* Function: skip_prologue */
/* OBSOLETE Find end of function prologue. */ */
/* OBSOLETE */
/* OBSOLETE CORE_ADDR */
/* OBSOLETE tic80_skip_prologue (CORE_ADDR pc) */
/* OBSOLETE { */
/* OBSOLETE CORE_ADDR func_addr, func_end; */
/* OBSOLETE struct symtab_and_line sal; */
/* OBSOLETE */
/* OBSOLETE /* See what the symbol table says */ */
/* OBSOLETE */
/* OBSOLETE if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) */
/* OBSOLETE { */
/* OBSOLETE sal = find_pc_line (func_addr, 0); */
/* OBSOLETE */
/* OBSOLETE if (sal.line != 0 && sal.end < func_end) */
/* OBSOLETE return sal.end; */
/* OBSOLETE else */
/* OBSOLETE /* Either there's no line info, or the line after the prologue is after */
/* OBSOLETE the end of the function. In this case, there probably isn't a */
/* OBSOLETE prologue. */ */
/* OBSOLETE return pc; */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE /* We can't find the start of this function, so there's nothing we can do. */ */
/* OBSOLETE return pc; */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE /* Function: tic80_scan_prologue */
/* OBSOLETE This function decodes the target function prologue to determine: */
/* OBSOLETE 1) the size of the stack frame */
/* OBSOLETE 2) which registers are saved on it */
/* OBSOLETE 3) the offsets of saved regs */
/* OBSOLETE 4) the frame size */
/* OBSOLETE This information is stored in the "extra" fields of the frame_info. */ */
/* OBSOLETE */
/* OBSOLETE static void */
/* OBSOLETE tic80_scan_prologue (struct frame_info *fi) */
/* OBSOLETE { */
/* OBSOLETE struct symtab_and_line sal; */
/* OBSOLETE CORE_ADDR prologue_start, prologue_end, current_pc; */
/* OBSOLETE */
/* OBSOLETE /* Assume there is no frame until proven otherwise. */ */
/* OBSOLETE fi->framereg = SP_REGNUM; */
/* OBSOLETE fi->framesize = 0; */
/* OBSOLETE fi->frameoffset = 0; */
/* OBSOLETE */
/* OBSOLETE /* this code essentially duplicates skip_prologue, */
/* OBSOLETE but we need the start address below. */ */
/* OBSOLETE */
/* OBSOLETE if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end)) */
/* OBSOLETE { */
/* OBSOLETE sal = find_pc_line (prologue_start, 0); */
/* OBSOLETE */
/* OBSOLETE if (sal.line == 0) /* no line info, use current PC */ */
/* OBSOLETE if (prologue_start != entry_point_address ()) */
/* OBSOLETE prologue_end = fi->pc; */
/* OBSOLETE else */
/* OBSOLETE return; /* _start has no frame or prologue */ */
/* OBSOLETE else if (sal.end < prologue_end) /* next line begins after fn end */ */
/* OBSOLETE prologue_end = sal.end; /* (probably means no prologue) */ */
/* OBSOLETE } */
/* OBSOLETE else */
/* OBSOLETE /* FIXME */ */
/* OBSOLETE prologue_end = prologue_start + 40; /* We're in the boondocks: allow for */ */
/* OBSOLETE /* 16 pushes, an add, and "mv fp,sp" */ */
/* OBSOLETE */
/* OBSOLETE prologue_end = min (prologue_end, fi->pc); */
/* OBSOLETE */
/* OBSOLETE /* Now search the prologue looking for instructions that set up the */
/* OBSOLETE frame pointer, adjust the stack pointer, and save registers. */ */
/* OBSOLETE */
/* OBSOLETE for (current_pc = prologue_start; current_pc < prologue_end; current_pc += 4) */
/* OBSOLETE { */
/* OBSOLETE unsigned int insn; */
/* OBSOLETE int regno; */
/* OBSOLETE int offset = 0; */
/* OBSOLETE */
/* OBSOLETE insn = read_memory_unsigned_integer (current_pc, 4); */
/* OBSOLETE */
/* OBSOLETE if ((insn & 0x301000) == 0x301000) /* Long immediate? */ */
/* OBSOLETE /* FIXME - set offset for long immediate instructions */ */
/* OBSOLETE current_pc += 4; */
/* OBSOLETE else */
/* OBSOLETE { */
/* OBSOLETE offset = insn & 0x7fff; /* extract 15-bit offset */ */
/* OBSOLETE if (offset & 0x4000) /* if negative, sign-extend */ */
/* OBSOLETE offset = -(0x8000 - offset); */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE if ((insn & 0x7fd0000) == 0x590000) /* st.{w,d} reg, xx(r1) */ */
/* OBSOLETE { */
/* OBSOLETE regno = ((insn >> 27) & 0x1f); */
/* OBSOLETE fi->fsr.regs[regno] = offset; */
/* OBSOLETE if (insn & 0x8000) /* 64-bit store (st.d)? */ */
/* OBSOLETE fi->fsr.regs[regno + 1] = offset + 4; */
/* OBSOLETE } */
/* OBSOLETE else if ((insn & 0xffff8000) == 0x086c8000) /* addu xx, r1, r1 */ */
/* OBSOLETE fi->framesize = -offset; */
/* OBSOLETE else if ((insn & 0xffff8000) == 0xf06c8000) /* addu xx, r1, r30 */ */
/* OBSOLETE { */
/* OBSOLETE fi->framereg = FP_REGNUM; /* fp is now valid */ */
/* OBSOLETE fi->frameoffset = offset; */
/* OBSOLETE break; /* end of stack adjustments */ */
/* OBSOLETE } */
/* OBSOLETE else if (insn == 0xf03b2001) /* addu r1, r0, r30 */ */
/* OBSOLETE { */
/* OBSOLETE fi->framereg = FP_REGNUM; /* fp is now valid */ */
/* OBSOLETE fi->frameoffset = 0; */
/* OBSOLETE break; /* end of stack adjustments */ */
/* OBSOLETE } */
/* OBSOLETE else */
/* OBSOLETE /* FIXME - handle long immediate instructions */ */
/* OBSOLETE break; /* anything else isn't prologue */ */
/* OBSOLETE } */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE /* Function: init_extra_frame_info */
/* OBSOLETE This function actually figures out the frame address for a given pc and */
/* OBSOLETE sp. This is tricky on the c80 because we sometimes don't use an explicit */
/* OBSOLETE frame pointer, and the previous stack pointer isn't necessarily recorded */
/* OBSOLETE on the stack. The only reliable way to get this info is to */
/* OBSOLETE examine the prologue. */ */
/* OBSOLETE */
/* OBSOLETE void */
/* OBSOLETE tic80_init_extra_frame_info (struct frame_info *fi) */
/* OBSOLETE { */
/* OBSOLETE int reg; */
/* OBSOLETE */
/* OBSOLETE if (fi->next) */
/* OBSOLETE fi->pc = FRAME_SAVED_PC (fi->next); */
/* OBSOLETE */
/* OBSOLETE /* Because zero is a valid register offset relative to SP, we initialize */
/* OBSOLETE the offsets to -1 to indicate unused entries. */ */
/* OBSOLETE for (reg = 0; reg < NUM_REGS; reg++) */
/* OBSOLETE fi->fsr.regs[reg] = -1; */
/* OBSOLETE */
/* OBSOLETE if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) */
/* OBSOLETE { */
/* OBSOLETE /* We need to setup fi->frame here because run_stack_dummy gets it wrong */
/* OBSOLETE by assuming it's always FP. */ */
/* OBSOLETE fi->frame = generic_read_register_dummy (fi->pc, fi->frame, SP_REGNUM); */
/* OBSOLETE fi->framesize = 0; */
/* OBSOLETE fi->frameoffset = 0; */
/* OBSOLETE return; */
/* OBSOLETE } */
/* OBSOLETE else */
/* OBSOLETE { */
/* OBSOLETE tic80_scan_prologue (fi); */
/* OBSOLETE */
/* OBSOLETE if (!fi->next) /* this is the innermost frame? */ */
/* OBSOLETE fi->frame = read_register (fi->framereg); */
/* OBSOLETE else */
/* OBSOLETE /* not the innermost frame */ */
/* OBSOLETE /* If this function uses FP as the frame register, and the function */
/* OBSOLETE it called saved the FP, get the saved FP. */ if (fi->framereg == FP_REGNUM && */
/* OBSOLETE fi->next->fsr.regs[FP_REGNUM] != (unsigned) -1) */
/* OBSOLETE fi->frame = read_memory_integer (fi->next->fsr.regs[FP_REGNUM], 4); */
/* OBSOLETE */
/* OBSOLETE /* Convert SP-relative offsets of saved registers to real addresses. */ */
/* OBSOLETE for (reg = 0; reg < NUM_REGS; reg++) */
/* OBSOLETE if (fi->fsr.regs[reg] == (unsigned) -1) */
/* OBSOLETE fi->fsr.regs[reg] = 0; /* unused entry */ */
/* OBSOLETE else */
/* OBSOLETE fi->fsr.regs[reg] += fi->frame - fi->frameoffset; */
/* OBSOLETE } */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE /* Function: find_callers_reg */
/* OBSOLETE Find REGNUM on the stack. Otherwise, it's in an active register. One thing */
/* OBSOLETE we might want to do here is to check REGNUM against the clobber mask, and */
/* OBSOLETE somehow flag it as invalid if it isn't saved on the stack somewhere. This */
/* OBSOLETE would provide a graceful failure mode when trying to get the value of */
/* OBSOLETE caller-saves registers for an inner frame. */ */
/* OBSOLETE */
/* OBSOLETE CORE_ADDR */
/* OBSOLETE tic80_find_callers_reg (struct frame_info *fi, int regnum) */
/* OBSOLETE { */
/* OBSOLETE for (; fi; fi = fi->next) */
/* OBSOLETE if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) */
/* OBSOLETE return generic_read_register_dummy (fi->pc, fi->frame, regnum); */
/* OBSOLETE else if (fi->fsr.regs[regnum] != 0) */
/* OBSOLETE return read_memory_integer (fi->fsr.regs[regnum], */
/* OBSOLETE REGISTER_RAW_SIZE (regnum)); */
/* OBSOLETE return read_register (regnum); */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE /* Function: frame_chain */
/* OBSOLETE Given a GDB frame, determine the address of the calling function's frame. */
/* OBSOLETE This will be used to create a new GDB frame struct, and then */
/* OBSOLETE INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame. */
/* OBSOLETE For c80, we save the frame size when we initialize the frame_info. */ */
/* OBSOLETE */
/* OBSOLETE CORE_ADDR */
/* OBSOLETE tic80_frame_chain (struct frame_info *fi) */
/* OBSOLETE { */
/* OBSOLETE CORE_ADDR fn_start, callers_pc, fp; */
/* OBSOLETE */
/* OBSOLETE /* is this a dummy frame? */ */
/* OBSOLETE if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) */
/* OBSOLETE return fi->frame; /* dummy frame same as caller's frame */ */
/* OBSOLETE */
/* OBSOLETE /* is caller-of-this a dummy frame? */ */
/* OBSOLETE callers_pc = FRAME_SAVED_PC (fi); /* find out who called us: */ */
/* OBSOLETE fp = tic80_find_callers_reg (fi, FP_REGNUM); */
/* OBSOLETE if (PC_IN_CALL_DUMMY (callers_pc, fp, fp)) */
/* OBSOLETE return fp; /* dummy frame's frame may bear no relation to ours */ */
/* OBSOLETE */
/* OBSOLETE if (find_pc_partial_function (fi->pc, 0, &fn_start, 0)) */
/* OBSOLETE if (fn_start == entry_point_address ()) */
/* OBSOLETE return 0; /* in _start fn, don't chain further */ */
/* OBSOLETE */
/* OBSOLETE if (fi->framereg == FP_REGNUM) */
/* OBSOLETE return tic80_find_callers_reg (fi, FP_REGNUM); */
/* OBSOLETE else */
/* OBSOLETE return fi->frame + fi->framesize; */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE /* Function: pop_frame */
/* OBSOLETE Discard from the stack the innermost frame, */
/* OBSOLETE restoring all saved registers. */ */
/* OBSOLETE */
/* OBSOLETE struct frame_info * */
/* OBSOLETE tic80_pop_frame (struct frame_info *frame) */
/* OBSOLETE { */
/* OBSOLETE int regnum; */
/* OBSOLETE */
/* OBSOLETE if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame)) */
/* OBSOLETE generic_pop_dummy_frame (); */
/* OBSOLETE else */
/* OBSOLETE { */
/* OBSOLETE for (regnum = 0; regnum < NUM_REGS; regnum++) */
/* OBSOLETE if (frame->fsr.regs[regnum] != 0) */
/* OBSOLETE write_register (regnum, */
/* OBSOLETE read_memory_integer (frame->fsr.regs[regnum], 4)); */
/* OBSOLETE */
/* OBSOLETE write_register (PC_REGNUM, FRAME_SAVED_PC (frame)); */
/* OBSOLETE write_register (SP_REGNUM, read_register (FP_REGNUM)); */
/* OBSOLETE #if 0 */
/* OBSOLETE if (read_register (PSW_REGNUM) & 0x80) */
/* OBSOLETE write_register (SPU_REGNUM, read_register (SP_REGNUM)); */
/* OBSOLETE else */
/* OBSOLETE write_register (SPI_REGNUM, read_register (SP_REGNUM)); */
/* OBSOLETE #endif */
/* OBSOLETE } */
/* OBSOLETE flush_cached_frames (); */
/* OBSOLETE return NULL; */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE /* Function: frame_saved_pc */
/* OBSOLETE Find the caller of this frame. We do this by seeing if LR_REGNUM is saved */
/* OBSOLETE in the stack anywhere, otherwise we get it from the registers. */ */
/* OBSOLETE */
/* OBSOLETE CORE_ADDR */
/* OBSOLETE tic80_frame_saved_pc (struct frame_info *fi) */
/* OBSOLETE { */
/* OBSOLETE if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) */
/* OBSOLETE return generic_read_register_dummy (fi->pc, fi->frame, PC_REGNUM); */
/* OBSOLETE else */
/* OBSOLETE return tic80_find_callers_reg (fi, LR_REGNUM); */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE /* Function: tic80_push_return_address (pc, sp) */
/* OBSOLETE Set up the return address for the inferior function call. */
/* OBSOLETE Necessary for targets that don't actually execute a JSR/BSR instruction */
/* OBSOLETE (ie. when using an empty CALL_DUMMY) */ */
/* OBSOLETE */
/* OBSOLETE CORE_ADDR */
/* OBSOLETE tic80_push_return_address (CORE_ADDR pc, CORE_ADDR sp) */
/* OBSOLETE { */
/* OBSOLETE write_register (LR_REGNUM, CALL_DUMMY_ADDRESS ()); */
/* OBSOLETE return sp; */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE */
/* OBSOLETE /* Function: push_arguments */
/* OBSOLETE Setup the function arguments for calling a function in the inferior. */
/* OBSOLETE */
/* OBSOLETE On the TI C80 architecture, there are six register pairs (R2/R3 to R12/13) */
/* OBSOLETE which are dedicated for passing function arguments. Up to the first six */
/* OBSOLETE arguments (depending on size) may go into these registers. */
/* OBSOLETE The rest go on the stack. */
/* OBSOLETE */
/* OBSOLETE Arguments that are smaller than 4 bytes will still take up a whole */
/* OBSOLETE register or a whole 32-bit word on the stack, and will be */
/* OBSOLETE right-justified in the register or the stack word. This includes */
/* OBSOLETE chars, shorts, and small aggregate types. */
/* OBSOLETE */
/* OBSOLETE Arguments that are four bytes or less in size are placed in the */
/* OBSOLETE even-numbered register of a register pair, and the odd-numbered */
/* OBSOLETE register is not used. */
/* OBSOLETE */
/* OBSOLETE Arguments of 8 bytes size (such as floating point doubles) are placed */
/* OBSOLETE in a register pair. The least significant 32-bit word is placed in */
/* OBSOLETE the even-numbered register, and the most significant word in the */
/* OBSOLETE odd-numbered register. */
/* OBSOLETE */
/* OBSOLETE Aggregate types with sizes between 4 and 8 bytes are passed */
/* OBSOLETE entirely on the stack, and are left-justified within the */
/* OBSOLETE double-word (as opposed to aggregates smaller than 4 bytes */
/* OBSOLETE which are right-justified). */
/* OBSOLETE */
/* OBSOLETE Aggregates of greater than 8 bytes are first copied onto the stack, */
/* OBSOLETE and then a pointer to the copy is passed in the place of the normal */
/* OBSOLETE argument (either in a register if available, or on the stack). */
/* OBSOLETE */
/* OBSOLETE Functions that must return an aggregate type can return it in the */
/* OBSOLETE normal return value registers (R2 and R3) if its size is 8 bytes or */
/* OBSOLETE less. For larger return values, the caller must allocate space for */
/* OBSOLETE the callee to copy the return value to. A pointer to this space is */
/* OBSOLETE passed as an implicit first argument, always in R0. */ */
/* OBSOLETE */
/* OBSOLETE CORE_ADDR */
/* OBSOLETE tic80_push_arguments (int nargs, value_ptr *args, CORE_ADDR sp, */
/* OBSOLETE unsigned char struct_return, CORE_ADDR struct_addr) */
/* OBSOLETE { */
/* OBSOLETE int stack_offset, stack_alloc; */
/* OBSOLETE int argreg; */
/* OBSOLETE int argnum; */
/* OBSOLETE struct type *type; */
/* OBSOLETE CORE_ADDR regval; */
/* OBSOLETE char *val; */
/* OBSOLETE char valbuf[4]; */
/* OBSOLETE int len; */
/* OBSOLETE int odd_sized_struct; */
/* OBSOLETE int is_struct; */
/* OBSOLETE */
/* OBSOLETE /* first force sp to a 4-byte alignment */ */
/* OBSOLETE sp = sp & ~3; */
/* OBSOLETE */
/* OBSOLETE argreg = ARG0_REGNUM; */
/* OBSOLETE /* The "struct return pointer" pseudo-argument goes in R0 */ */
/* OBSOLETE if (struct_return) */
/* OBSOLETE write_register (argreg++, struct_addr); */
/* OBSOLETE */
/* OBSOLETE /* Now make sure there's space on the stack */ */
/* OBSOLETE for (argnum = 0, stack_alloc = 0; */
/* OBSOLETE argnum < nargs; argnum++) */
/* OBSOLETE stack_alloc += ((TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 3) & ~3); */
/* OBSOLETE sp -= stack_alloc; /* make room on stack for args */ */
/* OBSOLETE */
/* OBSOLETE */
/* OBSOLETE /* Now load as many as possible of the first arguments into */
/* OBSOLETE registers, and push the rest onto the stack. There are 16 bytes */
/* OBSOLETE in four registers available. Loop thru args from first to last. */ */
/* OBSOLETE */
/* OBSOLETE argreg = ARG0_REGNUM; */
/* OBSOLETE for (argnum = 0, stack_offset = 0; argnum < nargs; argnum++) */
/* OBSOLETE { */
/* OBSOLETE type = VALUE_TYPE (args[argnum]); */
/* OBSOLETE len = TYPE_LENGTH (type); */
/* OBSOLETE memset (valbuf, 0, sizeof (valbuf)); */
/* OBSOLETE val = (char *) VALUE_CONTENTS (args[argnum]); */
/* OBSOLETE */
/* OBSOLETE /* FIXME -- tic80 can take doubleword arguments in register pairs */ */
/* OBSOLETE is_struct = (type->code == TYPE_CODE_STRUCT); */
/* OBSOLETE odd_sized_struct = 0; */
/* OBSOLETE */
/* OBSOLETE if (!is_struct) */
/* OBSOLETE { */
/* OBSOLETE if (len < 4) */
/* OBSOLETE { /* value gets right-justified in the register or stack word */ */
/* OBSOLETE memcpy (valbuf + (4 - len), val, len); */
/* OBSOLETE val = valbuf; */
/* OBSOLETE } */
/* OBSOLETE if (len > 4 && (len & 3) != 0) */
/* OBSOLETE odd_sized_struct = 1; /* such structs go entirely on stack */ */
/* OBSOLETE } */
/* OBSOLETE else */
/* OBSOLETE { */
/* OBSOLETE /* Structs are always passed by reference. */ */
/* OBSOLETE write_register (argreg, sp + stack_offset); */
/* OBSOLETE argreg++; */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE while (len > 0) */
/* OBSOLETE { */
/* OBSOLETE if (is_struct || argreg > ARGLAST_REGNUM || odd_sized_struct) */
/* OBSOLETE { /* must go on the stack */ */
/* OBSOLETE write_memory (sp + stack_offset, val, 4); */
/* OBSOLETE stack_offset += 4; */
/* OBSOLETE } */
/* OBSOLETE /* NOTE WELL!!!!! This is not an "else if" clause!!! */
/* OBSOLETE That's because some things get passed on the stack */
/* OBSOLETE AND in the registers! */ */
/* OBSOLETE if (!is_struct && argreg <= ARGLAST_REGNUM) */
/* OBSOLETE { /* there's room in a register */ */
/* OBSOLETE regval = extract_address (val, REGISTER_RAW_SIZE (argreg)); */
/* OBSOLETE write_register (argreg, regval); */
/* OBSOLETE argreg += 2; /* FIXME -- what about doubleword args? */ */
/* OBSOLETE } */
/* OBSOLETE /* Store the value 4 bytes at a time. This means that things */
/* OBSOLETE larger than 4 bytes may go partly in registers and partly */
/* OBSOLETE on the stack. */ */
/* OBSOLETE len -= REGISTER_RAW_SIZE (argreg); */
/* OBSOLETE val += REGISTER_RAW_SIZE (argreg); */
/* OBSOLETE } */
/* OBSOLETE } */
/* OBSOLETE return sp; */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE /* Function: tic80_write_sp */
/* OBSOLETE Because SP is really a read-only register that mirrors either SPU or SPI, */
/* OBSOLETE we must actually write one of those two as well, depending on PSW. */ */
/* OBSOLETE */
/* OBSOLETE void */
/* OBSOLETE tic80_write_sp (CORE_ADDR val) */
/* OBSOLETE { */
/* OBSOLETE #if 0 */
/* OBSOLETE unsigned long psw = read_register (PSW_REGNUM); */
/* OBSOLETE */
/* OBSOLETE if (psw & 0x80) /* stack mode: user or interrupt */ */
/* OBSOLETE write_register (SPU_REGNUM, val); */
/* OBSOLETE else */
/* OBSOLETE write_register (SPI_REGNUM, val); */
/* OBSOLETE #endif */
/* OBSOLETE write_register (SP_REGNUM, val); */
/* OBSOLETE } */
/* OBSOLETE */
/* OBSOLETE void */
/* OBSOLETE _initialize_tic80_tdep (void) */
/* OBSOLETE { */
/* OBSOLETE tm_print_insn = print_insn_tic80; */
/* OBSOLETE } */