i86enc2.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 687 行 · 第 1/2 页
C
687 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Intel instruction encoding, part II. Processes labels,
* jumps and the like.
*
****************************************************************************/
#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "ocentry.h"
#include "sysmacro.h"
#include "vergen.h"
#include "system.h"
#include "escape.h"
#include "model.h"
#include "pcencode.h"
#include "cgaux.h"
#include "cgdefs.h"
#include "seldef.h"
#include "typedef.h"
#include "pccode.h"
#include "objrep.h"
#include "fppatch.h"
#include "cypfunc.h"
#include "encode.h"
#include "feprotos.h"
extern hw_reg_set Low32Reg(hw_reg_set);
extern void EjectInst( void );
extern void LayRegAC(hw_reg_set);
extern hw_reg_set High32Reg(hw_reg_set);
extern void LayOpbyte(opcode);
extern void Format(oc_class);
extern void TellScrapLabel(label_handle);
extern offset AskAddress(label_handle);
extern label_handle AskForSymLabel(pointer,cg_class);
extern seg_id SetOP(seg_id);
extern seg_id AskCodeSeg( void );
extern void LayRegRM(hw_reg_set);
extern void LayRMRegOp(name*);
extern void LayModRM(name*);
extern void LayOpword(opcode);
extern void ReFormat(oc_class);
extern void Finalize( void );
extern pointer FindAuxInfo(name*,aux_class);
extern void InputOC(any_oc*);
extern void AddByte(byte);
extern int OptInsSize(oc_class,oc_dest_attr);
extern type_def *TypeAddress(cg_type);
extern void AddToTemp(byte);
extern void DoFESymRef( sym_handle, cg_class, offset, int);
extern void FlipCond(instruction*);
extern name *DeAlias(name*);
extern name *AllocUserTemp(pointer,type_class_def);
extern type_length NewBase(name*);
extern void EmitOffset(offset);
extern seg_id AskCodeSeg( void );
extern sym_handle AskForLblSym(label_handle);
extern bool AskIfRTLabel(label_handle);
extern byte *Copy(void*,void*,uint);
extern void CodeBytes( byte *src, byte_seq_len len );
extern void GenReturn( int pop, bool is_long, bool iret );
static void JumpReg( instruction *ins, name *reg_name );
static void Pushf(void);
extern int ILen;
extern fp_patches FPPatchType;
extern bool Used87;
extern byte OptForSize;
static byte UCondTable[] = {
/***************************
the 8086 code for an unsigned jmp
*/
5, /* OP_BIT_TEST_TRUE*/
4, /* OP_BIT_TEST_FALSE*/
4, /* OP_CMP_EQUAL*/
5, /* OP_CMP_NOT_EQUAL*/
7, /* OP_CMP_GREATER*/
6, /* OP_CMP_LESS_EQUAL*/
2, /* OP_CMP_LESS*/
3 }; /* OP_CMP_GREATER_EQUAL*/
static byte SCondTable[] = {
/***************************
the 8086 code for a signed jmp
*/
5, /* OP_BIT_TEST_TRUE*/
4, /* OP_BIT_TEST_FALSE*/
4, /* OP_CMP_EQUAL*/
5, /* OP_CMP_NOT_EQUAL*/
15, /* OP_CMP_GREATER*/
14, /* OP_CMP_LESS_EQUAL*/
12, /* OP_CMP_LESS*/
13 }; /* OP_CMP_GREATER_EQUAL*/
static byte RevCond[] = {
/************************
reverse the sense of an 8086 jmp (ie: ja -> jbe)
*/
1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14 }; /* i.e. XOR 1*/
typedef enum {
UNSIGNED, /* always an unsigned jump */
SIGNED_86, /* signed if 8086 instruction, else unsigned */
SIGNED_87, /* signed if 8087 instruction, else unsigned */
SIGNED_BOTH /* always signed */
} issigned;
static issigned Signed[] = {
/***************************
what kind of a jump does the instruction need following it
*/
UNSIGNED, /* U1*/
SIGNED_BOTH, /* I1*/
UNSIGNED, /* U2*/
SIGNED_BOTH, /* I2*/
UNSIGNED, /* U4*/
SIGNED_BOTH, /* I4*/
UNSIGNED, /* U8*/
SIGNED_BOTH, /* I8*/
UNSIGNED, /* CP*/
UNSIGNED, /* PT*/
SIGNED_86, /* FS*/
SIGNED_86, /* FD*/
SIGNED_86, /* FL*/
UNSIGNED }; /* XX*/
extern unsigned DepthAlign( unsigned depth )
/******************************************/
{
static byte AlignArray[10] = { 0 };
if( AlignArray[0] == 0 || depth == PROC_ALIGN ) {
Copy( FEAuxInfo( NULL, CODE_LABEL_ALIGNMENT ), AlignArray,
sizeof( AlignArray ) );
}
if( OptForSize ) return( 1 );
if( _CPULevel( CPU_486 ) ) {
if( depth == PROC_ALIGN || depth == DEEP_LOOP_ALIGN ) return( 16 );
return( 1 );
}
if( _CPULevel( CPU_386 ) ) {
if( depth == PROC_ALIGN || depth == DEEP_LOOP_ALIGN ) return( 4 );
return( 1 );
}
if( depth == PROC_ALIGN ) {
return( AlignArray[1] );
}
if( depth == 0 ) depth = 1;
if( depth >= AlignArray[0] ) {
depth = AlignArray[0] - 1;
}
return( AlignArray[depth+1] );
}
extern byte CondCode( instruction *cond ) {
/**********************************************
Return the condition code number for the encoding, associated with "cond"
*/
issigned is_signed;
if( _FPULevel( FPU_87 ) ) {
is_signed = SIGNED_87;
} else {
is_signed = SIGNED_86;
}
if( is_signed & Signed[ cond->type_class ] ) {
return( SCondTable[ cond->head.opcode-FIRST_CONDITION ] );
} else {
return( UCondTable[ cond->head.opcode-FIRST_CONDITION ] );
}
}
extern void GenSetCC( instruction *cond ) {
/**********************************************
given a conditional "cond", generate the correct setxx instruction
*/
_Code;
LayOpword( M_SETCC | CondCode( cond ) );
if( cond->result->n.class == N_REGISTER ) {
LayRMRegOp( cond->result );
} else {
LayModRM( cond->result );
}
AddToTemp( M_SECONDARY );
_Emit;
}
extern byte ReverseCondition( byte cond ) {
/**********************************************
reverse the sense of a conditional jump (already encoded)
*/
return( RevCond[ cond ] );
}
extern void DoCall( label_handle lbl, bool imported,
bool big, oc_class pop_bit ) {
/*****************************************************
call routine "lbl".
*/
imported = imported;
if( !big ) {
CodeHandle( OC_CALL | pop_bit,
OptInsSize( OC_CALL, OC_DEST_NEAR ), lbl );
} else if( AskIfRTLabel( lbl )
|| imported //NYI:multi-code-segment, this can go when FORTRAN is fixed up
|| AskCodeSeg() != FESegID( AskForLblSym( lbl ) ) ) {
CodeHandle( OC_CALL | ATTR_FAR | pop_bit,
OptInsSize( OC_CALL, OC_DEST_FAR ), lbl );
} else {
CodeHandle( OC_CALL | ATTR_FAR | pop_bit,
OptInsSize( OC_CALL, OC_DEST_CHEAP ), lbl );
}
}
static void CodeSequence( byte *p, byte_seq_len len ) {
/**********************************************************
Dump an inline sequence, taking into account the floating fixups and
the "seg foo", "offset foo" sequences.
*/
bool first;
byte *endp;
byte *startp;
byte type;
sym_handle sym = 0;
offset off = 0;
fe_attr attr = 0;
name *temp;
endp = p + len;
while( p != endp ) {
_Code;
if( p[0] == FLOATING_FIXUP_BYTE
&& p[1] != FLOATING_FIXUP_BYTE
&& p[1] != FIX_SYM_OFFSET
&& p[1] != FIX_SYM_SEGMENT
&& p[1] != FIX_SYM_RELOFF ) {
/* floating point fixup */
++p;
if( _IsEmulation() ) {
if( ( p[0] == 0x90 ) && ( p[1] == 0x9B ) ) { // inline FWAIT
FPPatchType = FPP_WAIT;
} else {
FPPatchType = FPP_NORMAL;
}
Used87 = TRUE;
}
}
first = TRUE;
startp = p;
for( ;; ) {
if( p == endp ) break;
if( ( p - startp ) >= ( INSSIZE - 5 ) ) break;
if( p[0] == FLOATING_FIXUP_BYTE ) {
type = p[1];
if( type != FLOATING_FIXUP_BYTE ) {
switch( type ) {
case FIX_SYM_OFFSET:
case FIX_SYM_SEGMENT:
case FIX_SYM_RELOFF:
p += 2;
sym = (sym_handle)*(unsigned long *)p;
p += sizeof( unsigned long );
off = (offset)*(unsigned long *)p;
p += sizeof( unsigned long );
attr = FEAttr( sym );
}
switch( type ) {
case FIX_SYM_SEGMENT:
ILen += 2;
if( attr & (FE_STATIC | FE_GLOBAL) ) {
DoFESymRef( sym, CG_FE, off, FE_FIX_BASE );
} else {
FEMessage( MSG_ERROR,
"aux seg used with local symbol" );
}
break;
case FIX_SYM_OFFSET:
ILen += WORD_SIZE;
if( attr & (FE_STATIC | FE_GLOBAL) ) {
DoFESymRef( sym, CG_FE, off, FE_FIX_OFF );
} else {
temp = DeAlias( AllocUserTemp( sym, U1 ) );
if( temp->t.location != NO_LOCATION ) {
EmitOffset( NewBase( temp )
- temp->v.offset + off );
} else {
FEMessage( MSG_ERROR,
"aux offset used with register symbol" );
}
}
break;
case FIX_SYM_RELOFF:
ILen += WORD_SIZE;
if( attr & FE_PROC ) {
DoFESymRef( sym, CG_FE, off, FE_FIX_SELF );
} else {
FEMessage( MSG_ERROR,
"aux reloff used with data symbol" );
}
break;
}
break; /* back to top of while for floating fixup */
} else {
++p;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?