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