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