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