aboutsummaryrefslogtreecommitdiff
path: root/gdb/fr30-tdep.c
diff options
context:
space:
mode:
authorStan Shebs <shebs@codesourcery.com>1999-04-16 01:34:07 +0000
committerStan Shebs <shebs@codesourcery.com>1999-04-16 01:34:07 +0000
commit071ea11e85eb9d529cc5eb3d35f6247466a21b99 (patch)
tree5deda65b8d7b04d1f4cbc534c3206d328e1267ec /gdb/fr30-tdep.c
parent1730ec6b1848f0f32154277f788fb29f88d8475b (diff)
downloadgdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.zip
gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.gz
gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.bz2
Initial creation of sourceware repository
Diffstat (limited to 'gdb/fr30-tdep.c')
-rw-r--r--gdb/fr30-tdep.c552
1 files changed, 0 insertions, 552 deletions
diff --git a/gdb/fr30-tdep.c b/gdb/fr30-tdep.c
deleted file mode 100644
index 0d442da..0000000
--- a/gdb/fr30-tdep.c
+++ /dev/null
@@ -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;
-}