These files are for an arch we don't care about.

This commit is contained in:
David E. O'Brien 2000-08-04 08:34:04 +00:00
parent 2111e67c80
commit 3378439583
8 changed files with 0 additions and 5171 deletions

View File

@ -1,169 +0,0 @@
/* Remote debugging interface for ABug Rom monitor for GDB, the GNU debugger.
Copyright 1995, 1996, 1998 Free Software Foundation, Inc.
Written by Rob Savoye of Cygnus Support
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 "gdbcore.h"
#include "target.h"
#include "monitor.h"
#include "serial.h"
/* Prototypes for local functions. */
static void abug_open PARAMS ((char *args, int from_tty));
static void
abug_supply_register (regname, regnamelen, val, vallen)
char *regname;
int regnamelen;
char *val;
int vallen;
{
int regno;
if (regnamelen != 2)
return;
switch (regname[0])
{
case 'S':
if (regname[1] != 'R')
return;
regno = PS_REGNUM;
break;
case 'P':
if (regname[1] != 'C')
return;
regno = PC_REGNUM;
break;
case 'D':
if (regname[1] < '0' || regname[1] > '7')
return;
regno = regname[1] - '0' + D0_REGNUM;
break;
case 'A':
if (regname[1] < '0' || regname[1] > '7')
return;
regno = regname[1] - '0' + A0_REGNUM;
break;
default:
return;
}
monitor_supply_register (regno, val);
}
/*
* This array of registers needs to match the indexes used by GDB. The
* whole reason this exists is because the various ROM monitors use
* different names than GDB does, and don't support all the
* registers either. So, typing "info reg sp" becomes an "A7".
*/
static char *abug_regnames[NUM_REGS] =
{
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
"PC",
};
/*
* Define the monitor command strings. Since these are passed directly
* through to a printf style function, we need can include formatting
* strings. We also need a CR or LF on the end.
*/
static struct target_ops abug_ops;
static char *abug_inits[] = {"\r", NULL};
static struct monitor_ops abug_cmds ;
static void
init_abug_cmds(void)
{
abug_cmds.flags = MO_CLR_BREAK_USES_ADDR;
abug_cmds.init = abug_inits; /* Init strings */
abug_cmds.cont = "g\r"; /* continue command */
abug_cmds.step = "t\r"; /* single step */
abug_cmds.stop = NULL; /* interrupt command */
abug_cmds.set_break = "br %x\r"; /* set a breakpoint */
abug_cmds.clr_break = "nobr %x\r"; /* clear a breakpoint */
abug_cmds.clr_all_break = "nobr\r"; /* clear all breakpoints */
abug_cmds.fill = "bf %x:%x %x;b\r"; /* fill (start count val) */
abug_cmds.setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */
abug_cmds.setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */
abug_cmds.setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */
abug_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
abug_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
abug_cmds.setmem.term = NULL; /* setreg.term */
abug_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
abug_cmds.getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */
abug_cmds.getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */
abug_cmds.getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */
abug_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
abug_cmds.getmem.resp_delim = " "; /* getmem.resp_delim */
abug_cmds.getmem.term = NULL; /* getmem.term */
abug_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
abug_cmds.setreg.cmd = "rm %s %x\r"; /* setreg.cmd (name, value) */
abug_cmds.setreg.resp_delim = "="; /* setreg.resp_delim */
abug_cmds.setreg.term = "? "; /* setreg.term */
abug_cmds.setreg.term_cmd = ".\r" ; /* setreg.term_cmd */
abug_cmds.getreg.cmd = "rm %s\r"; /* getreg.cmd (name) */
abug_cmds.getreg.resp_delim = "="; /* getreg.resp_delim */
abug_cmds.getreg.term = "? "; /* getreg.term */
abug_cmds.getreg.term_cmd = ".\r" ; /* getreg.term_cmd */
abug_cmds.dump_registers = "rd\r"; /* dump_registers */
abug_cmds.register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
abug_cmds.supply_register = abug_supply_register; /* supply_register */
abug_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
abug_cmds.load = "lo 0\r"; /* download command */
abug_cmds.loadresp = "\n"; /* load response */
abug_cmds.prompt = "135Bug>"; /* monitor command prompt */
abug_cmds.line_term = "\r"; /* end-of-line terminator */
abug_cmds.cmd_end = NULL; /* optional command terminator */
abug_cmds.target = &abug_ops; /* target operations */
abug_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
abug_cmds.regnames = abug_regnames; /* registers names */
abug_cmds.magic = MONITOR_OPS_MAGIC ; /* magic */
};
static void
abug_open(args, from_tty)
char *args;
int from_tty;
{
monitor_open (args, &abug_cmds, from_tty);
}
void
_initialize_abug_rom ()
{
init_abug_cmds() ;
init_monitor_ops (&abug_ops);
abug_ops.to_shortname = "abug";
abug_ops.to_longname = "ABug monitor";
abug_ops.to_doc = "Debug via the ABug monitor.\n\
Specify the serial device it is connected to (e.g. /dev/ttya).";
abug_ops.to_open = abug_open;
add_target (&abug_ops);
}

View File

@ -1,552 +0,0 @@
/* Target-dependent code for the Fujitsu FR30.
Copyright 1999, 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"
/* Function: pop_frame
This routine gets called when either the user uses the `return'
command, or the call dummy breakpoint gets hit. */
void
fr30_pop_frame ()
{
struct frame_info *frame = get_current_frame();
int regnum;
CORE_ADDR sp = read_register(SP_REGNUM);
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, sp + frame->framesize);
}
flush_cached_frames ();
}
/* Function: skip_prologue
Return the address of the first code past the prologue of the function. */
CORE_ADDR
fr30_skip_prologue(CORE_ADDR pc)
{
CORE_ADDR func_addr, func_end;
/* 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;
}
}
/* Either we didn't find the start of this function (nothing we can do),
or there's no line info, or the line after the prologue is after
the end of the function (there probably isn't a prologue). */
return pc;
}
/* Function: push_arguments
Setup arguments and RP for a call to the target. First four args
go in FIRST_ARGREG -> LAST_ARGREG, subsequent args go on stack...
Structs are passed by reference. XXX not right now Z.R.
64 bit quantities (doubles and long longs) may be split between
the regs and the stack.
When calling a function that returns a struct, a pointer to the struct
is passed in as a secret first argument (always in FIRST_ARGREG).
Stack space for the args has NOT been allocated: that job is up to us.
*/
CORE_ADDR
fr30_push_arguments(nargs, args, sp, struct_return, struct_addr)
int nargs;
value_ptr * args;
CORE_ADDR sp;
int struct_return;
CORE_ADDR struct_addr;
{
int argreg;
int argnum;
int stack_offset;
struct stack_arg {
char *val;
int len;
int offset;
};
struct stack_arg *stack_args =
(struct stack_arg*)alloca (nargs * sizeof (struct stack_arg));
int nstack_args = 0;
argreg = FIRST_ARGREG;
/* the struct_return pointer occupies the first parameter-passing reg */
if (struct_return)
write_register (argreg++, struct_addr);
stack_offset = 0;
/* Process args from left to right. Store as many as allowed in
registers, save the rest to be pushed on the stack */
for(argnum = 0; argnum < nargs; argnum++)
{
char * val;
value_ptr arg = args[argnum];
struct type * arg_type = check_typedef (VALUE_TYPE (arg));
struct type * target_type = TYPE_TARGET_TYPE (arg_type);
int len = TYPE_LENGTH (arg_type);
enum type_code typecode = TYPE_CODE (arg_type);
CORE_ADDR regval;
int newarg;
val = (char *) VALUE_CONTENTS (arg);
{
/* Copy the argument to general registers or the stack in
register-sized pieces. Large arguments are split between
registers and stack. */
while (len > 0)
{
if (argreg <= LAST_ARGREG)
{
int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
regval = extract_address (val, partial_len);
/* It's a simple argument being passed in a general
register. */
write_register (argreg, regval);
argreg++;
len -= partial_len;
val += partial_len;
}
else
{
/* keep for later pushing */
stack_args[nstack_args].val = val;
stack_args[nstack_args++].len = len;
break;
}
}
}
}
/* now do the real stack pushing, process args right to left */
while(nstack_args--)
{
sp -= stack_args[nstack_args].len;
write_memory(sp, stack_args[nstack_args].val,
stack_args[nstack_args].len);
}
/* Return adjusted stack pointer. */
return sp;
}
_initialize_fr30_tdep()
{
extern int print_insn_fr30(bfd_vma, disassemble_info *);
tm_print_insn = print_insn_fr30;
}
/* Function: check_prologue_cache
Check if prologue for this frame's PC has already been scanned.
If it has, copy the relevant information about that prologue and
return non-zero. Otherwise do not copy anything and return zero.
The information saved in the cache includes:
* the frame register number;
* the size of the stack frame;
* the offsets of saved regs (relative to the old SP); and
* the offset from the stack pointer to the frame pointer
The cache contains only one entry, since this is adequate
for the typical sequence of prologue scan requests we get.
When performing a backtrace, GDB will usually ask to scan
the same function twice in a row (once to get the frame chain,
and once to fill in the extra frame information).
*/
static struct frame_info prologue_cache;
static int
check_prologue_cache (fi)
struct frame_info * fi;
{
int i;
if (fi->pc == prologue_cache.pc)
{
fi->framereg = prologue_cache.framereg;
fi->framesize = prologue_cache.framesize;
fi->frameoffset = prologue_cache.frameoffset;
for (i = 0; i <= NUM_REGS; i++)
fi->fsr.regs[i] = prologue_cache.fsr.regs[i];
return 1;
}
else
return 0;
}
/* Function: save_prologue_cache
Copy the prologue information from fi to the prologue cache.
*/
static void
save_prologue_cache (fi)
struct frame_info * fi;
{
int i;
prologue_cache.pc = fi->pc;
prologue_cache.framereg = fi->framereg;
prologue_cache.framesize = fi->framesize;
prologue_cache.frameoffset = fi->frameoffset;
for (i = 0; i <= NUM_REGS; i++) {
prologue_cache.fsr.regs[i] = fi->fsr.regs[i];
}
}
/* Function: scan_prologue
Scan the prologue of the function that contains PC, and record what
we find in PI. PI->fsr must be zeroed by the called. Returns the
pc after the prologue. Note that the addresses saved in pi->fsr
are actually just frame relative (negative offsets from the frame
pointer). This is because we don't know the actual value of the
frame pointer yet. In some circumstances, the frame pointer can't
be determined till after we have scanned the prologue. */
static void
fr30_scan_prologue (fi)
struct frame_info * fi;
{
int sp_offset, fp_offset;
CORE_ADDR prologue_start, prologue_end, current_pc;
/* Check if this function is already in the cache of frame information. */
if (check_prologue_cache (fi))
return;
/* Assume there is no frame until proven otherwise. */
fi->framereg = SP_REGNUM;
fi->framesize = 0;
fi->frameoffset = 0;
/* Find the function prologue. If we can't find the function in
the symbol table, peek in the stack frame to find the PC. */
if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
{
/* Assume the prologue is everything between the first instruction
in the function and the first source line. */
struct symtab_and_line sal = find_pc_line (prologue_start, 0);
if (sal.line == 0) /* no line info, use current PC */
prologue_end = fi->pc;
else if (sal.end < prologue_end) /* next line begins after fn end */
prologue_end = sal.end; /* (probably means no prologue) */
}
else
{
/* XXX Z.R. What now??? The following is entirely bogus */
prologue_start = (read_memory_integer (fi->frame, 4) & 0x03fffffc) - 12;
prologue_end = prologue_start + 40;
}
/* Now search the prologue looking for instructions that set up the
frame pointer, adjust the stack pointer, and save registers. */
sp_offset = fp_offset = 0;
for (current_pc = prologue_start; current_pc < prologue_end; current_pc += 2)
{
unsigned int insn;
insn = read_memory_unsigned_integer (current_pc, 2);
if ((insn & 0xfe00) == 0x8e00) /* stm0 or stm1 */
{
int reg, mask = insn & 0xff;
/* scan in one sweep - create virtual 16-bit mask from either insn's mask */
if((insn & 0x0100) == 0)
{
mask <<= 8; /* stm0 - move to upper byte in virtual mask */
}
/* Calculate offsets of saved registers (to be turned later into addresses). */
for (reg = R4_REGNUM; reg <= R11_REGNUM; reg++)
if (mask & (1 << (15 - reg)))
{
sp_offset -= 4;
fi->fsr.regs[reg] = sp_offset;
}
}
else if((insn & 0xfff0) == 0x1700) /* st rx,@-r15 */
{
int reg = insn & 0xf;
sp_offset -= 4;
fi->fsr.regs[reg] = sp_offset;
}
else if((insn & 0xff00) == 0x0f00) /* enter */
{
fp_offset = fi->fsr.regs[FP_REGNUM] = sp_offset - 4;
sp_offset -= 4 * (insn & 0xff);
fi->framereg = FP_REGNUM;
}
else if(insn == 0x1781) /* st rp,@-sp */
{
sp_offset -= 4;
fi->fsr.regs[RP_REGNUM] = sp_offset;
}
else if(insn == 0x170e) /* st fp,@-sp */
{
sp_offset -= 4;
fi->fsr.regs[FP_REGNUM] = sp_offset;
}
else if(insn == 0x8bfe) /* mov sp,fp */
{
fi->framereg = FP_REGNUM;
}
else if((insn & 0xff00) == 0xa300) /* addsp xx */
{
sp_offset += 4 * (signed char)(insn & 0xff);
}
else if((insn & 0xff0f) == 0x9b00 && /* ldi:20 xx,r0 */
read_memory_unsigned_integer(current_pc+4, 2)
== 0xac0f) /* sub r0,sp */
{
/* large stack adjustment */
sp_offset -= (((insn & 0xf0) << 12) | read_memory_unsigned_integer(current_pc+2, 2));
current_pc += 4;
}
else if(insn == 0x9f80 && /* ldi:32 xx,r0 */
read_memory_unsigned_integer(current_pc+6, 2)
== 0xac0f) /* sub r0,sp */
{
/* large stack adjustment */
sp_offset -=
(read_memory_unsigned_integer(current_pc+2, 2) << 16 |
read_memory_unsigned_integer(current_pc+4, 2));
current_pc += 6;
}
}
/* The frame size is just the negative of the offset (from the original SP)
of the last thing thing we pushed on the stack. The frame offset is
[new FP] - [new SP]. */
fi->framesize = -sp_offset;
fi->frameoffset = fp_offset - sp_offset;
save_prologue_cache (fi);
}
/* 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 scan_prologue().
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 fr30_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
fr30_init_extra_frame_info (fi)
struct frame_info * fi;
{
int reg;
if (fi->next)
fi->pc = FRAME_SAVED_PC (fi->next);
memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
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;
}
fr30_scan_prologue (fi);
if (!fi->next) /* this is the innermost frame? */
fi->frame = read_register (fi->framereg);
else /* not the innermost frame */
/* If we have an FP, the callee saved it. */
if (fi->framereg == FP_REGNUM)
if (fi->next->fsr.regs[fi->framereg] != 0)
fi->frame = read_memory_integer (fi->next->fsr.regs[fi->framereg],
4);
/* Calculate actual addresses of saved registers using offsets determined
by fr30_scan_prologue. */
for (reg = 0; reg < NUM_REGS; reg++)
if (fi->fsr.regs[reg] != 0) {
fi->fsr.regs[reg] += fi->frame + fi->framesize - 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
fr30_find_callers_reg (fi, regnum)
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_unsigned_integer (fi->fsr.regs[regnum],
REGISTER_RAW_SIZE(regnum));
return read_register (regnum);
}
/* Function: frame_chain
Figure out the frame prior to FI. Unfortunately, this involves
scanning the prologue of the caller, which will also be done
shortly by fr30_init_extra_frame_info. For the dummy frame, we
just return the stack pointer that was in use at the time the
function call was made. */
CORE_ADDR
fr30_frame_chain (fi)
struct frame_info * fi;
{
CORE_ADDR fn_start, callers_pc, fp;
struct frame_info caller_fi;
int framereg;
/* 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 = fr30_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 */
framereg = fi->framereg;
/* If the caller is the startup code, we're at the end of the chain. */
if (find_pc_partial_function (callers_pc, 0, &fn_start, 0))
if (fn_start == entry_point_address ())
return 0;
memset (& caller_fi, 0, sizeof (caller_fi));
caller_fi.pc = callers_pc;
fr30_scan_prologue (& caller_fi);
framereg = caller_fi.framereg;
/* If the caller used a frame register, return its value.
Otherwise, return the caller's stack pointer. */
if (framereg == FP_REGNUM)
return fr30_find_callers_reg (fi, framereg);
else
return fi->frame + fi->framesize;
}
/* 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
fr30_frame_saved_pc (fi)
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 fr30_find_callers_reg (fi, RP_REGNUM);
}
/* Function: fix_call_dummy
Pokes the callee function's address into the CALL_DUMMY assembly stub.
Assumes that the CALL_DUMMY looks like this:
jarl <offset24>, r31
trap
*/
int
fr30_fix_call_dummy (dummy, sp, fun, nargs, args, type, gcc_p)
char *dummy;
CORE_ADDR sp;
CORE_ADDR fun;
int nargs;
value_ptr *args;
struct type *type;
int gcc_p;
{
long offset24;
offset24 = (long) fun - (long) entry_point_address ();
offset24 &= 0x3fffff;
offset24 |= 0xff800000; /* jarl <offset24>, r31 */
store_unsigned_integer ((unsigned int *)&dummy[2], 2, offset24 & 0xffff);
store_unsigned_integer ((unsigned int *)&dummy[0], 2, offset24 >> 16);
return 0;
}

View File

@ -1,155 +0,0 @@
/* Motorola m68k native support for Linux
Copyright (C) 1996,1998 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 "language.h"
#include "gdbcore.h"
#ifdef USG
#include <sys/types.h>
#endif
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/user.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/procfs.h>
#include <sys/file.h>
#include "gdb_stat.h"
#include "floatformat.h"
#include "target.h"
/* This table must line up with REGISTER_NAMES in tm-m68k.h */
static const int regmap[] =
{
PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7,
PT_A0, PT_A1, PT_A2, PT_A3, PT_A4, PT_A5, PT_A6, PT_USP,
PT_SR, PT_PC,
/* PT_FP0, ..., PT_FP7 */
21, 24, 27, 30, 33, 36, 39, 42,
/* PT_FPCR, PT_FPSR, PT_FPIAR */
45, 46, 47
};
/* BLOCKEND is the value of u.u_ar0, and points to the place where GS
is stored. */
int
m68k_linux_register_u_addr (blockend, regnum)
int blockend;
int regnum;
{
return (blockend + 4 * regmap[regnum]);
}
/* Given a pointer to a general register set in /proc format (gregset_t *),
unpack the register contents and supply them as gdb's idea of the current
register values. */
/* Note both m68k-tdep.c and m68klinux-nat.c contain definitions
for supply_gregset and supply_fpregset. The definitions
in m68k-tdep.c are valid if USE_PROC_FS is defined. Otherwise,
the definitions in m68klinux-nat.c will be used. This is a
bit of a hack. The supply_* routines do not belong in
*_tdep.c files. But, there are several lynx ports that currently
depend on these definitions. */
#ifndef USE_PROC_FS
void
supply_gregset (gregsetp)
gregset_t *gregsetp;
{
int regi;
for (regi = D0_REGNUM ; regi <= SP_REGNUM ; regi++)
supply_register (regi, (char *) (*gregsetp + regmap[regi]));
supply_register (PS_REGNUM, (char *) (*gregsetp + PT_SR));
supply_register (PC_REGNUM, (char *) (*gregsetp + PT_PC));
}
/* Given a pointer to a floating point register set in /proc format
(fpregset_t *), unpack the register contents and supply them as gdb's
idea of the current floating point register values. */
void
supply_fpregset (fpregsetp)
fpregset_t *fpregsetp;
{
int regi;
for (regi = FP0_REGNUM ; regi < FPC_REGNUM ; regi++)
supply_register (regi, (char *) &fpregsetp->fpregs[(regi - FP0_REGNUM) * 3]);
supply_register (FPC_REGNUM, (char *) &fpregsetp->fpcntl[0]);
supply_register (FPS_REGNUM, (char *) &fpregsetp->fpcntl[1]);
supply_register (FPI_REGNUM, (char *) &fpregsetp->fpcntl[2]);
}
#endif
int
kernel_u_size ()
{
return (sizeof (struct user));
}
/* Return non-zero if PC points into the signal trampoline. */
int
in_sigtramp (pc)
CORE_ADDR pc;
{
CORE_ADDR sp;
char buf[TARGET_SHORT_BIT / TARGET_CHAR_BIT];
int insn;
sp = read_register (SP_REGNUM);
if (pc - 2 < sp)
return 0;
if (read_memory_nobpt (pc, buf, sizeof (buf)))
return 0;
insn = extract_unsigned_integer (buf, sizeof (buf));
if (insn == 0xdefc /* addaw #,sp */
|| insn == 0x7077 /* moveq #119,d0 */
|| insn == 0x4e40 /* trap #0 */
|| insn == 0x203c /* movel #,d0 */)
return 1;
if (read_memory_nobpt (pc - 2, buf, sizeof (buf)))
return 0;
insn = extract_unsigned_integer (buf, sizeof (buf));
if (insn == 0xdefc /* addaw #,sp */
|| insn == 0x7077 /* moveq #119,d0 */
|| insn == 0x4e40 /* trap #0 */
|| insn == 0x203c /* movel #,d0 */)
return 1;
return 0;
}

View File

@ -1,353 +0,0 @@
/* Functions specific to running gdb native on an ns32k running NetBSD
Copyright 1989, 1992, 1993, 1994, 1996 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 <sys/types.h>
#include <sys/ptrace.h>
#include <machine/reg.h>
#include <machine/frame.h>
#include <machine/pcb.h>
#include "defs.h"
#include "inferior.h"
#include "target.h"
#include "gdbcore.h"
#define RF(dst, src) \
memcpy(&registers[REGISTER_BYTE(dst)], &src, sizeof(src))
#define RS(src, dst) \
memcpy(&dst, &registers[REGISTER_BYTE(src)], sizeof(dst))
void
fetch_inferior_registers (regno)
int regno;
{
struct reg inferior_registers;
struct fpreg inferior_fpregisters;
ptrace (PT_GETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_registers, 0);
ptrace (PT_GETFPREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_fpregisters, 0);
RF(R0_REGNUM + 0, inferior_registers.r_r0);
RF(R0_REGNUM + 1, inferior_registers.r_r1);
RF(R0_REGNUM + 2, inferior_registers.r_r2);
RF(R0_REGNUM + 3, inferior_registers.r_r3);
RF(R0_REGNUM + 4, inferior_registers.r_r4);
RF(R0_REGNUM + 5, inferior_registers.r_r5);
RF(R0_REGNUM + 6, inferior_registers.r_r6);
RF(R0_REGNUM + 7, inferior_registers.r_r7);
RF(SP_REGNUM , inferior_registers.r_sp);
RF(FP_REGNUM , inferior_registers.r_fp);
RF(PC_REGNUM , inferior_registers.r_pc);
RF(PS_REGNUM , inferior_registers.r_psr);
RF(FPS_REGNUM , inferior_fpregisters.r_fsr);
RF(FP0_REGNUM +0, inferior_fpregisters.r_freg[0]);
RF(FP0_REGNUM +2, inferior_fpregisters.r_freg[2]);
RF(FP0_REGNUM +4, inferior_fpregisters.r_freg[4]);
RF(FP0_REGNUM +6, inferior_fpregisters.r_freg[6]);
RF(LP0_REGNUM + 1, inferior_fpregisters.r_freg[1]);
RF(LP0_REGNUM + 3, inferior_fpregisters.r_freg[3]);
RF(LP0_REGNUM + 5, inferior_fpregisters.r_freg[5]);
RF(LP0_REGNUM + 7, inferior_fpregisters.r_freg[7]);
registers_fetched ();
}
void
store_inferior_registers (regno)
int regno;
{
struct reg inferior_registers;
struct fpreg inferior_fpregisters;
RS(R0_REGNUM + 0, inferior_registers.r_r0);
RS(R0_REGNUM + 1, inferior_registers.r_r1);
RS(R0_REGNUM + 2, inferior_registers.r_r2);
RS(R0_REGNUM + 3, inferior_registers.r_r3);
RS(R0_REGNUM + 4, inferior_registers.r_r4);
RS(R0_REGNUM + 5, inferior_registers.r_r5);
RS(R0_REGNUM + 6, inferior_registers.r_r6);
RS(R0_REGNUM + 7, inferior_registers.r_r7);
RS(SP_REGNUM , inferior_registers.r_sp);
RS(FP_REGNUM , inferior_registers.r_fp);
RS(PC_REGNUM , inferior_registers.r_pc);
RS(PS_REGNUM , inferior_registers.r_psr);
RS(FPS_REGNUM , inferior_fpregisters.r_fsr);
RS(FP0_REGNUM +0, inferior_fpregisters.r_freg[0]);
RS(FP0_REGNUM +2, inferior_fpregisters.r_freg[2]);
RS(FP0_REGNUM +4, inferior_fpregisters.r_freg[4]);
RS(FP0_REGNUM +6, inferior_fpregisters.r_freg[6]);
RS(LP0_REGNUM + 1, inferior_fpregisters.r_freg[1]);
RS(LP0_REGNUM + 3, inferior_fpregisters.r_freg[3]);
RS(LP0_REGNUM + 5, inferior_fpregisters.r_freg[5]);
RS(LP0_REGNUM + 7, inferior_fpregisters.r_freg[7]);
ptrace (PT_SETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_registers, 0);
ptrace (PT_SETFPREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_fpregisters, 0);
}
/* XXX - Add this to machine/regs.h instead? */
struct coreregs {
struct reg intreg;
struct fpreg freg;
};
/* Get registers from a core file. */
static void
fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
char *core_reg_sect;
unsigned core_reg_size;
int which;
unsigned int reg_addr; /* Unused in this version */
{
struct coreregs *core_reg;
core_reg = (struct coreregs *)core_reg_sect;
/*
* We have *all* registers
* in the first core section.
* Ignore which.
*/
if (core_reg_size < sizeof(*core_reg)) {
fprintf_unfiltered (gdb_stderr, "Couldn't read regs from core file\n");
return;
}
/* Integer registers */
RF(R0_REGNUM + 0, core_reg->intreg.r_r0);
RF(R0_REGNUM + 1, core_reg->intreg.r_r1);
RF(R0_REGNUM + 2, core_reg->intreg.r_r2);
RF(R0_REGNUM + 3, core_reg->intreg.r_r3);
RF(R0_REGNUM + 4, core_reg->intreg.r_r4);
RF(R0_REGNUM + 5, core_reg->intreg.r_r5);
RF(R0_REGNUM + 6, core_reg->intreg.r_r6);
RF(R0_REGNUM + 7, core_reg->intreg.r_r7);
RF(SP_REGNUM , core_reg->intreg.r_sp);
RF(FP_REGNUM , core_reg->intreg.r_fp);
RF(PC_REGNUM , core_reg->intreg.r_pc);
RF(PS_REGNUM , core_reg->intreg.r_psr);
/* Floating point registers */
RF(FPS_REGNUM , core_reg->freg.r_fsr);
RF(FP0_REGNUM +0, core_reg->freg.r_freg[0]);
RF(FP0_REGNUM +2, core_reg->freg.r_freg[2]);
RF(FP0_REGNUM +4, core_reg->freg.r_freg[4]);
RF(FP0_REGNUM +6, core_reg->freg.r_freg[6]);
RF(LP0_REGNUM + 1, core_reg->freg.r_freg[1]);
RF(LP0_REGNUM + 3, core_reg->freg.r_freg[3]);
RF(LP0_REGNUM + 5, core_reg->freg.r_freg[5]);
RF(LP0_REGNUM + 7, core_reg->freg.r_freg[7]);
registers_fetched ();
}
/* Register that we are able to handle ns32knbsd core file formats.
FIXME: is this really bfd_target_unknown_flavour? */
static struct core_fns nat_core_fns =
{
bfd_target_unknown_flavour,
fetch_core_registers,
NULL
};
void
_initialize_ns32knbsd_nat ()
{
add_core_fns (&nat_core_fns);
}
/*
* kernel_u_size() is not helpful on NetBSD because
* the "u" struct is NOT in the core dump file.
*/
#ifdef FETCH_KCORE_REGISTERS
/*
* Get registers from a kernel crash dump or live kernel.
* Called by kcore-nbsd.c:get_kcore_registers().
*/
void
fetch_kcore_registers (pcb)
struct pcb *pcb;
{
struct switchframe sf;
struct reg intreg;
int dummy;
/* Integer registers */
if (target_read_memory((CORE_ADDR)pcb->pcb_ksp, (char *)&sf, sizeof sf))
error("Cannot read integer registers.");
/* We use the psr at kernel entry */
if (target_read_memory((CORE_ADDR)pcb->pcb_onstack, (char *)&intreg, sizeof intreg))
error("Cannot read processor status register.");
dummy = 0;
RF(R0_REGNUM + 0, dummy);
RF(R0_REGNUM + 1, dummy);
RF(R0_REGNUM + 2, dummy);
RF(R0_REGNUM + 3, sf.sf_r3);
RF(R0_REGNUM + 4, sf.sf_r4);
RF(R0_REGNUM + 5, sf.sf_r5);
RF(R0_REGNUM + 6, sf.sf_r6);
RF(R0_REGNUM + 7, sf.sf_r7);
dummy = pcb->pcb_kfp + 8;
RF(SP_REGNUM , dummy);
RF(FP_REGNUM , sf.sf_fp);
RF(PC_REGNUM , sf.sf_pc);
RF(PS_REGNUM , intreg.r_psr);
/* Floating point registers */
RF(FPS_REGNUM , pcb->pcb_fsr);
RF(FP0_REGNUM +0, pcb->pcb_freg[0]);
RF(FP0_REGNUM +2, pcb->pcb_freg[2]);
RF(FP0_REGNUM +4, pcb->pcb_freg[4]);
RF(FP0_REGNUM +6, pcb->pcb_freg[6]);
RF(LP0_REGNUM + 1, pcb->pcb_freg[1]);
RF(LP0_REGNUM + 3, pcb->pcb_freg[3]);
RF(LP0_REGNUM + 5, pcb->pcb_freg[5]);
RF(LP0_REGNUM + 7, pcb->pcb_freg[7]);
registers_fetched ();
}
#endif /* FETCH_KCORE_REGISTERS */
void
clear_regs()
{
double zero = 0.0;
int null = 0;
/* Integer registers */
RF(R0_REGNUM + 0, null);
RF(R0_REGNUM + 1, null);
RF(R0_REGNUM + 2, null);
RF(R0_REGNUM + 3, null);
RF(R0_REGNUM + 4, null);
RF(R0_REGNUM + 5, null);
RF(R0_REGNUM + 6, null);
RF(R0_REGNUM + 7, null);
RF(SP_REGNUM , null);
RF(FP_REGNUM , null);
RF(PC_REGNUM , null);
RF(PS_REGNUM , null);
/* Floating point registers */
RF(FPS_REGNUM , zero);
RF(FP0_REGNUM +0, zero);
RF(FP0_REGNUM +2, zero);
RF(FP0_REGNUM +4, zero);
RF(FP0_REGNUM +6, zero);
RF(LP0_REGNUM + 0, zero);
RF(LP0_REGNUM + 1, zero);
RF(LP0_REGNUM + 2, zero);
RF(LP0_REGNUM + 3, zero);
return;
}
/* Return number of args passed to a frame.
Can return -1, meaning no way to tell. */
int
frame_num_args(fi)
struct frame_info *fi;
{
CORE_ADDR enter_addr;
CORE_ADDR argp;
int inst;
int args;
int i;
if (read_memory_integer (fi->frame, 4) == 0 && fi->pc < 0x10000) {
/* main is always called with three args */
return(3);
}
enter_addr = ns32k_get_enter_addr(fi->pc);
if (enter_addr = 0)
return(-1);
argp = enter_addr == 1 ? SAVED_PC_AFTER_CALL(fi) : FRAME_SAVED_PC(fi);
for (i = 0; i < 16; i++) {
/*
* After a bsr gcc may emit the following instructions
* to remove the arguments from the stack:
* cmpqd 0,tos - to remove 4 bytes from the stack
* cmpd tos,tos - to remove 8 bytes from the stack
* adjsp[bwd] -n - to remove n bytes from the stack
* Gcc sometimes delays emitting these instructions and
* may even throw a branch between our feet.
*/
inst = read_memory_integer(argp , 4);
args = read_memory_integer(argp + 2, 4);
if ((inst & 0xff) == 0xea) { /* br */
args = ((inst >> 8) & 0xffffff) | (args << 24);
if (args & 0x80) {
if (args & 0x40) {
args = ntohl(args);
} else {
args = ntohs(args & 0xffff);
if (args & 0x2000)
args |= 0xc000;
}
} else {
args = args & 0xff;
if (args & 0x40)
args |= 0x80;
}
argp += args;
continue;
}
if ((inst & 0xffff) == 0xb81f) /* cmpqd 0,tos */
return(1);
else if ((inst & 0xffff) == 0xbdc7) /* cmpd tos,tos */
return(2);
else if ((inst & 0xfffc) == 0xa57c) { /* adjsp[bwd] */
switch (inst & 3) {
case 0:
args = ((args & 0xff) + 0x80);
break;
case 1:
args = ((ntohs(args) & 0xffff) + 0x8000);
break;
case 3:
args = -ntohl(args);
break;
default:
return(-1);
}
if (args / 4 > 10 || (args & 3) != 0)
continue;
return(args / 4);
}
argp += 1;
}
return(-1);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,228 +0,0 @@
/* Remote target communications for d10v connected via a serial line.
Copyright 1988, 1991, 1992, 1993, 1994, 1995, 1996, 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 "gdb_string.h"
#include <fcntl.h>
#include "frame.h"
#include "inferior.h"
#include "bfd.h"
#include "symfile.h"
#include "target.h"
#include "wait.h"
/*#include "terminal.h"*/
#include "gdbcmd.h"
#include "objfiles.h"
#include "gdb-stabs.h"
#include "gdbthread.h"
#include "dcache.h"
#ifdef USG
#include <sys/types.h>
#endif
#include <signal.h>
#include "serial.h"
/* Prototypes for local functions */
static void remote_d10v_open PARAMS ((char *name, int from_tty));
/* Define the target subroutine names */
static struct target_ops remote_d10v_ops;
/* Open a connection to a remote debugger.
NAME is the filename used for communication. */
static void
remote_d10v_open (name, from_tty)
char *name;
int from_tty;
{
pop_target ();
push_remote_target (name, from_tty);
}
/* Translate a GDB virtual ADDR/LEN into a format the remote target
understands. Returns number of bytes that can be transfered
starting at taddr, ZERO if no bytes can be transfered. */
int
remote_d10v_translate_xfer_address (memaddr, nr_bytes, taddr)
CORE_ADDR memaddr;
int nr_bytes;
CORE_ADDR *taddr;
{
CORE_ADDR phys;
CORE_ADDR seg;
CORE_ADDR off;
char *from = "unknown";
char *to = "unknown";
unsigned short imap0 = read_register (IMAP0_REGNUM);
unsigned short imap1 = read_register (IMAP1_REGNUM);
unsigned short dmap = read_register (DMAP_REGNUM);
/* GDB interprets addresses as:
0x00xxxxxx: Logical data address segment (DMAP translated memory)
0x01xxxxxx: Logical instruction address segment (IMAP translated memory)
0x10xxxxxx: Physical data memory segment (On-chip data memory)
0x11xxxxxx: Physical instruction memory segment (On-chip insn memory)
0x12xxxxxx: Phisical unified memory segment (Unified memory)
The remote d10v board interprets addresses as:
0x00xxxxxx: Phisical unified memory segment (Unified memory)
0x01xxxxxx: Physical instruction memory segment (On-chip insn memory)
0x02xxxxxx: Physical data memory segment (On-chip data memory)
Translate according to current IMAP/dmap registers */
enum {
targ_unified = 0x00000000,
targ_insn = 0x01000000,
targ_data = 0x02000000,
};
seg = (memaddr >> 24);
off = (memaddr & 0xffffffL);
switch (seg)
{
case 0x00: /* in logical data address segment */
{
from = "logical-data";
if (off <= 0x7fffL)
{
/* On chip data */
phys = targ_data + off;
if (off + nr_bytes > 0x7fffL)
/* don't cross VM boundary */
nr_bytes = 0x7fffL - off + 1;
to = "chip-data";
}
else if (off <= 0xbfffL)
{
short map = dmap;
if (map & 0x1000)
{
/* Instruction memory */
phys = targ_insn | ((map & 0xf) << 14) | (off & 0x3fff);
to = "chip-insn";
}
else
{
/* Unified memory */
phys = targ_unified | ((map & 0x3ff) << 14) | (off & 0x3fff);
to = "unified";
}
if (off + nr_bytes > 0xbfffL)
/* don't cross VM boundary */
nr_bytes = (0xbfffL - off + 1);
}
else
{
/* Logical address out side of data segments, not supported */
return (0);
}
break;
}
case 0x01: /* in logical instruction address segment */
{
short map;
from = "logical-insn";
if (off <= 0x1ffffL)
{
map = imap0;
}
else if (off <= 0x3ffffL)
{
map = imap1;
}
else
{
/* Logical address outside of IMAP[01] segment, not
supported */
return (0);
}
if ((off & 0x1ffff) + nr_bytes > 0x1ffffL)
{
/* don't cross VM boundary */
nr_bytes = 0x1ffffL - (off & 0x1ffffL) + 1;
}
if (map & 0x1000)
/* Instruction memory */
{
phys = targ_insn | off;
to = "chip-insn";
}
else
{
phys = ((map & 0x7fL) << 17) + (off & 0x1ffffL);
if (phys > 0xffffffL)
/* Address outside of unified address segment */
return (0);
phys |= targ_unified;
to = "unified";
}
break;
}
case 0x10: /* Physical data memory segment */
from = "phys-data";
phys = targ_data | off;
to = "chip-data";
break;
case 0x11: /* Physical instruction memory */
from = "phys-insn";
phys = targ_insn | off;
to = "chip-insn";
break;
case 0x12: /* Physical unified memory */
from = "phys-unified";
phys = targ_unified | off;
to = "unified";
break;
default:
return (0);
}
*taddr = phys;
return nr_bytes;
}
void
_initialize_remote_d10v ()
{
remote_d10v_ops.to_shortname = "d10v";
remote_d10v_ops.to_longname = "Remote d10v serial target in gdb-specific protocol";
remote_d10v_ops.to_doc = "Use a remote d10v via a serial line, using a gdb-specific protocol.\n\
Specify the serial device it is connected to (e.g. /dev/ttya).";
remote_d10v_ops.to_open = remote_d10v_open;
add_target (&remote_d10v_ops);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,884 +0,0 @@
/* Target-dependent code for the NEC V850 for GDB, the GNU debugger.
Copyright 1996, 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"
static char *v850_generic_reg_names[] = REGISTER_NAMES;
static char *v850e_reg_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",
"eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "sr6", "sr7",
"sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
"ctpc", "ctpsw", "dbpc", "dbpsw", "ctbp", "sr21", "sr22", "sr23",
"sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31",
"pc", "fp"
};
char **v850_register_names = v850_generic_reg_names;
struct
{
char **regnames;
int mach;
} v850_processor_type_table[] =
{
{ v850_generic_reg_names, bfd_mach_v850 },
{ v850e_reg_names, bfd_mach_v850e },
{ v850e_reg_names, bfd_mach_v850ea },
{ NULL, 0 }
};
/* 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 cur_frameoffset; /* Current frameoffset */
int reg; /* Saved register number */
};
struct prologue_info
{
int framereg;
int frameoffset;
int start_function;
struct pifsr *pifsrs;
};
static CORE_ADDR v850_scan_prologue PARAMS ((CORE_ADDR pc,
struct prologue_info *fs));
/* Should call_function allocate stack space for a struct return? */
int
v850_use_struct_convention (gcc_p, type)
int gcc_p;
struct type *type;
{
return (TYPE_NFIELDS (type) > 1 || TYPE_LENGTH (type) > 4);
}
/* Structure for mapping bits in register lists to register numbers. */
struct reg_list
{
long mask;
int regno;
};
/* Helper function for v850_scan_prologue to handle prepare instruction. */
static void
handle_prepare (int insn, int insn2, CORE_ADDR *current_pc_ptr,
struct prologue_info *pi, struct pifsr **pifsr_ptr)
{
CORE_ADDR current_pc = *current_pc_ptr;
struct pifsr *pifsr = *pifsr_ptr;
long next = insn2 & 0xffff;
long list12 = ((insn & 1) << 16) + (next & 0xffe0);
long offset = (insn & 0x3e) << 1;
static struct reg_list reg_table [] =
{
{ 0x00800, 20 }, /* r20 */
{ 0x00400, 21 }, /* r21 */
{ 0x00200, 22 }, /* r22 */
{ 0x00100, 23 }, /* r23 */
{ 0x08000, 24 }, /* r24 */
{ 0x04000, 25 }, /* r25 */
{ 0x02000, 26 }, /* r26 */
{ 0x01000, 27 }, /* r27 */
{ 0x00080, 28 }, /* r28 */
{ 0x00040, 29 }, /* r29 */
{ 0x10000, 30 }, /* ep */
{ 0x00020, 31 }, /* lp */
{ 0, 0 } /* end of table */
};
int i;
if ((next & 0x1f) == 0x0b) /* skip imm16 argument */
current_pc += 2;
else if ((next & 0x1f) == 0x13) /* skip imm16 argument */
current_pc += 2;
else if ((next & 0x1f) == 0x1b) /* skip imm32 argument */
current_pc += 4;
/* Calculate the total size of the saved registers, and add it
it to the immediate value used to adjust SP. */
for (i = 0; reg_table[i].mask != 0; i++)
if (list12 & reg_table[i].mask)
offset += REGISTER_RAW_SIZE (regtable[i].regno);
pi->frameoffset -= offset;
/* Calculate the offsets of the registers relative to the value
the SP will have after the registers have been pushed and the
imm5 value has been subtracted from it. */
if (pifsr)
{
for (i = 0; reg_table[i].mask != 0; i++)
{
if (list12 & reg_table[i].mask)
{
int reg = reg_table[i].regno;
offset -= REGISTER_RAW_SIZE (reg);
pifsr->reg = reg;
pifsr->offset = offset;
pifsr->cur_frameoffset = pi->frameoffset;
#ifdef DEBUG
printf_filtered ("\tSaved register r%d, offset %d", reg, pifsr->offset);
#endif
pifsr++;
}
}
}
#ifdef DEBUG
printf_filtered ("\tfound ctret after regsave func");
#endif
/* Set result parameters. */
*current_pc_ptr = current_pc;
*pifsr_ptr = pifsr;
}
/* Helper function for v850_scan_prologue to handle pushm/pushl instructions.
FIXME: the SR bit of the register list is not supported; must check
that the compiler does not ever generate this bit. */
static void
handle_pushm (int insn, int insn2, struct prologue_info *pi,
struct pifsr **pifsr_ptr)
{
struct pifsr *pifsr = *pifsr_ptr;
long list12 = ((insn & 0x0f) << 16) + (insn2 & 0xfff0);
long offset = 0;
static struct reg_list pushml_reg_table [] =
{
{ 0x80000, PS_REGNUM }, /* PSW */
{ 0x40000, 1 }, /* r1 */
{ 0x20000, 2 }, /* r2 */
{ 0x10000, 3 }, /* r3 */
{ 0x00800, 4 }, /* r4 */
{ 0x00400, 5 }, /* r5 */
{ 0x00200, 6 }, /* r6 */
{ 0x00100, 7 }, /* r7 */
{ 0x08000, 8 }, /* r8 */
{ 0x04000, 9 }, /* r9 */
{ 0x02000, 10 }, /* r10 */
{ 0x01000, 11 }, /* r11 */
{ 0x00080, 12 }, /* r12 */
{ 0x00040, 13 }, /* r13 */
{ 0x00020, 14 }, /* r14 */
{ 0x00010, 15 }, /* r15 */
{ 0, 0 } /* end of table */
};
static struct reg_list pushmh_reg_table [] =
{
{ 0x80000, 16 }, /* r16 */
{ 0x40000, 17 }, /* r17 */
{ 0x20000, 18 }, /* r18 */
{ 0x10000, 19 }, /* r19 */
{ 0x00800, 20 }, /* r20 */
{ 0x00400, 21 }, /* r21 */
{ 0x00200, 22 }, /* r22 */
{ 0x00100, 23 }, /* r23 */
{ 0x08000, 24 }, /* r24 */
{ 0x04000, 25 }, /* r25 */
{ 0x02000, 26 }, /* r26 */
{ 0x01000, 27 }, /* r27 */
{ 0x00080, 28 }, /* r28 */
{ 0x00040, 29 }, /* r29 */
{ 0x00010, 30 }, /* r30 */
{ 0x00020, 31 }, /* r31 */
{ 0, 0 } /* end of table */
};
struct reg_list *reg_table;
int i;
/* Is this a pushml or a pushmh? */
if ((insn2 & 7) == 1)
reg_table = pushml_reg_table;
else
reg_table = pushmh_reg_table;
/* Calculate the total size of the saved registers, and add it
it to the immediate value used to adjust SP. */
for (i = 0; reg_table[i].mask != 0; i++)
if (list12 & reg_table[i].mask)
offset += REGISTER_RAW_SIZE (regtable[i].regno);
pi->frameoffset -= offset;
/* Calculate the offsets of the registers relative to the value
the SP will have after the registers have been pushed and the
imm5 value is subtracted from it. */
if (pifsr)
{
for (i = 0; reg_table[i].mask != 0; i++)
{
if (list12 & reg_table[i].mask)
{
int reg = reg_table[i].regno;
offset -= REGISTER_RAW_SIZE (reg);
pifsr->reg = reg;
pifsr->offset = offset;
pifsr->cur_frameoffset = pi->frameoffset;
#ifdef DEBUG
printf_filtered ("\tSaved register r%d, offset %d", reg, pifsr->offset);
#endif
pifsr++;
}
}
}
#ifdef DEBUG
printf_filtered ("\tfound ctret after regsave func");
#endif
/* Set result parameters. */
*pifsr_ptr = pifsr;
}
/* Function: scan_prologue
Scan the prologue of the function that contains PC, and record what
we find in PI. PI->fsr must be zeroed by the called. Returns the
pc after the prologue. Note that the addresses saved in pi->fsr
are actually just frame relative (negative offsets from the frame
pointer). This is because we don't know the actual value of the
frame pointer yet. In some circumstances, the frame pointer can't
be determined till after we have scanned the prologue. */
static CORE_ADDR
v850_scan_prologue (pc, pi)
CORE_ADDR pc;
struct prologue_info *pi;
{
CORE_ADDR func_addr, prologue_end, current_pc;
struct pifsr *pifsr, *pifsr_tmp;
int fp_used;
int ep_used;
int reg;
CORE_ADDR save_pc, save_end;
int regsave_func_p;
int r12_tmp;
/* First, figure out the bounds of the prologue so that we can limit the
search to something reasonable. */
if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
{
struct symtab_and_line sal;
sal = find_pc_line (func_addr, 0);
if (func_addr == entry_point_address ())
pi->start_function = 1;
else
pi->start_function = 0;
#if 0
if (sal.line == 0)
prologue_end = pc;
else
prologue_end = sal.end;
#else
prologue_end = pc;
#endif
}
else
{ /* We're in the boondocks */
func_addr = pc - 100;
prologue_end = pc;
}
prologue_end = min (prologue_end, pc);
/* Now, search the prologue looking for instructions that setup fp, save
rp, adjust sp and such. We also record the frame offset of any saved
registers. */
pi->frameoffset = 0;
pi->framereg = SP_REGNUM;
fp_used = 0;
ep_used = 0;
pifsr = pi->pifsrs;
regsave_func_p = 0;
save_pc = 0;
save_end = 0;
r12_tmp = 0;
#ifdef DEBUG
printf_filtered ("Current_pc = 0x%.8lx, prologue_end = 0x%.8lx\n",
(long)func_addr, (long)prologue_end);
#endif
for (current_pc = func_addr; current_pc < prologue_end; )
{
int insn, insn2;
#ifdef DEBUG
printf_filtered ("0x%.8lx ", (long)current_pc);
(*tm_print_insn) (current_pc, &tm_print_insn_info);
#endif
insn = read_memory_unsigned_integer (current_pc, 2);
current_pc += 2;
if ((insn & 0x0780) >= 0x0600) /* Four byte instruction? */
{
insn2 = read_memory_unsigned_integer (current_pc, 2);
current_pc += 2;
}
if ((insn & 0xffc0) == ((10 << 11) | 0x0780) && !regsave_func_p)
{ /* jarl <func>,10 */
long low_disp = insn2 & ~ (long) 1;
long disp = (((((insn & 0x3f) << 16) + low_disp)
& ~ (long) 1) ^ 0x00200000) - 0x00200000;
save_pc = current_pc;
save_end = prologue_end;
regsave_func_p = 1;
current_pc += disp - 4;
prologue_end = (current_pc
+ (2 * 3) /* moves to/from ep */
+ 4 /* addi <const>,sp,sp */
+ 2 /* jmp [r10] */
+ (2 * 12) /* sst.w to save r2, r20-r29, r31 */
+ 20); /* slop area */
#ifdef DEBUG
printf_filtered ("\tfound jarl <func>,r10, disp = %ld, low_disp = %ld, new pc = 0x%.8lx\n",
disp, low_disp, (long)current_pc + 2);
#endif
continue;
}
else if ((insn & 0xffc0) == 0x0200 && !regsave_func_p)
{ /* callt <imm6> */
long ctbp = read_register (CTBP_REGNUM);
long adr = ctbp + ((insn & 0x3f) << 1);
save_pc = current_pc;
save_end = prologue_end;
regsave_func_p = 1;
current_pc = ctbp + (read_memory_unsigned_integer (adr, 2) & 0xffff);
prologue_end = (current_pc
+ (2 * 3) /* prepare list2,imm5,sp/imm */
+ 4 /* ctret */
+ 20); /* slop area */
#ifdef DEBUG
printf_filtered ("\tfound callt, ctbp = 0x%.8lx, adr = %.8lx, new pc = 0x%.8lx\n",
ctbp, adr, (long)current_pc);
#endif
continue;
}
else if ((insn & 0xffc0) == 0x0780) /* prepare list2,imm5 */
{
handle_prepare (insn, insn2, &current_pc, pi, &pifsr);
continue;
}
else if (insn == 0x07e0 && regsave_func_p && insn2 == 0x0144)
{ /* ctret after processing register save function */
current_pc = save_pc;
prologue_end = save_end;
regsave_func_p = 0;
#ifdef DEBUG
printf_filtered ("\tfound ctret after regsave func");
#endif
continue;
}
else if ((insn & 0xfff0) == 0x07e0 && (insn2 & 5) == 1)
{ /* pushml, pushmh */
handle_pushm (insn, insn2, pi, &pifsr);
continue;
}
else if ((insn & 0xffe0) == 0x0060 && regsave_func_p)
{ /* jmp after processing register save function */
current_pc = save_pc;
prologue_end = save_end;
regsave_func_p = 0;
#ifdef DEBUG
printf_filtered ("\tfound jmp after regsave func");
#endif
continue;
}
else if ((insn & 0x07c0) == 0x0780 /* jarl or jr */
|| (insn & 0xffe0) == 0x0060 /* jmp */
|| (insn & 0x0780) == 0x0580) /* branch */
{
#ifdef DEBUG
printf_filtered ("\n");
#endif
break; /* Ran into end of prologue */
}
else if ((insn & 0xffe0) == ((SP_REGNUM << 11) | 0x0240)) /* add <imm>,sp */
pi->frameoffset += ((insn & 0x1f) ^ 0x10) - 0x10;
else if (insn == ((SP_REGNUM << 11) | 0x0600 | SP_REGNUM)) /* addi <imm>,sp,sp */
pi->frameoffset += insn2;
else if (insn == ((FP_RAW_REGNUM << 11) | 0x0000 | SP_REGNUM)) /* mov sp,fp */
{
fp_used = 1;
pi->framereg = FP_RAW_REGNUM;
}
else if (insn == ((R12_REGNUM << 11) | 0x0640 | R0_REGNUM)) /* movhi hi(const),r0,r12 */
r12_tmp = insn2 << 16;
else if (insn == ((R12_REGNUM << 11) | 0x0620 | R12_REGNUM)) /* movea lo(const),r12,r12 */
r12_tmp += insn2;
else if (insn == ((SP_REGNUM << 11) | 0x01c0 | R12_REGNUM) && r12_tmp) /* add r12,sp */
pi->frameoffset = r12_tmp;
else if (insn == ((EP_REGNUM << 11) | 0x0000 | SP_REGNUM)) /* mov sp,ep */
ep_used = 1;
else if (insn == ((EP_REGNUM << 11) | 0x0000 | R1_REGNUM)) /* mov r1,ep */
ep_used = 0;
else if (((insn & 0x07ff) == (0x0760 | SP_REGNUM) /* st.w <reg>,<offset>[sp] */
|| (fp_used
&& (insn & 0x07ff) == (0x0760 | FP_RAW_REGNUM))) /* st.w <reg>,<offset>[fp] */
&& pifsr
&& (((reg = (insn >> 11) & 0x1f) >= SAVE1_START_REGNUM && reg <= SAVE1_END_REGNUM)
|| (reg >= SAVE2_START_REGNUM && reg <= SAVE2_END_REGNUM)
|| (reg >= SAVE3_START_REGNUM && reg <= SAVE3_END_REGNUM)))
{
pifsr->reg = reg;
pifsr->offset = insn2 & ~1;
pifsr->cur_frameoffset = pi->frameoffset;
#ifdef DEBUG
printf_filtered ("\tSaved register r%d, offset %d", reg, pifsr->offset);
#endif
pifsr++;
}
else if (ep_used /* sst.w <reg>,<offset>[ep] */
&& ((insn & 0x0781) == 0x0501)
&& pifsr
&& (((reg = (insn >> 11) & 0x1f) >= SAVE1_START_REGNUM && reg <= SAVE1_END_REGNUM)
|| (reg >= SAVE2_START_REGNUM && reg <= SAVE2_END_REGNUM)
|| (reg >= SAVE3_START_REGNUM && reg <= SAVE3_END_REGNUM)))
{
pifsr->reg = reg;
pifsr->offset = (insn & 0x007e) << 1;
pifsr->cur_frameoffset = pi->frameoffset;
#ifdef DEBUG
printf_filtered ("\tSaved register r%d, offset %d", reg, pifsr->offset);
#endif
pifsr++;
}
#ifdef DEBUG
printf_filtered ("\n");
#endif
}
if (pifsr)
pifsr->framereg = 0; /* Tie off last entry */
/* Fix up any offsets to the final offset. If a frame pointer was created, use it
instead of the stack pointer. */
for (pifsr_tmp = pi->pifsrs; pifsr_tmp && pifsr_tmp != pifsr; pifsr_tmp++)
{
pifsr_tmp->offset -= pi->frameoffset - pifsr_tmp->cur_frameoffset;
pifsr_tmp->framereg = pi->framereg;
#ifdef DEBUG
printf_filtered ("Saved register r%d, offset = %d, framereg = r%d\n",
pifsr_tmp->reg, pifsr_tmp->offset, pifsr_tmp->framereg);
#endif
}
#ifdef DEBUG
printf_filtered ("Framereg = r%d, frameoffset = %d\n", pi->framereg, pi->frameoffset);
#endif
return current_pc;
}
/* 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 scan_prologue().
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
v850_init_extra_frame_info (fi)
struct frame_info *fi;
{
struct prologue_info pi;
struct pifsr pifsrs[NUM_REGS + 1], *pifsr;
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;
}
}
/* Function: frame_chain
Figure out the frame prior to FI. Unfortunately, this involves
scanning the prologue of the caller, which will also be done
shortly by v850_init_extra_frame_info. For the dummy frame, we
just return the stack pointer that was in use at the time the
function call was made. */
CORE_ADDR
v850_frame_chain (fi)
struct frame_info *fi;
{
struct prologue_info pi;
CORE_ADDR callers_pc, fp;
/* First, find out who called us */
callers_pc = FRAME_SAVED_PC (fi);
/* If caller is a call-dummy, then our FP bears no relation to his FP! */
fp = v850_find_callers_reg (fi, FP_RAW_REGNUM);
if (PC_IN_CALL_DUMMY(callers_pc, fp, fp))
return fp; /* caller is call-dummy: return oldest value of FP */
/* Caller is NOT a call-dummy, so everything else should just work.
Even if THIS frame is a call-dummy! */
pi.pifsrs = NULL;
v850_scan_prologue (callers_pc, &pi);
if (pi.start_function)
return 0; /* Don't chain beyond the start function */
if (pi.framereg == FP_RAW_REGNUM)
return v850_find_callers_reg (fi, pi.framereg);
return fi->frame - pi.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
v850_find_callers_reg (fi, regnum)
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_unsigned_integer (fi->fsr.regs[regnum],
REGISTER_RAW_SIZE(regnum));
return read_register (regnum);
}
/* Function: skip_prologue
Return the address of the first code past the prologue of the function. */
CORE_ADDR
v850_skip_prologue (pc)
CORE_ADDR pc;
{
CORE_ADDR func_addr, func_end;
/* 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
v850_pop_frame (frame)
struct frame_info *frame;
{
int regnum;
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 ();
}
/* Function: push_arguments
Setup arguments and RP for a call to the target. First four args
go in R6->R9, subsequent args go into sp + 16 -> sp + ... Structs
are passed by reference. 64 bit quantities (doubles and long
longs) may be split between the regs and the stack. When calling a
function that returns a struct, a pointer to the struct is passed
in as a secret first argument (always in R6).
Stack space for the args has NOT been allocated: that job is up to us.
*/
CORE_ADDR
v850_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 argreg;
int argnum;
int len = 0;
int stack_offset;
/* 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; /* possibly over-allocating, but it works... */
/* (you might think we could allocate 16 bytes */
/* less, but the ABI seems to use it all! ) */
argreg = ARG0_REGNUM;
/* the struct_return pointer occupies the first parameter-passing reg */
if (struct_return)
write_register (argreg++, struct_addr);
stack_offset = 16;
/* The offset onto the stack at which we will start copying parameters
(after the registers are used up) begins at 16 rather than at zero.
I don't really know why, that's just the way it seems to work. */
/* 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. */
for (argnum = 0; argnum < nargs; argnum++)
{
int len;
char *val;
char valbuf[REGISTER_RAW_SIZE(ARG0_REGNUM)];
if (TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_STRUCT
&& TYPE_LENGTH (VALUE_TYPE (*args)) > 8)
{
store_address (valbuf, 4, VALUE_ADDRESS (*args));
len = 4;
val = valbuf;
}
else
{
len = TYPE_LENGTH (VALUE_TYPE (*args));
val = (char *)VALUE_CONTENTS (*args);
}
while (len > 0)
if (argreg <= ARGLAST_REGNUM)
{
CORE_ADDR regval;
regval = extract_address (val, REGISTER_RAW_SIZE (argreg));
write_register (argreg, regval);
len -= REGISTER_RAW_SIZE (argreg);
val += REGISTER_RAW_SIZE (argreg);
argreg++;
}
else
{
write_memory (sp + stack_offset, val, 4);
len -= 4;
val += 4;
stack_offset += 4;
}
args++;
}
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
v850_push_return_address (pc, sp)
CORE_ADDR pc;
CORE_ADDR sp;
{
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
v850_frame_saved_pc (fi)
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 v850_find_callers_reg (fi, RP_REGNUM);
}
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;
{
generic_get_saved_register (raw_buffer, optimized, addrp,
frame, regnum, lval);
}
/* Function: fix_call_dummy
Pokes the callee function's address into the CALL_DUMMY assembly stub.
Assumes that the CALL_DUMMY looks like this:
jarl <offset24>, r31
trap
*/
int
v850_fix_call_dummy (dummy, sp, fun, nargs, args, type, gcc_p)
char *dummy;
CORE_ADDR sp;
CORE_ADDR fun;
int nargs;
value_ptr *args;
struct type *type;
int gcc_p;
{
long offset24;
offset24 = (long) fun - (long) entry_point_address ();
offset24 &= 0x3fffff;
offset24 |= 0xff800000; /* jarl <offset24>, r31 */
store_unsigned_integer ((unsigned int *)&dummy[2], 2, offset24 & 0xffff);
store_unsigned_integer ((unsigned int *)&dummy[0], 2, offset24 >> 16);
return 0;
}
/* Change the register names based on the current machine type. */
static int
v850_target_architecture_hook (ap)
const bfd_arch_info_type *ap;
{
int i, j;
if (ap->arch != bfd_arch_v850)
return 0;
for (i = 0; v850_processor_type_table[i].regnames != NULL; i++)
{
if (v850_processor_type_table[i].mach == ap->mach)
{
v850_register_names = v850_processor_type_table[i].regnames;
return 1;
}
}
fatal ("Architecture `%s' unreconized", ap->printable_name);
}
void
_initialize_v850_tdep ()
{
tm_print_insn = print_insn_v850;
target_architecture_hook = v850_target_architecture_hook;
}