diff options
author | Fred Fish <fnf@specifix.com> | 1992-07-31 23:17:54 +0000 |
---|---|---|
committer | Fred Fish <fnf@specifix.com> | 1992-07-31 23:17:54 +0000 |
commit | 672786833c63ec2f9504a7eb0a75d99f0617c7b2 (patch) | |
tree | 6646e9d1df6389f2272327eb4d69abcfccd58c5a /gdb/i860-tdep.c | |
parent | 14f1fc24fab58318fd104cafb548269bec0f8650 (diff) | |
download | gdb-672786833c63ec2f9504a7eb0a75d99f0617c7b2.zip gdb-672786833c63ec2f9504a7eb0a75d99f0617c7b2.tar.gz gdb-672786833c63ec2f9504a7eb0a75d99f0617c7b2.tar.bz2 |
Update cygnus copies of currently undistributed i860 files maintained by
Peggy Fieland at stratus.com.
Diffstat (limited to 'gdb/i860-tdep.c')
-rw-r--r-- | gdb/i860-tdep.c | 791 |
1 files changed, 630 insertions, 161 deletions
diff --git a/gdb/i860-tdep.c b/gdb/i860-tdep.c index 4d631db..3c5f940 100644 --- a/gdb/i860-tdep.c +++ b/gdb/i860-tdep.c @@ -1,7 +1,7 @@ -/* Target-dependent code for the i860 for GDB, the GNU debugger. - Copyright is unclear on this module!!! - Copyright (C) 1992 Free Software Foundation, Inc. - SVR4 and ELF/DWARF changes Contributed by Peggy Fieland (pfieland@stratus.com) +/* Machine-dependent code which would otherwise be in inflow.c and core.c, + for GDB, the GNU debugger. + Copyright (C) 1986, 1987 Free Software Foundation, Inc. + This code is for the i860 cpu. GDB is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone @@ -19,11 +19,12 @@ In other words, go ahead and share GDB, but don't try to stop anyone else from sharing it farther. Help stamp out software hoarding! */ -#include "defs.h" +#include <stdio.h> #include <stdlib.h> #include <stdarg.h> +#include "defs.h" #include "tm-i860.h" #include "frame.h" #include "inferior.h" @@ -31,11 +32,12 @@ #include "symtab.h" #include "value.h" -#include "tm-i860.h" #include "i860-opcode.h" -#include "break.h" +#include "breakpoint.h" +#include "i860-break.h" #include "command.h" +#include "target.h" #ifdef notdef #include <sys/types.h> @@ -67,18 +69,22 @@ extern int read_memory_integer(); extern int print_insn(); extern void bzero(); extern void bcopy(); -extern int store_inferior_registers(int); -extern int outside_startup_file(); int btdebug = 0; /* change value to 1 to enable debugging code */ +int ansi_conformant; #define BTDEBUG if (btdebug) btdebug_message extern int errno; extern int attach_flag; +extern char registers[]; +static CORE_ADDR get_saved_basereg(); #define INSTRUCTION_LENGTH 4 #define REGISTER_LENGTH 4 +#define ALIGN_ARG(size,len) ((size + (len-1))&(-len)) +#define NUM_FLOAT_ARG_REGS 8 +#define NUM_INT_ARG_REGS 12 /* routine to print debugging messages */ void btdebug_message(char *format, ...) @@ -92,6 +98,59 @@ void btdebug_message(char *format, ...) } +/* Peggy Fieland. Routine that attempts to find the start of the entry sequence + for a routine. */ +/* maximum number of instrutions to search back */ +#define MAX_ROUTINE_SIZE 4096 +CORE_ADDR find_entry_start(pc) +CORE_ADDR pc; +{ + CORE_ADDR instr, top_pc; + int i; + + top_pc = pc; + for (i = 0; i < MAX_ROUTINE_SIZE; ++i) + + { + instr = (unsigned)( adj_read_memory_integer (top_pc)); + /* Recognize "addu|adds -X,sp,sp" insn. */ + + if ((instr & 0xEFFF0000) == 0x84420000) + { + return (top_pc); + } + top_pc -= INSTRUCTION_LENGTH; + } + return (0); +} + + + +/* Written by Peggy Fieland (Margaret_Fieland@vos.stratus.com) */ +/* get the contents of a base register. Used for dwarf OP_BASEREG */ +/* At present, only OP_BASEREG generated is for R28. NOTE that for stuff based on R28, + the value we want is the VALUE AT PROCEDURE INVOKATION, and thus is the frame we + use to get the value is the caller's frame. */ +CORE_ADDR get_saved_basereg (frame, basereg) +FRAME frame; +int basereg; +{ + CORE_ADDR addr; + if (basereg == R28) /* Unconditionally ??? */ + { + frame = get_prev_frame (frame); + get_saved_register((char *) &addr, (int *) NULL, (CORE_ADDR *) NULL, frame, + basereg, (enum lval_type *)NULL); + + } + else + get_saved_register((char *) &addr, (int *) NULL, (CORE_ADDR *) NULL, frame, + basereg, (enum lval_type *)NULL); + + return (addr); +} + + /* return nonzero if the routine containing pc has been * compiled with -g. We assume -g if the first instruction is @@ -101,12 +160,16 @@ void btdebug_message(char *format, ...) */ static int g_routine(pc) + CORE_ADDR pc; { CORE_ADDR instr; CORE_ADDR top_pc; top_pc = get_pc_function_start(pc); + if (top_pc == NULL) + top_pc = find_entry_start (pc); + if (top_pc != NULL) { instr = (unsigned)( adj_read_memory_integer (top_pc)); @@ -146,25 +209,38 @@ CORE_ADDR pc; return(0); } + /* return the stack offset where r1 (return linkage ) register is stored */ -static int find_r1_offset(pc) -CORE_ADDR pc; +static CORE_ADDR find_r1(pc,sp,fp) +CORE_ADDR pc,sp, fp; { int r1_off,i; - CORE_ADDR instr; + CORE_ADDR instr, ret_pc; /* look for the instruction and examine the offset */ - for (i=INSTRUCTION_LENGTH*1; i< INSTRUCTION_LENGTH*4; i+=INSTRUCTION_LENGTH){ - instr = (unsigned)( adj_read_memory_integer(pc+i)); - if ((instr & 0xFFE0F801) == 0x1C400801) { /* st.l r1,X(sp) */ + for (i=INSTRUCTION_LENGTH*1; i< INSTRUCTION_LENGTH*4; i+=INSTRUCTION_LENGTH) + { + instr = (unsigned)( adj_read_memory_integer(pc+i)); + if ((instr & 0xFFE0F801) == 0x1C400801) + { + /* st.l r1,X(sp) */ - r1_off = SIGN_EXT16(((instr&0x001F0000) >> 5) | - (instr&0x000007FE)); - return(r1_off); + r1_off = SIGN_EXT16(((instr&0x001F0000) >> 5) | + (instr&0x000007FE)); + ret_pc = read_memory_integer(sp+r1_off,sizeof(long)); + return(ret_pc); + } + else if ((instr & 0xFFE0F801) == 0x1C600801) + { + /* st.l r1,X(fp) */ + r1_off = SIGN_EXT16(((instr&0x001F0000) >> 5) | + (instr&0x000007FE)); + ret_pc = read_memory_integer(fp+r1_off,sizeof(long)); + return(ret_pc); + } } - } - return(-1); + return(0); } CORE_ADDR skip_prologue(CORE_ADDR); @@ -193,9 +269,6 @@ CORE_ADDR rp, fp; else return (1); } - - - /* get the pc and frame pointer (or sp ) * for the routine that called us * when we (this_pc) is not within a -g routine @@ -204,9 +277,10 @@ CORE_ADDR rp, fp; /* note this is written for Metaware version R2.1d compiler */ /* Modified by Peggy Fieland Margaret_Fieland@vos.stratus.com */ -static int caller_pc(this_pc,this_sp,to_pc,to_fp) - CORE_ADDR this_pc,this_sp; +static int caller_pc(this_pc,this_sp,this_fp,to_pc,to_fp, called_from_frame_chain) + CORE_ADDR this_pc,this_sp, this_fp; CORE_ADDR *to_pc, *to_fp; + int called_from_frame_chain; { CORE_ADDR func_start; int sp_offset,offset; @@ -216,8 +290,19 @@ static int caller_pc(this_pc,this_sp,to_pc,to_fp) func_start = get_pc_function_start(this_pc); + if (func_start == NULL) + func_start = find_entry_start (this_pc); + BTDEBUG("caller_pc func_start %x\n", func_start); + if ((func_start == NULL)) + { + /* error in traceback */ + fprintf(stderr, "error, unable to find start of function\n"); + return(0); + + } + if (func_start!= NULL) { if( has_a_frame(func_start) ){ @@ -236,18 +321,22 @@ static int caller_pc(this_pc,this_sp,to_pc,to_fp) } else { - /* if we get here, procedure doesn't have a frame. If we didn't + /* if we get here, procedure doesn't have a frame. If we do anything weird, the frame pointer and return register have the values we want. Check them to see if they are valid. */ CORE_ADDR temp_rp, temp_fp; + /* temporary warning, since at the moment we don't have support for + the shared library */ + temp_rp = read_register(RP_REGNUM); temp_fp = read_register(FP_REGNUM); if (!valid_regs(temp_rp, temp_fp)) { - printf("error frame_chain\n"); + fprintf(stderr, + "error - unable to find return address, traceback terminating\n"); return(0); } BTDEBUG("caller_pc no frame, using r1 %x and fp %x\n", @@ -259,14 +348,15 @@ static int caller_pc(this_pc,this_sp,to_pc,to_fp) BTDEBUG("sp_offset = %d %x\n",sp_offset,sp_offset); - offset = find_r1_offset(func_start); + pc = find_r1(func_start, this_sp, this_fp); - if( offset < 0 ){ - printf("cant find return address for routine at %x\n", - func_start); - return(0); - } - pc = read_memory_integer(this_sp+offset,sizeof(long)); + if(pc == NULL) + { + + /* r1 wasn't stored between pc and function start */ + pc = read_register (RP_REGNUM); + } + sp= this_sp - sp_offset; BTDEBUG("callers pc = %x sp = %x\n",pc,sp); @@ -281,7 +371,8 @@ static int caller_pc(this_pc,this_sp,to_pc,to_fp) BTDEBUG("caller_a_g\n"); if( ! (offset = find_fp_offset(func_start)) ) { - printf("error fp_offset\n"); + fprintf(stderr, "error - unable to find caller frame for routine at 0x%x, " + "traceback terminating\n", func_start); return(0); } BTDEBUG("offset = %x %d\n",offset,offset); @@ -308,7 +399,9 @@ static int caller_pc(this_pc,this_sp,to_pc,to_fp) if (!valid_regs(temp_rp, temp_fp)) { - printf("error frame_chain\n"); + fprintf(stderr, + "error - unable to find return address, traceback terminating\n"); + return(0); } BTDEBUG("caller_pc no frame, using r1 %x and fp %x\n", @@ -338,7 +431,6 @@ struct breakpoint *brk; CORE_ADDR nextadr, prevadr; int val = not_branch; long offset; /* Must be signed for sign-extend */ - extern char registers[]; prevadr = nextadr = 0; brk->address1 = 0; @@ -488,21 +580,23 @@ struct breakpoint *brk; /* bc /bnc */ /* bc.t /bnc.t*/ if ((instr & 0xF8000000) == 0x68000000) /* br or call */ - printf(" Breakpoint adjusted to avoid br/call delay slot and multiple breakpoints\n"); + BTDEBUG(" Breakpoint adjusted to avoid br/call delay slot and multiple breakpoints\n"); if ((instr & 0xF4000000) == 0x74000000) /* bc.t or bnc.t */ - printf(" Breakpoint adjusted to avoid bc.t/bnc.t delay slot and multiple breakpoints\n"); + BTDEBUG(" Breakpoint adjusted to avoid bc.t/bnc.t delay slot and" + "multiple breakpoints\n"); + /* it IS really OK to set a break on the instruction AFTER the conditional branch -- it DOESN't have a delay slot */ if ((instr & 0xF4000000) == 0x70000000) /* bc / bnc */ - /* printf(" Breakpoint adjusted to avoid bc/bnc delay slot and multiple breakpoints\n"); */ adjust = 0; } else if ((instr & 0xFC00003F) == 0x4C000002 || /* bri/ calli */ (instr & 0xFC000000) == 0x40000000) { adjust++; - printf(" Breakpoint adjusted to avoid calli/bri delay slot and multiple breakpoints\n"); + BTDEBUG(" Breakpoint adjusted to avoid calli/bri delay slot and" + " multiple breakpoints\n"); } else if ((instr & 0xF0000000) == 0x50000000) /* bte - btne */ { @@ -516,7 +610,8 @@ struct breakpoint *brk; ((instr & 0xFC000000) == 0xB4000000) { adjust++; - printf(" Breakpoint adjusted to avoid bla delay slot and multiple breakpoints\n"); + BTDEBUG(" Breakpoint adjusted to avoid bla delay slot and" + " multiple breakpoints\n"); } if (adjust != 0) { @@ -618,15 +713,19 @@ int signal; { CORE_ADDR pc; branch_type place_brk(); - + int *shadow0, *shadow1, *shadow2, *shadow3; + + shadow0 = (int *) &brk.shadow_contents[0]; + shadow1 = (int *) &brk.shadow_contents[4]; + shadow2 = (int *) &brk.shadow_contents[8]; + shadow3 = (int *) &brk.shadow_contents[12]; pc = read_register (PC_REGNUM); if (!one_stepped) { brk.address = pc; place_brk (pc, SINGLE_STEP_MODE, &brk); - brk.shadow_contents[0] = brk.shadow_contents[1] = 0; - brk.shadow_contents[2] = brk.shadow_contents[3] = 0; + *shadow0 = *shadow1 = *shadow2 = *shadow3 = 0; if (brk.mode == DIM) { @@ -640,10 +739,10 @@ int signal; } if (( brk.address1 != NULL)) { - adj_read_memory (brk.act_addr[2], &brk.shadow_contents[2], + adj_read_memory (brk.act_addr[2], shadow2, INSTRUCTION_LENGTH); adj_write_memory (brk.act_addr[2], break_insn, INSTRUCTION_LENGTH); - adj_read_memory (brk.act_addr[3], &brk.shadow_contents[3], + adj_read_memory (brk.act_addr[3], shadow3, INSTRUCTION_LENGTH); /* adj_write_memory (brk.act_addr[3], float_insn, INSTRUCTION_LENGTH); */ @@ -663,11 +762,11 @@ int signal; btdebug_message("\n"); } - adj_read_memory (brk.act_addr[0], &brk.shadow_contents[0], + adj_read_memory (brk.act_addr[0], shadow0, INSTRUCTION_LENGTH); adj_write_memory (brk.act_addr[0], break_insn, INSTRUCTION_LENGTH); - adj_read_memory (brk.act_addr[1], &brk.shadow_contents[1], + adj_read_memory (brk.act_addr[1], shadow1, INSTRUCTION_LENGTH); /* adj_write_memory (brk.act_addr[1], float_insn, INSTRUCTION_LENGTH); */ @@ -683,7 +782,7 @@ int signal; print_insn( brk.act_addr[2], stderr); btdebug_message("\n"); } - adj_read_memory (brk.act_addr[2], &brk.shadow_contents[2], + adj_read_memory (brk.act_addr[2], shadow2, INSTRUCTION_LENGTH); adj_write_memory (brk.act_addr[2], break_insn, INSTRUCTION_LENGTH); } @@ -698,7 +797,7 @@ int signal; print_insn( brk.act_addr[0], stderr); btdebug_message("\n"); } - adj_read_memory (brk.act_addr[0], &brk.shadow_contents[0], + adj_read_memory (brk.act_addr[0], shadow0, INSTRUCTION_LENGTH); adj_write_memory (brk.act_addr[0], break_insn,INSTRUCTION_LENGTH); } @@ -712,12 +811,12 @@ int signal; /* Remove breakpoints */ if (brk.mode == DIM) { - adj_write_memory (brk.act_addr[0], &brk.shadow_contents[0], + adj_write_memory (brk.act_addr[0], shadow0, INSTRUCTION_LENGTH); - adj_write_memory (brk.act_addr[1], &brk.shadow_contents[1], + adj_write_memory (brk.act_addr[1], shadow1, INSTRUCTION_LENGTH); } else { - adj_write_memory (brk.act_addr[0], &brk.shadow_contents[0], + adj_write_memory (brk.act_addr[0], shadow0, INSTRUCTION_LENGTH); } @@ -725,12 +824,12 @@ int signal; { if (brk.mode == DIM) { - adj_write_memory (brk.act_addr[2], &brk.shadow_contents[2], + adj_write_memory (brk.act_addr[2], shadow2, INSTRUCTION_LENGTH); - adj_write_memory (brk.act_addr[3], &brk.shadow_contents[3], + adj_write_memory (brk.act_addr[3], shadow3, INSTRUCTION_LENGTH); } else { - adj_write_memory (brk.act_addr[2], &brk.shadow_contents[2], + adj_write_memory (brk.act_addr[2], shadow2, INSTRUCTION_LENGTH); } } @@ -898,18 +997,18 @@ frame_find_saved_regs(frame_info, frame_saved_regs) at fp + NUM_REGS*4 */ for (i = 1; i < NUM_REGS; i++) /* skip reg 0 */ - if (i != SP_REGNUM && i != FP0_REGNUM && i != FP0_REGNUM + 1) - /* the register numbers used in the instruction and the ones used to index - the regs array are not the same -- compensate */ - frame_saved_regs->regs[i+R0] = frame_info->frame + i*REGISTER_LENGTH; - - frame_saved_regs->regs[SP_REGNUM] = frame_info->frame + NUM_REGS*REGISTER_LENGTH; + /* the register numbers used in the instruction and the ones used to index + the regs array are not the same -- compensate */ + frame_saved_regs->regs[i+R0] = frame_info->frame + i*REGISTER_LENGTH; call_dummy_set = 0; return; } pc = get_pc_function_start (frame_info->pc); + if (pc == NULL) + pc = find_entry_start (frame_info->pc); + if (pc != NULL) { instr = (unsigned)(adj_read_memory_integer (pc)); @@ -1051,8 +1150,10 @@ frame_chain(thisframe) CORE_ADDR instr; int offset; CORE_ADDR thisfp = thisframe->frame; - - /* get the frame pointer actually sp for a non -g + struct frame_saved_regs fsr; + CORE_ADDR thissp; + + /* get the frame pointer actually sp for a non -g * for the routine that called us routine */ @@ -1064,8 +1165,10 @@ frame_chain(thisframe) } if( ! g_routine(thisframe->pc) ){ + thissp = get_saved_basereg (thisframe, SP_REGNUM); + BTDEBUG( "non g at %x\n",thisframe->pc); - caller_pc(thisframe->pc,thisframe->sp,&pc,&fp); + caller_pc(thisframe->pc, thissp, thisfp,&pc,&fp, 1); BTDEBUG("caller_pc returned %x %x \n",pc,fp); return(fp); @@ -1079,7 +1182,9 @@ frame_chain(thisframe) /* handle the Metaware-type pseudo-frame */ func_start = get_pc_function_start(thisframe->pc); - + if (func_start == NULL) + func_start = find_entry_start (thisframe->pc); + if (func_start != NULL) { @@ -1108,6 +1213,9 @@ int no_stored_rp(CORE_ADDR pc) CORE_ADDR func_start, prologue_end; func_start = get_pc_function_start(pc); + if (func_start == NULL) + func_start = find_entry_start (pc); + if (func_start != NULL) { prologue_end = func_start; @@ -1142,11 +1250,12 @@ FRAME frame_struct; CORE_ADDR pc1; CORE_ADDR sp ; CORE_ADDR fp; + struct frame_saved_regs fsr; frame = frame_struct->frame; pc = frame_struct->pc; - sp = frame_struct->sp; - + + BTDEBUG("frame_saved_pc input: frame %x, pc %x", frame, pc); @@ -1163,21 +1272,23 @@ FRAME frame_struct; } else if( ! g_routine(pc) ) { - caller_pc(pc,sp,&pc,&frame); + sp = get_saved_basereg (frame_struct, SP_REGNUM); + + caller_pc(pc,sp,frame_struct->frame, &pc,&frame, 0); } else { pc = read_memory_integer (frame + 4, sizeof(long)); - if (!outside_startup_file(pc)) + if (inside_entry_file(pc)) { - BTDEBUG("pc %x outside startup file \n",pc); + BTDEBUG("pc %x outside entry file \n",pc); pc1 = read_memory_integer (frame, sizeof(long)); - if (outside_startup_file(pc1)) + if (!inside_entry_file(pc1)) pc = pc1; else pc = 0; @@ -1189,42 +1300,141 @@ FRAME frame_struct; } /* Pass arguments to a function in the inferior process - ABI compliant - Note that this routine DOES NOT HANDLE memory argument lists, ie - it gives up if there are too many arguments to pass in registers.*/ + Modified by Peggy Fieland (Margaret_Fieland@vos.stratus.com) to account + for newer ABI conventions. Note that now, unfortunately, we MUST KNOW + if we expect a float or a double. For now, we will assume that the + caller of this routine has the types of these arguments correct.... + NOTE THAT THIS ROUTINE DOES NO ARGUMENT COERCION -- it's all in the + caller. + Modified by Peggy Fieland to handle memory argument lists. + */ -void -pass_function_arguments(args, nargs, struct_return) +#define IS_EVEN_REG(fl) (((fl - FP0_REGNUM)%2) == 0) +CORE_ADDR +pass_function_arguments(args, nargs, struct_return, struct_addr, sp) value *args; int nargs; int struct_return; + CORE_ADDR struct_addr; + CORE_ADDR sp; { - int ireg = (struct_return) ? 17 : 16; - int freg = FP0_REGNUM + 8; + int ireg = (struct_return) ? R17 : R16; + int freg = F8; int i; struct type *type; value arg; - long tmp; - value value_arg_coerce(); - + signed long tmp; + unsigned long ul_tmp; + signed short s_tmp; + unsigned short us_tmp; + signed char c_tmp; + unsigned char uc_tmp; + CORE_ADDR arg_ptr; + int len; + + if (struct_return) + { + write_register(R16, struct_addr); + } + + arg_ptr = sp; /* Space was allocated for memory argument list in i860_arg_coerce */ + + /* Loop through the arguments, putting the values in a register or memory as appropriate. */ for (i = 0; i < nargs; i++) { - arg = value_arg_coerce(args[i]); + arg = args[i]; type = VALUE_TYPE(arg); + len = TYPE_LENGTH(type); if (type == builtin_type_double) { - write_register_bytes(REGISTER_BYTE(freg), VALUE_CONTENTS(arg), sizeof(double)); - freg += 2; + /* see ABI . Note freg MUST BE INCREMENTED even if arg goes into the + memory argument list for this code to work correctly for subsequent + arguments. */ + if (!IS_EVEN_REG(freg)) + freg += 1; + /* see if argument can be put in a register, or whether it must go + into the memory argument list */ + if (freg < F8 + NUM_FLOAT_ARG_REGS) + { + /* It can go in a register */ + bcopy(VALUE_CONTENTS(arg), &tmp, sizeof(double)); + write_register_bytes(REGISTER_BYTE(freg), (char *) &tmp, TYPE_LENGTH(type)); + freg += 2; + } + else + { + /* It goes into memory argument list */ + arg_ptr = ALIGN_ARG( arg_ptr, sizeof(double)); + write_memory (arg_ptr, VALUE_CONTENTS (arg), len); + arg_ptr += len; + } + + } + else if (type == builtin_type_float) + { + if (freg < F8 + NUM_FLOAT_ARG_REGS) + { + /* It can go in a register */ + bcopy(VALUE_CONTENTS(arg), &tmp, sizeof(long)); + write_register_bytes (REGISTER_BYTE(freg), (char *) &tmp, TYPE_LENGTH(type)); + freg++; + } + else + { + /* It goes into the memory argument list */ + arg_ptr = ALIGN_ARG(arg_ptr, sizeof(float)); + write_memory (arg_ptr, VALUE_CONTENTS (arg), len); + arg_ptr += len; + } } else { - bcopy(VALUE_CONTENTS(arg), &tmp, sizeof(long)); - write_register(ireg, tmp); - ireg++; + /* All structs are passed by value, and hence they all go into the memory + argument list (see ABI); otherwise, as above, see if we have run + out of registers */ + + /* Cast value correctly so we can load it into a register or into the + memory argument list -- see ABI */ + if (TYPE_LENGTH(type) < sizeof(long)) + { + if (TYPE_FLAGS(type) & TYPE_FLAG_UNSIGNED) + arg = value_cast(builtin_type_unsigned_int, arg); + else + arg = value_cast (builtin_type_int, arg); + type = VALUE_TYPE(arg); + len = TYPE_LENGTH(type); + } + + if ((TYPE_CODE(type) == TYPE_CODE_STRUCT) || (ireg >= R16 + NUM_INT_ARG_REGS)) + { + /* It goes into the memory argument list. Minimum alignment requirements + are on a 4-byte boundary */ + + if ((TYPE_CODE(type) == TYPE_CODE_INT) || + (TYPE_CODE(type) == TYPE_CODE_ENUM) || + (TYPE_CODE(type) == TYPE_CODE_CHAR) || + (TYPE_CODE(type) == TYPE_CODE_BOOL)) + arg_ptr = ALIGN_ARG(arg_ptr, len); + else + arg_ptr = ALIGN_ARG (arg_ptr, sizeof(long)); /* align on 4-byte boundary */ + write_memory (arg_ptr, VALUE_CONTENTS (arg), len); + arg_ptr += len; + } + else + { + + bcopy(VALUE_CONTENTS(arg), &tmp, sizeof(long)); + write_register(ireg, tmp); + ireg++; + } + } } - if (ireg >= 28 || freg >= FP0_REGNUM + 16) - error("Too many arguments to function"); + + + return (sp); + } @@ -1243,19 +1453,23 @@ char *doro_reg[] = { }; #define NREGS 32 -#if 0 -/* This routine is uncalled -- remove this routine sometime */ + get_reg(regno) { char raw_buffer[32]; int addr; int virtual_buffer; - - read_relative_register_raw_bytes (regno, raw_buffer); + + /* NOTE that only integer and floating point registers can be relative to a frame */ + + if ((regno >= R0) && (regno <= F31)) /* user register */ + read_relative_register_raw_bytes (regno, raw_buffer); + else + bcopy (®isters[regno << 2], raw_buffer, sizeof (long)); + REGISTER_CONVERT_TO_VIRTUAL (addr, raw_buffer, &virtual_buffer); return(virtual_buffer); } -#endif #if 0 @@ -1347,10 +1561,12 @@ int ss; } #endif -extern char registers[]; /* i860-specific routine to print the register set. Note that we ALWAYS print information - on the floating point registers, so we ignore the parameter fpregs */ + on the floating point registers, so we ignore the parameter fpregs. + NOTE also that only integer and floating point registers can be relative to a frame -- + see subroutine get_reg (above ) */ + void i860_do_registers_info(regnum,fpregs) int regnum; int fpregs; @@ -1366,10 +1582,7 @@ void i860_do_registers_info(regnum,fpregs) if (regnum != -1) /* print one register */ { - if ((regnum >=F0 ) && (regnum <= F31)) - bcopy (®isters[ADJ_FREG(regnum)<<2], &val, sizeof (long)); - else - bcopy (®isters[regnum<<2], &val, sizeof (long)); + val = get_reg(regnum); printf("%-4s 0x%08x\t", reg_names[regnum], val); printf("\n\t"); fflush(stdout); } @@ -1379,31 +1592,31 @@ void i860_do_registers_info(regnum,fpregs) printf("\n Control/Status Registers :- \n\t"); for (j=0; j<=DB; j++) { - bcopy (®isters[j<<2], &val, sizeof (long)); + val = get_reg(j); printf("%-4s 0x%08x\t", reg_names[j], val); } printf("\n\t"); fflush(stdout); /* EPSR */ - bcopy (®isters[EPSR<<2], &val, sizeof (long)); + val = get_reg(EPSR); printf("%-4s 0x%08x\t", reg_names[EPSR], val); /* FSR */ - bcopy (®isters[FSR<<2], &val, sizeof (long)); + val = get_reg(FSR); printf("%-4s 0x%08x\t", reg_names[FSR], val); /* CCR */ - bcopy (®isters[CCR<<2], &val, sizeof (long)); + val = get_reg(CCR); printf("%-4s 0x%08x\t", reg_names[CCR], val); /* BEAR*/ - bcopy (®isters[BEAR<<2], &val, sizeof (long)); + val = get_reg(BEAR); printf("%-4s 0x%08x\t", reg_names[BEAR], val); #ifdef JIM_ADD_PRIV for (j=P0; j<=P3; j++) { - bcopy (®isters[j<<2], &val, sizeof (long)); + val = get_reg(j); printf("%-4s 0x%08x\t", reg_names[j], val); } #endif @@ -1415,7 +1628,7 @@ void i860_do_registers_info(regnum,fpregs) { printf("\n\t"); fflush(stdout); } - bcopy (®isters[j<<2], &val, sizeof (long)); + val = get_reg(j); printf("%-4s 0x%08x\t", reg_names[j], val); } @@ -1426,7 +1639,7 @@ void i860_do_registers_info(regnum,fpregs) { printf("\n\t"); fflush(stdout); } - bcopy (®isters[ADJ_FREG(j)<<2], &val, sizeof (long)); + val = get_reg(j); printf("%-4s 0x%08x\t", reg_names[j], val); } @@ -1438,8 +1651,8 @@ void i860_do_registers_info(regnum,fpregs) { printf("\n\t"); fflush(stdout); } - bcopy (®isters[j<<2], &val, sizeof (long)); - bcopy (®isters[(j+1)<<2], &valh, sizeof (long)); + val = get_reg(j); + valh = get_reg(j+1); printf("%-6s 0x%08x %08x\t", reg_names[j], val,valh); } @@ -1447,8 +1660,8 @@ void i860_do_registers_info(regnum,fpregs) { unsigned int valh; j = PSV_I1; - bcopy (®isters[j<<2], &val, sizeof (long)); - bcopy (®isters[(j+1)<<2], &valh, sizeof (long)); + val = get_reg(j); + valh = get_reg(j+1); printf("\t\t\t%-8s 0x%08x %08x \n", reg_names[j], val,valh); } @@ -1456,10 +1669,12 @@ void i860_do_registers_info(regnum,fpregs) for (j=PSV_L1; j<=PSV_L3; j+=REGISTER_LENGTH) { unsigned int valh, val2,val3; - bcopy (®isters[j<<2], &val, sizeof (long)); - bcopy (®isters[(j+1)<<2], &valh, sizeof (long)); - bcopy (®isters[(j+2)<<2], &val2, sizeof (long)); - bcopy (®isters[(j+3)<<2], &val3, sizeof (long)); + + val = get_reg(j); + valh = get_reg(j+1); + val2 = get_reg(j+2); + val3 = get_reg(j+3); + printf("\t\t%-8s 0x%08x %08x %08x %08x\n", reg_names[j], val,valh,val2,val3); } @@ -1468,11 +1683,13 @@ void i860_do_registers_info(regnum,fpregs) for (i=PSV_FSR1,j=PSV_A1,k=PSV_M1; j<=PSV_A3; i++,j+=2,k+=2) { unsigned int valh,val2,val3,val4; - bcopy (®isters[i<<2], &val4, sizeof (long)); - bcopy (®isters[j<<2], &val, sizeof (long)); - bcopy (®isters[(j+1)<<2], &valh, sizeof (long)); - bcopy (®isters[k<<2], &val2, sizeof (long)); - bcopy (®isters[(k+1)<<2], &val3, sizeof (long)); + + val4 = get_reg(i); + val = get_reg(j); + valh = get_reg(j+1); + val2 = get_reg(k); + val3 = get_reg(k+1); + printf(" %-4s 0x%08x %08x\t", reg_names[j], val,valh); printf("%-4s 0x%08x %08x\t", reg_names[k], val2,val3); printf("%-4s 0x%08x\n", reg_names[i], val4); @@ -1515,8 +1732,7 @@ void i860_dbrk_breakpoint() /* set a "read" data breakpoint. */ void -d_ro_break_command(arg) -char *arg; +d_ro_break_command(char *arg, int num) { dbrkval = strtoul(arg, NULL, 0); dbrkmod = 0x01; @@ -1525,8 +1741,7 @@ char *arg; /* set a "write" data breakpoint. */ void -d_wo_break_command(arg) -char *arg; +d_wo_break_command(char *arg, int num) { dbrkval = strtoul(arg, NULL, 0); dbrkmod = 0x02; @@ -1535,27 +1750,24 @@ char *arg; /* set a "read/write" data breakpoint. */ void -d_rw_break_command(arg) -char *arg; -{ - dbrkval = strtoul(arg, NULL, 0); - dbrkmod = 0x03; - BTDEBUG(" rw_dbreak - %x %x\n", dbrkval, dbrkmod); -} +d_rw_break_command(char *arg, int num) +{ + dbrkval = strtoul(arg, NULL, 0); + dbrkmod = 0x03; + BTDEBUG(" rw_dbreak - %x %x\n", dbrkval, dbrkmod); + } /* clear data breakpoint. */ -void -clear_dbreak() -{ - dbrkval = 0; - dbrkmod = 0; -} - -/* i860-specific breakpoint initialization. Includes adding the i860-specific - data breakpoint commands. */ -void -i860_init_breakpoints() -{ + void clear_dbreak(char *arg, int num) + { + dbrkval = 0; + dbrkmod = 0; + } + +/* i860-specific breakpoint initialization. Includes adding the +i860-specific data breakpoint commands. */ +void i860_init_breakpoints() +{ dbrkval = dbrkmod = 0; add_com ("dbro", class_breakpoint, d_ro_break_command, "Set a data breakpoint READ ONLY, 32-bit data element."); @@ -1574,21 +1786,28 @@ int i860_insert_breakpoint(b) struct breakpoint *b; { int val; + int *shadow0, *shadow1, *shadow2, *shadow3; + + shadow0 = (int *)&b->shadow_contents[0]; + shadow1 = (int *)&b->shadow_contents[4]; + shadow2 = (int *)&b->shadow_contents[8]; + shadow3 = (int *)&b->shadow_contents[12]; place_brk( b->address, BREAK_MODE, b ); + if (b->mode == DIM) { - adj_read_memory (b->act_addr[0], &b->shadow_contents[0], INSTRUCTION_LENGTH); + adj_read_memory (b->act_addr[0], shadow0, INSTRUCTION_LENGTH); val = adj_write_memory (b->act_addr[0], break_insn, INSTRUCTION_LENGTH); if (val != 0 ) return val; - adj_read_memory (b->act_addr[1], &b->shadow_contents[1], INSTRUCTION_LENGTH); + adj_read_memory (b->act_addr[1], shadow1, INSTRUCTION_LENGTH); /* val = adj_write_memory (b->act_addr[1], float_insn, INSTRUCTION_LENGTH); */ if (val != 0) return val; } else { - adj_read_memory (b->act_addr[0], &b->shadow_contents[0], INSTRUCTION_LENGTH); + adj_read_memory (b->act_addr[0], shadow0, INSTRUCTION_LENGTH); val = adj_write_memory (b->act_addr[0], break_insn, INSTRUCTION_LENGTH); } if (b->address1 != 0) @@ -1596,23 +1815,22 @@ struct breakpoint *b; if (b->mode == DIM) { - adj_read_memory (b->act_addr[2], &b->shadow_contents[2], INSTRUCTION_LENGTH); + adj_read_memory (b->act_addr[2], shadow2, INSTRUCTION_LENGTH); val = adj_write_memory (b->act_addr[2], break_insn, INSTRUCTION_LENGTH); if (val) return val; - adj_read_memory (b->act_addr[3], &b->shadow_contents[3], INSTRUCTION_LENGTH); + adj_read_memory (b->act_addr[3], shadow3, INSTRUCTION_LENGTH); /* val = adj_write_memory (b->act_addr[3], float_insn, INSTRUCTION_LENGTH); */ if (val != 0) return val; } else { - adj_read_memory (b->act_addr[2], &b->shadow_contents[0], INSTRUCTION_LENGTH); + adj_read_memory (b->act_addr[2], shadow0, INSTRUCTION_LENGTH); val = adj_write_memory (b->act_addr[2], break_insn, INSTRUCTION_LENGTH); } } if (val != 0) return val; - BTDEBUG("Inserted breakpoint at 0x%x, shadow 0x%x, 0x%x.\n", - b->address, b->shadow_contents[0], b->shadow_contents[1]); + b->inserted = 1; return 0; } @@ -1621,38 +1839,43 @@ int i860_remove_breakpoint(b) struct breakpoint *b; { int val; + int *shadow0, *shadow1, *shadow2, *shadow3; + + shadow0 = (int *)&b->shadow_contents[0]; + shadow1 = (int *)&b->shadow_contents[4]; + shadow2 = (int *)&b->shadow_contents[8]; + shadow3 = (int *)&b->shadow_contents[12]; + if (b->inserted) { if (b->mode == DIM) { - val =adj_write_memory (b->act_addr[0], &(b->shadow_contents[0]), + val =adj_write_memory (b->act_addr[0], shadow0, INSTRUCTION_LENGTH); - val =adj_write_memory (b->act_addr[1], &(b->shadow_contents[1]), + val =adj_write_memory (b->act_addr[1],shadow1, INSTRUCTION_LENGTH); if (b->address1 != NULL) { - val =adj_write_memory (b->act_addr[2], &(b->shadow_contents[2]), + val =adj_write_memory (b->act_addr[2],shadow2, INSTRUCTION_LENGTH); - val =adj_write_memory (b->act_addr[3], &(b->shadow_contents[3]), + val =adj_write_memory (b->act_addr[3], shadow3, INSTRUCTION_LENGTH); } } else { - val =adj_write_memory (b->act_addr[0], b->shadow_contents, + val =adj_write_memory (b->act_addr[0], shadow0, INSTRUCTION_LENGTH); if (b->address1 != NULL) { - val =adj_write_memory (b->act_addr[2], b->shadow_contents, + val =adj_write_memory (b->act_addr[2],shadow0, INSTRUCTION_LENGTH); } } if (val != 0) return val; b->inserted = 0; - BTDEBUG( "Removed breakpoint at 0x%x, shadow 0x%x, 0x%x.\n", - b->address, b->shadow_contents[0], b->shadow_contents[1]); } return 0; @@ -1758,3 +1981,249 @@ int regno; } } #endif + + +/* Push an empty stack frame, to record the current PC, etc. */ +/* We have this frame with fp pointing to a block where all GDB-visible + registers are stored in the order GDB knows them, and sp at the next + alignment point below fp. Note: fp + NUM_REGS*4 was the old sp + */ +extern CORE_ADDR text_end; +CORE_ADDR dummy_start_addr; +void i860_push_frame() +{ + register CORE_ADDR old_fp = read_register(FP_REGNUM); + register CORE_ADDR old_sp = read_register(SP_REGNUM); + register CORE_ADDR fp ; + extern char registers[]; + + fp = old_sp - REGISTER_BYTES; + write_memory(fp, registers, REGISTER_BYTES); /* write out old register values */ + /* reset FP and SP */ + write_register(FP_REGNUM, fp); + write_register(SP_REGNUM, (fp &~ 15)); /* re-align */ + call_dummy_set = 1; +} +/* Discard from the stack the innermost frame, + restoring all saved registers. */ + +void i860_pop_frame() +{ register FRAME frame = get_current_frame (); + register CORE_ADDR fp; + struct frame_info *fi; + int i; + + fi = get_frame_info (frame); + fp = fi->frame; + + if (call_dummy_set && fi -> pc >= call_dummy_start && + fi -> pc <= call_dummy_start + CALL_DUMMY_LENGTH) + { + + read_memory(fp, registers, REGISTER_BYTES); + + target_store_registers(-1); + + { + /* since we stomped on code that will be executed when we exit the program, + restore it. */ + extern REGISTER_TYPE call_save_code[4]; + + write_memory (call_dummy_start, (char *) call_save_code, 16); + + } + call_dummy_set = 0; + } + else + { + register int regnum; + struct frame_saved_regs fsr; + char raw_buffer[12]; + + get_frame_saved_regs (fi, &fsr); + for (regnum = FP0_REGNUM + 31; regnum >= FP0_REGNUM; regnum--) + if (fsr.regs[regnum]) + write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); + for (regnum = R31; regnum >= 1; regnum--) + if (fsr.regs[regnum]) + if (regnum != SP_REGNUM) + write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); + else + write_register (SP_REGNUM, fsr.regs[SP_REGNUM]); + if (fsr.regs[PS_REGNUM]) + write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); + if (fsr.regs[FPS_REGNUM]) + write_register (FPS_REGNUM, read_memory_integer (fsr.regs[FPS_REGNUM],4)); + if (fsr.regs[PC_REGNUM]) + write_register (PC_REGNUM,CLEAN_PC( read_memory_integer (fsr.regs[PC_REGNUM], 4))); + } + + flush_cached_frames (); + + set_current_frame (create_new_frame (read_register (FP_REGNUM), + read_pc ())); + +} + +CORE_ADDR i860_arg_coerce(nargs, args, struct_return, sp) + int nargs; + value *args; + int struct_return; + CORE_ADDR sp; +{ + + register int scalar; + register enum type_code code2; + register struct type *type; + int i; + value arg; + int num_int_args = 0; + int num_float_args = 0; + int size = 0; + CORE_ADDR arg_ptr; + + /* if we return a structure, it's address is in R16, and thus it uses up one of the integer + argument registers. See the ABI. */ + if (struct_return) + num_int_args += 1; + + /* loop to do the right thing with all the arguments and calculate the size of the memory + argument list. We keep count of the number of integer and the number of float parameters, + as well as the size of the memory argument list. */ + + for (i = 0; i < nargs; i++) + { + + /* NOTE that this is all hunky dory in spite of the fact that we don't actually + have the signature of the called procedure EXCEPT if we are passing in floats! + This is true, since registers are 4 bytes, and the minimum alignment in the + memory argument list is 4 bytes. See the ABI for more gory details. The switch + "ansi-conformant" is an attempt to get around this problem. */ + + code2 = TYPE_CODE (VALUE_TYPE(args[i])); + + /* Only coerce if we've got switch "ansi-conformant" off. + Actually, it's OK ( and probably helpful) to coerce ALL integer arguments + (see comment above), but never mind, we make them the right size in + pass_function_arguments. */ + + if ((!ansi_conformant) && (code2 != TYPE_CODE_STRUCT)) + value_arg_coerce(args[i]); + + arg = args[i]; + type = VALUE_TYPE(args[i]); + + /* All structures are passed by value in the memory argument list. */ + if (code2 == TYPE_CODE_STRUCT) + { + size = ALIGN_ARG(size, sizeof(long)); + size += TYPE_LENGTH(type); + } + else if (type == builtin_type_float) + { + num_float_args += 1; + if (num_float_args > NUM_FLOAT_ARG_REGS) + { + size = ALIGN_ARG(size, TYPE_LENGTH(type)) ; + size += TYPE_LENGTH(type); + } + } + else if (type == builtin_type_double) + { + /* floating register alignment -- see ABI */ + if ((num_float_args%2) != 0) + num_float_args += 1; + + num_float_args += 2; /* use up two registers */ + + if (num_float_args > NUM_FLOAT_ARG_REGS) + { + size = ALIGN_ARG(size, TYPE_LENGTH(type)) ; + size += TYPE_LENGTH(type); + } + } + else + { + int len = max (sizeof(long), TYPE_LENGTH(type)); + + num_int_args += 1; + + if (num_int_args > NUM_INT_ARG_REGS) + { + /* see ABI -- in-memory arguments have AT LEAST word alignment */ + if ((TYPE_CODE(type) == TYPE_CODE_INT) || + (TYPE_CODE(type) == TYPE_CODE_ENUM) || + (TYPE_CODE(type) == TYPE_CODE_CHAR) || + (TYPE_CODE(type) == TYPE_CODE_BOOL)) + size = ALIGN_ARG(size, len); + else + size = ALIGN_ARG(size, sizeof(long)); + size += len; + } + } + + } + + + /* recalculate the stack pointer, leaving enough space for the memory argument list and + realigning the stack pointer. */ + if (size != 0) + { + arg_ptr = sp - size; + + arg_ptr = arg_ptr & (-16); /* realign stack */ + write_register (R28,arg_ptr); + sp = arg_ptr; + } + +return (sp); + +} +void i860_extract_return_value(type,regbuf,valbuf) +struct type *type; +char regbuf[REGISTER_BYTES]; +char *valbuf; +{ + register int len = TYPE_LENGTH (type); + double tmp_db; + float tmp_flt; + + if ((TYPE_CODE(type) == TYPE_CODE_FLT)) + { + if (len == sizeof (float)) + { + /* FIXME + NOTE that this assumes that the function declaration was ANSI_CONFORMANT -- + at the present time I can't think of ANY WAY to disambiguate the two following + cases: + float really_does_return_a_float(float ff) + { ...} + and + float actually_returns_a_double(ff) + float ff; + {...} + */ + bcopy ((char *) (regbuf) + REGISTER_BYTE(ADJ_FREG(F8)), (valbuf), TYPE_LENGTH (type)) ; + } + else + bcopy ((char *) (regbuf) + REGISTER_BYTE(F8), (valbuf), TYPE_LENGTH (type)) ; + } + else + bcopy ((char *) (regbuf) + REGISTER_BYTE(R16), (valbuf), TYPE_LENGTH (type)); + +} +void i860_store_return_value(type,valbuf) +struct type *type; +char *valbuf; +{ + register int len = TYPE_LENGTH (type); + double tmp_db; + + if ((TYPE_CODE(type) == TYPE_CODE_FLT) ) + { + write_register_bytes (REGISTER_BYTE (F8), valbuf, len); + } + else + write_register_bytes (REGISTER_BYTE (R16), valbuf, TYPE_LENGTH (type)); + +} |