alphafmt.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,226 行 · 第 1/4 页
C
1,226 行
/****************************************************************************
*
* 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 formats and encodings.
*
****************************************************************************/
#include "as.h"
#ifndef _STANDALONE_
#include "asinline.h"
#endif
typedef struct reloc_entry *reloc_list;
struct reloc_entry {
reloc_list next;
op_reloc_target target;
owl_reloc_type type;
unsigned loc; // offset of the reloc from &result[0].
bool is_named; // does it have a corr. named symbol
};
typedef struct asm_reloc {
reloc_list first;
reloc_list last;
} asm_reloc;
typedef void (*fmt_func)( ins_table *, instruction *, uint_32 *, asm_reloc * );
typedef struct {
fmt_func func;
op_type ops[ MAX_OPERANDS ];
} alpha_format;
typedef enum {
DOMOV_ORIGINAL,
DOMOV_ABS,
} domov_option;
#define MAX_VARIETIES 3
typedef op_type ot_array[MAX_VARIETIES][3];
#define _FiveBits( x ) ( (x) & 0x001f )
#define _SixBits( x ) ( (x) & 0x003f )
#define _SevenBits( x ) ( (x) & 0x007f )
#define _EightBits( x ) ( (x) & 0x00ff )
#define _ElevenBits( x ) ( (x) & 0x07ff )
#define _FourteenBits( x ) ( (x) & 0x3fff )
#define _SixteenBits( x ) ( (x) & 0xffff )
#define _TwentyOneBits( x ) ( (x) & 0x001fffff )
#define _LIT_value( x ) ( _EightBits( x ) << 1 )
#define _LIT_bit 1
#define _LIT_unshifted( x ) ( _LIT_value( x ) | _LIT_bit )
#define _Opcode( x ) ( _SixBits( x ) << 26 )
#define _Ra( x ) ( _FiveBits( x ) << 21 )
#define _Rb( x ) ( _FiveBits( x ) << 16 )
#define _Rc( x ) ( _FiveBits( x ) << 0 )
#define _Memory_disp( x ) ( _SixteenBits( x ) << 0 )
#define _Mem_Func( x ) ( _SixteenBits( x ) << 0 )
#define _Branch_disp( x ) ( _TwentyOneBits( x ) << 0 )
#define _Op_Func( x ) ( _SevenBits( x ) << 5 )
#define _FP_Op_Func( x ) ( _ElevenBits( x ) << 5 )
#define _LIT( x ) ( _LIT_unshifted( x ) << 12 )
#define _Longword_offset( x ) ( (x) >> 2 )
#define MAX_EXTENDED_INS 20 // Including the default buffer, we have
// 21 dwords for an ins that emits multiple
// instructions. (eg. ldb)
#define RA_REG_IDX 26
#define SP_REG_IDX 30
#define FP_REG_IDX 15
#define ZERO_REG_IDX 31
// Check if ".set noat" is in effect before using this
#define AT_REG_IDX RegIndex( AT_REG )
#define ZERO_REG MakeReg( RC_GPR, ZERO_REG_IDX )
#define OPCODE_BIS 0x11
#define FUNCCODE_BIS 0x0020
#define OPCODE_LDA 0x8
#define OPCODE_LDAH 0x9
#define OP_HAS_RELOC( op ) ((op)->flags & (RELOC | UNNAMED_RELOC))
#define OP_RELOC_NAMED( op ) ((op)->flags & RELOC)
static unsigned numExtendedIns = 0; // >= 1 when we use extendedIns
static uint_32 result[ MAX_EXTENDED_INS + 1 ];
static owl_reloc_type reloc_translate[] = {
OWL_RELOC_ABSOLUTE, // Corresponds to ASM_RELOC_UNSPECIFIED
OWL_RELOC_WORD,
OWL_RELOC_HALF_HI,
OWL_RELOC_HALF_HA,
OWL_RELOC_HALF_LO,
OWL_RELOC_BRANCH_REL, // j^ reloc
OWL_RELOC_JUMP_REL, // jump hint
};
static bool ensureOpAbsolute( ins_operand *op, uint_8 opIdx ) {
//*************************************************************
if( OP_HAS_RELOC( op ) ) {
Error( RELOC_NOT_ALLOWED, opIdx );
return( FALSE );
}
return( TRUE );
}
static void addReloc( asm_reloc *reloc, op_reloc_target target, owl_reloc_type type, unsigned loc, bool is_named ) {
//******************************************************************************************************************
reloc_list new_entry;
new_entry = MemAlloc( sizeof( struct reloc_entry ) );
new_entry->next = NULL;
new_entry->target = target;
new_entry->type = type;
new_entry->loc = loc;
new_entry->target = target;
new_entry->is_named = is_named;
if( reloc->first == NULL ) {
reloc->first = new_entry;
} else {
reloc->last->next = new_entry;
}
reloc->last = new_entry;
}
static owl_reloc_type relocType( asm_reloc_type type, owl_reloc_type default_type ) {
//***********************************************************************************
owl_reloc_type ret;
if( type == ASM_RELOC_UNSPECIFIED ) {
return( default_type );
}
switch( default_type ) {
case OWL_RELOC_HALF_HI:
case OWL_RELOC_HALF_LO:
if( ( ret = reloc_translate[type] ) != OWL_RELOC_HALF_HI &&
ret != OWL_RELOC_HALF_LO ) {
Error( INVALID_RELOC_MODIFIER );
}
break;
case OWL_RELOC_BRANCH_REL: // j^ reloc
if( ( ret = reloc_translate[type] ) != default_type ) {
Error( INVALID_RELOC_MODIFIER );
}
break;
case OWL_RELOC_JUMP_REL: // jump hint
// we accept j^ to be specified for jump hint for now.
if( ( ret = reloc_translate[type] ) != OWL_RELOC_JUMP_REL &&
ret != OWL_RELOC_BRANCH_REL ) {
Error( INVALID_RELOC_MODIFIER );
}
ret = OWL_RELOC_JUMP_REL;
break;
default:
//Error( "internal - unexpected default type" );
assert( FALSE );
ret = OWL_RELOC_ABSOLUTE;
}
return( ret );
}
static void doReloc( asm_reloc *reloc, ins_operand *op, owl_reloc_type rtype, uint_32 *offset ) {
//***********************************************************************************************
if( op == NULL ) return;
if( !( OP_HAS_RELOC( op ) ) ) return;
addReloc( reloc, op->reloc.target, relocType( op->reloc.type, rtype ),
(unsigned)offset - (unsigned)result, ( op->flags & RELOC ) );
}
/*
IT_OPERATE:
QF_V..........+0x40
IT_FP_xxxx:
QF_S..........+0x400
QF_U..........+0x100
QF_V..........+0x100
QF_I..........+0x200
QF_C..........-0x080
QF_M..........-0x040
QF_D..........+0x040
*/
static ins_funccode getFuncCode( ins_table *table, instruction *ins ) {
//*********************************************************************
ins_funccode fc;
fc = table->funccode;
switch( table->template ) {
case IT_OPERATE:
case IT_PSEUDO_NOT:
if( ins->format->flags & QF_V ) {
fc += 0x40;
} else {
assert( ins->format->flags == 0 ); // No other valid flags
}
break;
case IT_FP_OPERATE:
case IT_FP_CONVERT:
case IT_PSEUDO_NEGF:
if( ins->format->flags & QF_S ) fc += 0x400;
if( ins->format->flags & QF_U ) fc += 0x100;
if( ins->format->flags & QF_V ) fc += 0x100;
if( ins->format->flags & QF_I ) fc += 0x200;
if( ins->format->flags & QF_C ) fc -= 0x080;
if( ins->format->flags & QF_M ) fc -= 0x040;
if( ins->format->flags & QF_D ) fc += 0x040;
break;
default:
assert( FALSE ); // Others should have no need to call this.
}
return( fc );
}
static void doOpcodeRaRb( uint_32 *buffer, ins_opcode opcode, uint_8 ra, uint_8 rb, uint_32 remain ) {
//****************************************************************************************************
*buffer = _Opcode( opcode ) | _Ra( ra ) | _Rb( rb ) | remain;
}
static void doOpcodeFcRaRc( uint_32 *buffer, ins_opcode opcode, ins_funccode fc, uint_8 ra, uint_8 rc, uint_32 extra ) {
//**********************************************************************************************************************
// This procedure doesn't fill in all the bits (missing bits 20-12).
// But we can fill it in using extra.
*buffer = _Opcode( opcode ) | _Op_Func( fc ) | _Ra( ra ) | _Rc( rc ) |
extra;
}
static void doFPInst( uint_32 *buffer, ins_opcode opcode, uint_8 ra, uint_8 rb, uint_8 rc, uint_32 remain ) {
//***********************************************************************************************************
*buffer = _Opcode( opcode ) | _Ra( ra ) | _Rb( rb ) |
_FP_Op_Func( remain ) | _Rc( rc );
}
#ifndef _STANDALONE_
static void doAutoVar( asm_reloc *reloc, op_reloc_target targ, uint_32 *buffer, ins_table *table, instruction *ins ) {
//********************************************************************************************************************
ins_operand *op;
op = ins->operands[1];
if( op->reg != ZERO_REG ) {
Error( BAD_BASE_REG_FOR_STACKVAR );
return;
}
addReloc( reloc, targ, OWL_RELOC_FP_OFFSET, (unsigned)buffer - (unsigned)&result[ 0 ], TRUE );
doOpcodeRaRb( buffer, table->opcode, RegIndex( ins->operands[0]->reg ),
FP_REG_IDX, 0 );
}
#endif
static unsigned ldaConst32( uint_32 *buffer, uint_8 d_reg, uint_8 s_reg, ins_operand *op, op_const c, asm_reloc *reloc, bool force_pair ) {
//*****************************************************************************************************************************************
// LDA-LDAH sequence for 32-bit constants
// Given: lda $d_reg, foobar+c($s_reg)
// info for foobar is stored in op
// c should be passed in also
// Returns # of ins generated
int_32 tmp;
int ctr;
unsigned ret = 1;
int_16 low, high[2];
uint_8 base_reg;
owl_reloc_type type;
bool hi_reloc_emitted = FALSE;
if( force_pair ) {
assert( reloc != NULL );
if( op->reloc.type != ASM_RELOC_UNSPECIFIED ) {
Error( INVALID_RELOC_MODIFIER );
return( ret );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?