i86enc2.c

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

C
687
字号
            }
            if( first ) {
                LayOpbyte( *p );
                first = FALSE;
            } else {
                AddByte( *p );
            }
            ++p;
        }
        _Emit;
    }
}


extern  void    GenCall( instruction *ins ) {
/********************************************
    Generate a call for "ins". (eg: call foo, or call far ptr foo)
*/

    name                *op;
    sym_handle          sym;
    bool                big;
    oc_class            pop_bit;
    call_class          class;
    byte_seq            *code;
    label_handle        lbl;

    if( ins->flags.call_flags & CALL_INTERRUPT ) {
        Pushf();
    }
    op = ins->operands[ CALL_OP_ADDR ];
    class = *(call_class *)FindAuxInfo( op, CALL_CLASS );
    code = FindAuxInfo( op, CALL_BYTES );
    if( code != NULL ) {
        _Emit;
        if( code->length & DO_FLOATING_FIXUPS ) {
            CodeSequence( code->data, code->length & ~DO_FLOATING_FIXUPS );
        } else {
            CodeBytes( code->data, code->length );
        }
    } else if( ( class & SUICIDAL ) && _IsntTargetModel( NEW_P5_PROFILING ) ) {
        sym = op->v.symbol;
        lbl = FEBack( sym )->lbl;
        if( ( class & FAR ) != EMPTY && ( FEAttr( sym ) & FE_IMPORT ) ) {
            CodeHandle( OC_JMP | ATTR_FAR,
                        OptInsSize( OC_JMP, OC_DEST_FAR ), lbl );
        } else {
            CodeHandle( OC_JMP, OptInsSize( OC_JMP, OC_DEST_NEAR ), lbl );
        }
    } else {
        if( ins->flags.call_flags & CALL_POPS_PARMS ) {
            pop_bit = ATTR_POP;
        } else {
            pop_bit = 0;
        }
        if( class & FAR ) {
            big = TRUE;
        } else {
            big = FALSE;
        }
        sym = op->v.symbol;
        if( op->m.memory_type == CG_FE ) {
            DoCall( FEBack( sym )->lbl,
                  (FEAttr(sym) & (FE_COMMON|FE_IMPORT)) != 0, big, pop_bit );
        } else {
            DoCall( sym, TRUE, big, pop_bit );
        }
    }
}


extern  void    GenICall( instruction *ins ) {
/*********************************************
    Generate an indirect call for "ins" (eg: call dword ptr [eax])
*/

    oc_class    entry;
    unsigned    opcode;

    if( ins->flags.call_flags & CALL_INTERRUPT ) {
        Pushf();
    }
    entry = 0;
    if( ins->flags.call_flags & CALL_POPS_PARMS ) {
        entry |= ATTR_POP;
    }
    if( ( ins->flags.call_flags & CALL_ABORTS ) && _IsntTargetModel( NEW_P5_PROFILING ) ) {
        entry |= OC_JMPI;
    } else {
        entry |= OC_CALLI;
    }
    if( ins->operands[ CALL_OP_ADDR ]->n.name_class == PT
     || ins->operands[ CALL_OP_ADDR ]->n.name_class == CP ) {
        entry |= ATTR_FAR;
        opcode = M_CJILONG;
    } else {
        opcode = M_CJINEAR;
    }
    ReFormat( entry );
    LayOpword( opcode );
    LayModRM( ins->operands[ CALL_OP_ADDR ] );
    _Emit;
}


extern  void    GenRCall( instruction *ins ) {
/*********************************************
    generate a call to a register (eg: call eax)
*/

    name                *op;
    oc_class            pop_bit;

    if( ins->flags.call_flags & CALL_INTERRUPT ) {
        Pushf();
    }
    if( ins->flags.call_flags & CALL_POPS_PARMS ) {
        pop_bit = ATTR_POP;
    } else {
        pop_bit = 0;
    }
    ReFormat( OC_CALLI | pop_bit );
    LayOpword( M_CJINEAR );
    op = ins->operands[ CALL_OP_ADDR ];
    LayRegRM( op->r.reg );
    _Emit;
}


static  void    Pushf( void ) {
/***********************/

    LayOpbyte( 0x9c ); /* PUSHF*/
    _Emit;
    _Code;
}


extern  void    GenSelEntry( bool starts ) {
/*******************************************
    dump a queue that a select table is starting/ending ("starts") into
    the code segment queue.
*/

    oc_select   temp;

    temp.op.class = OC_INFO + INFO_SELECT;
    temp.op.reclen = sizeof( oc_select );
    temp.op.objlen = 0;
    temp.starts = starts;
    InputOC( (any_oc *)&temp );
}


extern  void    Gen1ByteValue( byte value ) {
/********************************************
    drop an 8 bit integer into the queue.
*/

    _Code;
    AddByte( value );
    _Emit;
}


extern  void    Gen2ByteValue( unsigned_16 value ) {
/***************************************************
    drop a 16 bit integer into the queue.
*/

    _Code;
    AddByte( value & 0xFF );
    AddByte( ( value >> 8 ) & 0xFF );
    _Emit;
}


extern  void    Gen4ByteValue( unsigned_32 value ) {
/***************************************************
    drop a 32 bit integer into the queue.
*/

    _Code;
    AddByte( value & 0xFF );
    AddByte( ( value >> 8 ) & 0xFF );
    AddByte( ( value >> 16 ) & 0xFF );
    AddByte( ( value >> 24 ) & 0xFF );
    _Emit;
}


extern  void    GenCodePtr( pointer label ) {
/********************************************
    Dump a near reference to a label into the code segment.
*/

    CodeHandle( OC_LREF, TypeAddress( T_NEAR_CODE_PTR )->length, label );
}


extern  void    GenCallLabel( pointer label ) {
/**********************************************
    generate a call to a label within the procedure (near call)
*/

    DoCall( label, FALSE, FALSE, EMPTY );
}


extern  void    GenLabelReturn( void ) {
/*********************************
    generate a return from CALL_LABEL instruction (near return)
*/

    GenReturn( 0, FALSE, FALSE );
}

extern  void    GenReturn( int pop, bool is_long, bool iret ) {
/**************************************************************
    Generate a return instruction
*/

    oc_ret      oc;

    oc.op.class = OC_RET;
    oc.op.reclen = sizeof( oc_ret );
    oc.op.objlen = 1;
    oc.pops = pop;
    if( pop != 0 ) {
        oc.op.class |= ATTR_POP;
        oc.op.objlen += 2;
    }
    if( is_long ) {
        oc.op.class |= ATTR_FAR;
    }
    if( iret ) {
        oc.op.class |= ATTR_IRET;
    }
    InputOC( (any_oc *)&oc );
}

extern  void    GenMJmp( instruction *ins ) {
/********************************************
    Generate a jump indirect through memory instruction.
*/

    label_handle        lbl;
    name                *base;

    if( ins->head.opcode != OP_SELECT && _IsTargetModel( BIG_CODE ) ) {
        ReFormat( OC_JMPI | ATTR_FAR );
        LayOpword( M_CJILONG );
    } else {
        ReFormat( OC_JMPI );
        LayOpword( M_CJINEAR );
    }
    LayModRM( ins->operands[ 0 ] );
    if( ins->head.opcode == OP_SELECT &&
        ins->operands[ 0 ]->n.class == N_INDEXED ) {
        base = ins->operands[ 0 ]->i.base;
        if( base != NULL ) {
            lbl = AskForSymLabel( base->v.symbol, CG_TBL );
            if( AskAddress( lbl ) != ADDR_UNKNOWN ) {
                TellScrapLabel( lbl );
            }
        }
    }
}

extern  void    GenRJmp( instruction *ins ) {
/********************************************
    Generate a jump to register instruction (eg: jmp eax)
*/

    JumpReg( ins, ins->operands[ 0 ] );
}


static  void    JumpReg( instruction *ins, name *reg_name ) {
/************************************************************
    Generate a jump to register instruction (eg: jmp eax)
*/

    hw_reg_set  regs;

    ins = ins;
    regs = reg_name->r.reg;
    if( reg_name->n.size > WORD_SIZE ) {
        /* fake up intersegment jump*/
        _Code;
        LayOpbyte( M_PUSH );
        LayRegAC( High32Reg( regs ) );
        _Next;
        LayOpbyte( M_PUSH );
        LayRegAC( Low32Reg( regs ) );
        _Emit;
        GenReturn( 0, TRUE, FALSE );
    } else {
        ReFormat( OC_JMPI );
        LayOpword( M_CJINEAR );
        LayRegRM( regs );
        _Emit;
    }
}

static  void    DoCodeBytes( byte *src, byte_seq_len len, oc_class class ) {
/***************************************************************************
    Dump bytes "src" directly into the queue, for length "len".
*/

    oc_entry    *temp;

    _Alloc( temp, sizeof( oc_header ) + MAX_OBJ_LEN );
    temp->class = class;
    temp->objlen = len;
    temp->reclen = sizeof( oc_header ) + len;
    while( len > MAX_OBJ_LEN ) {
        temp->objlen = MAX_OBJ_LEN;
        temp->reclen = sizeof( oc_header  )+ MAX_OBJ_LEN;
        Copy( src, &temp->data[ 0 ], MAX_OBJ_LEN );
        InputOC( (any_oc *)temp );
        src += MAX_OBJ_LEN;
        len -= MAX_OBJ_LEN;
    }
    temp->objlen = len;
    temp->reclen = sizeof( oc_header ) + len;
    Copy( src, &temp->data[ 0 ], len );
    InputOC( (any_oc *)temp );
    _Free( temp, sizeof( oc_header ) + MAX_OBJ_LEN );
}

extern  void    CodeBytes( byte *src, byte_seq_len len ) {
/********************************************************/

    DoCodeBytes( src, len, OC_BDATA );
}

extern  void    EyeCatchBytes( byte *src, uint len ) {
/************************************************/

    DoCodeBytes( src, len, OC_IDATA );
}

⌨️ 快捷键说明

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