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 + -
显示快捷键?