i86enc32.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,002 行 · 第 1/3 页
C
1,002 行
/****************************************************************************
*
* 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: 32-bit instruction encodings.
*
****************************************************************************/
#include <stddef.h>
#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "pattern.h"
#include "ocentry.h"
#include "vergen.h"
#include "pccode.h"
#include "system.h"
#include "escape.h"
#include "model.h"
#include "pcencode.h"
#include "objrep.h"
#include "zoiks.h"
#include "zeropage.h"
#include "fppatch.h"
#include "cfloat.h"
#include "procdef.h"
#include "rtclass.h"
#include "cgaux.h"
#include "p5prof.h"
#include "feprotos.h"
extern void RTCall( rt_class rtn, oc_class pop_bit );
extern void DoSymRef(name*,offset,bool);
extern void LayRegAC(hw_reg_set);
extern void LayOpword(opcode);
extern hw_reg_set High32Reg(hw_reg_set);
extern hw_reg_set Low32Reg(hw_reg_set);
extern hw_reg_set CalcSegment(sym_handle,cg_class);
extern name *DeAlias(name*);
extern void AddByte(byte);
extern void LayRMRegOp(name*);
extern void LayOpbyte(opcode);
extern void LayRegRM(hw_reg_set);
extern void DoSegRef(seg_id);
extern void GenSeg(hw_reg_set);
extern void LayW(type_class_def);
extern void AddWCons(name*,type_class_def);
extern void AddSData(signed_32,type_class_def);
extern void AddToTemp(byte );
extern void LayOpword(opcode);
extern void DoAbsPatch(abspatch_handle*,int);
extern type_class_def OpndSize(hw_reg_set );
extern void LayReg(hw_reg_set );
extern void GCondFwait(void);
extern hw_reg_set High64Reg(hw_reg_set);
extern hw_reg_set Low64Reg(hw_reg_set);
extern type_length NewBase(name*);
extern int GetLog2(unsigned_32);
extern unsigned UseRepForm(unsigned);
extern void DoNothing(instruction*);
extern bool BaseIsSP(name*);
extern seg_id AskCode16Seg( void );
extern sym_handle AskForLblSym(label_handle);
extern label_handle AskForLabel(sym_handle);
extern void DoLblRef( label_handle, seg_id, offset, byte );
extern uint Length(pointer);
extern bool GetEnvVar(char*,char*,int);
extern int CountIns( block *blk );
extern bool OptForSize;
extern template Temp; /* template for oc_entries*/
extern byte Inst[]; /* template for instructions*/
extern int ILen;
extern proc_def *CurrProc;
/* forward declarations */
extern void DoRelocConst( name *op, type_class_def kind );
extern void DoMAddr( name *op );
static void Add32Displacement( signed_32 val );
static void LayIdxModRM( name *op );
void doProfilingCode( char *fe_name, label_handle *data,
bool prolog );
#define RMR_MOD_IND 0x80
#define RMR_MOD_DIR 5
#define RMR_MOD_SIB 4
#define D0 (0 << S_RMR_MOD)
#define D8 (1 << S_RMR_MOD)
#define D32 (2 << S_RMR_MOD)
static void OpndSizeIf( bool if_32 )
/**********************************/
{
if( ( if_32 && _IsTargetModel( USE_32 ) ) || _IsntTargetModel( USE_32 ) ) {
AddToTemp( M_OPND_SIZE );
}
}
static void TakeUpSlack( type_length size )
/*****************************************/
{
while( size >= 2 ) {
if( _IsTargetModel( USE_32 ) ) AddByte( M_OPND_SIZE );
AddByte( M_MOVSW );
size -= 2;
}
while( size >= 1 ) {
AddByte( M_MOVSB );
size -= 1;
}
}
extern void DoRepOp( instruction *ins )
/*****************************************/
{
type_length size;
bool first;
size = ins->result->n.size;
first = TRUE;
if( ins->head.opcode == OP_MOV && !UseRepForm( size ) ) {
while( size >= 4 ) {
if( first ) {
LayOpbyte( M_MOVSW );
OpndSizeIf( FALSE );
first = FALSE;
} else {
if( _IsntTargetModel( USE_32 ) ) AddByte( M_OPND_SIZE );
AddByte( M_MOVSW );
}
size -= 4;
}
TakeUpSlack( size );
} else {
LayOpbyte( M_REPE );
if( ins->head.opcode == OP_MOV ) {
if( ( size & (4-1) ) == 0 || OptForSize <= 50 ) {
if( _IsntTargetModel( USE_32 ) ) AddByte( M_OPND_SIZE );
AddByte( M_MOVSW );
TakeUpSlack( size & (4-1) );
} else {
AddByte( M_MOVSB );
}
} else {
if( ins->operands[ 1 ]->n.size & 1 ) {
AddByte( M_CMPSB );
} else {
AddByte( M_CMPSW );
if( _IsntTargetModel( USE_32 ) ) AddByte( M_OPND_SIZE );
}
}
}
}
static hw_reg_set IndexTab[] = {
#define INDICES 8
#define BP_INDEX 5
HW_D( HW_EAX ),
HW_D( HW_ECX ),
HW_D( HW_EDX ),
HW_D( HW_EBX ),
HW_D( HW_SP ),
HW_D( HW_BP ),
HW_D( HW_ESI ),
HW_D( HW_EDI )
};
static byte Displacement( signed_32 val, hw_reg_set regs )
/************************************************************/
{
if( val == 0 && !HW_COvlap( regs, HW_BP ) ) return( D0 );
if( val <= 127 && val >= -128 ) {
AddByte( val & 0xff );
return( D8 );
} else {
Add32Displacement( val );
return( D32 );
}
}
static byte DoIndex( hw_reg_set regs )
/****************************************/
{
int i;
i = 0;
while( i < INDICES ) {
if( HW_Equal( regs, IndexTab[ i ] ) ) break;
i++;
}
if( i >= INDICES ) {
_Zoiks( ZOIKS_033 );
}
i <<= S_RMR_RM;
return( i );
}
static byte DoScaleIndex( hw_reg_set base_reg,
hw_reg_set idx_reg, int scale )
/***********************************************************/
{
byte sib;
sib = scale << 6;
sib |= DoIndex( base_reg ) >> S_RMR_RM;
sib |= ( DoIndex( idx_reg ) >> S_RMR_RM ) << S_RMR_REG;
AddByte( sib );
return( RMR_MOD_SIB );
}
extern type_length TmpLoc( name *base, name *op )
/***********************************************/
{
return( NewBase( base ) + op->v.offset - base->v.offset );
}
static byte DoDisp( type_length val, hw_reg_set base_reg, name *op )
/**********************************************************************/
{
name *base;
if( op == NULL ) {
return( Displacement( val, base_reg ) );
} else if( op->n.class == N_TEMP ) {
base = DeAlias( op );
if( base->t.location == NO_LOCATION ) {
_Zoiks( ZOIKS_034 );
}
val += TmpLoc( base, op );
return( Displacement( val, base_reg ) );
} else if( op->n.class == N_MEMORY ) {
ILen += 4;
DoSymRef( op, val, FALSE );
return( D32 );
} else if( op->n.class == N_CONSTANT ) {
DoRelocConst( op, U4 );
return( D32 );
} else {
_Zoiks( ZOIKS_126 );
return( 0 );
}
}
extern byte DoMDisp( name *op, bool alt_encoding )
/****************************************************/
{
hw_reg_set regs;
alt_encoding = alt_encoding;
regs = CalcSegment( op->v.symbol, op->m.memory_type );
if( HW_COvlap( regs, HW_SEGS ) ) {
GenSeg( regs );
}
DoMAddr( op );
return( RMR_MOD_DIR );
}
static void EA( hw_reg_set base, hw_reg_set index,
int scale, signed_32 val, name *mem_loc, bool lea )
/*********************************************************************/
{
if( HW_CEqual( index, HW_SP ) ) _Zoiks( ZOIKS_079 );
if( HW_CEqual( base, HW_EMPTY ) ) {
if( HW_CEqual( index, HW_EMPTY ) ) {
// [d32]
if( scale != 0 || val != 0 ) _Zoiks( ZOIKS_079 );
Inst[ RMR ] |= DoMDisp( mem_loc, TRUE );
} else {
if( scale != 0 ) {
// [d32+scale_index]
Inst[ RMR ] |= DoScaleIndex( HW_BP, index, scale );
Inst[ RMR ] |= D0;
if( mem_loc != NULL ) {
ILen += 4;
DoSymRef( mem_loc, val, FALSE );
} else {
Add32Displacement( val );
}
} else {
// [(d0|d8|d32)+index]
Inst[ RMR ] |= DoIndex( index );
Inst[ RMR ] |= DoDisp( val, index, mem_loc );
}
}
} else {
// [(d0|d8|d32)+base+scale_index]
if( HW_CEqual( index, HW_EMPTY ) ) {
if( scale == 0 && !HW_CEqual( base, HW_SP ) ) {
Inst[ RMR ] |= DoIndex( base );
} else {
Inst[ RMR ] |= DoScaleIndex( base, HW_SP, scale );
}
} else {
if( scale == 0 && HW_CEqual( base, HW_BP )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?