mipsenc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,073 行 · 第 1/3 页
C
1,073 行
{
mips_ins encoding;
encoding = _Opcode( 0 ) | _Rs( 0 ) | _Rt( rt ) | _Rd( rd ) | _Shift( sa ) | _Function( fc );
EmitIns( encoding );
}
extern void GenJType( uint_8 opcode, pointer label )
/***************************************************/
{
mips_ins encoding;
encoding = _Opcode( opcode );
EmitInsReloc( encoding, label, OWL_RELOC_JUMP_ABS );
// TODO: Handle delay slot better
EmitIns( MIPS_NOP );
}
static void GenFloatRType( type_class_def type, uint_8 fnc, uint_8 fd, uint_8 fs, uint_8 ft )
/********************************************************************************************/
{
mips_ins ins;
int fmt;
// Select operand format
if( type == FS ) {
fmt = 0x10;
} else if( type == FD || type == FL ) {
fmt = 0x11;
} else {
assert( 0 );
}
// Opcode is always COP1
ins = _Opcode( 0x11 ) | _FPFormat( fmt ) | _Ft( ft ) | _Fs( fs ) | _Fd( fd ) | _Function( fnc );
EmitIns( ins );
}
#if 0
static uint_8 BranchOpcodes[][2] = {
{ 0x39, 0x31 }, /* OP_CMP_EQUAL */
{ 0x3d, 0x35 }, /* OP_CMP_NOT_EQUAL */
{ 0x3f, 0x37 }, /* OP_CMP_GREATER */
{ 0x3b, 0x33 }, /* OP_CMP_LESS_EQUAL */
{ 0x3a, 0x32 }, /* OP_CMP_LESS */
{ 0x3e, 0x36 }, /* OP_CMP_GREATER_EQUAL */
};
#endif
extern void GenRET( void )
/*************************/
{
oc_ret oc;
oc.op.class = OC_RET;
oc.op.reclen = sizeof( oc_ret );
oc.op.objlen = 4;
oc.pops = FALSE; /* not used */
InputOC( (any_oc *)&oc );
}
static pointer symLabel( name *mem )
/***********************************/
{
return( AskForSymLabel( mem->v.symbol, mem->m.memory_type ) );
}
static uint_8 loadOpcodes[] = {
0x24, /* U1 */
0x20, /* I1 */
0x25, /* U2 */
0x21, /* I2 */
0x23, /* U4 */ // 0x27 for MIPS64
0x23, /* I4 */
0x37, /* U8 */
0x37, /* I8 */
0x23, /* CP */
0x23, /* PT */
0x31, /* FS */
0x35, /* FD */
0x35, /* FL */
};
static uint_8 storeOpcodes[] = {
0x28, /* U1 */
0x28, /* I1 */
0x29, /* U2 */
0x29, /* I2 */
0x2b, /* U4 */
0x2b, /* I4 */
0x3f, /* U8 */
0x3f, /* I8 */
0x2b, /* CP */
0x2b, /* PT */
0x39, /* FS */
0x3d, /* FD */
0x3d, /* FL */
};
extern type_length TempLocation( name *temp )
/********************************************/
{
name *base;
type_length offset;
assert( temp->n.class == N_TEMP );
base = DeAlias( temp );
if( base->t.location == NO_LOCATION ) {
_Zoiks( ZOIKS_030 );
}
offset = CurrProc->targ.stack_map.locals.start;
if( temp->t.temp_flags & STACK_PARM ) {
offset = CurrProc->targ.frame_size;
}
return( offset + base->t.location + temp->v.offset - base->v.offset );
}
extern void GenCallLabelReg( pointer label, uint reg )
/*****************************************************/
{
// This is used for calling into certain cg support routines. We'd
// kinda like to use 'jal', except we must use something other
// than ra for the return address. So 'jalr' it is...
// Load address into $at (lui/addiu)
// TODO: This should be different for PIC
GenMEMINSRELOC( 0x0f, MIPS_GPR_SCRATCH, MIPS_ZERO_SINK, 0,
label, OWL_RELOC_HALF_HI );
GenMEMINSRELOC( 0x09, MIPS_GPR_SCRATCH, MIPS_GPR_SCRATCH, 0,
label, OWL_RELOC_HALF_LO );
// 'jalr reg,$at'
GenRType( 0x00, 0x09, reg, MIPS_GPR_SCRATCH, 0 );
// WARNING! WARNING! WARNING!
// There's no delay slot here. Caller must handle that.
}
extern void GenCallLabel( pointer label )
/****************************************/
{
CodeHandle( OC_CALL, 4, label );
}
static void doCall( instruction *ins )
/*************************************/
{
pointer sym;
risc_byte_seq *code;
code_lbl *lbl;
code = NULL;
sym = ins->operands[CALL_OP_ADDR]->v.symbol;
lbl = symLabel( ins->operands[CALL_OP_ADDR] );
if( !AskIfRTLabel( lbl ) ) {
code = FEAuxInfo( sym, CALL_BYTES );
}
if( code != NULL ) {
ObjEmitSeq( code );
} else {
GenCallLabel( symLabel( ins->operands[CALL_OP_ADDR] ) );
}
}
static void addressTemp( name *temp, uint_8 *reg, int_16 *offset )
/*****************************************************************/
{
type_length temp_offset;
temp_offset = TempLocation( temp );
if( temp_offset > MIPS_MAX_OFFSET ) {
// gen some code to load temp address into SCRATCH_REG
GenLOADS32( temp_offset, MIPS_GPR_SCRATCH );
// 'or $sp,$at,$zero', aka 'move $sp,$at'
GenRType( 0x00, 0x25, MIPS_STACK_REG, MIPS_GPR_SCRATCH, MIPS_ZERO_SINK );
*offset = 0;
*reg = MIPS_GPR_SCRATCH;
} else {
*offset = temp_offset;
*reg = MIPS_STACK_REG;
if( CurrProc->targ.base_is_fp ) {
*reg = MIPS_FRAME_REG;
}
}
}
static void getMemEncoding( name *mem, uint_8 *reg_index, int_16 *offset )
/*************************************************************************/
{
switch( mem->n.class ) {
case N_INDEXED:
assert( mem->i.index->n.class == N_REGISTER );
assert( mem->i.scale == 0 );
assert( mem->i.constant == (type_length)((signed_16)mem->i.constant) );
assert( ( mem->i.index_flags & X_LOW_ADDR_BASE ) == 0 );
*reg_index = _NameReg( mem->i.index );
*offset = (int_16)mem->i.constant;
break;
case N_TEMP:
addressTemp( mem, reg_index, offset );
break;
case N_MEMORY:
default:
*reg_index = MIPS_ZERO_SINK;
*offset = 0;
_Zoiks( ZOIKS_078 );
break;
}
}
static void doLoadStore( instruction *ins, bool load )
/*****************************************************/
{
name *mem;
name *reg;
uint_8 opcode;
uint_8 index;
int_16 offset;
if( load ) {
mem = ins->operands[0];
reg = ins->result;
opcode = loadOpcodes[_OpClass( ins )];
} else {
reg = ins->operands[0];
mem = ins->result;
opcode = storeOpcodes[ins->type_class];
}
assert( reg->n.class == N_REGISTER );
getMemEncoding( mem, &index, &offset );
GenMEMINS( opcode, _NameReg( reg ), index, offset );
}
static void doLoadStoreUnaligned( instruction *ins, bool load )
/**************************************************************/
{
#if 0
name *mem;
name *reg;
uint_8 opcode1;
uint_8 opcode2;
uint_8 index;
int_16 offset;
if( load ) {
mem = ins->operands[0];
reg = ins->result;
// 'lwl', 'lwr'
opcode1 = 0x22; opcode2 = 0x26;
} else {
reg = ins->operands[0];
mem = ins->result;
// 'swl', 'swr'
opcode1 = 0x2a; opcode2 = 0x2e;
}
assert( reg->n.class == N_REGISTER );
getMemEncoding( mem, &index, &offset );
// TODO: make sure offset can't overflow
GenMEMINS( opcode1, _NameReg( reg ), index, offset + 3 );
GenMEMINS( opcode2, _NameReg( reg ), index, offset );
#else
doLoadStore( ins, load );
#endif
}
static void GenCallIndirect( instruction *call )
/***********************************************/
{
uint_8 reg_index;
uint_8 mem_index;
int_16 mem_offset;
name *addr;
reg_index = MIPS_GPR_SCRATCH; /* use the volatile scratch reg if possible */
addr = call->operands[CALL_OP_ADDR];
switch( addr->n.class ) {
case N_REGISTER:
reg_index = _NameReg( addr );
break;
case N_TEMP:
case N_INDEXED:
getMemEncoding( addr, &mem_index, &mem_offset );
GenMEMINS( 0x23, reg_index, mem_index, mem_offset );
break;
}
// 'jalr ra,reg_index'
GenRType( 0x00, 0x09, MIPS_RETURN_ADDR, reg_index, 0 );
// TODO: Handle delay slot better
EmitIns( MIPS_NOP );
}
static void doZero( instruction *ins, type_class_def class )
/***********************************************************/
{
unsigned size;
size = TypeClassSize[class];
switch( size ) {
case 1:
// 'andi res,op1,0x00ff'
GenIType( 0x0c, _NameReg( ins->result ), _NameReg( ins->operands[0] ), 0x00ff );
break;
case 2:
// 'andi res,op1,0xffff'
GenIType( 0x0c, _NameReg( ins->result ), _NameReg( ins->operands[0] ), 0x0ffff );
break;
default:
_Zoiks( ZOIKS_091 );
}
}
static void doSignExtend( instruction *ins, type_class_def from )
/****************************************************************/
{
unsigned from_size;
int res_index;
int src_index;
int shift_amt;
res_index = _NameReg( ins->result );
src_index = _NameReg( ins->operands[0] );
from_size = TypeClassSize[from];
if( from_size == 4 ) {
// 'addu rd,$zero,rs' - MIPS64 only?
GenRType( 0x00, 0x21, res_index, MIPS_ZERO_SINK, src_index );
} else {
// MIPS32 ISA Release 2 has 'seb'/'seh' instructions for this
shift_amt = (REG_SIZE - from_size) * 8;
// 'sll rd,rs,n'
GenIShift( 0x00, res_index, src_index, shift_amt );
// 'sra rd,rs,n'
GenIShift( 0x03, res_index, res_index, shift_amt );
}
}
// This is NT stuff - probably irreleveant unless someone wanted to
// support the MIPS version of NT!
#define RDTEB_ENCODING 0x000000ab
#define RDTEB_MAGIC_CONST 0x2c
#define V0 0
static bool encodeThreadDataRef( instruction *ins )
/*****************************************************/
{
name *op;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?