Wed Jan 22 01:31:16 1997 Geoffrey Noer <noer@cygnus.com>

Start mn10200 gdb port by adding copies of mn10300
        target-specific files with all instances of mn10300 changed
        to mn10200 to start with.
        * mn10200-tdep.c: new
        * config/mn10200/tm-mn10200.h: new, REGISTER_SIZE is 24 bits not 32,
        SP_REGNUM and FP_REGNUM are different, also no lar or lir.
        * config/mn10200/mn10200.mt: new
This commit is contained in:
Geoffrey Noer 1997-01-22 09:41:02 +00:00
parent 95b475477e
commit 879b939859
4 changed files with 539 additions and 0 deletions

View File

@ -1,3 +1,13 @@
Wed Jan 22 01:31:16 1997 Geoffrey Noer <noer@cygnus.com>
Start mn10200 gdb port by adding copies of mn10300
target-specific files with all instances of mn10300 changed
to mn10200 to start with.
* mn10200-tdep.c: new
* config/mn10200/tm-mn10200.h: new, REGISTER_SIZE is 24 bits not 32,
SP_REGNUM and FP_REGNUM are different, also no lar or lir.
* config/mn10200/mn10200.mt: new
Tue Jan 21 18:32:23 1997 Stu Grossman (grossman@lisa.cygnus.com)
* configure.in configure: Check if host has libdl if doing

View File

@ -0,0 +1,6 @@
# Target: Matsushita mn10200
TDEPFILES= mn10200-tdep.o
TM_FILE= tm-mn10200.h
SIM_OBS = remote-sim.o
SIM = ../sim/mn10200/libsim.a -lm

View File

@ -0,0 +1,145 @@
/* Parameters for execution on a Matsushita mn10200 processor.
Copyright 1997 Free Software Foundation, Inc.
Contributed by Geoffrey Noer <noer@cygnus.com>
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. */
#define TARGET_BYTE_ORDER LITTLE_ENDIAN
#define REGISTER_SIZE 3
#define MAX_REGISTER_RAW_SIZE REGISTER_SIZE
#define NUM_REGS 12
#define REGISTER_BYTES (NUM_REGS * REGISTER_SIZE)
#define REGISTER_NAMES \
{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", \
"sp", "pc", "mdr", "psw"}
#define FP_REGNUM 6
#define SP_REGNUM 7
#define PC_REGNUM 9
#define MDR_REGNUM 10
#define PSW_REGNUM 11
#define LIR_REGNUM 12
#define LAR_REGNUM 13
#define REGISTER_VIRTUAL_TYPE(REG) builtin_type_int
#define REGISTER_BYTE(REG) ((REG) * REGISTER_SIZE)
#define REGISTER_VIRTUAL_SIZE(REG) REGISTER_SIZE
#define REGISTER_RAW_SIZE(REG) REGISTER_SIZE
#define MAX_REGISTER_VIRTUAL_SIZE REGISTER_SIZE
#define BREAKPOINT {0xff}
#define FUNCTION_START_OFFSET 0
#define DECR_PC_AFTER_BREAK 0
#define INNER_THAN <
#define SAVED_PC_AFTER_CALL(frame) \
read_memory_integer (read_register (SP_REGNUM), REGISTER_SIZE)
#ifdef __STDC__
struct frame_info;
struct frame_saved_regs;
struct type;
struct value;
#endif
#define EXTRA_FRAME_INFO struct frame_saved_regs fsr;
extern void mn10200_init_extra_frame_info PARAMS ((struct frame_info *fi));
#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) mn10200_init_extra_frame_info (fi)
#define INIT_FRAME_PC /* Not necessary */
extern void mn10200_frame_find_saved_regs PARAMS ((struct frame_info *fi, struct frame_saved_regs *regaddr));
#define FRAME_FIND_SAVED_REGS(fi, regaddr) regaddr = fi->fsr
extern CORE_ADDR mn10200_frame_chain PARAMS ((struct frame_info *fi));
#define FRAME_CHAIN(fi) mn10200_frame_chain (fi)
#define FRAME_CHAIN_VALID(FP, FI) generic_frame_chain_valid (FP, FI)
extern CORE_ADDR mn10200_find_callers_reg PARAMS ((struct frame_info *fi, int regnum));
extern CORE_ADDR mn10200_frame_saved_pc PARAMS ((struct frame_info *));
#define FRAME_SAVED_PC(FI) (mn10200_frame_saved_pc (FI))
/* 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, REGBUF + REGISTER_BYTE (0), TYPE_LENGTH (TYPE))
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
extract_address (REGBUF + REGISTER_BYTE (0), \
REGISTER_RAW_SIZE (0))
#define STORE_RETURN_VALUE(TYPE, VALBUF) \
write_register_bytes(REGISTER_BYTE (0), VALBUF, TYPE_LENGTH (TYPE));
extern CORE_ADDR mn10200_skip_prologue PARAMS ((CORE_ADDR pc));
#define SKIP_PROLOGUE(pc) pc = mn10200_skip_prologue (pc)
#define FRAME_ARGS_SKIP 0
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
#define FRAME_NUM_ARGS(val, fi) ((val) = -1)
extern void mn10200_pop_frame PARAMS ((struct frame_info *frame));
#define POP_FRAME mn10200_pop_frame (get_current_frame ())
#define USE_GENERIC_DUMMY_FRAMES
#define CALL_DUMMY {0}
#undef CALL_DUMMY /* for now, no function calls */
#define CALL_DUMMY_START_OFFSET (0)
#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
#define FIX_CALL_DUMMY(DUMMY, START, FUNADDR, NARGS, ARGS, TYPE, GCCP)
#define CALL_DUMMY_ADDRESS() entry_point_address ()
extern CORE_ADDR mn10200_push_return_address PARAMS ((CORE_ADDR, CORE_ADDR));
#define PUSH_RETURN_ADDRESS(PC, SP) mn10200_push_return_address (PC, SP)
#define PUSH_DUMMY_FRAME generic_push_dummy_frame ()
extern CORE_ADDR
mn10200_push_arguments PARAMS ((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) \
(SP) = mn10200_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR)
#define STORE_STRUCT_RETURN(STRUCT_ADDR, SP)
#define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP)
#define USE_STRUCT_CONVENTION(GCC_P, TYPE) \
(TYPE_NFIELDS (TYPE) > 1 || TYPE_LENGTH (TYPE) > 4)
/* override the default get_saved_register function with
one that takes account of generic CALL_DUMMY frames */
#define GET_SAVED_REGISTER
/* Define this for Wingdb */
#define TARGET_MN10200

378
gdb/mn10200-tdep.c Normal file
View File

@ -0,0 +1,378 @@
/* Target-dependent code for the Matsushita MN10200 for GDB, the GNU debugger.
Copyright 1997 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 "frame.h"
#include "inferior.h"
#include "obstack.h"
#include "target.h"
#include "value.h"
#include "bfd.h"
#include "gdb_string.h"
#include "gdbcore.h"
#include "symfile.h"
/* Info gleaned from scanning a function's prologue. */
struct pifsr /* Info about one saved reg */
{
int framereg; /* Frame reg (SP or FP) */
int offset; /* Offset from framereg */
int reg; /* Saved register number */
};
struct prologue_info
{
int framereg;
int frameoffset;
int start_function;
struct pifsr *pifsrs;
};
/* Function: frame_chain
Figure out and return the caller's frame pointer given current
frame_info struct.
We start out knowing the current pc, current sp, current fp.
We want to determine the caller's fp and caller's pc. To do this
correctly, we have to be able to handle the case where we are in the
middle of the prologue which involves scanning the prologue.
We don't handle dummy frames yet but we would probably just return the
stack pointer that was in use at the time the function call was made?
*/
CORE_ADDR
mn10200_frame_chain (fi)
struct frame_info *fi;
{
struct prologue_info pi;
CORE_ADDR callers_pc, callers_fp, curr_sp;
CORE_ADDR past_prologue_addr;
int past_prologue = 1; /* default to being past prologue */
int n_movm_args = 4;
struct pifsr *pifsr, *pifsr_tmp;
/* current pc is fi->pc */
/* current fp is fi->frame */
/* current sp is: */
curr_sp = read_register (SP_REGNUM);
/*
printf("curr pc = 0x%x ; curr fp = 0x%x ; curr sp = 0x%x\n",
fi->pc, fi->frame, curr_sp);
*/
/* first inst after prologue is: */
past_prologue_addr = mn10200_skip_prologue (fi->pc);
/* Are we in the prologue? */
/* Yes if mn10200_skip_prologue returns an address after the
current pc in which case we have to scan prologue */
if (fi->pc < mn10200_skip_prologue (fi->pc))
past_prologue = 0;
/* scan prologue if we're not past it */
if (!past_prologue)
{
/* printf("scanning prologue\n"); */
/* FIXME -- fill out this case later */
return 0x666; /* bogus value */
}
if (past_prologue) /* if we don't need to scan the prologue */
{
/* printf("we're past the prologue\n"); */
callers_pc = fi->frame - REGISTER_SIZE;
callers_fp = fi->frame - ((n_movm_args + 1) * REGISTER_SIZE);
/*
printf("callers_pc = 0x%x ; callers_fp = 0x%x\n",
callers_pc, callers_fp);
printf("*callers_pc = 0x%x ; *callers_fp = 0x%x\n",
read_memory_integer(callers_pc, REGISTER_SIZE),
read_memory_integer(callers_fp, REGISTER_SIZE));
*/
return read_memory_integer(callers_fp, REGISTER_SIZE);
}
/* we don't get here */
}
/* 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
mn10200_find_callers_reg (fi, regnum)
struct frame_info *fi;
int regnum;
{
/* printf("mn10200_find_callers_reg\n"); */
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_unsigned_integer (fi->fsr.regs[regnum],
REGISTER_RAW_SIZE(regnum));
return read_register (regnum);
}
/* Function: skip_prologue
Return the address of the first inst past the prologue of the function.
*/
CORE_ADDR
mn10200_skip_prologue (pc)
CORE_ADDR pc;
{
CORE_ADDR func_addr, func_end;
/* printf("mn10200_skip_prologue\n"); */
/* See what the symbol table says */
if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
{
struct symtab_and_line sal;
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: pop_frame
This routine gets called when either the user uses the `return'
command, or the call dummy breakpoint gets hit. */
void
mn10200_pop_frame (frame)
struct frame_info *frame;
{
int regnum;
/* printf("mn10200_pop_frame start\n"); */
if (PC_IN_CALL_DUMMY(frame->pc, frame->frame, frame->frame))
generic_pop_dummy_frame ();
else
{
write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
for (regnum = 0; regnum < NUM_REGS; regnum++)
if (frame->fsr.regs[regnum] != 0)
write_register (regnum,
read_memory_unsigned_integer (frame->fsr.regs[regnum],
REGISTER_RAW_SIZE(regnum)));
write_register (SP_REGNUM, FRAME_FP (frame));
}
flush_cached_frames ();
/* printf("mn10200_pop_frame end\n"); */
}
/* Function: push_arguments
Setup arguments for a call to the target. Arguments go in
order on the stack.
*/
CORE_ADDR
mn10200_push_arguments (nargs, args, sp, struct_return, struct_addr)
int nargs;
value_ptr *args;
CORE_ADDR sp;
unsigned char struct_return;
CORE_ADDR struct_addr;
{
int argnum = 0;
int len = 0;
int stack_offset = 0; /* copy args to this offset onto stack */
/* printf("mn10200_push_arguments start\n"); */
/* First, just for safety, make sure stack is aligned */
sp &= ~3;
/* Now make space on the stack for the args. */
for (argnum = 0; argnum < nargs; argnum++)
len += ((TYPE_LENGTH(VALUE_TYPE(args[argnum])) + 3) & ~3);
sp -= len;
/* Push all arguments onto the stack. */
for (argnum = 0; argnum < nargs; argnum++)
{
int len;
char *val;
if (TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_STRUCT
&& TYPE_LENGTH (VALUE_TYPE (*args)) > 8)
{
/* for now, pretend structs aren't special */
len = TYPE_LENGTH (VALUE_TYPE (*args));
val = (char *)VALUE_CONTENTS (*args);
}
else
{
len = TYPE_LENGTH (VALUE_TYPE (*args));
val = (char *)VALUE_CONTENTS (*args);
}
while (len > 0)
{
write_memory (sp + stack_offset, val, 4);
len -= 4;
val += 4;
stack_offset += 4;
}
args++;
}
/* printf"mn10200_push_arguments end\n"); */
return sp;
}
/* Function: push_return_address (pc)
Set up the return address for the inferior function call.
Needed for targets where we don't actually execute a JSR/BSR instruction */
CORE_ADDR
mn10200_push_return_address (pc, sp)
CORE_ADDR pc;
CORE_ADDR sp;
{
/* printf("mn10200_push_return_address\n"); */
/* write_register (RP_REGNUM, CALL_DUMMY_ADDRESS ()); */
return sp;
}
/* Function: frame_saved_pc
Find the caller of this frame. We do this by seeing if RP_REGNUM
is saved in the stack anywhere, otherwise we get it from the
registers. If the inner frame is a dummy frame, return its PC
instead of RP, because that's where "caller" of the dummy-frame
will be found. */
CORE_ADDR
mn10200_frame_saved_pc (fi)
struct frame_info *fi;
{
/* printf("mn10200_frame_saved_pc\n"); */
return (read_memory_integer(fi->frame - REGISTER_SIZE, REGISTER_SIZE));
}
void
get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
char *raw_buffer;
int *optimized;
CORE_ADDR *addrp;
struct frame_info *frame;
int regnum;
enum lval_type *lval;
{
/* printf("get_saved_register\n"); */
generic_get_saved_register (raw_buffer, optimized, addrp,
frame, regnum, lval);
}
/* Function: init_extra_frame_info
Setup the frame's frame pointer, pc, and frame addresses for saved
registers. Most of the work is done in frame_chain().
Note that when we are called for the last frame (currently active frame),
that fi->pc and fi->frame will already be setup. However, fi->frame will
be valid only if this routine uses FP. For previous frames, fi-frame will
always be correct (since that is derived from v850_frame_chain ()).
We can be called with the PC in the call dummy under two circumstances.
First, during normal backtracing, second, while figuring out the frame
pointer just prior to calling the target function (see run_stack_dummy).
*/
void
mn10200_init_extra_frame_info (fi)
struct frame_info *fi;
{
struct prologue_info pi;
struct pifsr pifsrs[NUM_REGS + 1], *pifsr;
int reg;
if (fi->next)
fi->pc = FRAME_SAVED_PC (fi->next);
memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
/* The call dummy doesn't save any registers on the stack, so we can return
now. */
/*
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
return;
pi.pifsrs = pifsrs;
*/
/* v850_scan_prologue (fi->pc, &pi); */
/*
if (!fi->next && pi.framereg == SP_REGNUM)
fi->frame = read_register (pi.framereg) - pi.frameoffset;
for (pifsr = pifsrs; pifsr->framereg; pifsr++)
{
fi->fsr.regs[pifsr->reg] = pifsr->offset + fi->frame;
if (pifsr->framereg == SP_REGNUM)
fi->fsr.regs[pifsr->reg] += pi.frameoffset;
}
*/
/* printf("init_extra_frame_info\n"); */
}
void
_initialize_mn10200_tdep ()
{
/* printf("_initialize_mn10200_tdep\n"); */
tm_print_insn = print_insn_mn10200;
}