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 + -
显示快捷键?