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