i86enc.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,335 行 · 第 1/5 页

C
2,335
字号
/****************************************************************************
*
*                            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:  Take the instruction stream from the code generator and
*               writes the instructions into the object file.
*
****************************************************************************/
#include <stdio.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 "regset.h"
#include "rttable.h"
#include "rtclass.h"
#include "zoiks.h"
#include "zeropage.h"
#include "fppatch.h"
#include "cfloat.h"
#include "cgaux.h"
#include "feprotos.h"
#include "p5prof.h"
#include "procdef.h"

extern  void            DoAbsPatch(abspatch_handle*,int);
extern  void            DoFunnyRef(int);
extern  hw_reg_set      High32Reg(hw_reg_set);
extern  hw_reg_set      Low32Reg(hw_reg_set);
extern  void            DoSegRef(seg_id);
extern  hw_reg_set      CalcSegment(sym_handle,cg_class);
extern  void            EmitDbgInfo(instruction*);
extern  void            DoCall(label_handle,bool,bool,oc_class);
extern  void            RTCall( rt_class rtn, oc_class pop_bit );
extern  label_handle    RTLabel(int);
extern  void            GenMJmp(instruction*);
extern  void            GenRJmp(instruction*);
extern  void            GenICall(instruction*);
extern  void            GenRCall(instruction*);
extern  void            GenCall(instruction*);
extern  abspatch_handle *NextFramePatch( void );
extern  bool            AskIsFrameIndex(name*);
extern  void            GenCondJump(instruction*);
extern  int             NumOperands(instruction*);
extern  void            InputOC(any_oc*);
extern  void            DoRepOp( instruction *ins );
extern  void            Do4CXShift(instruction *,void (*)(instruction*) );
extern  void            LayLeaOp(instruction*);
extern  void            LayModRM(name*);
extern  byte            DoMDisp(name*,bool);
extern  void            DoMAddr(name*);
extern  void            DoRelocConst(name*,type_class_def);
extern  void            Do4Shift(instruction*);
extern  void            Do4RShift(instruction*);
extern  void            Gen4RNeg(instruction*);
extern  void            Gen4Neg(instruction*);
extern  void            Pow2Div(instruction*);
extern  void            By2Div(instruction*);
extern  void            Pow2Div286(instruction*);
extern  void            LayLeaRegOp(instruction*);
extern  pointer         Copy(pointer,pointer,uint);
extern  void            GenUnkLea(pointer);
extern  name            *IntEquivalent(name*);
extern  void            LookupRoutine(instruction*);
extern  void            AdjustStackDepth(instruction*);
extern  void            AdjustStackDepthDirect(int adjust);

extern  hw_reg_set      FullReg(hw_reg_set);
extern  bool            BaseIsSP(name*);
extern  type_length     TmpLoc(name*,name*);
extern  name            *DeAlias(name*);
extern  seg_id          AskBackSeg( void );
extern  seg_id          AskCodeSeg( void );
extern  void            DoLblRef(label_handle,seg_id,offset,byte);
extern  void            AddWData(signed_32,type_class_def );
extern  label_handle    AskForNewLabel( void );
extern  name            *LowPart(name *,type_class_def);
extern  name            *HighPart(name *,type_class_def);
extern  void            CodeLabel(label_handle, unsigned);
extern  int             OptInsSize(oc_class,oc_dest_attr);
extern  void            DoFESymRef(sym_handle,cg_class,offset,int);
extern  void            GenJumpLabel( label_handle );
extern  void            GenKillLabel( label_handle );
extern  segment_id      GenP5ProfileData( char *fe_name, label_handle *data, label_handle *stack );
extern  void            EndBlockProfiling( void );
extern  void            LayOpbyte( opcode op );
extern  void            LayOpword( opcode op );
extern  void            LayW( type_class_def class );
extern  void            GenSeg( hw_reg_set regs );
extern  void            GenLoadDS(void);
extern  void            LayRMRegOp( name *r );
extern  void            AddWCons( name *op, type_class_def kind );
extern  void            LayReg( hw_reg_set r );
extern  void            GCondFwait(void);
extern  void            GFldz(void);
extern  void            AddSData( signed_32 value, type_class_def kind );
extern  void            GFwait(void);
extern  void            GCondFwait(void);
extern  void            GFldM( pointer what );

static  void            AddSWCons( opcode_defs op, name *opnd, type_class_def class );
static  void            TransferIns(void);
static  void            LayST( name *op );
static  void            LayMF( name *op );
static  void            AddSCons( name *op, type_class_def kind );
static  void            LayACRegOp( name *r );
static  void            LayRegOp( name *r );
static  void            LaySROp( name *r );
static  void            SetCC(void);
static  void            CallMathFunc( instruction *ins );
static  void            MathFunc( instruction *ins );
static  void            PopSeg( hw_reg_set reg );
static  void            PushSeg( hw_reg_set reg );
static  void            GFld1(void);
static  int             FPRegTrans( hw_reg_set reg );


extern    pccode_def            PCCodeTable[];
extern    name                  *FPStatWord;
extern    byte                  OptForSize;
extern    bool                  Used87;
extern  proc_def        *CurrProc;

          template              Temp;   /* template for oc_entries*/
          byte                  Inst[INSSIZE];  /* template for instructions*/

static    int   ICur;           /* cursor for writing into Inst*/
static    int   IEsc;           /* number of initial bytes that must be*/
                                /* checked for escapes when copied into Temp*/
          int   ILen;           /* length of object instruction*/
          fp_patches    FPPatchType;

static  hw_reg_set RegTab[] = {
#define REGS 24
        HW_D( HW_AL ),          HW_D( HW_AX ),          HW_D( HW_EAX ),
        HW_D( HW_CL ),          HW_D( HW_CX ),          HW_D( HW_ECX ),
        HW_D( HW_DL ),          HW_D( HW_DX ),          HW_D( HW_EDX ),
        HW_D( HW_BL ),          HW_D( HW_BX ),          HW_D( HW_EBX ),
        HW_D( HW_AH ),          HW_D( HW_SP ),          HW_D( HW_SP ),
        HW_D( HW_CH ),          HW_D( HW_BP ),          HW_D( HW_BP ),
        HW_D( HW_DH ),          HW_D( HW_SI ),          HW_D( HW_ESI ),
        HW_D( HW_BH ),          HW_D( HW_DI ),          HW_D( HW_EDI ) };

static  hw_reg_set SegTab[] = {
#define SEGS 6
        HW_D( HW_ES ),          HW_D( HW_CS ),
        HW_D( HW_SS ),          HW_D( HW_DS ),
        HW_D( HW_FS ),          HW_D( HW_GS ) };

static  fp_patches SegPatchTab[] = {
        FPP_ES,         FPP_CS,
        FPP_SS,         FPP_DS,
        FPP_FS,         FPP_GS };

        hw_reg_set FPRegs[] = {
        HW_D( HW_ST0 ),
        HW_D( HW_ST1 ),
        HW_D( HW_ST2 ),
        HW_D( HW_ST3 ),
        HW_D( HW_ST4 ),
        HW_D( HW_ST5 ),
        HW_D( HW_ST6 ),
        HW_D( HW_ST7 ) };

/* routines that maintain instruction buffers*/

extern  void    Format( oc_class class ) {
/*****************************************
    Get Temp and Inst ready to accept instructions.  Each instruction is
    formatted into Inst, transferred into Temp (as an opcode_entry) and
    then dumped into the peephole optimizer.
*/

    FPPatchType = FPP_NONE;
    Temp.oc.class = class;
    Temp.oc.objlen = 0;
    Temp.oc.reclen = sizeof( oc_header );
    ICur = 0;
    ILen = 0;
    IEsc = 0;
}

extern  void    ReFormat( oc_class class ) {
/*******************************************
    Change the class of Temp
*/

    Temp.oc.class = class;
}

extern  void    AddByte( byte b ) {
/**********************************
    Add a byte to Inst[]
*/

    b &= 0xff;
    if( b == ESC ) {
        Inst[  ICur++  ] = ESC;
    }
    Inst[  ICur++  ] = b;
    ILen++;
}

extern  void    AddToTemp( byte b ) {
/************************************
    Add a byte to the end of Temp
*/

    if( b == ESC ) {
        Temp.data[  Temp.oc.reclen++ - sizeof( oc_header )  ] = ESC;
    }
    Temp.data[  Temp.oc.reclen++ - sizeof( oc_header )  ] = b;
    Temp.oc.objlen++;
}

extern  void    InsertByte( byte b ) {
/*************************************
    Insert a byte into the beginning of Temp. It may not be ESC!
*/

    int         i;
    byte        *src;
    byte        *dst;

    i = Temp.oc.reclen - sizeof( oc_header );
    dst = &Temp.data[  i  ];
    src = &Temp.data[  i - 1  ];
    while( --i >= 0 ) {
        *dst = *src;
        --dst;
        --src;
    }
    Temp.data[ 0 ] = b;
    Temp.oc.reclen++;
}


extern  void    EmitByte( byte b ) {
/***********************************
    Plop a byte into Inst[]
*/

    Inst[  ICur++  ] = b;
}

extern  void    EmitPtr( pointer p ) {
/*************************************
    Plop a pointer into Inst[]
*/

    *(pointer *)(Inst+ICur) = p;
    ICur += sizeof( pointer );
}

extern  void    EmitSegId( seg_id seg ) {
/****************************************
    Plop a seg_id into Inst[]
*/

    *(seg_id *)(Inst+ICur) = seg;
    ICur += sizeof( seg_id );
}

extern  void    EmitOffset( offset i ) {
/***************************************
    Plop an "offset" int Inst[] (a machine word)
*/

    *(offset *)(Inst+ICur) = i;
    ICur += sizeof( offset );
}

extern  void    EjectInst( void ) {
/**********************************
    Dump the current instruction into the peephole optimizer
*/

    TransferIns();
    ICur = 0;
    ILen = 0;
    IEsc = 0;
}

static  void    TransferIns( void ) {
/************************************
    Transfer an instruction from Inst[] to Temp
*/

    int i;
    int j;

    i = 0;
    j = Temp.oc.reclen - sizeof( oc_header );
    while( i < IEsc ) {
        if( Inst[  i  ] == ESC ) {
            Temp.data[  j++  ] = ESC;
            Temp.oc.reclen++;
        }
        Temp.data[  j++  ] = Inst[  i++  ];
    }
    Copy( &Inst[  i  ], &Temp.data[  j  ], ICur - i );
    Temp.oc.reclen += ICur;
    Temp.oc.objlen += ILen;
}

extern  void    Finalize( void ) {
/*********************************
    Invoked by macro _Emit. Spits Temp into the peephole optimizer
*/

    EjectInst();
    if( FPPatchType != FPP_NONE ) {
        DoFunnyRef( FPPatchType );
        FPPatchType = FPP_NONE;
    }
    if( Temp.oc.objlen != 0 ) {
        InputOC( (any_oc *)&Temp.oc );
    }
}


static  void    LayInitial( instruction *ins, gentype gen ) {
/************************************************************
    Do some really magical jiggery pokery based on "gen" to get the
    right opcode int Inst[].  See PCCodeTable if you want, but this is
    not for the faint of heart!
*/

    int         index;
    pccode_def  *table;

    table = PCCodeTable;
    for(;;) {
        if( gen < table->low_gen ) break;
        if( table->width == 0 ) return;
        ++ table;
    }
    -- table;
    index = 0;
    for(;;) {
        if( table->opcode_list[  index  ] == ins->head.opcode ) break;
        if( table->opcode_list[  index  ] == OP_NOP ) break;
        ++ index;
    }
    index = index * table->width + gen - table->low_gen;
    if( table->flags & NEED_WAIT ) {
        Used87 = TRUE;
        #if !( _TARGET & _TARG_80386 )
            if( gen == G_FINIT || !_CPULevel( CPU_286 ) || _IsEmulation() ) {
                if( _IsEmulation() ) {
                    FPPatchType = FPP_NORMAL;
                }
                LayOpbyte( 0x9b );
                _Next;
            }
        #endif
    }
    if( table->flags & BYTE_OPCODE ) {
        LayOpbyte( table->opcode_table[  index  ] );
    } else {
        LayOpword( table->opcode_table[  index  ] );
    }
    if( table->flags & BYTE_WORD ) {
        LayW( ins->type_class );
    }
    if( table->flags & SIGN_UNSIGN ) {
        if( ins->type_class == I1
         || ins->type_class == I2
         || ins->type_class == I4 ) {
            if( ins->head.opcode >= OP_MUL && ins->head.opcode <= OP_MOD ) {
                Inst[ RMR ] |= B_RMR_MUL_SGN;
            } else if( ins->head.opcode == OP_RSHIFT ) {
                Inst[ RMR ] |= B_RMR_SHR_SAR;
            }
        }
    }
}

static  byte    SegTrans( hw_reg_set regs ) {
/********************************************
    Return the encoding of a segment register name
*/

    int i;

    HW_COnlyOn( regs, HW_SEGS );
    i = 0;
    while( i < SEGS ) {
        if( HW_Equal( regs, SegTab[  i  ] ) ) break;
        i++;
    }
    if( i >= SEGS ) {
        _Zoiks( ZOIKS_032 );
    }
    return( i );
}

static  byte    RegTrans( hw_reg_set regs ) {
/********************************************
    Return the encoding of a register name
*/

    int i;

    HW_CTurnOff( regs, HW_SEGS );
    i = 0;
    while( i < REGS ) {
        if( HW_Equal( regs, RegTab[  i  ] ) ) break;
        i++;
    }
    if( i >= REGS ) {
        _Zoiks( ZOIKS_031 );
    }
    i = i / 3;
    return( i );
}

#if _TARGET & _TARG_80386
static  bool    NeedOpndSize( instruction *ins ) {
/*************************************************
        Do we REALLY, REALLY need the operand size override.
*/
    int         i;
    hw_reg_set  result_reg;
    hw_reg_set  full_reg;
    instruction *next;

    switch( ins->head.opcode ) {
    case OP_MOD:
    case OP_DIV:
    case OP_RSHIFT:
        return( TRUE );
    default:
        break;
    }
    if( _OpIsCondition( ins->head.opcode ) ) return( TRUE );

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?