ppcenc.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 973 行 · 第 1/3 页

C
973
字号

    code = code;
    sym = ins->operands[CALL_OP_ADDR]->v.symbol;
    code = FEAuxInfo( sym, CALL_BYTES );
    if( code != NULL ) {
        ObjBytes( code->data, code->length );
    } else {
        lbl = symLabel( ins->operands[CALL_OP_ADDR] );
        lbl = GetWeirdPPCDotDotLabel( lbl );
        GenBRANCH( 18, lbl, TRUE, FALSE );
        encoding = 0x60000000;  // ..znop for linker thunk
        OutReloc( lbl, PPC_RELOC_GLUE, 0 );
        ObjBytes( (char *)&encoding, sizeof( ppc_ins ) );
    }
}


static  void    getMemEncoding( name *mem, reg_index *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 );
        *index = RegTrans( mem->i.index->r.reg );
        *offset = (int_16)mem->i.constant;
        break;
    case N_TEMP:
        *index = RegTrans( FrameReg() );
        *offset = TempLocation( mem );
        break;
    case N_MEMORY:
    default:
        *index = ZERO_SINK;
        *offset = 0;
        _Zoiks( ZOIKS_119 );
        break;
    }
}


static  opcode  loadOpcodes[] = {
    34,                 /* U1 */
    34,                 /* I1 */
    40,                 /* U2 */
    42,                 /* I2 */
    32,                 /* U4 */
    32,                 /* I4 */
    00,                 /* U8 */
    00,                 /* I8 */
    32,                 /* CP */
    32,                 /* PT */
    48,                 /* FS */
    50,                 /* FD */
    50,                 /* FL */
};

static  opcode  storeOpcodes[] = {
    38,                 /* U1 */
    38,                 /* I1 */
    44,                 /* U2 */
    44,                 /* I2 */
    36,                 /* U4 */
    36,                 /* I4 */
    00,                 /* U8 */
    00,                 /* I8 */
    36,                 /* CP */
    36,                 /* PT */
    52,                 /* FS */
    54,                 /* FD */
    54,                 /* FL */
};


static  void    doLoadStore( instruction *ins, bool load )
/********************************************************/
{
    name        *mem;
    name        *reg;
    opcode      op;
    reg_index   index;
    int_16      offset;

    if( load ) {
        mem = ins->operands[0];
        reg = ins->result;
        op = loadOpcodes[ins->type_class];
    } else {
        reg = ins->operands[0];
        mem = ins->result;
        op = storeOpcodes[ins->type_class];
    }
    assert( op != 0 );
    assert( reg->n.class == N_REGISTER );
    getMemEncoding( mem, &index, &offset );
    GenMEMINS( op, RegTrans( reg->r.reg ), index, offset );
}


static  void    doSign( instruction *ins )
/****************************************/
{
    switch( ins->base_type_class ) {
    case U1:
    case I1:
        // extsb
        GenOPINS( 31, 954, _NameReg( ins->result ), 0, _NameReg( ins->operands[0] ) );
        break;
    case U2:
    case I2:
        // extsh
        GenOPINS( 31, 922, _NameReg( ins->result ), 0, _NameReg( ins->operands[0] ) );
        break;
    default:
        _Zoiks( ZOIKS_091 );
    }
}


static  void    doZero( instruction *ins )
/****************************************/
{
    switch( ins->base_type_class ) {
    case U1:
    case I1:
        // andi op1,0x00ff -> res
        GenOPIMM( 28, _NameReg( ins->operands[0] ), _NameReg( ins->result ), 0x00ff );
        break;
    case U2:
    case I2:
        // andi op1,0xffff -> res
        GenOPIMM( 28, _NameReg( ins->operands[0] ), _NameReg( ins->result ), 0xffff );
        break;
    default:
        _Zoiks( ZOIKS_091 );
    }
}


static  void    GenCallIndirect( instruction *call )
/**************************************************/
{
    reg_index   src;
    reg_index   reg;
    reg_index   mem_index;
    int_16      mem_offset;
    name        *addr;
    opcode      ldw;
    opcode      stw;

    reg = VOLATILE_REG; /* use the volatile scratch reg if possible */
    src = VOLATILE_REG;
    addr = call->operands[CALL_OP_ADDR];
    ldw = loadOpcodes[U4];
    stw = storeOpcodes[U4];
    GenMEMINS( stw, TOC_REG, STACK_REG, 4 );
    switch( addr->n.class ) {
    case N_REGISTER:
        src = _NameReg( addr );
        break;
    case N_TEMP:
    case N_INDEXED:
        getMemEncoding( addr, &mem_index, &mem_offset );
        GenMEMINS( ldw, src, mem_index, mem_offset );
        break;
    }
    GenMEMINS( ldw, TOC_REG, src, 4 );  // careful - src, reg could be same reg
    GenMEMINS( ldw, reg, src, 0 );
    GenMTSPR( reg, SPR_CTR, FALSE );
    GenRAWINS( 0x4e9e0421 );
    GenMEMINS( ldw, TOC_REG, STACK_REG, 4 );
}


static  void    GenVaStart( instruction *ins )
/********************************************/
{
    opcode      stb;
    opcode      stw;
    opcode      li;
    reg_index   reg;
    reg_index   tmp;
    reg_index   stack;

    assert( ins->operands[0]->n.class == N_REGISTER );
    reg = _NameReg( ins->operands[0] );
    tmp = VOLATILE_REG;
    stack = RegTrans( FrameReg() );
    stb = storeOpcodes[U1];
    stw = storeOpcodes[U4];
    li = 14;    // addi
    GenOPIMM( li, tmp, ZERO_SINK, CurrProc->state.parm.gr );
    GenMEMINS( stb, tmp, reg, 0 );
    GenOPIMM( li, tmp, ZERO_SINK, CurrProc->state.parm.fr );
    GenMEMINS( stb, tmp, reg, 1 );
    GenOPIMM( li, tmp, stack, CurrProc->state.parm.offset + CurrProc->targ.frame_size + STACK_HEADER_SIZE );
    GenMEMINS( stw, tmp, reg, 4 );
    GenOPIMM( li, tmp, stack, CurrProc->targ.stack_map.saved_regs.start );
    GenMEMINS( stw, tmp, reg, 8 );
}


static  void    DbgBlkInfo( instruction *ins )
/********************************************/
{
    offset lc;

    lc = AskLocation();
    if( ins->flags.nop_flags & NOP_DBGINFO_START ) {
        DbgBlkBeg( (dbg_block *)ins->operands[0], lc );
    } else {
        DbgBlkEnd( (dbg_block *)ins->operands[0], lc );
    }
}


extern  void    GenRET( void )
/****************************/
{
   ppc_ins      encoding;

   encoding = 0x4e800020;       // FIXME - need linkage docs
   _Emit( encoding );
}


static  void    Encode( instruction *ins )
/****************************************/
{
    reg_index           a;      // usually used for the result
    reg_index           b;
    reg_index           s;
    reg_index           temp;
    opcode              op1;
    opcode              op2;
    opcode              *ops;
    signed_16           mem_offset;
    reg_index           mem_index;


    switch( ins->u.gen_table->generate ) {
    case G_MOVE_FP:
        assert( ins->result->n.class == N_REGISTER );
        assert( ins->operands[0]->n.class == N_REGISTER );
        GenOPINS( 63, 72, 0, _NameReg( ins->operands[0] ), _NameReg( ins->result ) );
        break;
    case G_MOVE:
        // or op, op -> dst
        assert( ins->result->n.class == N_REGISTER );
        assert( ins->operands[0]->n.class == N_REGISTER );
        b = _NameReg( ins->operands[0] );
        GenOPINS( 31, 444, _NameReg( ins->result ), b, b );
        break;
    case G_LOAD:
    case G_STORE:
        doLoadStore( ins, ins->u.gen_table->generate == G_LOAD );
        break;
    case G_CALL:
        doCall( ins );
        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 );
        /* addis k(r0) -> rn */
        GenOPIMM( 15, _NameReg( ins->result ), ZERO_SINK, ins->operands[0]->c.int_value & 0xffff );
        break;
    case G_MOVE_UI:
        /* a load of an unsigned 16-bit immediate */
        /* use or rd, imm(r0) */
        GenOPIMM( 24, _NameReg( ins->result ), ZERO_SINK, ins->operands[0]->c.int_value );
        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:
            // addi rd, imm(r0)
            GenOPIMM( 14, _NameReg( ins->result ), 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 );
            // addi rd,off(ri|sp)
            GenOPIMM( 14, _NameReg( ins->result ), mem_index, mem_offset );
            break;
        case N_MEMORY:
            assert( ins->result->n.class == N_REGISTER );
            OutReloc( symLabel( ins->operands[0] ), PPC_RELOC_TOC_OFFSET, 2 );
            GenMEMINS( 32, _NameReg( ins->result ), TOC_REG, 0 );
            break;
        default:
            _Zoiks( ZOIKS_119 );
        }
        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 );
        if( ins->head.opcode == OP_MUL ) {
            ops = FindOpcodes( ins );
            GenFPOPINS( ops[0], ops[1],
                        _NameReg( ins->operands[0] ),
                        _NameReg( ins->operands[1] ),
                        _NameReg( ins->result ) );
            break;
        }
        /* fall through */
    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 );

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?