@ -18,45 +18,26 @@
*/
# include "qemu/osdep.h"
/* Enable TCI assertions only when debugging TCG (and without NDEBUG defined).
* Without assertions , the interpreter runs much faster . */
# if defined(CONFIG_DEBUG_TCG)
# define tci_assert(cond) assert(cond)
# else
# define tci_assert(cond) ((void)(cond))
# endif
# include "qemu-common.h"
# include "tcg/tcg.h" /* MAX_OPC_PARAM_IARGS */
# include "exec/cpu_ldst.h"
# include "tcg/tcg-op.h"
# include "qemu/compiler.h"
# include <ffi.h>
# if MAX_OPC_PARAM_IARGS != 6
# error Fix needed, number of supported input arguments changed!
# endif
# if TCG_TARGET_REG_BITS == 32
typedef uint64_t ( * helper_function ) ( tcg_target_ulong , tcg_target_ulong ,
tcg_target_ulong , tcg_target_ulong ,
tcg_target_ulong , tcg_target_ulong ,
tcg_target_ulong , tcg_target_ulong ,
tcg_target_ulong , tcg_target_ulong ,
tcg_target_ulong , tcg_target_ulong ) ;
/*
* Enable TCI assertions only when debugging TCG ( and without NDEBUG defined ) .
* Without assertions , the interpreter runs much faster .
*/
# if defined(CONFIG_DEBUG_TCG)
# define tci_assert(cond) assert(cond)
# else
typedef uint64_t ( * helper_function ) ( tcg_target_ulong , tcg_target_ulong ,
tcg_target_ulong , tcg_target_ulong ,
tcg_target_ulong , tcg_target_ulong ) ;
# define tci_assert(cond) ((void)(cond))
# endif
__thread uintptr_t tci_tb_ptr ;
static tcg_target_ulong tci_read_reg ( const tcg_target_ulong * regs , TCGReg index )
{
tci_assert ( index < TCG_TARGET_NB_REGS ) ;
return regs [ index ] ;
}
static void
tci_write_reg ( tcg_target_ulong * regs , TCGReg index , tcg_target_ulong value )
{
@ -133,6 +114,7 @@ static tcg_target_ulong tci_read_label(const uint8_t **tb_ptr)
* I = immediate ( tcg_target_ulong )
* l = label or pointer
* m = immediate ( TCGMemOpIdx )
* n = immediate ( call return length )
* r = register
* s = signed ldst offset
*/
@ -153,6 +135,18 @@ static void tci_args_l(const uint8_t **tb_ptr, void **l0)
check_size ( start , tb_ptr ) ;
}
static void tci_args_nll ( const uint8_t * * tb_ptr , uint8_t * n0 ,
void * * l1 , void * * l2 )
{
const uint8_t * start = * tb_ptr ;
* n0 = tci_read_b ( tb_ptr ) ;
* l1 = ( void * ) tci_read_label ( tb_ptr ) ;
* l2 = ( void * ) tci_read_label ( tb_ptr ) ;
check_size ( start , tb_ptr ) ;
}
static void tci_args_rr ( const uint8_t * * tb_ptr ,
TCGReg * r0 , TCGReg * r1 )
{
@ -487,11 +481,14 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
{
const uint8_t * tb_ptr = v_tb_ptr ;
tcg_target_ulong regs [ TCG_TARGET_NB_REGS ] ;
long tcg_temps [ CPU_TEMP_BUF_NLONGS ] ;
uintptr_t sp_value = ( uintptr_t ) ( tcg_temps + CPU_TEMP_BUF_NLONGS ) ;
uint64_t stack [ ( TCG_STATIC_CALL_ARGS_SIZE + TCG_STATIC_FRAME_SIZE )
/ sizeof ( uint64_t ) ] ;
void * call_slots [ TCG_STATIC_CALL_ARGS_SIZE / sizeof ( uint64_t ) ] ;
regs [ TCG_AREG0 ] = ( tcg_target_ulong ) env ;
regs [ TCG_REG_CALL_STACK ] = sp_value ;
regs [ TCG_REG_CALL_STACK ] = ( uintptr_t ) stack ;
/* Other call_slots entries initialized at first use (see below). */
call_slots [ 0 ] = NULL ;
tci_assert ( tb_ptr ) ;
for ( ; ; ) {
@ -509,40 +506,58 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
# endif
TCGMemOpIdx oi ;
int32_t ofs ;
void * ptr ;
void * ptr , * cif ;
/* Skip opcode and size entry. */
tb_ptr + = 2 ;
switch ( opc ) {
case INDEX_op_call :
tci_args_l ( & tb_ptr , & ptr ) ;
/*
* Set up the ffi_avalue array once , delayed until now
* because many TB ' s do not make any calls . In tcg_gen_callN ,
* we arranged for every real argument to be " left-aligned "
* in each 64 - bit slot .
*/
if ( unlikely ( call_slots [ 0 ] = = NULL ) ) {
for ( int i = 0 ; i < ARRAY_SIZE ( call_slots ) ; + + i ) {
call_slots [ i ] = & stack [ i ] ;
}
}
tci_args_nll ( & tb_ptr , & len , & ptr , & cif ) ;
/* Helper functions may need to access the "return address" */
tci_tb_ptr = ( uintptr_t ) tb_ptr ;
# if TCG_TARGET_REG_BITS == 32
tmp64 = ( ( helper_function ) ptr ) ( tci_read_reg ( regs , TCG_REG_R0 ) ,
tci_read_reg ( regs , TCG_REG_R1 ) ,
tci_read_reg ( regs , TCG_REG_R2 ) ,
tci_read_reg ( regs , TCG_REG_R3 ) ,
tci_read_reg ( regs , TCG_REG_R4 ) ,
tci_read_reg ( regs , TCG_REG_R5 ) ,
tci_read_reg ( regs , TCG_REG_R6 ) ,
tci_read_reg ( regs , TCG_REG_R7 ) ,
tci_read_reg ( regs , TCG_REG_R8 ) ,
tci_read_reg ( regs , TCG_REG_R9 ) ,
tci_read_reg ( regs , TCG_REG_R10 ) ,
tci_read_reg ( regs , TCG_REG_R11 ) ) ;
tci_write_reg ( regs , TCG_REG_R0 , tmp64 ) ;
tci_write_reg ( regs , TCG_REG_R1 , tmp64 > > 32 ) ;
# else
tmp64 = ( ( helper_function ) ptr ) ( tci_read_reg ( regs , TCG_REG_R0 ) ,
tci_read_reg ( regs , TCG_REG_R1 ) ,
tci_read_reg ( regs , TCG_REG_R2 ) ,
tci_read_reg ( regs , TCG_REG_R3 ) ,
tci_read_reg ( regs , TCG_REG_R4 ) ,
tci_read_reg ( regs , TCG_REG_R5 ) ) ;
tci_write_reg ( regs , TCG_REG_R0 , tmp64 ) ;
# endif
ffi_call ( cif , ptr , stack , call_slots ) ;
/* Any result winds up "left-aligned" in the stack[0] slot. */
switch ( len ) {
case 0 : /* void */
break ;
case 1 : /* uint32_t */
/*
* Note that libffi has an odd special case in that it will
* always widen an integral result to ffi_arg .
*/
if ( sizeof ( ffi_arg ) = = 4 ) {
regs [ TCG_REG_R0 ] = * ( uint32_t * ) stack ;
break ;
}
/* fall through */
case 2 : /* uint64_t */
if ( TCG_TARGET_REG_BITS = = 32 ) {
tci_write_reg64 ( regs , TCG_REG_R1 , TCG_REG_R0 , stack [ 0 ] ) ;
} else {
regs [ TCG_REG_R0 ] = stack [ 0 ] ;
}
break ;
default :
g_assert_not_reached ( ) ;
}
break ;
case INDEX_op_br :
tci_args_l ( & tb_ptr , & ptr ) ;
tb_ptr = ptr ;
@ -1119,7 +1134,7 @@ int print_insn_tci(bfd_vma addr, disassemble_info *info)
TCGCond c ;
TCGMemOpIdx oi ;
uint8_t pos , len ;
void * ptr ;
void * ptr , * cif ;
const uint8_t * tb_ptr ;
status = info - > read_memory_func ( addr , buf , 2 , info ) ;
@ -1147,13 +1162,18 @@ int print_insn_tci(bfd_vma addr, disassemble_info *info)
switch ( op ) {
case INDEX_op_br :
case INDEX_op_call :
case INDEX_op_exit_tb :
case INDEX_op_goto_tb :
tci_args_l ( & tb_ptr , & ptr ) ;
info - > fprintf_func ( info - > stream , " %-12s %p " , op_name , ptr ) ;
break ;
case INDEX_op_call :
tci_args_nll ( & tb_ptr , & len , & ptr , & cif ) ;
info - > fprintf_func ( info - > stream , " %-12s %d, %p, %p " ,
op_name , len , ptr , cif ) ;
break ;
case INDEX_op_brcond_i32 :
case INDEX_op_brcond_i64 :
tci_args_rrcl ( & tb_ptr , & r0 , & r1 , & c , & ptr ) ;