mipsfmt.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,508 行 · 第 1/4 页
C
1,508 行
RegIndex( op1->reg ), op2, op2->constant, reloc );
}
static void ITRegJump( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//********************************************************************************************
{
int targ_idx;
int retn_idx;
assert( ins->num_operands < 3 );
if( ins->num_operands == 2 ) {
targ_idx = RegIndex( ins->operands[1]->reg );
retn_idx = RegIndex( ins->operands[0]->reg );
} else {
targ_idx = RegIndex( ins->operands[0]->reg );
if( table->funccode & 1 )
retn_idx = MIPS_RETURN_ADDR; // jalr
else
retn_idx = 0; // jr
}
doOpcodeRType( buffer, table->opcode, table->funccode,
retn_idx, targ_idx, 0 );
numExtendedIns += doDelaySlotNOP( buffer );
return;
}
static void ITJump( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//*****************************************************************************************
{
ins_operand *op0, *op1;
ins_opcount num_op;
bool link;
// 'j' and 'jal' may both be used with the jump target given as either
// an expression or a GPR; this means the instructions will end up being
// encoded as j/jal or jr/jalr depending on operands.
num_op = ins->num_operands;
link = table->opcode & 1;
// First check if the operands are of the right types
if( !jmpOperandsValidate( ins, num_op, link ) )
return;
op0 = ins->operands[0];
if( op0->type == OP_IMMED ) { // real j/jal (to absolute address)
doAbsJump( buffer, table, op0, reloc );
} else if( num_op == 1 ) {
if( link ) { // jalr $ra,rs
if( op0->reg == MIPS_RETURN_ADDR ) {
// TODO: warn - non-restartable instruction
}
doOpcodeRType( buffer, 0, FNCCODE_JALR, RegIndex( MIPS_RETURN_ADDR ),
RegIndex( op0->reg ), 0 );
} else { // jr rs
doOpcodeRType( buffer, 0, FNCCODE_JR, 0, RegIndex( op0->reg ), 0 );
}
} else { // jalr rd,rs
op1 = ins->operands[1];
if( op0->reg == op0->reg ) {
// TODO: warn - non-restartable instruction
}
doOpcodeRType( buffer, 0, FNCCODE_JALR, RegIndex( op1->reg ),
RegIndex( op0->reg ), 0 );
}
numExtendedIns += doDelaySlotNOP( buffer );
return;
}
static bool retOperandsValidate( instruction *ins, ins_opcount num_op )
//*********************************************************************
// Can be used by ret, jsr_coroutine
{
static op_type verify1[][3] = { { OP_GPR, OP_NOTHING, OP_NOTHING },
{ OP_IMMED, OP_NOTHING, OP_NOTHING } };
static op_type verify2[][3] = { { OP_GPR, OP_REG_INDIRECT, OP_NOTHING },
{ OP_GPR, OP_IMMED, OP_NOTHING },
{ OP_REG_INDIRECT, OP_IMMED, OP_NOTHING }};
static op_type verify3[][3] = { { OP_GPR, OP_REG_INDIRECT, OP_IMMED } };
ot_array *verify;
ot_array *verify_table[3] = { &verify1, &verify2, &verify3 };
unsigned num_var;
if( num_op == 0 ) return( TRUE );
assert( num_op <= 3 );
verify = verify_table[num_op - 1];
if( num_op == 1 ) {
num_var = sizeof( verify1 ) / sizeof( **verify1 ) / 3;
} else if( num_op == 2 ) {
num_var = sizeof( verify2 ) / sizeof( **verify2 ) / 3;
} else {
num_var = sizeof( verify3 ) / sizeof( **verify3 ) / 3;
}
assert( num_var <= MAX_VARIETIES );
return( opValidate( verify, ins, num_op, num_var ) );
}
static void ITRet( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//****************************************************************************************
// Both ret and jsr coroutine use this
{
ins_operand *op0, *op1;
ins_opcount num_op;
uint_8 d_reg_idx; // default d_reg if not specified
num_op = ins->num_operands;
// First check if the operands are of the right types
if( !retOperandsValidate( ins, num_op ) ) return;
if( num_op == 3 ) {
stdMemJump( table, ins, buffer, reloc );
return;
}
if( table->funccode == 0x0003 ) { // jsr_coroutine
// This is according to the MS asaxp documentation.
d_reg_idx = MIPS_RETURN_ADDR;
} else {
assert( table->funccode == 0x0002 ); // ret
d_reg_idx = 31; // $zero
}
if( num_op == 2 ) {
if( (op0 = ins->operands[0])->type == OP_GPR ) {
if( (op1 = ins->operands[1])->type == OP_REG_INDIRECT ) {
doMemJump( buffer, table, RegIndex( op0->reg ),
RegIndex( op1->reg ), NULL, 1, reloc );
return;
}
assert( op1->type == OP_IMMED );
doMemJump( buffer, table, RegIndex( op0->reg ), MIPS_RETURN_ADDR,
op1, op1->constant, reloc );
return;
}
assert( op0->type == OP_REG_INDIRECT );
op1 = ins->operands[1];
assert( op1->type == OP_IMMED );
doMemJump( buffer, table, d_reg_idx, RegIndex( op0->reg ),
op1, op1->constant, reloc );
return;
}
if( num_op == 1 ) {
if( (op0 = ins->operands[0])->type == OP_GPR ) {
doMemJump( buffer, table, RegIndex( op0->reg ), MIPS_RETURN_ADDR,
NULL, 1, reloc );
return;
}
assert( op0->type == OP_IMMED );
doMemJump( buffer, table, d_reg_idx, MIPS_RETURN_ADDR,
op0, op0->constant, reloc );
return;
}
assert( num_op == 0 );
doMemJump( buffer, table, d_reg_idx, MIPS_RETURN_ADDR, NULL, 1, reloc );
}
static void ITMemNone( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//********************************************************************************************
{
assert( ins->num_operands == 0 );
reloc = reloc;
doOpcodeRsRt( buffer, table->opcode, 31, 31, _Mem_Func( table->funccode ) );
}
static void ITBranch( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//*******************************************************************************************
{
ins_operand *op;
assert( ins->num_operands == 2 );
op = ins->operands[1];
doOpcodeRsRt( buffer, table->opcode, RegIndex( ins->operands[0]->reg ), 0,
_Immed( _Longword_offset( op->constant ) ) );
doReloc( reloc, op, OWL_RELOC_BRANCH_REL, buffer );
numExtendedIns += doDelaySlotNOP( buffer );
}
static void ITBranchTwo( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//**********************************************************************************************
{
ins_operand *op;
assert( ins->num_operands == 3 );
op = ins->operands[2];
doOpcodeIType( buffer, table->opcode, RegIndex( ins->operands[1]->reg ),
RegIndex( ins->operands[0]->reg ),
_Immed( _Longword_offset( op->constant ) ) );
doReloc( reloc, op, OWL_RELOC_BRANCH_REL, buffer );
numExtendedIns += doDelaySlotNOP( buffer );
}
static void ITBranchZero( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//***********************************************************************************************
{
ins_operand *op;
assert( ins->num_operands == 2 );
op = ins->operands[1];
doOpcodeIType( buffer, table->opcode, table->funccode,
RegIndex( ins->operands[0]->reg ),
_Immed( _Longword_offset( op->constant ) ) );
doReloc( reloc, op, OWL_RELOC_BRANCH_REL, buffer );
numExtendedIns += doDelaySlotNOP( buffer );
}
static void ITBranchCop( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//**********************************************************************************************
{
ins_operand *op;
uint_32 opcode;
assert( ins->num_operands == 1 );
opcode = cop_codes[table->opcode >> 8];
op = ins->operands[0];
doOpcodeIType( buffer, opcode, table->funccode, table->opcode & 0xff,
_Immed( _Longword_offset( op->constant ) ) );
doReloc( reloc, op, OWL_RELOC_BRANCH_REL, buffer );
numExtendedIns += doDelaySlotNOP( buffer );
}
static void ITCop0Spc( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//********************************************************************************************
{
uint_32 opcode;
assert( ins->num_operands == 0 );
opcode = cop_codes[0];
doOpcodeCopOp( buffer, opcode, table->opcode, 0 );
}
static void ITOperate( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//********************************************************************************************
{
assert( ins->num_operands == 3 );
reloc = reloc;
doOpcodeRType( buffer, table->opcode, table->funccode,
RegIndex( ins->operands[0]->reg ),
RegIndex( ins->operands[1]->reg ),
RegIndex( ins->operands[2]->reg ) );
}
static void ITMulDiv( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//*******************************************************************************************
{
assert( ins->num_operands == 2 );
reloc = reloc;
doOpcodeRType( buffer, table->opcode, table->funccode, 0,
RegIndex( ins->operands[0]->reg ),
RegIndex( ins->operands[1]->reg ) );
}
static void ITMovFromSpc( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//***********************************************************************************************
{
assert( ins->num_operands == 1 );
reloc = reloc;
doOpcodeRType( buffer, table->opcode, table->funccode,
RegIndex( ins->operands[0]->reg ), 0, 0 );
}
static void ITMovToSpc( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//*********************************************************************************************
{
assert( ins->num_operands == 1 );
reloc = reloc;
doOpcodeRType( buffer, table->opcode, table->funccode, 0,
RegIndex( ins->operands[0]->reg ), 0 );
}
static void ITMovCop( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//*******************************************************************************************
{
assert( ins->num_operands == 2 );
reloc = reloc;
doOpcodeRType( buffer, table->opcode, 0, RegIndex( ins->operands[1]->reg ),
table->funccode, RegIndex( ins->operands[0]->reg ) );
}
static void ITOperateImm( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//***********************************************************************************************
{
ins_operand *op;
assert( ins->num_operands == 3 );
reloc = reloc;
op = ins->operands[2];
ensureOpAbsolute( op, 2 );
doOpcodeFcRsRtImm( buffer, table->opcode, table->funccode,
RegIndex( ins->operands[1]->reg ),
RegIndex( ins->operands[0]->reg ), op->constant );
}
static void ITShiftImm( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//*********************************************************************************************
{
ins_operand *op;
assert( ins->num_operands == 3 );
reloc = reloc;
op = ins->operands[2];
doOpcodeFcRdRtSa( buffer, table->opcode, table->funccode,
RegIndex( ins->operands[0]->reg ),
RegIndex( ins->operands[1]->reg ), op->constant );
}
static void ITFPOperate( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//**********************************************************************************************
{
ins_funccode fc;
assert( ins->num_operands == 3 );
reloc = reloc;
fc = getFuncCode( table, ins );
doFPInst( buffer, table->opcode, RegIndex( ins->operands[0]->reg ),
RegIndex( ins->operands[1]->reg ),
RegIndex( ins->operands[2]->reg ), fc );
}
static void ITFPConvert( 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 ITBr( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
//***************************************************************************************
{
ins_operand *op0, *op1;
assert( ins->num_operands == 1 || ins->num_operands == 2 );
op0 = ins->operands[0];
if( ins->num_operands == 1 ) {
if( op0->type != OP_IMMED ) {
Error( IMPROPER_OPERAND, 0 );
return;
}
doOpcodeRsRt( buffer, table->opcode, 31, 0,
_Immed( _Longword_offset( op0->constant ) ) );
doReloc( reloc, op0, OWL_RELOC_BRANCH_REL, buffer );
return;
}
// num_operands == 2
op1 = ins->operands[1];
if( op0->type != OP_GPR ) {
Error( IMPROPER_OPERAND, 0 );
return;
}
if( op1->type != OP_IMMED ) {
Error( IMPROPER_OPERAND, 1 );
return;
}
ITBranch( table, ins, buffer, reloc );
}
static void ITMTMFFpcr( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?