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