@ -630,132 +630,120 @@ value_assign (struct value *toval, struct value *fromval)
}
break ;
case lval_register :
if ( VALUE_BITSIZE ( toval ) )
{
char buffer [ sizeof ( LONGEST ) ] ;
int len =
REGISTER_RAW_SIZE ( VALUE_REGNO ( toval ) ) - VALUE_OFFSET ( toval ) ;
if ( len > ( int ) sizeof ( LONGEST ) )
error ( " Can't handle bitfields in registers larger than %d bits. " ,
( int ) sizeof ( LONGEST ) * HOST_CHAR_BIT ) ;
if ( VALUE_BITPOS ( toval ) + VALUE_BITSIZE ( toval )
> len * HOST_CHAR_BIT )
/* Getting this right would involve being very careful about
byte order . */
error ( " Can't assign to bitfields that cross register "
" boundaries. " ) ;
read_register_bytes ( VALUE_ADDRESS ( toval ) + VALUE_OFFSET ( toval ) ,
buffer , len ) ;
modify_field ( buffer , value_as_long ( fromval ) ,
VALUE_BITPOS ( toval ) , VALUE_BITSIZE ( toval ) ) ;
write_register_bytes ( VALUE_ADDRESS ( toval ) + VALUE_OFFSET ( toval ) ,
buffer , len ) ;
}
else if ( use_buffer )
write_register_bytes ( VALUE_ADDRESS ( toval ) + VALUE_OFFSET ( toval ) ,
raw_buffer , use_buffer ) ;
else
{
/* Do any conversion necessary when storing this type to more
than one register . */
# ifdef REGISTER_CONVERT_FROM_TYPE
memcpy ( raw_buffer , VALUE_CONTENTS ( fromval ) , TYPE_LENGTH ( type ) ) ;
REGISTER_CONVERT_FROM_TYPE ( VALUE_REGNO ( toval ) , type , raw_buffer ) ;
write_register_bytes ( VALUE_ADDRESS ( toval ) + VALUE_OFFSET ( toval ) ,
raw_buffer , TYPE_LENGTH ( type ) ) ;
# else
write_register_bytes ( VALUE_ADDRESS ( toval ) + VALUE_OFFSET ( toval ) ,
VALUE_CONTENTS ( fromval ) , TYPE_LENGTH ( type ) ) ;
# endif
}
target_changed_event ( ) ;
/* Assigning to the stack pointer, frame pointer, and other
( architecture and calling convention specific ) registers may
cause the frame cache to be out of date . We just do this
on all assignments to registers for simplicity ; I doubt the slowdown
matters . */
reinit_frame_cache ( ) ;
break ;
case lval_reg_frame_relative :
case lval_register :
{
struct frame_id old_frame ;
/* value is stored in a series of registers in the frame
specified by the structure . Copy that value out , modify
it , and copy it back in . */
int amount_to_copy = ( VALUE_BITSIZE ( toval ) ? 1 : TYPE_LENGTH ( type ) ) ;
int reg_size = REGISTER_RAW_SIZE ( VALUE_FRAME_REGNUM ( toval ) ) ;
int byte_offset = VALUE_OFFSET ( toval ) % reg_size ;
int reg_offset = VALUE_OFFSET ( toval ) / reg_size ;
int amount_copied ;
/* Make the buffer large enough in all cases. */
/* FIXME (alloca): Not safe for very large data types. */
char * buffer = ( char * ) alloca ( amount_to_copy
+ sizeof ( LONGEST )
+ MAX_REGISTER_RAW_SIZE ) ;
int amount_to_copy ;
char * buffer ;
int value_reg ;
int reg_offset ;
int byte_offset ;
int regno ;
struct frame_info * frame ;
/* Since modifying a register can trash the frame chain, we
save the old frame and then restore the new frame
afterwards . */
get_frame_id ( selected_frame , & old_frame ) ;
/* Figure out which frame this is in currently. */
if ( VALUE_LVAL ( toval ) = = lval_register )
{
frame = get_current_frame ( ) ;
value_reg = VALUE_REGNO ( toval ) ;
}
else
{
for ( frame = get_current_frame ( ) ;
frame & & FRAME_FP ( frame ) ! = VALUE_FRAME ( toval ) ;
frame = get_prev_frame ( frame ) )
;
value_reg = VALUE_FRAME_REGNUM ( toval ) ;
}
if ( ! frame )
error ( " Value being assigned to is no longer active. " ) ;
amount_to_copy + = ( reg_size - amount_to_copy % reg_size ) ;
/* Locate the first register that falls in the value that
needs to be transfered . Compute the offset of the value in
that register . */
{
int offset ;
for ( reg_offset = value_reg , offset = 0 ;
offset + REGISTER_RAW_SIZE ( reg_offset ) < = VALUE_OFFSET ( toval ) ;
reg_offset + + ) ;
byte_offset = VALUE_OFFSET ( toval ) - offset ;
}
/* Copy it out. */
for ( ( regno = VALUE_FRAME_REGNUM ( toval ) + reg_offset ,
amount_copied = 0 ) ;
/* Compute the number of register aligned values that need to
be copied . */
if ( VALUE_BITSIZE ( toval ) )
amount_to_copy = byte_offset + 1 ;
else
amount_to_copy = byte_offset + TYPE_LENGTH ( type ) ;
/* And a bounce buffer. Be slightly over generous. */
buffer = ( char * ) alloca ( amount_to_copy
+ MAX_REGISTER_RAW_SIZE ) ;
/* Copy it in. */
for ( regno = reg_offset , amount_copied = 0 ;
amount_copied < amount_to_copy ;
amount_copied + = reg_size , regno + + )
amount_copied + = REGISTER_RAW_SIZE ( regno ) , regno + + )
{
get_saved_register ( buffer + amount_copied ,
( int * ) NULL , ( CORE_ADDR * ) NULL ,
frame , regno , ( enum lval_type * ) NULL ) ;
frame_register_read ( frame , regno , buffer + amount_copied ) ;
}
/* Modify what needs to be modified. */
if ( VALUE_BITSIZE ( toval ) )
{
modify_field ( buffer + byte_offset ,
value_as_long ( fromval ) ,
VALUE_BITPOS ( toval ) , VALUE_BITSIZE ( toval ) ) ;
}
else if ( use_buffer )
memcpy ( buffer + byte_offset , raw_buffer , use_buffer ) ;
{
memcpy ( buffer + VALUE_OFFSET ( toval ) , raw_buffer , use_buffer ) ;
}
else
{
memcpy ( buffer + byte_offset , VALUE_CONTENTS ( fromval ) ,
TYPE_LENGTH ( type ) ) ;
/* Do any conversion necessary when storing this type to
more than one register . */
# ifdef REGISTER_CONVERT_FROM_TYPE
REGISTER_CONVERT_FROM_TYPE ( value_reg , type ,
( buffer + byte_offset ) ) ;
# endif
}
/* Copy it back. */
for ( ( regno = VALUE_FRAME_REGNUM ( toval ) + reg_offset ,
amount_copied = 0 ) ;
/* Copy it out. */
for ( regno = reg_offset , amount_copied = 0 ;
amount_copied < amount_to_copy ;
amount_copied + = reg_size , regno + + )
amount_copied + = REGISTER_RAW_SIZE ( regno ) , regno + + )
{
enum lval_type lval ;
CORE_ADDR addr ;
int optim ;
int realnum ;
/* Just find out where to put it. */
get_saved_register ( ( char * ) NULL ,
& optim , & addr , frame , regno , & lval ) ;
frame_register ( frame , regno , & optim , & lval , & addr , & realnum ,
NULL ) ;
if ( optim )
error ( " Attempt to assign to a value that was optimized out. " ) ;
if ( lval = = lval_memory )
write_memory ( addr , buffer + amount_copied , reg_size ) ;
write_memory ( addr , buffer + amount_copied ,
REGISTER_RAW_SIZE ( regno ) ) ;
else if ( lval = = lval_register )
write_register_bytes ( addr , buffer + amount_copied , reg_size ) ;
regcache_cooked_write ( current_regcache , realnum ,
( buffer + amount_copied ) ) ;
else
error ( " Attempt to assign to an unmodifiable value. " ) ;
}
@ -763,6 +751,27 @@ value_assign (struct value *toval, struct value *fromval)
if ( register_changed_hook )
register_changed_hook ( - 1 ) ;
target_changed_event ( ) ;
/* Assigning to the stack pointer, frame pointer, and other
( architecture and calling convention specific ) registers
may cause the frame cache to be out of date . We just do
this on all assignments to registers for simplicity ; I
doubt the slowdown matters . */
reinit_frame_cache ( ) ;
/* Having destoroyed the frame cache, restore the selected
frame . */
/* FIXME: cagney/2002-11-02: There has to be a better way of
doing this . Instead of constantly saving / restoring the
frame . Why not create a get_selected_frame ( ) function
that , having saved the selected frame ' s ID can
automatically re - find the previously selected frame
automatically . */
{
struct frame_info * fi = frame_find_by_id ( old_frame ) ;
if ( fi ! = NULL )
select_frame ( fi ) ;
}
}
break ;