alphafmt.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,226 行 · 第 1/4 页
C
1,226 行
}
low = ( c & 0xffff );
tmp = c - (int_32)low;
high[0] = ( ( tmp & 0xffff0000 ) >> 16 );
if( c >= 0x7fff8000 ) {
// if c is in range 0x7FFF8000..0x7FFFFFFF, tmp = 0x80000000
// => high[0] = 0x8000 => negative! So we need to split high[0]
// up to high[0] + high[1] and load them up in different LDAH's.
high[1] = 0x4000;
tmp -= 0x40000000;
high[0] = ( ( tmp & 0xffff0000 ) >> 16 );
} else {
high[1] = 0;
}
for( ctr = 0; ctr < 2; ctr++ ) {
if( high[ctr] != 0 ) {
base_reg = ( ctr == 0 ? s_reg : d_reg );
doOpcodeRaRb( buffer, OPCODE_LDAH,
d_reg, base_reg, _Memory_disp( high[ctr] ) );
if( reloc && !hi_reloc_emitted ) {
type = relocType( op->reloc.type, OWL_RELOC_HALF_HI );
if( type == OWL_RELOC_HALF_HI ) {
doReloc( reloc, op, OWL_RELOC_HALF_HI, buffer );
hi_reloc_emitted = TRUE; // only need to generate h^ once
} else {
assert( type == OWL_RELOC_HALF_LO );
// a l^ modifier was specified explicitly
// Do the reloc at the end (lda)
// Doing it in ldah will be wrong.
}
}
++ret;
++buffer;
}
}
if( !hi_reloc_emitted && force_pair ) { // no LDAH has been generated yet
// force_pair => no modifier should've been specified
// We are asked to force one, so here
doOpcodeRaRb( buffer, OPCODE_LDAH, d_reg, s_reg,
_Memory_disp( 0 ) );
doReloc( reloc, op, OWL_RELOC_HALF_HI, buffer );
++buffer;
++ret;
}
base_reg = ( ret == 1 ? s_reg : d_reg );
doOpcodeRaRb( buffer, OPCODE_LDA, d_reg, base_reg,
_Memory_disp( low ) );
if( reloc ) {
doReloc( reloc, op, OWL_RELOC_HALF_LO, buffer );
}
return( ret );
}
#if 0
static unsigned forceLoadAddressComplete( uint_8 d_reg, uint_8 s_reg, ins_operand *op, uint_32 *buffer, asm_reloc *reloc ) {
//***********************************************************************************************************************
/* Generate:
LDAH $d_reg, h^foo($s_reg)
LDA $d_reg, l^foo+c($d_reg)
store them in buffer[0], buffer[1]
*/
doOpcodeRaRb( buffer, OPCODE_LDAH, d_reg, s_reg,
_Memory_disp( 0 ) );
doReloc( reloc, op, OWL_RELOC_HALF_HI, buffer );
buffer++;
doOpcodeRaRb( buffer, OPCODE_LDA, d_reg, d_reg,
_Memory_disp( op->constant ) );
doReloc( reloc, op, OWL_RELOC_HALF_LO, buffer );
return( 2 );
}
#endif
static unsigned load32BitLiteral( uint_32 *buffer, ins_operand *op0, ins_operand *op1, domov_option m_opt ) {
//***********************************************************************************************************
op_const val;
if( m_opt == DOMOV_ABS ) {
val = abs( op0->constant );
} else {
val = op0->constant;
}
return( ldaConst32( buffer, RegIndex( op1->reg ), ZERO_REG_IDX,
op0, val, NULL, FALSE ) );
}
static void doMov( uint_32 *buffer, ins_operand *operands[], domov_option m_opt ) {
//*********************************************************************************
ins_operand *op0, *op1;
uint_32 extra;
uint_32 abs_val;
bool ready = TRUE;
op0 = operands[0];
op1 = operands[1];
if( op0->type == OP_GPR ) {
extra = _Rb( RegIndex( op0->reg ) );
} else if( ( op0->constant & 0xff ) == op0->constant ) { // OP_IMMED implied
extra = _LIT( op0->constant ); // this lit is between 0..255
(void)ensureOpAbsolute( op0, 0 );
} else if( m_opt == DOMOV_ABS &&
( ( ( abs_val = abs( op0->constant ) ) & 0xff ) == abs_val ) ) {
extra = _LIT( abs_val ); // this lit is between 0..255
// ensureOpAbsolute( op0, 0 ); should be done before calling doMov
} else {
ready = FALSE;
}
if( ready ) {
doOpcodeFcRaRc( buffer, OPCODE_BIS, FUNCCODE_BIS,
ZERO_REG_IDX, RegIndex( op1->reg ), extra );
return;
}
// Otherwise it's OP_IMMED with a greater than 8-bit literal.
// We'll then use multiple LDA, LDAH instructions to load the literal.
if( !ensureOpAbsolute( op0, 0 ) ) return;
numExtendedIns += load32BitLiteral( buffer, op0, op1, m_opt ) - 1;
}
static void ITLoadAddress( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc ) {
//**************************************************************************************************
ins_operand *op;
ins_operand *ops[2];
unsigned inc;
op_const val;
uint_8 s_reg;
assert( ins->num_operands == 2 );
assert( table->opcode == OPCODE_LDA );
op = ins->operands[1];
// If op is IMMED foo, it's actually REG_INDIRECT that we want: foo($zero)
if( op->type == OP_IMMED ) {
op->type = OP_REG_INDIRECT;
op->reg = ZERO_REG;
}
assert( op->type == OP_REG_INDIRECT );
val = op->constant;
s_reg = RegIndex( op->reg );
if( !OP_HAS_RELOC( op ) && s_reg == ZERO_REG_IDX ) {
// doMov() can only be called when op->reg is ZERO_REG and no reloc
ops[0] = op;
ops[1] = ins->operands[0];
doMov( buffer, ops, DOMOV_ORIGINAL );
return;
}
if( OP_HAS_RELOC( op ) ) {
#ifndef _STANDALONE_
if( OP_RELOC_NAMED( op ) ) {
char *name;
name = SymName( op->reloc.target.ptr );
if( AsmQueryExternal( name ) == SYM_STACK ) {
doAutoVar( reloc, op->reloc.target, buffer, table, ins );
return;
}
}
#endif
if( op->reloc.type == ASM_RELOC_UNSPECIFIED ) {
// Then we should emit LDA-LDAH pair.
inc = ldaConst32( buffer, RegIndex( ins->operands[0]->reg ),
s_reg, op, op->constant, reloc, TRUE );
numExtendedIns += inc - 1;
return;
}
}
inc = ldaConst32( buffer, RegIndex( ins->operands[0]->reg ), s_reg, op,
op->constant, reloc, FALSE );
numExtendedIns += inc - 1;
/*
doOpcodeRaRb( buffer, table->opcode, RegIndex( ins->operands[0]->reg ),
s_reg, _Memory_disp( val ) );
doReloc( reloc, op, OWL_RELOC_HALF_LO, buffer );*/
}
#if 0
static void ITMemLDAH( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc ) {
//**********************************************************************************************
ins_operand *op;
assert( table->opcode == OPCODE_LDAH );
op = ins->operands[1];
// If op is IMMED foo, it's actually REG_INDIRECT that we want: foo($zero)
if( op->type == OP_IMMED ) {
op->type = OP_REG_INDIRECT;
op->reg = ZERO_REG;
}
assert( op->type == OP_REG_INDIRECT );
doOpcodeRaRb( buffer, table->opcode, RegIndex( ins->operands[0]->reg ),
RegIndex( op->reg ), _Memory_disp( op->constant ) );
doReloc( reloc, op, OWL_RELOC_HALF_HI, buffer );
}
#endif
static void ITMemAll( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc ) {
//*********************************************************************************************
ins_operand *op;
owl_reloc_type type;
ins_opcode opcode;
assert( ins->num_operands == 2 );
op = ins->operands[1];
// If op is IMMED foo, it's actually REG_INDIRECT that we want: foo($zero)
if( op->type == OP_IMMED ) {
op->type = OP_REG_INDIRECT;
op->reg = ZERO_REG;
}
assert( op->type == OP_REG_INDIRECT );
#ifndef _STANDALONE_
if( OP_RELOC_NAMED( op ) ) {
char *name;
name = SymName( op->reloc.target.ptr );
if( AsmQueryExternal( name ) == SYM_STACK ) {
doAutoVar( reloc, op->reloc.target, buffer, table, ins );
return;
}
}
#endif
opcode = table->opcode;
doOpcodeRaRb( buffer, opcode, RegIndex( ins->operands[0]->reg ),
RegIndex( op->reg ), _Memory_disp( op->constant ) );
type = ( opcode == OPCODE_LDAH ) ? OWL_RELOC_HALF_HI : OWL_RELOC_HALF_LO;
doReloc( reloc, op, type, buffer );
}
static void ITMemA( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc ) {
//*******************************************************************************************
assert( ins->num_operands == 1 );
reloc = reloc;
doOpcodeRaRb( buffer, table->opcode, RegIndex( ins->operands[0]->reg ),
31, _Mem_Func( table->funccode ) );
}
static void ITMemB( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc ) {
//*******************************************************************************************
assert( ins->num_operands == 1 );
reloc = reloc;
doOpcodeRaRb( buffer, table->opcode, 31, RegIndex( ins->operands[0]->reg ),
_Mem_Func( table->funccode ) );
}
static void doMemJump( uint_32 *buffer, ins_table *table, uint_8 ra, uint_8 rb, ins_operand *addr_op, uint_32 hint, asm_reloc *reloc ) {
//**************************************************************************************************************************************
// Note that addr_op maybe NULL. If not, addr_op->constant == hint.
assert( addr_op == NULL || addr_op->constant == hint );
assert( addr_op == NULL || addr_op->type == OP_IMMED );
doOpcodeRaRb( buffer, table->opcode, ra, rb,
(table->funccode << 14) | _FourteenBits(hint) );
doReloc( reloc, addr_op, OWL_RELOC_JUMP_REL, buffer );
}
static void opError( instruction *ins, op_type actual, op_type wanted, int i ) {
//******************************************************************************
// Stuff out an error message.
ins = ins;
actual = actual;
wanted = wanted; // it's a set of flags
if( ( wanted & OP_NOTHING ) != OP_NOTHING ) {
Error( OPERAND_INCORRECT, i );
} else {
Error( OPERAND_UNEXPECTED, i );
}
}
static bool opValidate( ot_array *verify, instruction *ins, ins_opcount num_op, unsigned num_var ) {
//**************************************************************************************************
int ctr, var, lasterr;
op_type actual, wanted;
for( var = 0; var < num_var; var++ ) {
lasterr = -1;
for( ctr = 0; ctr < num_op; ctr++ ) {
if( ins->operands[ctr]->type != (*verify)[var][ctr] ) {
lasterr = ctr;
actual = ins->operands[ctr]->type;
wanted = (*verify)[var][ctr];
break;
}
}
if( lasterr == -1 ) { // passed
break;
}
}
if( lasterr != -1 ) {
opError( ins, actual, wanted, lasterr );
return( FALSE );
}
return( TRUE );
}
static bool jmpOperandsValidate( instruction *ins, ins_opcount num_op ) {
//***********************************************************************
// Used by jmp, jsr
static op_type verify1[][3] = { { OP_REG_INDIRECT, OP_NOTHING, OP_NOTHING },
{ OP_IMMED, OP_NOTHING, OP_NOTHING } };
static op_type verify2[][3] = { { OP_GPR, OP_REG_INDIRECT, OP_NOTHING },
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?