mipsenc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,073 行 · 第 1/3 页
C
1,073 行
label_handle tls_index;
op = ins->operands[0];
if( op->n.class != N_MEMORY ) return( FALSE );
if( op->m.memory_type != CG_FE ) return( FALSE );
if( ( FEAttr( op->v.symbol ) & FE_THREAD_DATA ) == 0 ) return( FALSE );
/*
* Put out a sequence that looks like:
ldah at, h^__tls_index(zero)
lda at, l^__tls_index(at)
rdteb
ldl v0, 0x2c(v0)
s4addl at, v0, v0
ldl v0, (v0)
lda rn, l^variable(v0)
In order to be able to zap v0 (which rdteb does),
we always set the zap set on a LEA foo -> rn instruction
to be v0 when foo is a piece of thread-local storage.
This is done in FixMemRefs.
*/
tls_index = RTLabel( RT_TLS_INDEX - BEG_RTNS );
#if 0
GenMEMINSRELOC( 0x09, MIPS_GPR_SCRATCH, MIPS_ZERO_SINK, 0,
tls_index, OWL_RELOC_HALF_HI );
GenMEMINSRELOC( 0x08, MIPS_GPR_SCRATCH, MIPS_GPR_SCRATCH, 0,
tls_index, OWL_RELOC_HALF_LO );
EmitIns( RDTEB_ENCODING );
GenMEMINS( loadOpcodes[I4], V0, V0, RDTEB_MAGIC_CONST );
GenOPINS( 0x0010, 0x0002, MIPS_GPR_SCRATCH, V0, V0 );
GenMEMINS( loadOpcodes[I4], V0, V0, 0 );
GenMEMINSRELOC( 0x08, _NameReg( ins->result ),
V0, 0, symLabel( op ), OWL_RELOC_HALF_LO );
#else
assert( 0 );
#endif
return( TRUE );
}
static void Encode( instruction *ins )
/*************************************/
{
uint_8 *opcodes;
uint_8 opcode;
uint_16 function;
uint_8 reg_index;
uint_8 mem_index;
int_16 mem_offset;
signed_16 high;
signed_16 extra;
signed_16 low;
signed_16 imm_value;
switch( ins->u.gen_table->generate ) {
case G_CALL:
assert( ins->operands[CALL_OP_ADDR]->n.class == N_MEMORY );
doCall( ins );
break;
case G_CALLI:
GenCallIndirect( ins );
break;
case G_UNARY:
assert( ins->operands[0]->n.class == N_REGISTER );
assert( ins->result->n.class == N_REGISTER );
switch( ins->head.opcode ) {
case OP_NEGATE:
// 'neg.fmt fd,fs'
switch( ins->type_class ) {
case FS:
case FD:
case FL:
GenFloatRType( ins->type_class, 0x07, _NameReg( ins->result ),
_NameReg( ins->operands[0] ), 0 );
break;
default:
// 'subu rd,$zero,rs'
GenRType( 0x00, 0x23, _NameReg( ins->result ),
MIPS_ZERO_SINK, _NameReg( ins->operands[0] ) );
}
break;
case OP_COMPLEMENT:
// 'nor rd,$zero,rs'
GenRType( 0x00, 0x27, _NameReg( ins->result ),
MIPS_ZERO_SINK, _NameReg( ins->operands[0] ) );
break;
default:
_Zoiks( ZOIKS_028 );
}
break;
case G_MOVE_FP:
assert( ins->operands[0]->n.class == N_REGISTER );
assert( ins->result->n.class == N_REGISTER );
// 'mov.s fd,fs'
GenFloatRType( FS, 0x06, _NameReg( ins->result ),
_NameReg( ins->operands[0] ), 0 );
break;
case G_ZERO:
assert( ins->operands[0]->n.class == N_REGISTER );
assert( ins->result->n.class == N_REGISTER );
assert( ins->head.opcode == OP_CONVERT );
doZero( ins, ins->base_type_class );
break;
case G_SIGN:
assert( ins->operands[0]->n.class == N_REGISTER );
assert( ins->result->n.class == N_REGISTER );
assert( ins->head.opcode == OP_CONVERT );
doSignExtend( ins, ins->base_type_class );
break;
case G_CVTTS:
assert( ins->operands[0]->n.class == N_REGISTER );
assert( ins->result->n.class == N_REGISTER );
// 'cvt.s.d fd,fs'
GenFloatRType( FD, 0x20, _NameReg( ins->result ),
_NameReg( ins->operands[0] ), 0 );
break;
case G_FREGTOMI8:
assert( ins->operands[0]->n.class == N_REGISTER );
assert( ins->result->n.class != N_REGISTER );
reg_index = _NameReg( ins->operands[0] );
// 'sdc1 rt,offset(base)' - MIPS32-R2/MIPS64 only?
GenIType( 0x3d, reg_index, mem_index, mem_offset );
break;
case G_MI8TOFREG:
assert( ins->operands[0]->n.class != N_REGISTER );
assert( ins->result->n.class == N_REGISTER );
reg_index = _NameReg( ins->result );
getMemEncoding( ins->operands[0], &mem_index, &mem_offset );
// 'ldc1 rt,offset(base)' - MIPS32-R2/MIPS64 only?
GenIType( 0x35, reg_index, mem_index, mem_offset );
break;
case G_BINARY_FP:
assert( ins->operands[0]->n.class == N_REGISTER );
assert( ins->operands[1]->n.class == N_REGISTER );
assert( ins->result->n.class == N_REGISTER );
function = FindFloatingOpcodes( ins );
reg_index = _OpIsSet( ins->head.opcode ) ? 0 : _NameReg( ins->result );
GenFloatRType( ins->type_class, function, reg_index,
_NameReg( ins->operands[0] ), _NameReg( ins->operands[1] ) );
break;
case G_BINARY:
assert( ins->operands[0]->n.class == N_REGISTER );
assert( ins->operands[1]->n.class == N_REGISTER );
assert( ins->result->n.class == N_REGISTER );
opcodes = FindOpcodes( ins );
switch( ins->head.opcode ) {
case OP_LSHIFT:
case OP_RSHIFT:
// 'sllv', 'srlv' and 'srav' have the operands backwards
GenRType( opcodes[0], opcodes[1], _NameReg( ins->result ),
_NameReg( ins->operands[1] ), _NameReg( ins->operands[0] ) );
break;
case OP_MUL:
GenRType( opcodes[0], opcodes[1], 0, _NameReg( ins->operands[0] ),
_NameReg( ins->operands[1] ) );
// 'mflo rd'
GenRType( 0, 0x12, _NameReg( ins->result ), 0, 0 );
break;
case OP_DIV:
// TODO: do something if divisor is zero
GenRType( opcodes[0], opcodes[1], 0, _NameReg( ins->operands[0] ),
_NameReg( ins->operands[1] ) );
// 'mflo rd'
GenRType( 0, 0x12, _NameReg( ins->result ), 0, 0 );
break;
case OP_MOD:
// TODO: do something if divisor is zero
GenRType( opcodes[0], opcodes[1], 0, _NameReg( ins->operands[0] ),
_NameReg( ins->operands[1] ) );
// 'mfhi rd'
GenRType( 0, 0x10, _NameReg( ins->result ), 0, 0 );
break;
default:
GenRType( opcodes[0], opcodes[1], _NameReg( ins->result ),
_NameReg( ins->operands[0] ), _NameReg( ins->operands[1] ) );
break;
}
break;
case G_BINARY_IMM:
assert( ins->operands[0]->n.class == N_REGISTER );
assert( ins->operands[1]->n.class == N_CONSTANT );
assert( ins->result->n.class == N_REGISTER );
imm_value = ins->operands[1]->c.int_value;
switch( ins->head.opcode ) {
case OP_LSHIFT:
// 'sll rd,rs,n'
GenIShift( 0x00, _NameReg( ins->result ),
_NameReg( ins->operands[0] ), imm_value );
break;
case OP_RSHIFT:
if( _IsSigned( ins->type_class ) ) {
// 'sra rd,rs,n'
GenIShift( 0x03, _NameReg( ins->result ),
_NameReg( ins->operands[0] ), imm_value );
} else {
// 'srl rd,rs,n'
GenIShift( 0x02, _NameReg( ins->result ),
_NameReg( ins->operands[0] ), imm_value );
}
break;
case OP_SUB:
case OP_EXT_SUB:
// Have to flip sign since there's no 'subiu'
imm_value = -imm_value;
// Fall through
default:
opcode = FindImmedOpcode( ins );
GenIType( opcode, _NameReg( ins->result ),
_NameReg( ins->operands[0] ), imm_value );
break;
}
break;
case G_BYTE_CONST:
// TODO: this may not be needed on MIPS (since we can easily load 16-bit const)?
assert( ins->operands[0]->n.class == N_CONSTANT );
assert( ins->result->n.class == N_REGISTER );
// 'addiu rt,$zero,immed'
GenIType( 0x09, _NameReg( ins->result ), MIPS_ZERO_SINK,
(uint_8)ins->operands[0]->c.int_value );
break;
case G_MOVE:
assert( ins->operands[0]->n.class == N_REGISTER );
assert( ins->result->n.class == N_REGISTER );
// 'or rd,rs,$zero'
GenRType( 0x00, 0x25, _NameReg( ins->result ),
_NameReg( ins->operands[0] ), MIPS_ZERO_SINK );
if( TypeClassSize[ins->type_class] == 8 ) {
// Move the odd register, too
// TODO: there should probably be a separate G_MOVE8?
GenRType( 0x00, 0x25, _NameReg( ins->result ) + 1,
_NameReg( ins->operands[0] ) + 1, MIPS_ZERO_SINK );
}
break;
case G_LEA_HIGH:
assert( ins->operands[0]->n.class == N_CONSTANT );
assert( ins->operands[0]->c.const_type == CONS_HIGH_ADDR );
assert( ins->result->n.class == N_REGISTER );
// 'lui rt,immed'
GenIType( 0x0f, _NameReg( ins->result ), MIPS_ZERO_SINK, ins->operands[0]->c.int_value & 0xffff );
break;
case G_LEA:
assert( ins->operands[0]->n.class == N_CONSTANT );
assert( ins->result->n.class == N_REGISTER );
switch( ins->operands[0]->c.const_type ) {
case CONS_ABSOLUTE:
// 'addiu rt,$zero,immed'
GenIType( 0x09, _NameReg( ins->result ), MIPS_ZERO_SINK, ins->operands[0]->c.int_value );
break;
case CONS_LOW_ADDR:
case CONS_HIGH_ADDR:
case CONS_OFFSET:
case CONS_ADDRESS:
_Zoiks( ZOIKS_028 );
break;
}
break;
case G_LOAD_ADDR:
switch( ins->operands[0]->n.class ) {
case N_INDEXED:
case N_TEMP:
assert( ins->result->n.class == N_REGISTER );
getMemEncoding( ins->operands[0], &mem_index, &mem_offset );
// 'addiu rt,rs,immed'
GenIType( 0x09, _NameReg( ins->result ), mem_index, mem_offset );
break;
case N_MEMORY:
assert( ins->result->n.class == N_REGISTER );
FactorInt32( ins->operands[0]->v.offset, &high, &extra, &low );
if( extra != 0 ) {
_Zoiks( ZOIKS_132 );
}
if( !encodeThreadDataRef( ins ) ) {
// 'lui rt,immed'
GenMEMINSRELOC( 0x0f, _NameReg( ins->result ), MIPS_ZERO_SINK, high,
symLabel( ins->operands[0] ), OWL_RELOC_HALF_HI );
// 'addiu rt,rs,immed'
GenMEMINSRELOC( 0x09, _NameReg( ins->result ), _NameReg( ins->result ), low,
symLabel( ins->operands[0] ), OWL_RELOC_HALF_LO );
}
break;
default:
_Zoiks( ZOIKS_078 );
}
break;
case G_MOVE_UI:
// a load of an unsigned 16-bit immediate
// 'ori rt,rs,immed'
GenIType( 0x0d, _NameReg( ins->result ), MIPS_ZERO_SINK, ins->operands[0]->c.int_value );
break;
case G_LOAD_UA:
doLoadStoreUnaligned( ins, TRUE );
break;
case G_LOAD:
doLoadStore( ins, TRUE );
break;
case G_STORE_UA:
doLoadStoreUnaligned( ins, FALSE );
break;
case G_STORE:
doLoadStore( ins, FALSE );
break;
case G_CVTTQ:
_Zoiks( ZOIKS_028 );
break;
case G_DEBUG:
EmitDbgInfo( ins );
break;
case G_CONDBR:
GenCondJump( ins );
break;
case G_NO:
return;
case G_UNKNOWN:
_Zoiks( ZOIKS_097 );
break;
default:
_Zoiks( ZOIKS_028 );
}
if( _IsTargetModel( ASM_OUTPUT ) ) {
DumpString( " " );
DumpGen( ins->u.gen_table );
DumpString( " - " );
DumpInsOnly( ins );
DumpNL();
}
}
extern void GenObjCode( instruction *ins )
/*****************************************/
{
_AlignmentCheck( ins, 4 );
Encode( ins );
}
extern void GenLabelReturn( void )
/*******************************/
{
GenRET();
}
extern byte ReverseCondition( byte cond )
/****************************************/
{
return( FlipOpcode( cond ) );
}
extern byte CondCode( instruction *ins )
/***************************************/
{
return( ins->head.opcode );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?