aboutsummaryrefslogtreecommitdiff
path: root/gdb/i860-tdep.c
diff options
context:
space:
mode:
authorFred Fish <fnf@specifix.com>1992-07-31 23:17:54 +0000
committerFred Fish <fnf@specifix.com>1992-07-31 23:17:54 +0000
commit672786833c63ec2f9504a7eb0a75d99f0617c7b2 (patch)
tree6646e9d1df6389f2272327eb4d69abcfccd58c5a /gdb/i860-tdep.c
parent14f1fc24fab58318fd104cafb548269bec0f8650 (diff)
downloadgdb-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.c791
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 (&registers[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 (&registers[ADJ_FREG(regnum)<<2], &val, sizeof (long));
- else
- bcopy (&registers[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 (&registers[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 (&registers[EPSR<<2], &val, sizeof (long));
+ val = get_reg(EPSR);
printf("%-4s 0x%08x\t", reg_names[EPSR], val);
/* FSR */
- bcopy (&registers[FSR<<2], &val, sizeof (long));
+ val = get_reg(FSR);
printf("%-4s 0x%08x\t", reg_names[FSR], val);
/* CCR */
- bcopy (&registers[CCR<<2], &val, sizeof (long));
+ val = get_reg(CCR);
printf("%-4s 0x%08x\t", reg_names[CCR], val);
/* BEAR*/
- bcopy (&registers[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 (&registers[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 (&registers[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 (&registers[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 (&registers[j<<2], &val, sizeof (long));
- bcopy (&registers[(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 (&registers[j<<2], &val, sizeof (long));
- bcopy (&registers[(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 (&registers[j<<2], &val, sizeof (long));
- bcopy (&registers[(j+1)<<2], &valh, sizeof (long));
- bcopy (&registers[(j+2)<<2], &val2, sizeof (long));
- bcopy (&registers[(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 (&registers[i<<2], &val4, sizeof (long));
- bcopy (&registers[j<<2], &val, sizeof (long));
- bcopy (&registers[(j+1)<<2], &valh, sizeof (long));
- bcopy (&registers[k<<2], &val2, sizeof (long));
- bcopy (&registers[(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));
+
+}