mipsfmt.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,508 行 · 第 1/4 页
C
1,508 行
//*********************************************************************************************
{
assert( ins->num_operands == 1 || ins->num_operands == 3 );
if( ins->num_operands == 1 ) {
uint_8 reg_num;
reg_num = RegIndex( ins->operands[0]->reg );
doFPInst( buffer, table->opcode, reg_num, reg_num, reg_num,
table->funccode );
return;
}
ITFPOperate( table, ins, buffer, reloc );
}
static void ITPseudoClr( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//**********************************************************************************************
{
assert( ins->num_operands == 1 );
reloc = reloc;
doOpcodeFcRsRt( buffer, table->opcode, table->funccode, 31,
RegIndex( ins->operands[0]->reg ), _Rd( 31 ) );
}
static void ITPseudoFclr( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//***********************************************************************************************
{
assert( ins->num_operands == 1 );
reloc = reloc;
doFPInst( buffer, table->opcode, 31, 31,
RegIndex( ins->operands[0]->reg ), table->funccode );
}
static void ITPseudoLImm( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//***********************************************************************************************
{
assert( ins->num_operands == 2 );
table = table;
reloc = reloc;
doLoadImm( buffer, ins->operands );
}
static void ITPseudoLAddr( 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 );
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 == MIPS_ZERO_SINK ) {
// 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 ) {
// We should emit lui/addiu pair.
inc = loadConst32( buffer, RegIndex( ins->operands[0]->reg ),
s_reg, op, op->constant, reloc, TRUE );
numExtendedIns += inc - 1;
return;
}
}
inc = loadConst32( buffer, RegIndex( ins->operands[0]->reg ), s_reg, op,
op->constant, reloc, FALSE );
numExtendedIns += inc - 1;
}
static void ITPseudoMov( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//**********************************************************************************************
{
assert( ins->num_operands == 2 );
reloc = reloc;
doOpcodeRType( buffer, 0, FNCCODE_OR, RegIndex( ins->operands[0]->reg ),
RegIndex( ins->operands[1]->reg ), MIPS_ZERO_SINK );
}
static void ITPseudoFmov( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//***********************************************************************************************
{
uint_8 reg_idx0;
assert( ins->num_operands == 2 );
reloc = reloc;
reg_idx0 = RegIndex( ins->operands[0]->reg );
doFPInst( buffer, table->opcode, reg_idx0, reg_idx0,
RegIndex( ins->operands[1]->reg ), table->funccode );
}
static void ITPseudoNot( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//**********************************************************************************************
{
ins_funccode fc;
ins_operand *op;
uint_32 extra;
assert( ins->num_operands == 2 );
reloc = reloc;
op = ins->operands[0];
if( op->type == OP_GPR ) {
extra = _Rt( RegIndex( op->reg ) );
} else { // OP_IMMED
assert( op->type == OP_IMMED );
extra = _LIT( op->constant );
(void)ensureOpAbsolute( op, 0 );
}
fc = getFuncCode( table, ins );
doOpcodeFcRsRt( buffer, table->opcode, fc, 31,
RegIndex( ins->operands[1]->reg ), extra );
}
static void ITPseudoNegf( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//***********************************************************************************************
{
ins_funccode fc;
assert( ins->num_operands == 2 );
reloc = reloc;
fc = getFuncCode( table, ins );
doFPInst( buffer, table->opcode, 31, RegIndex( ins->operands[0]->reg ),
RegIndex( ins->operands[1]->reg ), fc );
}
static void ITPseudoFneg( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//***********************************************************************************************
{
uint_8 reg_idx0;
assert( ins->num_operands == 2 );
reloc = reloc;
reg_idx0 = RegIndex( ins->operands[0]->reg );
doFPInst( buffer, table->opcode, reg_idx0, reg_idx0,
RegIndex( ins->operands[1]->reg ), table->funccode );
}
static void ITPseudoAbs( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//**********************************************************************************************
{
uint_8 s_reg_idx, d_reg_idx, rc_reg_idx;
ins_operand *src_op;
bool same_reg;
assert( ins->num_operands == 2 );
reloc = reloc;
src_op = ins->operands[0];
if( src_op->type == OP_IMMED ) {
// Then just evaluate it and do a mov instead.
// mov abs(src_op->constant), d_reg
if( ensureOpAbsolute( src_op, 0 ) ) {
doMov( buffer, ins->operands, DOMOV_ABS );
}
return;
}
assert( src_op->type == OP_GPR );
/* Emit an instruction sequence like:
1. subq/v $zero, $s_reg, $at // if( $s_reg == $d_reg )
2. cmovlt $s_reg, $at, $s_reg
---or---
1. subq/v $zero, $s_reg, $d_reg // if( $s_reg != $d_reg )
2. cmovgt $s_reg, $s_reg, $d_reg
*/
s_reg_idx = RegIndex( src_op->reg );
d_reg_idx = RegIndex( ins->operands[1]->reg );
if( same_reg = ( s_reg_idx == d_reg_idx ) ) {
// Then $at reg will be needed.
if( !_DirIsSet( AT ) ) {
Warning( INS_USES_AT_REG );
}
rc_reg_idx = AT_REG_IDX;
} else {
rc_reg_idx = d_reg_idx;
}
doOpcodeFcRsRt( buffer, table->opcode, table->funccode, 31,
rc_reg_idx, _Rt( s_reg_idx ) );
// So buffer gets ins #1. Now do ins #2.
++buffer;
#define OPCODE_CMOVGT 0x11
#define OPCODE_CMOVLT 0x11
#define FUNCCODE_CMOVGT 0x0066
#define FUNCCODE_CMOVLT 0x0044
if( same_reg ) {
doOpcodeFcRsRt( buffer, OPCODE_CMOVLT,
FUNCCODE_CMOVLT, s_reg_idx, s_reg_idx,
_Rt( AT_REG_IDX ) );
} else {
doOpcodeFcRsRt( buffer, OPCODE_CMOVGT,
FUNCCODE_CMOVGT, s_reg_idx, d_reg_idx,
_Rt( s_reg_idx ) );
}
++numExtendedIns;
}
mips_format MIPSFormatTable[] = {
#define PICK( a, b, c, d, e ) { b, { c, d, e } },
#include "mipsfmt.inc"
#undef PICK
};
bool MIPSValidate( instruction *ins )
//***********************************
// Make sure that all operands of the given instruction
// are of the type we are expecting. If not, we print
// out an error message.
{
int i;
mips_format *fmt;
ins_operand *op;
fmt = &MIPSFormatTable[ins->format->table_entry->template];
for( i = 0; i < ins->num_operands; i++ ) {
op = ins->operands[i];
if( ( op->type & fmt->ops[i] ) != op->type ) {
opError( ins, op->type, fmt->ops[i], i );
return( FALSE );
}
}
if( i < MAX_OPERANDS ) {
if( ( fmt->ops[i] & OP_NOTHING ) != OP_NOTHING ) {
Error( NOT_ENOUGH_INSOP );
return( FALSE );
}
} // NOTE: It might not catch all improper operand combinations
// because we're using flags here
return( TRUE );
}
#ifdef _STANDALONE_
static void emitIns( owl_section_handle hdl, char *inscode, int size )
//********************************************************************
{
ObjEmitData( hdl, inscode, size, TRUE );
}
#else
static void emitIns( char *inscode, int size )
//********************************************
{
ObjEmitData( inscode, size, TRUE );
}
#endif
#ifdef _STANDALONE_
void MIPSEmit( owl_section_handle hdl, instruction *ins )
//*******************************************************
#else
void MIPSEmit( instruction *ins )
//*******************************
#endif
// Encode the given instruction (including emitting any
// relocs to the appropriate places), and emit the code
// to the given section.
{
int ctr;
ins_table *table;
asm_reloc reloc = { NULL, NULL };
reloc_list curr_reloc;
#ifdef _STANDALONE_
uint_8 old_alignment;
if( OWLTellSectionType( hdl ) & OWL_SEC_ATTR_BSS ) {
Error( INVALID_BSS_STATEMENT );
return;
}
old_alignment = CurrAlignment;
if( CurrAlignment < 2 ) { // Instructions should at least be dword aligned
CurrAlignment = 2;
}
#endif
table = ins->format->table_entry;
MIPSFormatTable[table->template].func( table, ins, result, &reloc );
for( ctr = 0; ctr <= numExtendedIns; ctr++ ) {
if( ( curr_reloc = reloc.first ) != NULL ) {
assert( curr_reloc->loc >= ctr * sizeof( *result ) );
if( curr_reloc->loc == ctr * sizeof( *result ) ) {
reloc.first = curr_reloc->next;
if( curr_reloc->is_named ) {
#ifdef _STANDALONE_
ObjEmitReloc( hdl, SymName( curr_reloc->target.ptr ),
curr_reloc->type, TRUE, TRUE );
#else
ObjEmitReloc( SymName( curr_reloc->target.ptr ),
curr_reloc->type, TRUE, TRUE );
#endif
} else {
#ifdef _STANDALONE_
ObjEmitReloc( hdl, &curr_reloc->target.label,
curr_reloc->type, TRUE, FALSE );
#else
ObjEmitReloc( &curr_reloc->target.label,
curr_reloc->type, TRUE, FALSE );
#endif
}
#ifndef NDEBUG
switch( curr_reloc->type ) {
case OWL_RELOC_WORD:
_DBGMSG1( "word" ); break;
case OWL_RELOC_HALF_LO:
_DBGMSG1( "l^" ); break;
case OWL_RELOC_HALF_HI:
_DBGMSG1( "h^" ); break;
case OWL_RELOC_BRANCH_REL:
_DBGMSG1( "j^" ); break;
case OWL_RELOC_JUMP_REL:
_DBGMSG1( "jump hint" ); break;
default:
_DBGMSG1( "absolute (shouldn't use)" ); break;
}
_DBGMSG1( " reloc emitted for the instruction.\n" );
#endif
MemFree( curr_reloc );
}
}
#ifdef _STANDALONE_
emitIns( hdl, (char *)&result[ctr], sizeof( uint_32 ) );
#else
emitIns( (char *)&result[ctr], sizeof( uint_32 ) );
#endif
#ifndef NDEBUG
#ifdef _STANDALONE_
if( _IsOption( DUMP_INSTRUCTIONS ) ) {
printf( " [%#010x]\n", result[ctr] );
}
#endif
#endif
}
assert( reloc.first == NULL ); // Should all be emitted already!
reloc.last = NULL;
if( numExtendedIns != 0 ) {
if( !_DirIsSet( MACRO ) ) {
Warning( MACRO_INSTRUCTION );
}
numExtendedIns = 0;
}
#ifdef _STANDALONE_
CurrAlignment = old_alignment;
#endif
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?