Wed Oct 30 18:14:14 1996 Michael Snyder <msnyder@cleaver.cygnus.com>

* m32r-tdep.c, m32r-rom.c: New files.
        * config/m32r/m32r.mt: New file.
        * config/m32r/tm-m32r.h: New file.
This commit is contained in:
Michael Snyder 1996-10-31 02:27:58 +00:00
parent 1d3d059535
commit 70ab088d08
3 changed files with 600 additions and 1 deletions

View File

@ -1,9 +1,17 @@
start-sanitize-m32r
Wed Oct 30 18:14:14 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
* m32r-tdep.c, m32r-rom.c: New files.
* config/m32r/m32r.mt: New file.
* config/m32r/tm-m32r.h: New file.
end-sanitize-m32r
Tue Oct 29 16:56:01 1996 Geoffrey Noer <noer@cygnus.com>
* config/i386/xm-cygwin32.h:
* config/powerpc/xm-cygwin32.h:
add #define LSEEK_NOT_LINEAR so source lines aren't unexpectedly
truncated
truncated.
Tue Oct 29 18:36:43 1996 Michael Meissner <meissner@tiktok.cygnus.com>

211
gdb/config/m32r/tm-m32r.h Normal file
View File

@ -0,0 +1,211 @@
/* Parameters for execution on a Mitsubishi m32r processor.
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. */
/* mvs_check TARGET_BYTE_ORDER BIG_ENDIAN */
#define TARGET_BYTE_ORDER BIG_ENDIAN
/* mvs_check REGISTER_NAMES */
#define REGISTER_NAMES \
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
"r8", "r9", "r10", "r11", "r12", "fp", "lr", "sp", \
"psw", "cbr", "spi", "spu", "bpc", "pc", "accl", "acch", \
/* "cond", "sm", "bsm", "ie", "bie", "bcarry", */ \
}
/* mvs_check NUM_REGS */
#define NUM_REGS 24
/* mvs_check REGISTER_SIZE */
#define REGISTER_SIZE 4
/* mvs_check MAX_REGISTER_RAW_SIZE */
#define MAX_REGISTER_RAW_SIZE 4
/* mvs_check *_REGNUM */
#define R0_REGNUM 0
#define ARG0_REGNUM 0
#define ARGLAST_REGNUM 3
#define V0_REGNUM 0
#define V1_REGNUM 1
#define FP_REGNUM 13
#define RP_REGNUM 14
#define SP_REGNUM 15
#define PSW_REGNUM 16
#define CBR_REGNUM 17
#define SPI_REGNUM 18
#define SPU_REGNUM 19
#define BPC_REGNUM 20
#define PC_REGNUM 21
#define ACCL_REGNUM 22
#define ACCH_REGNUM 23
/* mvs_check REGISTER_BYTES */
#define REGISTER_BYTES (NUM_REGS * 4)
/* mvs_check REGISTER_VIRTUAL_TYPE */
#define REGISTER_VIRTUAL_TYPE(REG) builtin_type_int
/* mvs_check REGISTER_BYTE */
#define REGISTER_BYTE(REG) ((REG) * 4)
/* mvs_check REGISTER_VIRTUAL_SIZE */
#define REGISTER_VIRTUAL_SIZE(REG) 4
/* mvs_check REGISTER_RAW_SIZE */
#define REGISTER_RAW_SIZE(REG) 4
/* mvs_check MAX_REGISTER_VIRTUAL_SIZE */
#define MAX_REGISTER_VIRTUAL_SIZE 4
/* mvs_check BREAKPOINT */
#define BREAKPOINT {0x10, 0xf1}
/* mvs_no_check FUNCTION_START_OFFSET */
#define FUNCTION_START_OFFSET 0
/* mvs_check DECR_PC_AFTER_BREAK */
#define DECR_PC_AFTER_BREAK 0
/* mvs_check INNER_THAN */
#define INNER_THAN <
/* mvs_check SAVED_PC_AFTER_CALL */
#define SAVED_PC_AFTER_CALL(fi) read_register (RP_REGNUM)
#ifdef __STDC__
struct frame_info;
struct frame_saved_regs;
struct type;
struct value;
#endif
/* #define EXTRA_FRAME_INFO struct frame_saved_regs fsr; */
/* Define other aspects of the stack frame.
we keep a copy of the worked out return pc lying around, since it
is a useful bit of info */
/* mvs_check EXTRA_FRAME_INFO */
#define EXTRA_FRAME_INFO struct frame_saved_regs fsr;
extern void m32r_init_extra_frame_info PARAMS ((struct frame_info *fi));
/* mvs_check INIT_EXTRA_FRAME_INFO */
#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) m32r_init_extra_frame_info (fi)
/* mvs_no_check INIT_FRAME_PC */
#define INIT_FRAME_PC /* Not necessary */
extern void
m32r_frame_find_saved_regs PARAMS ((struct frame_info *fi,
struct frame_saved_regs *regaddr));
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
/* mvs_check FRAME_FIND_SAVED_REGS */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
m32r_frame_find_saved_regs(frame_info, &(frame_saved_regs))
extern CORE_ADDR m32r_frame_chain PARAMS ((struct frame_info *fi));
/* mvs_check FRAME_CHAIN */
#define FRAME_CHAIN(fi) m32r_frame_chain (fi)
extern CORE_ADDR m32r_find_callers_reg PARAMS ((struct frame_info *fi,
int regnum));
/* mvs_check FRAME_SAVED_PC */
#define FRAME_SAVED_PC(fi) (m32r_find_callers_reg (fi, RP_REGNUM))
/* mvs_check EXTRACT_RETURN_VALUE */
#define EXTRACT_RETURN_VALUE(TYPE, REGBUF, VALBUF) \
memcpy ((VALBUF), \
(char *)(REGBUF) + REGISTER_BYTE (V0_REGNUM) + \
((TYPE_LENGTH (TYPE) > 4 ? 8 : 4) - TYPE_LENGTH (TYPE)), \
TYPE_LENGTH (TYPE))
/* mvs_check STORE_RETURN_VALUE */
#define STORE_RETURN_VALUE(TYPE, VALBUF) \
write_register_bytes(REGISTER_BYTE (V0_REGNUM) + \
((TYPE_LENGTH (TYPE) > 4 ? 8:4) - TYPE_LENGTH (TYPE)),\
(VALBUF), TYPE_LENGTH (TYPE));
/* mvs_check EXTRACT_STRUCT_VALUE_ADDRESS */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
(extract_address (REGBUF + REGISTER_BYTE (V0_REGNUM), \
REGISTER_RAW_SIZE (V0_REGNUM)))
extern CORE_ADDR m32r_skip_prologue PARAMS ((CORE_ADDR pc));
/* mvs_check SKIP_PROLOGUE */
#define SKIP_PROLOGUE(pc) pc = m32r_skip_prologue (pc)
/* mvs_no_check FRAME_ARGS_SKIP */
#define FRAME_ARGS_SKIP 0
/* mvs_no_check FRAME_ARGS_ADDRESS */
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
/* mvs_no_check FRAME_LOCALS_ADDRESS */
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
/* mvs_no_check FRAME_NUM_ARGS */
#define FRAME_NUM_ARGS(val, fi) ((val) = -1)
extern struct frame_info *m32r_pop_frame PARAMS ((struct frame_info *frame));
/* mvs_check POP_FRAME */
#define POP_FRAME m32r_pop_frame (get_current_frame ())
/* mvs_no_check CALL_DUMMY */
/* #define CALL_DUMMY { 0 } */
/* mvs_no_check CALL_DUMMY_START_OFFSET */
#define CALL_DUMMY_START_OFFSET (0)
/* mvs_no_check CALL_DUMMY_BREAKPOINT_OFFSET */
#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
extern void m32r_push_dummy_frame PARAMS ((void));
/* mvs_no_check PUSH_DUMMY_FRAME */
#define PUSH_DUMMY_FRAME m32r_push_dummy_frame ()
/* mvs_no_check FIX_CALL_DUMMY */
#define FIX_CALL_DUMMY(DUMMY1, START_SP, FUNADDR, NARGS, \
ARGS, VALUE_TYPE, USING_GCC)
/* mvs_no_check CALL_DUMMY_LOCATION_AT_ENTRY_POINT */
#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
/* mvs_no_check STACK_ALIGN */
#define STACK_ALIGN(x) ((x + 3) & ~3)
extern CORE_ADDR
m32r_push_arguments PARAMS ((int nargs, struct value **args, CORE_ADDR sp,
unsigned char struct_return,
CORE_ADDR struct_addr));
/* mvs_no_check PUSH_ARGUMENTS */
#define PUSH_ARGUMENTS(NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) \
(SP) = m32r_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR)
/* mvs_no_check STORE_STRUCT_RETURN */
#define STORE_STRUCT_RETURN(STRUCT_ADDR, SP)
/* mvs_no_check CALL_DUMMY_ADDRESS */
#define CALL_DUMMY_ADDRESS() (entry_point_address ())
extern int m32r_pc_in_call_dummy PARAMS ((CORE_ADDR pc));
/* mvs_no_check PC_IN_CALL_DUMMY */
#define PC_IN_CALL_DUMMY(PC, SP, FP) m32r_pc_in_call_dummy (PC)
/* mvs_check USE_STRUCT_CONVENTION */
#define USE_STRUCT_CONVENTION(GCC_P, TYPE) \
(TYPE_LENGTH (TYPE) > 8)

380
gdb/m32r-tdep.c Normal file
View File

@ -0,0 +1,380 @@
/* Target-dependent code for the Mitsubishi m32r 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"
struct dummy_frame
{
struct dummy_frame *next;
CORE_ADDR fp;
CORE_ADDR sp;
CORE_ADDR rp;
CORE_ADDR pc;
};
void
m32r_frame_find_saved_regs PARAMS ((struct frame_info *fi,
struct frame_saved_regs *regaddr))
{
*regaddr = fi->fsr;
}
static struct dummy_frame *dummy_frame_stack = NULL;
/* Find end of function prologue */
CORE_ADDR
m32r_skip_prologue (pc)
CORE_ADDR pc;
{
CORE_ADDR func_addr, func_end;
struct symtab_and_line sal;
/* See what the symbol table says */
if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
{
sal = find_pc_line (func_addr, 0);
if (sal.line != 0 && sal.end < func_end)
return sal.end;
else
/* Either there's no line info, or the line after the prologue is after
the end of the function. In this case, there probably isn't a
prologue. */
return pc;
}
/* We can't find the start of this function, so there's nothing we can do. */
return pc;
}
/* This function decodes the target function prologue to determine
1) the size of the stack frame, and 2) which registers are saved on it.
It saves the offsets of saved regs in the frame_saved_regs argument,
and returns the frame size.
*/
static unsigned long
m32r_scan_prologue (fi, fsr)
struct frame_info *fi;
struct frame_saved_regs *fsr;
{
struct symtab_and_line sal;
CORE_ADDR prologue_start, prologue_end, current_pc;
unsigned long framesize;
/* this code essentially duplicates skip_prologue,
but we need the start address below. */
if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
{
sal = find_pc_line (prologue_start, 0);
if (sal.line == 0) /* no line info, use current PC */
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
prologue_end = prologue_start + 100; /* We're in the boondocks */
prologue_end = min (prologue_end, fi->pc);
/* Now, search the prologue looking for instructions that setup fp, save
rp (and other regs), adjust sp and such. */
framesize = 0;
memset (fsr->regs, '\000', sizeof fsr->regs);
for (current_pc = prologue_start; current_pc < prologue_end; current_pc += 2)
{
int insn;
int regno;
insn = read_memory_unsigned_integer (current_pc, 2);
if (insn & 0x80) /* Four byte instruction? */
current_pc += 2;
if ((insn & 0xf0ff) == 0x207f) { /* st reg, @-sp */
framesize += 4;
regno = ((insn >> 8) & 0xf);
fsr->regs[regno] = framesize;
}
else if ((insn >> 8) == 0x4f) { /* addi sp */
framesize += -((char) (insn & 0xff)); /* offset */
break; /* end of stack adjustments */
}
}
return framesize;
}
/* This function actually figures out the frame address for a given pc and
sp. This is tricky on the v850 because we only use an explicit frame
pointer when using alloca(). The only reliable way to get this info is to
examine the prologue.
*/
void
m32r_init_extra_frame_info (fi)
struct frame_info *fi;
{
int reg;
int framesize;
if (fi->next)
fi->pc = FRAME_SAVED_PC (fi->next);
framesize = m32r_scan_prologue (fi, &fi->fsr);
if (PC_IN_CALL_DUMMY (fi->pc, NULL, NULL))
fi->frame = dummy_frame_stack->sp;
else if (!fi->next)
fi->frame = read_register (SP_REGNUM);
for (reg = 0; reg < NUM_REGS; reg++)
if (fi->fsr.regs[reg] != 0)
fi->fsr.regs[reg] = fi->frame + framesize - fi->fsr.regs[reg];
}
/* 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. */
CORE_ADDR
m32r_find_callers_reg (fi, regnum)
struct frame_info *fi;
int regnum;
{
#if 0
/* XXX - Won't work if multiple dummy frames are active */
if (PC_IN_CALL_DUMMY (fi->pc, NULL, NULL))
switch (regnum)
{
case SP_REGNUM:
return dummy_frame_stack->sp;
break;
case FP_REGNUM:
return dummy_frame_stack->fp;
break;
case RP_REGNUM:
return dummy_frame_stack->pc;
break;
case PC_REGNUM:
return dummy_frame_stack->pc;
break;
}
#endif
for (; fi; fi = fi->next)
if (fi->fsr.regs[regnum] != 0)
return read_memory_integer (fi->fsr.regs[regnum], 4);
return read_register (regnum);
}
/* Given a GDB frame, determine the address of the calling function's frame.
This will be used to create a new GDB frame struct, and then
INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
For m32r, simply get the saved FP off the stack.
*/
CORE_ADDR
m32r_frame_chain (fi)
struct frame_info *fi;
{
CORE_ADDR saved_fp = fi->fsr.regs[FP_REGNUM];
if (saved_fp == 0)
return 0; /* frameless assembly language fn (such as _start) */
return read_memory_integer (saved_fp, 4);
}
/* All we do here is record SP and FP on the call dummy stack */
void
m32r_push_dummy_frame ()
{
struct dummy_frame *dummy_frame;
dummy_frame = xmalloc (sizeof (struct dummy_frame));
dummy_frame->fp = read_register (FP_REGNUM);
dummy_frame->sp = read_register (SP_REGNUM);
dummy_frame->rp = read_register (RP_REGNUM);
dummy_frame->pc = read_register (PC_REGNUM);
dummy_frame->next = dummy_frame_stack;
dummy_frame_stack = dummy_frame;
}
/*
* MISSING FUNCTION HEADER COMMENT
*/
int
m32r_pc_in_call_dummy (pc)
CORE_ADDR pc;
{
return dummy_frame_stack
&& pc >= CALL_DUMMY_ADDRESS ()
&& pc <= CALL_DUMMY_ADDRESS () + DECR_PC_AFTER_BREAK;
}
/* Discard from the stack the innermost frame,
restoring all saved registers. */
struct frame_info *
m32r_pop_frame (frame)
struct frame_info *frame;
{
int regnum;
#if 0
if (PC_IN_CALL_DUMMY (frame->pc, NULL, NULL))
{
struct dummy_frame *dummy_frame;
dummy_frame = dummy_frame_stack;
if (!dummy_frame)
error ("Can't pop dummy frame!");
dummy_frame_stack = dummy_frame->next;
write_register (FP_REGNUM, dummy_frame->fp);
write_register (SP_REGNUM, dummy_frame->sp);
write_register (RP_REGNUM, dummy_frame->rp);
write_register (PC_REGNUM, dummy_frame->pc);
free (dummy_frame);
flush_cached_frames ();
return NULL;
}
#endif
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_integer (frame->fsr.regs[regnum], 4));
write_register (SP_REGNUM, read_register (FP_REGNUM));
if (read_register (PSW_REGNUM) & 0x80)
write_register (SPU_REGNUM, read_register (SP_REGNUM));
else
write_register (SPI_REGNUM, read_register (SP_REGNUM));
/* registers_changed (); */
flush_cached_frames ();
return NULL;
}
/* Put arguments in the right places, and setup return address register (RP) to
point at a convenient place to put a breakpoint. 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).
By the time we get here, stack space has been allocated for the args, but
not for the struct return pointer. */
CORE_ADDR
m32r_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;
argreg = ARG0_REGNUM;
#if 0
if (struct_return)
{
write_register (argreg++, struct_addr);
sp -= 4;
}
for (argnum = 0; argnum < nargs; argnum++)
{
int len;
char *val;
char valbuf[4];
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 + argnum * 4, val, 4);
len -= 4;
val += 4;
}
args++;
}
write_register (RP_REGNUM, entry_point_address ());
#endif
return sp;
}
void
_initialize_m32r_tdep ()
{
tm_print_insn = print_insn_m32r;
}