alphafmt.c

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

C
1,226
字号
    }
    low = ( c & 0xffff );
    tmp = c - (int_32)low;
    high[0] = ( ( tmp & 0xffff0000 ) >> 16 );
    if( c >= 0x7fff8000 ) {
        // if c is in range 0x7FFF8000..0x7FFFFFFF, tmp = 0x80000000
        // => high[0] = 0x8000 => negative! So we need to split high[0]
        // up to high[0] + high[1] and load them up in different LDAH's.
        high[1] = 0x4000;
        tmp -= 0x40000000;
        high[0] = ( ( tmp & 0xffff0000 ) >> 16 );
    } else {
        high[1] = 0;
    }
    for( ctr = 0; ctr < 2; ctr++ ) {
        if( high[ctr] != 0 ) {
            base_reg = ( ctr == 0 ? s_reg : d_reg );
            doOpcodeRaRb( buffer, OPCODE_LDAH,
                          d_reg, base_reg, _Memory_disp( high[ctr] ) );
            if( reloc && !hi_reloc_emitted ) {
                type = relocType( op->reloc.type, OWL_RELOC_HALF_HI );
                if( type == OWL_RELOC_HALF_HI ) {
                    doReloc( reloc, op, OWL_RELOC_HALF_HI, buffer );
                    hi_reloc_emitted = TRUE; // only need to generate h^ once
                } else {
                    assert( type == OWL_RELOC_HALF_LO );
                    // a l^ modifier was specified explicitly
                    // Do the reloc at the end (lda)
                    // Doing it in ldah will be wrong.
                }
            }
            ++ret;
            ++buffer;
        }
    }
    if( !hi_reloc_emitted && force_pair ) { // no LDAH has been generated yet
        // force_pair => no modifier should've been specified
        // We are asked to force one, so here
        doOpcodeRaRb( buffer, OPCODE_LDAH, d_reg, s_reg,
                      _Memory_disp( 0 ) );
        doReloc( reloc, op, OWL_RELOC_HALF_HI, buffer );
        ++buffer;
        ++ret;
    }
    base_reg = ( ret == 1 ? s_reg : d_reg );
    doOpcodeRaRb( buffer, OPCODE_LDA, d_reg, base_reg,
                  _Memory_disp( low ) );
    if( reloc ) {
        doReloc( reloc, op, OWL_RELOC_HALF_LO, buffer );
    }
    return( ret );
}

#if 0
static unsigned forceLoadAddressComplete( uint_8 d_reg, uint_8 s_reg, ins_operand *op, uint_32 *buffer, asm_reloc *reloc ) {
//***********************************************************************************************************************

    /* Generate:
        LDAH    $d_reg, h^foo($s_reg)
        LDA     $d_reg, l^foo+c($d_reg)
       store them in buffer[0], buffer[1]
    */
    doOpcodeRaRb( buffer, OPCODE_LDAH, d_reg, s_reg,
                  _Memory_disp( 0 ) );
    doReloc( reloc, op, OWL_RELOC_HALF_HI, buffer );
    buffer++;
    doOpcodeRaRb( buffer, OPCODE_LDA, d_reg, d_reg,
                  _Memory_disp( op->constant ) );
    doReloc( reloc, op, OWL_RELOC_HALF_LO, buffer );
    return( 2 );
}
#endif


static unsigned load32BitLiteral( uint_32 *buffer, ins_operand *op0, ins_operand *op1, domov_option m_opt ) {
//***********************************************************************************************************

    op_const        val;

    if( m_opt == DOMOV_ABS ) {
        val = abs( op0->constant );
    } else {
        val = op0->constant;
    }
    return( ldaConst32( buffer, RegIndex( op1->reg ), ZERO_REG_IDX,
                        op0, val, NULL, FALSE ) );
}

static void doMov( uint_32 *buffer, ins_operand *operands[], domov_option m_opt ) {
//*********************************************************************************

    ins_operand     *op0, *op1;
    uint_32         extra;
    uint_32         abs_val;
    bool            ready = TRUE;

    op0 = operands[0];
    op1 = operands[1];
    if( op0->type == OP_GPR ) {
        extra = _Rb( RegIndex( op0->reg ) );
    } else if( ( op0->constant & 0xff ) == op0->constant ) { // OP_IMMED implied
        extra = _LIT( op0->constant ); // this lit is between 0..255
        (void)ensureOpAbsolute( op0, 0 );
    } else if( m_opt == DOMOV_ABS &&
               ( ( ( abs_val = abs( op0->constant ) ) & 0xff ) == abs_val ) ) {
        extra = _LIT( abs_val ); // this lit is between 0..255
        // ensureOpAbsolute( op0, 0 );  should be done before calling doMov
    } else {
        ready = FALSE;
    }
    if( ready ) {
        doOpcodeFcRaRc( buffer, OPCODE_BIS, FUNCCODE_BIS,
                        ZERO_REG_IDX, RegIndex( op1->reg ), extra );
        return;
    }
    // Otherwise it's OP_IMMED with a greater than 8-bit literal.
    // We'll then use multiple LDA, LDAH instructions to load the literal.
    if( !ensureOpAbsolute( op0, 0 ) ) return;
    numExtendedIns += load32BitLiteral( buffer, op0, op1, m_opt ) - 1;
}

static void ITLoadAddress( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc ) {
//**************************************************************************************************

    ins_operand         *op;
    ins_operand         *ops[2];
    unsigned            inc;
    op_const            val;
    uint_8              s_reg;

    assert( ins->num_operands == 2 );
    assert( table->opcode == OPCODE_LDA );
    op = ins->operands[1];
    // If op is IMMED foo, it's actually REG_INDIRECT that we want: foo($zero)
    if( op->type == OP_IMMED ) {
        op->type = OP_REG_INDIRECT;
        op->reg = ZERO_REG;
    }
    assert( op->type == OP_REG_INDIRECT );
    val = op->constant;
    s_reg = RegIndex( op->reg );
    if( !OP_HAS_RELOC( op ) && s_reg == ZERO_REG_IDX ) {
        // doMov() can only be called when op->reg is ZERO_REG and no reloc
        ops[0] = op;
        ops[1] = ins->operands[0];
        doMov( buffer, ops, DOMOV_ORIGINAL );
        return;
    }
    if( OP_HAS_RELOC( op ) ) {
        #ifndef _STANDALONE_
        if( OP_RELOC_NAMED( op ) ) {
            char        *name;

            name = SymName( op->reloc.target.ptr );
            if( AsmQueryExternal( name ) == SYM_STACK ) {
                doAutoVar( reloc, op->reloc.target, buffer, table, ins );
                return;
            }
        }
        #endif
        if( op->reloc.type == ASM_RELOC_UNSPECIFIED ) {
            // Then we should emit LDA-LDAH pair.
            inc = ldaConst32( buffer, RegIndex( ins->operands[0]->reg ),
                              s_reg, op, op->constant, reloc, TRUE );
            numExtendedIns += inc - 1;
            return;
        }
    }
    inc = ldaConst32( buffer, RegIndex( ins->operands[0]->reg ), s_reg, op,
                      op->constant, reloc, FALSE );
    numExtendedIns += inc - 1;
/*
    doOpcodeRaRb( buffer, table->opcode, RegIndex( ins->operands[0]->reg ),
                  s_reg, _Memory_disp( val ) );
    doReloc( reloc, op, OWL_RELOC_HALF_LO, buffer );*/
}

#if 0
static void ITMemLDAH( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc ) {
//**********************************************************************************************

    ins_operand *op;

    assert( table->opcode == OPCODE_LDAH );
    op = ins->operands[1];
    // If op is IMMED foo, it's actually REG_INDIRECT that we want: foo($zero)
    if( op->type == OP_IMMED ) {
        op->type = OP_REG_INDIRECT;
        op->reg = ZERO_REG;
    }
    assert( op->type == OP_REG_INDIRECT );
    doOpcodeRaRb( buffer, table->opcode, RegIndex( ins->operands[0]->reg ),
                  RegIndex( op->reg ), _Memory_disp( op->constant ) );
    doReloc( reloc, op, OWL_RELOC_HALF_HI, buffer );
}
#endif

static void ITMemAll( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc ) {
//*********************************************************************************************

    ins_operand     *op;
    owl_reloc_type  type;
    ins_opcode      opcode;

    assert( ins->num_operands == 2 );
    op = ins->operands[1];
    // If op is IMMED foo, it's actually REG_INDIRECT that we want: foo($zero)
    if( op->type == OP_IMMED ) {
        op->type = OP_REG_INDIRECT;
        op->reg = ZERO_REG;
    }
    assert( op->type == OP_REG_INDIRECT );
    #ifndef _STANDALONE_
    if( OP_RELOC_NAMED( op ) ) {
        char    *name;

        name = SymName( op->reloc.target.ptr );
        if( AsmQueryExternal( name ) == SYM_STACK ) {
            doAutoVar( reloc, op->reloc.target, buffer, table, ins );
            return;
        }
    }
    #endif
    opcode = table->opcode;
    doOpcodeRaRb( buffer, opcode, RegIndex( ins->operands[0]->reg ),
                  RegIndex( op->reg ), _Memory_disp( op->constant ) );
    type = ( opcode == OPCODE_LDAH ) ? OWL_RELOC_HALF_HI : OWL_RELOC_HALF_LO;
    doReloc( reloc, op, type, buffer );
}

static void ITMemA( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc ) {
//*******************************************************************************************

    assert( ins->num_operands == 1 );
    reloc = reloc;
    doOpcodeRaRb( buffer, table->opcode, RegIndex( ins->operands[0]->reg ),
                  31, _Mem_Func( table->funccode ) );
}

static void ITMemB( ins_table *table, instruction *ins, uint_32 *buffer, asm_reloc *reloc ) {
//*******************************************************************************************

    assert( ins->num_operands == 1 );
    reloc = reloc;
    doOpcodeRaRb( buffer, table->opcode, 31, RegIndex( ins->operands[0]->reg ),
                  _Mem_Func( table->funccode ) );
}

static void doMemJump( uint_32 *buffer, ins_table *table, uint_8 ra, uint_8 rb, ins_operand *addr_op, uint_32 hint, asm_reloc *reloc ) {
//**************************************************************************************************************************************

    // Note that addr_op maybe NULL. If not, addr_op->constant == hint.
    assert( addr_op == NULL || addr_op->constant == hint );
    assert( addr_op == NULL || addr_op->type == OP_IMMED );
    doOpcodeRaRb( buffer, table->opcode, ra, rb,
                  (table->funccode << 14) | _FourteenBits(hint) );
    doReloc( reloc, addr_op, OWL_RELOC_JUMP_REL, buffer );
}

static void opError( instruction *ins, op_type actual, op_type wanted, int i ) {
//******************************************************************************
// Stuff out an error message.

    ins = ins;
    actual = actual;
    wanted = wanted;    // it's a set of flags
    if( ( wanted & OP_NOTHING ) != OP_NOTHING ) {
        Error( OPERAND_INCORRECT, i );
    } else {
        Error( OPERAND_UNEXPECTED, i );
    }
}

static bool opValidate( ot_array *verify, instruction *ins, ins_opcount num_op, unsigned num_var ) {
//**************************************************************************************************

    int             ctr, var, lasterr;
    op_type         actual, wanted;

    for( var = 0; var < num_var; var++ ) {
        lasterr = -1;
        for( ctr = 0; ctr < num_op; ctr++ ) {
            if( ins->operands[ctr]->type != (*verify)[var][ctr] ) {
                lasterr = ctr;
                actual = ins->operands[ctr]->type;
                wanted = (*verify)[var][ctr];
                break;
            }
        }
        if( lasterr == -1 ) {   // passed
            break;
        }
    }
    if( lasterr != -1 ) {
        opError( ins, actual, wanted, lasterr );
        return( FALSE );
    }
    return( TRUE );
}

static bool jmpOperandsValidate( instruction *ins, ins_opcount num_op ) {
//***********************************************************************
// Used by jmp, jsr

    static op_type  verify1[][3] = { { OP_REG_INDIRECT, OP_NOTHING, OP_NOTHING },
                                     { OP_IMMED, OP_NOTHING, OP_NOTHING } };
    static op_type  verify2[][3] = { { OP_GPR, OP_REG_INDIRECT, OP_NOTHING },

⌨️ 快捷键说明

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