axpenc.c

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

C
956
字号
/****************************************************************************
*
*                            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:  Alpha AXP instruction encoding.
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "pattern.h"
#include "symdbg.h"
#include "vergen.h"
#include "ocentry.h"
#include "axpencod.h"
#include "reloc.h"
#include "offset.h"
#include "optopts.h"
#include "optlbl.h"
#include "zoiks.h"
#include "model.h"
#include "coff.h"
#include "procdef.h"
#include "encode.h"
#include "cgaux.h"
#include "rtclass.h"
#include "feprotos.h"
#include <assert.h>
#include <stdio.h>

extern void DumpInsOnly( instruction * );
extern void DumpString( char * );
extern void DumpPtr( pointer );
extern void DumpInt( int );
extern void DumpNL(void);
extern void DumpGen(struct opcode_entry*);
extern void DumpPtr( void *ptr );

extern void             ObjBytes( char *buffer, int size );
extern uint_8           RegTrans( hw_reg_set );
extern void             OutLabel( label_handle );
extern void             OutReloc( label_handle, axp_reloc, unsigned );
extern pointer          AskForSymLabel( pointer, cg_class );
extern hw_reg_set       StackReg( void );
extern hw_reg_set       FrameReg( void );
extern name             *DeAlias( name * );
extern void             TryScrapLabel( code_lbl * );
extern  offset          AskLocation();
extern  void            OutLineNum( unsigned_16 line, bool label_line );
extern void             EmitDbgInfo(instruction*);
extern  void            ObjEmitSeq( risc_byte_seq * );
extern  bool            AskIfRTLabel( code_lbl * );
extern  void            InputOC( any_oc * );
extern  opcode_defs     FlipOpcode( opcode_defs );
extern  void            FactorInt32( signed_32 val, signed_16 *, signed_16 *, signed_16 * );
extern  label_handle    RTLabel( int );

extern type_class_def   Unsigned[];
extern type_length      TypeClassSize[];
extern proc_def         *CurrProc;

#define _NameReg( op )                  ( (op)->r.arch_index )

#define _IsSigned( type )               ( Unsigned[ type ] != type )

#define _BinaryOpcode( a, b )           { { a, b }, { a, b } }
#define _SignedOpcode( a, b, c, d )     { { a, b }, { c, d } }

// Our table for opcode values is really a list of pairs of
// primary opcode / function code pairs. Their is two entries
// for each opcode in case the sign of the instruction matters;
// for example, for OP_RSHIFT we need to generate either sra or
// srl. If the sign of the type of the instruction doesn't
// matter, we can just use the _BinaryOpcode macro to create
// identical cases, otherwise we give each pair explicitly.


static  uint_8  BinaryOpcodes4[][2][2] = {
        _BinaryOpcode( 0x10, 0x00 ),                    /* OP_ADD */
        _BinaryOpcode( 0x10, 0x00 ),                    /* OP_EXT_ADD */
        _BinaryOpcode( 0x10, 0x09 ),                    /* OP_SUB */
        _BinaryOpcode( 0x10, 0x09 ),                    /* OP_EXT_SUB */
        _BinaryOpcode( 0x13, 0x00 ),                    /* OP_MUL */
        _BinaryOpcode( 0x13, 0x00 ),                    /* OP_EXT_MUL */
        _BinaryOpcode( 0x00, 0x00 ),                    /* OP_DIV */
        _BinaryOpcode( 0x00, 0x00 ),                    /* OP_MOD */
        _BinaryOpcode( 0x11, 0x00 ),                    /* OP_AND */
        _BinaryOpcode( 0x11, 0x20 ),                    /* OP_OR */
        _BinaryOpcode( 0x11, 0x40 ),                    /* OP_XOR */
        _SignedOpcode( 0x12, 0x34, 0x12, 0x3c ),        /* OP_RSHIFT */
        _BinaryOpcode( 0x12, 0x39 ),                    /* OP_LSHIFT */
        _BinaryOpcode( 0x00, 0x00 ),                    /* OP_POW */
        _BinaryOpcode( 0x00, 0x00 ),                    /* OP_ATAN2 */
        _BinaryOpcode( 0x00, 0x00 ),                    /* OP_FMOD */
};

static  uint_8  BinaryOpcodes8[][2][2] = {
        _BinaryOpcode( 0x10, 0x20 ),                    /* OP_ADD */
        _BinaryOpcode( 0x10, 0x20 ),                    /* OP_EXT_ADD */
        _BinaryOpcode( 0x10, 0x29 ),                    /* OP_SUB */
        _BinaryOpcode( 0x10, 0x29 ),                    /* OP_EXT_SUB */
        _BinaryOpcode( 0x13, 0x20 ),                    /* OP_MUL */
        _BinaryOpcode( 0x13, 0x20 ),                    /* OP_EXT_MUL */
        _BinaryOpcode( 0x00, 0x00 ),                    /* OP_DIV */
        _BinaryOpcode( 0x00, 0x00 ),                    /* OP_MOD */
        _BinaryOpcode( 0x11, 0x00 ),                    /* OP_AND */
        _BinaryOpcode( 0x11, 0x20 ),                    /* OP_OR */
        _BinaryOpcode( 0x11, 0x40 ),                    /* OP_XOR */
        _SignedOpcode( 0x12, 0x34, 0x12, 0x3c ),        /* OP_RSHIFT */
        _BinaryOpcode( 0x12, 0x39 ),                    /* OP_LSHIFT */
        _BinaryOpcode( 0x00, 0x00 ),                    /* OP_POW */
        _BinaryOpcode( 0x00, 0x00 ),                    /* OP_ATAN2 */
        _BinaryOpcode( 0x00, 0x00 ),                    /* OP_FMOD */
};

static  uint_8  SetOpcodes[][2][2] = {
        _BinaryOpcode( 0x10, 0x2d ),                    /* OP_SET_EQUAL */
        _BinaryOpcode( 0x00, 0x00 ),                    /* OP_SET_NOT_EQUAL */
        _BinaryOpcode( 0x00, 0x00 ),                    /* OP_SET_GREATER */
        _SignedOpcode( 0x10, 0x3d, 0x10, 0x6d ),        /* OP_SET_LESS_EQUAL */
        _SignedOpcode( 0x10, 0x1d, 0x10, 0x4d ),        /* OP_SET_LESS */
        _BinaryOpcode( 0x00, 0x00 ),                    /* OP_SET_GREATER_EQUAL */
};

// For floating point operate format instructions, the size of the
// instruction type (not the sign) is what determines the opcode. So
// we have a pair of function code values for each codegen logical
// opcode. We don't need the primary opcode since it is always 0x16.
// Note that we are in for some minor discomfort if we need to start
// enabling different trap bits on instructions.

static  uint_16 FloatingBinaryOpcodes[][2] = {
        { 0x080, 0x0a0 },                               /* OP_ADD */
        { 0x080, 0x0a0 },                               /* OP_EXT_ADD */
        { 0x581, 0x5a1 },                               /* OP_SUB */
        { 0x581, 0x5a1 },                               /* OP_EXT_SUB */
        { 0x582, 0x5a2 },                               /* OP_MUL */
        { 0x582, 0x5a2 },                               /* OP_EXT_MUL */
        { 0x583, 0x5a3 },                               /* OP_DIV */
};

static  uint_16 FloatingSetOpcodes[][1] = {
        { 0xa5 },                                       /* OP_SET_EQUAL */
        { 0x00 },                                       /* OP_SET_NOT_EQUAL */
        { 0x00 },                                       /* OP_SET_GREATER */
        { 0xa7 },                                       /* OP_SET_LESS_EQUAL */
        { 0xa6 },                                       /* OP_SET_LESS */
        { 0x00 },                                       /* OP_SET_GREATER_EQUAL */
};

static  uint_8  AlphaByteOpcodes[][2] = {
        { 0x12, 0x06 },                                 /* OP_EXTRACT_LOW */
        { 0x12, 0x4a },                                 /* OP_EXTRACT_HIGH */
        { 0x12, 0x0b },                                 /* OP_INSERT_LOW */
        { 0x12, 0x47 },                                 /* OP_INSERT_HIGH */
        { 0x12, 0x02 },                                 /* OP_MASK_LOW */
        { 0x12, 0x42 },                                 /* OP_MASK_HIGH */
        { 0x12, 0x30 },                                 /* OP_ZAP */
        { 0x12, 0x31 },                                 /* OP_ZAP_NOT */
};

// This is the bit pattern to OR into the function opcode when encoding
// an Alpha byte manipulation instruction. Note that it depends only upon
// the size of the register subset to be acted upon. Some of these
// combination can yield invalid instructions, but hopefully these will
// never be combined together.
static  uint_8  AlphaByteInsSizeBits[] = {
        0x00,                                           /* U1 */
        0x00,                                           /* I1 */
        0x10,                                           /* U2 */
        0x10,                                           /* I2 */
        0x20,                                           /* U4 */
        0x20,                                           /* I4 */
        0x30,                                           /* U8 */
        0x30,                                           /* I8 */
        0x20,                                           /* CP */
        0x20,                                           /* PT */
        0x20,                                           /* FS */
        0x30,                                           /* FD */
        0x30,                                           /* FL */
        0x00,                                           /* XX */
};

// Used for faking up a set of opcodes for an instruction when
// including an exhaustive table would have been too painful.
static  uint_8  ScratchOpcodes[2];

extern  void EmitInsReloc( axp_ins ins, pointer sym, owl_reloc_type type ) {
/**************************************************************************/

    oc_riscins          oc;

    oc.op.objlen = 4;
    oc.op.class = OC_RCODE;
    oc.op.reclen = sizeof( oc_riscins );
    oc.opcode = ins;
    oc.sym = sym;
    oc.reloc = type;
    InputOC( (any_oc *)&oc );
}

static  void EmitIns( axp_ins ins ) {
/***********************************/

    EmitInsReloc( ins, NULL, 0 );
}

static  void GenFPOPINS( uint_8 opcode, uint_16 function, uint_8 reg_a, uint_8 reg_b, uint_8 reg_c ) {
/****************************************************************************************************/

    axp_ins             ins;

    ins = _Opcode( opcode ) | _A( reg_a ) | _B( reg_b ) | _C( reg_c ) | _FPFunction( function );
    EmitIns( ins );
}

extern  void GenOPINS( uint_8 opcode, uint_8 function, uint_8 reg_a, uint_8 reg_b, uint_8 reg_c ) {
/*************************************************************************************************/

    axp_ins             ins;

    ins = _Opcode( opcode ) | _A( reg_a ) | _B( reg_b ) | _C( reg_c ) | _Function( function );
    EmitIns( ins );
}

static  void    GenOPIMM( uint_8 opcode, uint_8 function, uint_8 reg_a, uint_8 imm, uint_8 reg_c ) {
/**************************************************************************************************/

    axp_ins             ins;

    ins = _Opcode( opcode ) | _A( reg_a ) | _LIT( imm ) | ( 1 << 12 ) | _C( reg_c ) | _Function( function );
    EmitIns( ins );
}

extern  void    GenLOADS32( signed_32 value, uint_8 reg ) {
/*********************************************************/

    signed_16           high;
    signed_16           extra;
    signed_16           low;
    uint_8              curr;

    curr = AXP_ZERO_SINK;
    FactorInt32( value, &high, &extra, &low );
    if( low != 0 ) {
        // la low(curr) -> reg
        GenMEMINS( 0x08, reg, curr, low );
        curr = reg;
    }
    if( extra != 0 ) {
        // lah extra(curr) -> reg
        GenMEMINS( 0x09, reg, curr, extra );
        curr = reg;
    }
    if( high != 0 ) {
        // lah high(curr) -> reg
        GenMEMINS( 0x09, reg, curr, high );
        curr = reg;
    }
}

static  uint_8  *FindOpcodes( instruction *ins ) {
/************************************************/

    uint_8      *opcodes;

    if( _OpIsBinary( ins->head.opcode ) ) {
        if( ins->type_class == U8 || ins->type_class == I8 ) {
            opcodes = &BinaryOpcodes8[ ins->head.opcode - FIRST_BINARY_OP ][ _IsSigned( ins->type_class ) ][ 0 ];
        } else {
            opcodes = &BinaryOpcodes4[ ins->head.opcode - FIRST_BINARY_OP ][ _IsSigned( ins->type_class ) ][ 0 ];
        }
    } else if( _OpIsSet( ins->head.opcode ) ) {
        opcodes = &SetOpcodes[ ins->head.opcode - FIRST_SET_OP ][ _IsSigned( ins->type_class ) ][ 0 ];
    } else if( _OpIsAlphaByteIns( ins->head.opcode ) ) {
        // WARNING: must use these values before calling FindOpcodes again
        opcodes = &ScratchOpcodes[0];
        opcodes[ 0 ] = AlphaByteOpcodes[ ins->head.opcode - FIRST_ALPHA_BYTE_INS ][ 0 ];
        opcodes[ 1 ] = AlphaByteOpcodes[ ins->head.opcode - FIRST_ALPHA_BYTE_INS ][ 1 ];
        if( ins->head.opcode != OP_ZAP && ins->head.opcode != OP_ZAP_NOT ) {
            opcodes[ 1 ] |= AlphaByteInsSizeBits[ ins->base_type_class ];
        }
    } else {
        assert( 0 );
    }
    return( opcodes );
}

static  uint_16 FindFloatingOpcodes( instruction *ins ) {
/*******************************************************/

    uint_16     opcode;

    assert( _IsFloating( ins->type_class ) );
    if( _OpIsBinary( ins->head.opcode ) ) {

⌨️ 快捷键说明

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