i86enc2.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 687 行 · 第 1/2 页
C
687 行
}
if( first ) {
LayOpbyte( *p );
first = FALSE;
} else {
AddByte( *p );
}
++p;
}
_Emit;
}
}
extern void GenCall( instruction *ins ) {
/********************************************
Generate a call for "ins". (eg: call foo, or call far ptr foo)
*/
name *op;
sym_handle sym;
bool big;
oc_class pop_bit;
call_class class;
byte_seq *code;
label_handle lbl;
if( ins->flags.call_flags & CALL_INTERRUPT ) {
Pushf();
}
op = ins->operands[ CALL_OP_ADDR ];
class = *(call_class *)FindAuxInfo( op, CALL_CLASS );
code = FindAuxInfo( op, CALL_BYTES );
if( code != NULL ) {
_Emit;
if( code->length & DO_FLOATING_FIXUPS ) {
CodeSequence( code->data, code->length & ~DO_FLOATING_FIXUPS );
} else {
CodeBytes( code->data, code->length );
}
} else if( ( class & SUICIDAL ) && _IsntTargetModel( NEW_P5_PROFILING ) ) {
sym = op->v.symbol;
lbl = FEBack( sym )->lbl;
if( ( class & FAR ) != EMPTY && ( FEAttr( sym ) & FE_IMPORT ) ) {
CodeHandle( OC_JMP | ATTR_FAR,
OptInsSize( OC_JMP, OC_DEST_FAR ), lbl );
} else {
CodeHandle( OC_JMP, OptInsSize( OC_JMP, OC_DEST_NEAR ), lbl );
}
} else {
if( ins->flags.call_flags & CALL_POPS_PARMS ) {
pop_bit = ATTR_POP;
} else {
pop_bit = 0;
}
if( class & FAR ) {
big = TRUE;
} else {
big = FALSE;
}
sym = op->v.symbol;
if( op->m.memory_type == CG_FE ) {
DoCall( FEBack( sym )->lbl,
(FEAttr(sym) & (FE_COMMON|FE_IMPORT)) != 0, big, pop_bit );
} else {
DoCall( sym, TRUE, big, pop_bit );
}
}
}
extern void GenICall( instruction *ins ) {
/*********************************************
Generate an indirect call for "ins" (eg: call dword ptr [eax])
*/
oc_class entry;
unsigned opcode;
if( ins->flags.call_flags & CALL_INTERRUPT ) {
Pushf();
}
entry = 0;
if( ins->flags.call_flags & CALL_POPS_PARMS ) {
entry |= ATTR_POP;
}
if( ( ins->flags.call_flags & CALL_ABORTS ) && _IsntTargetModel( NEW_P5_PROFILING ) ) {
entry |= OC_JMPI;
} else {
entry |= OC_CALLI;
}
if( ins->operands[ CALL_OP_ADDR ]->n.name_class == PT
|| ins->operands[ CALL_OP_ADDR ]->n.name_class == CP ) {
entry |= ATTR_FAR;
opcode = M_CJILONG;
} else {
opcode = M_CJINEAR;
}
ReFormat( entry );
LayOpword( opcode );
LayModRM( ins->operands[ CALL_OP_ADDR ] );
_Emit;
}
extern void GenRCall( instruction *ins ) {
/*********************************************
generate a call to a register (eg: call eax)
*/
name *op;
oc_class pop_bit;
if( ins->flags.call_flags & CALL_INTERRUPT ) {
Pushf();
}
if( ins->flags.call_flags & CALL_POPS_PARMS ) {
pop_bit = ATTR_POP;
} else {
pop_bit = 0;
}
ReFormat( OC_CALLI | pop_bit );
LayOpword( M_CJINEAR );
op = ins->operands[ CALL_OP_ADDR ];
LayRegRM( op->r.reg );
_Emit;
}
static void Pushf( void ) {
/***********************/
LayOpbyte( 0x9c ); /* PUSHF*/
_Emit;
_Code;
}
extern void GenSelEntry( bool starts ) {
/*******************************************
dump a queue that a select table is starting/ending ("starts") into
the code segment queue.
*/
oc_select temp;
temp.op.class = OC_INFO + INFO_SELECT;
temp.op.reclen = sizeof( oc_select );
temp.op.objlen = 0;
temp.starts = starts;
InputOC( (any_oc *)&temp );
}
extern void Gen1ByteValue( byte value ) {
/********************************************
drop an 8 bit integer into the queue.
*/
_Code;
AddByte( value );
_Emit;
}
extern void Gen2ByteValue( unsigned_16 value ) {
/***************************************************
drop a 16 bit integer into the queue.
*/
_Code;
AddByte( value & 0xFF );
AddByte( ( value >> 8 ) & 0xFF );
_Emit;
}
extern void Gen4ByteValue( unsigned_32 value ) {
/***************************************************
drop a 32 bit integer into the queue.
*/
_Code;
AddByte( value & 0xFF );
AddByte( ( value >> 8 ) & 0xFF );
AddByte( ( value >> 16 ) & 0xFF );
AddByte( ( value >> 24 ) & 0xFF );
_Emit;
}
extern void GenCodePtr( pointer label ) {
/********************************************
Dump a near reference to a label into the code segment.
*/
CodeHandle( OC_LREF, TypeAddress( T_NEAR_CODE_PTR )->length, label );
}
extern void GenCallLabel( pointer label ) {
/**********************************************
generate a call to a label within the procedure (near call)
*/
DoCall( label, FALSE, FALSE, EMPTY );
}
extern void GenLabelReturn( void ) {
/*********************************
generate a return from CALL_LABEL instruction (near return)
*/
GenReturn( 0, FALSE, FALSE );
}
extern void GenReturn( int pop, bool is_long, bool iret ) {
/**************************************************************
Generate a return instruction
*/
oc_ret oc;
oc.op.class = OC_RET;
oc.op.reclen = sizeof( oc_ret );
oc.op.objlen = 1;
oc.pops = pop;
if( pop != 0 ) {
oc.op.class |= ATTR_POP;
oc.op.objlen += 2;
}
if( is_long ) {
oc.op.class |= ATTR_FAR;
}
if( iret ) {
oc.op.class |= ATTR_IRET;
}
InputOC( (any_oc *)&oc );
}
extern void GenMJmp( instruction *ins ) {
/********************************************
Generate a jump indirect through memory instruction.
*/
label_handle lbl;
name *base;
if( ins->head.opcode != OP_SELECT && _IsTargetModel( BIG_CODE ) ) {
ReFormat( OC_JMPI | ATTR_FAR );
LayOpword( M_CJILONG );
} else {
ReFormat( OC_JMPI );
LayOpword( M_CJINEAR );
}
LayModRM( ins->operands[ 0 ] );
if( ins->head.opcode == OP_SELECT &&
ins->operands[ 0 ]->n.class == N_INDEXED ) {
base = ins->operands[ 0 ]->i.base;
if( base != NULL ) {
lbl = AskForSymLabel( base->v.symbol, CG_TBL );
if( AskAddress( lbl ) != ADDR_UNKNOWN ) {
TellScrapLabel( lbl );
}
}
}
}
extern void GenRJmp( instruction *ins ) {
/********************************************
Generate a jump to register instruction (eg: jmp eax)
*/
JumpReg( ins, ins->operands[ 0 ] );
}
static void JumpReg( instruction *ins, name *reg_name ) {
/************************************************************
Generate a jump to register instruction (eg: jmp eax)
*/
hw_reg_set regs;
ins = ins;
regs = reg_name->r.reg;
if( reg_name->n.size > WORD_SIZE ) {
/* fake up intersegment jump*/
_Code;
LayOpbyte( M_PUSH );
LayRegAC( High32Reg( regs ) );
_Next;
LayOpbyte( M_PUSH );
LayRegAC( Low32Reg( regs ) );
_Emit;
GenReturn( 0, TRUE, FALSE );
} else {
ReFormat( OC_JMPI );
LayOpword( M_CJINEAR );
LayRegRM( regs );
_Emit;
}
}
static void DoCodeBytes( byte *src, byte_seq_len len, oc_class class ) {
/***************************************************************************
Dump bytes "src" directly into the queue, for length "len".
*/
oc_entry *temp;
_Alloc( temp, sizeof( oc_header ) + MAX_OBJ_LEN );
temp->class = class;
temp->objlen = len;
temp->reclen = sizeof( oc_header ) + len;
while( len > MAX_OBJ_LEN ) {
temp->objlen = MAX_OBJ_LEN;
temp->reclen = sizeof( oc_header )+ MAX_OBJ_LEN;
Copy( src, &temp->data[ 0 ], MAX_OBJ_LEN );
InputOC( (any_oc *)temp );
src += MAX_OBJ_LEN;
len -= MAX_OBJ_LEN;
}
temp->objlen = len;
temp->reclen = sizeof( oc_header ) + len;
Copy( src, &temp->data[ 0 ], len );
InputOC( (any_oc *)temp );
_Free( temp, sizeof( oc_header ) + MAX_OBJ_LEN );
}
extern void CodeBytes( byte *src, byte_seq_len len ) {
/********************************************************/
DoCodeBytes( src, len, OC_BDATA );
}
extern void EyeCatchBytes( byte *src, uint len ) {
/************************************************/
DoCodeBytes( src, len, OC_IDATA );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?