i86enc16.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 745 行 · 第 1/2 页
C
745 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#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"
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 EjectInst(void);
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 AddWData(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 void Finalize(void);
extern type_length NewBase(name*);
extern int GetLog2(unsigned_32);
extern unsigned UseRepForm(unsigned);
/* forward declarations */
extern void DoRelocConst( name *op, type_class_def kind );
static void SetOff( name *op, int val );
extern byte OptForSize;
extern template Temp; /* template for oc_entries*/
extern byte Inst[]; /* template for instructions*/
extern zero_page_scheme ZPageType;
extern int ILen;
#define RMR_MOD_DIR 6
#define RMR_MOD_IND 0x80
#define D0 (0 << S_RMR_MOD)
#define D8 (1 << S_RMR_MOD)
#define D16 (2 << S_RMR_MOD)
static void OpndSizeIf( void ) {
/*************************/
if( _IsTargetModel( USE_32 ) ) {
AddToTemp( M_OPND_SIZE );
}
}
static hw_reg_set IndexTab[] = {
#define INDICES 8
#define BP_INDEX 6
HW_D_2( HW_BX, HW_SI ),
HW_D_2( HW_BX, HW_DI ),
HW_D_2( HW_BP, HW_SI ),
HW_D_2( HW_BP, HW_DI ),
HW_D_1( HW_SI ),
HW_D_1( HW_DI ),
HW_D_1( HW_BP ),
HW_D_1( HW_BX ) };
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 Displacement( signed_32 val, hw_reg_set regs ) {
/********************************************************/
HW_CTurnOff( regs, HW_SEGS );
if( val == 0 && !HW_CEqual( regs, HW_BP ) ) return( D0 );
if( val <= 127 && val >= -128 ) {
AddByte( val & 0xff );
return( D8 );
} else {
val &= 0xffff;
AddByte( val );
AddByte( val >> 8 );
return( D16 );
}
}
static byte DoDisp( name *op, hw_reg_set regs ) {
/*****************************************************/
name *base;
int val;
byte dmod;
name *temp_base;
val = op->i.constant; /* use integer value*/
base = op->i.base;
if( !HasTrueBase( op ) ) {
dmod = Displacement( val, regs );
} else if( base->n.class == N_TEMP ) {
temp_base = DeAlias( base );
if( temp_base->t.location == NO_LOCATION ) {
_Zoiks( ZOIKS_034 );
}
val += NewBase( temp_base ) + base->v.offset - temp_base->v.offset;
dmod = Displacement( val, regs );
} else {
dmod = D16;
ILen += 2;
DoSymRef( op->i.base, val, FALSE );
}
return( dmod );
}
extern void DoRepOp( instruction *ins ) {
/*******************************************/
int size;
size = ins->result->n.size;
if( ins->head.opcode == OP_MOV && !UseRepForm( size ) ) {
LayOpbyte( M_MOVSW );
size -= 2;
while( size > 1 ) {
AddByte( M_MOVSW );
size -= 2;
}
if( size == 1 ) {
AddByte( M_MOVSB );
}
} else {
LayOpbyte( M_REPE );
if( ins->head.opcode == OP_MOV ) {
if( ( size & 1 ) == 0 || OptForSize <= 50 ) {
AddByte( M_MOVSW );
if( size & 1 ) {
AddByte( M_MOVSB );
}
} else {
AddByte( M_MOVSB );
}
} else {
if( ins->operands[ 1 ]->n.size & 1 ) {
AddByte( M_CMPSB );
} else {
AddByte( M_CMPSW );
}
}
}
}
extern void Do4CXShift( instruction *ins, void (*rtn)(instruction *) ) {
/**************************************************************************/
hw_reg_set hreg;
hw_reg_set lreg;
unsigned shift;
if( ins->operands[ 1 ]->n.class == N_CONSTANT ) {
shift = ins->operands[ 1 ]->c.int_value;
if( shift<16 && OptForSize<50 && ins->result->n.class==N_REGISTER ) {
hreg = ins->result->r.reg;
lreg = Low32Reg( hreg );
hreg = High32Reg( hreg );
if( ins->head.opcode == OP_LSHIFT ) {
LayOpbyte( 0xb0 ); /* Move register immediate (byte)*/
LayRegAC( HW_CL );
AddByte( shift );
_Next;
LayOpword( M_SHL1 | B_KEY_W | 0x02 ); /* SHL reg,CL (word) */
LayRegRM( hreg );
_Next;
LayOpword( 0x00d3 ); /* ROL reg,CL (word) */
LayRegRM( lreg );
_Next;
LayOpword( M_XORRR | B_KEY_W );
LayReg( lreg );
LayRegRM( hreg );
_Next;
LayOpword( 0x2081 ); /* AND reg,immed (word) */
LayRegRM( lreg );
AddWData( ((unsigned_16)~0) << shift, U2 );
_Next;
LayOpword( M_XORRR | B_KEY_W );
LayReg( lreg );
LayRegRM( hreg );
return;
} else if( ins->type_class == U4 ) {
LayOpbyte( 0xb0 ); /* Move register immediate (byte)*/
LayRegAC( HW_CL );
AddByte( shift );
_Next;
LayOpword( M_SHR1 | B_KEY_W | 0x02 ); /* SHR reg,CL (word) */
LayRegRM( lreg );
_Next;
LayOpword( 0x08d3 ); /* ROR reg,CL (word) */
LayRegRM( hreg );
_Next;
LayOpword( M_XORRR | B_KEY_W );
LayReg( hreg );
LayRegRM( lreg );
_Next;
LayOpword( 0x2081 ); /* AND reg,immed (word) */
LayRegRM( hreg );
AddWData( ((unsigned_16)~0) >> shift, U2 );
_Next;
LayOpword( M_XORRR | B_KEY_W );
LayReg( hreg );
LayRegRM( lreg );
return;
}
}
LayOpbyte( 0xb8 ); /* Move register immediate (word)*/
LayRegAC( HW_CX );
AddWCons( ins->operands[ 1 ], U2 );
_Next;
rtn( ins );
_Next;
LayOpword( M_LOOP );
Inst[ DATALO ] = - ( -3 + 2 + Temp.oc.objlen );
} else {
LayOpbyte( 0xe3 ); /* JCXZ*/
AddByte( 0 ); /* to be patched*/
_Next;
rtn( ins );
_Next;
LayOpword( M_LOOP );
Inst[ DATALO ] = - (-2 + 2 + Temp.oc.objlen );
Temp.data[ 1 ] = -Inst[ DATALO ];
}
}
extern void LayLeaRegOp( instruction *ins ) {
/***********************************************/
name *left;
name *right;
left = ins->operands[ 0 ];
right = ins->operands[ 1 ];
Inst[ RMR ] |= DoIndex( left->r.reg );
if( ins->head.opcode == OP_ADD ) {
if( right->c.const_type == CONS_ABSOLUTE ) {
Inst[ RMR ] |=
Displacement( right->c.int_value,
left->r.reg );
} else {
Inst[ RMR ] |= D16;
DoRelocConst( right, U2 );
}
} else {
Inst[ RMR ] |= Displacement( -right->c.int_value,
left->r.reg );
}
}
static void CheckSize( void ) {
/***************************/
if( _IsTargetModel( USE_32 ) ) {
AddToTemp( M_ADDR_SIZE );
}
}
extern void DoMAddr( name *op ) {
/*************************************/
ILen += 2;
if( op->n.class == N_CONSTANT ) {
_Zoiks( ZOIKS_035 );
} else { /* assume global name*/
DoSymRef( op, op->v.offset, FALSE );
}
}
extern byte DoMDisp( name *op, bool alt_encoding ) {
/********************************************************/
hw_reg_set regs;
zero_page_scheme zptype;
regs = CalcSegment( op->v.symbol, op->m.memory_type );
if( ( alt_encoding == FALSE && ZPageType != ZP_USES_DS )
|| !HW_COvlap( regs, HW_SS ) ) {
zptype = ZP_USES_SS;
} else {
zptype = ZPageType;
}
switch( zptype ) {
case ZP_USES_SS:
if( HW_COvlap( regs, HW_SEGS ) ) {
GenSeg( regs );
}
DoMAddr( op );
return( RMR_MOD_DIR );
case ZP_USES_DS:
DoMAddr( op );
return( RMR_MOD_DIR );
case ZP_USES_BP:
DoMAddr( op );
return( DoIndex( HW_BP ) + RMR_MOD_IND );
case ZP_USES_DI:
DoMAddr( op );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?