i86ver.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 291 行
C
291 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Instruction conditions verification for Intel processors.
*
****************************************************************************/
#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "regset.h"
#include "model.h"
#include "vergen.h"
#include "pattern.h"
#include "cfloat.h"
extern int NumOperands(instruction*);
extern bool OtherVerify(vertype,instruction*,name*,name*,name*);
extern byte OptForSize;
extern bool DoVerify( vertype kind, instruction *ins ) {
/**********************************************************/
name *op1 = NULL;
name *op2 = NULL;
name *result;
result = ins->result;
if( ins->num_operands != 0 ) {
op1 = ins->operands[ 0 ];
if( ins->num_operands != 1 ) {
op2 = ins->operands[ 1 ];
}
}
switch( kind ) {
case V_80186:
if( _CPULevel( CPU_186 ) ) return( TRUE );
break;
case V_80386:
if( _CPULevel( CPU_386 ) ) return( TRUE );
break;
case V_DIFF_TYPES:
if( op1->n.name_class != result->n.name_class ) return( TRUE );
break;
case V_HIGHEQLOW:
if( op1->c.const_type != CONS_ABSOLUTE ) return( FALSE );
if(!CFIsI32( op1->c.value ) && !CFIsU32( op1->c.value )) return(FALSE);
if( ( op1->c.int_value & 0xffff0000 )
== ( op1->c.int_value << 16 ) ) return( TRUE );
break;
case V_OP2HIGH_B_ZERO:
if( op2->c.const_type == CONS_ABSOLUTE
&& ( op2->c.int_value & 0x0000ff00 ) == 0 ) return( TRUE );
break;
case V_OP2LOW_B_FF:
if( op2->c.const_type == CONS_ABSOLUTE
&& ( ~op2->c.int_value & 0x000000ff ) == 0 ) return( TRUE );
break;
case V_OP2LOW_B_ZERO:
if( op2->c.const_type == CONS_ABSOLUTE
&& ( op2->c.int_value & 0x000000ff ) == 0 ) return( TRUE );
break;
case V_OP2LOW_W_FFFF:
if( op2->c.const_type == CONS_ABSOLUTE
&& ( ~op2->c.int_value & 0x0000ffff ) == 0 ) return( TRUE );
break;
case V_LSHONE:
if( !_CPULevel( CPU_286 ) ) return( FALSE );
if( ins->head.opcode != OP_LSHIFT ) return( FALSE );
return( OtherVerify( V_OP2ONE, ins, op1, op2, result ) );
case V_OP2TWO_SIZE:
if( OptForSize <= 50 ) return( FALSE );
return( OtherVerify( V_OP2TWO, ins, op1, op2, result ) );
case V_BYTESHIFT:
if( ins->head.opcode != OP_LSHIFT
&& ins->type_class != U4 ) return( FALSE );
if( op2->c.const_type != CONS_ABSOLUTE ) return( FALSE );
if( op2->c.int_value != 8 ) return( FALSE );
if( op1->n.class == N_REGISTER
&& !HW_CEqual( op1->r.reg, HW_ABCD ) ) return( FALSE );
if( result->n.class == N_REGISTER
&& !HW_CEqual( result->r.reg, HW_ABCD ) ) return( FALSE );
return( TRUE );
case V_CYP2SHIFT:
if( op2->c.const_type != CONS_ABSOLUTE ) return( FALSE );
if( op2->c.int_value != 8 ) return( FALSE );
if( _CPULevel( CPU_186 ) ) return( FALSE );
if( !HW_COvlap( ins->head.live.regs, HW_AX ) ) return( TRUE );
return( FALSE );
case V_CYP4SHIFT:
if( op2->c.const_type != CONS_ABSOLUTE ) return( FALSE );
if( op2->c.int_value < 16 ) return( FALSE );
return( TRUE );
case V_OP2HIGH_B_FF:
if( op2->c.const_type == CONS_ABSOLUTE
&& ( op2->c.int_value & 0x0000ff00 ) == 0x0000ff00 ) return( TRUE );
break;
case V_OP2HIGH_W_FFFF_REG:
if( op1->n.class == N_REGISTER && HW_Ovlap( op1->r.reg, HW_BP ) ) break;
case V_OP2HIGH_W_FFFF:
if( op2->c.const_type == CONS_ABSOLUTE
&& ( op2->c.int_value & 0xffff0000 ) == 0xffff0000 ) return( TRUE );
break;
case V_OP2HIGH_W_ZERO_REG:
if( op1->n.class == N_REGISTER && HW_Ovlap( op1->r.reg, HW_BP ) ) break;
case V_OP2HIGH_W_ZERO:
if( op2->c.const_type == CONS_ABSOLUTE
&& ( op2->c.int_value & 0xffff0000 ) == 0 ) return( TRUE );
break;
case V_OP2LOW_W_ZERO:
if( op2->c.const_type == CONS_ABSOLUTE
&& ( op2->c.int_value & 0x0000ffff ) == 0 ) return( TRUE );
break;
case V_OP2PTR:
if( op2->n.name_class == PT || op2->n.name_class == CP ) return( TRUE );
break;
case V_LEA_GOOD:
if( OptForSize > 50 ) return( FALSE );
/* fall through */
case V_LEA:
if( op2->c.const_type != CONS_ABSOLUTE ) return( FALSE );
switch( ins->head.opcode ) {
#if _TARGET & _TARG_80386
case OP_MUL:
switch( op2->c.int_value ) {
case 3:
case 5:
case 9:
return( TRUE );
}
break;
case OP_LSHIFT:
if( op1 == result && _CPULevel( CPU_586 ) ) return( FALSE );
if( OptForSize >= 50 ) return( FALSE );
switch( op2->c.int_value ) {
case 1:
case 2:
case 3:
return( TRUE );
}
break;
#endif
case OP_ADD:
case OP_SUB:
if( OptForSize < 50 && !_CPULevel( CPU_286 ) ) return( FALSE );
return( TRUE );
default:
break;
}
break;
case V_SIZE:
if( OptForSize > 50 ) return( TRUE );
break;
case V_DIV_BUG: /* cant do idiv from mem on 80186 (or 8086 for compatibility)*/
if( !_CPULevel( CPU_286 )
&& ins->type_class != U1 && ins->type_class != U2 ) return( TRUE );
break;
case V_OP1SP:
if( HW_CEqual( op1->r.reg, HW_SP ) ) return( TRUE );
break;
case V_WORDREG_AVAIL:
if( !HW_COvlap( ins->head.live.regs, HW_AX ) ) return( TRUE );
if( !HW_COvlap( ins->head.live.regs, HW_BX ) ) return( TRUE );
if( !HW_COvlap( ins->head.live.regs, HW_CX ) ) return( TRUE );
if( !HW_COvlap( ins->head.live.regs, HW_DX ) ) return( TRUE );
if( !HW_COvlap( ins->head.live.regs, HW_SI ) ) return( TRUE );
if( !HW_COvlap( ins->head.live.regs, HW_DI ) ) return( TRUE );
break;
case V_AC_BETTER:
if( op2->c.const_type != CONS_ABSOLUTE ) return( TRUE );
if( op2->c.int_value > 127 ) return( TRUE );
if( op2->c.int_value < -128 ) return( TRUE );
break;
case V_OP2POW2_286:
if( !_CPULevel( CPU_286 ) ) return( FALSE );
return( OtherVerify( V_OP2POW2, ins, op1, op2, result ) );
case V_OP1ADDR:
case V_OP1LOC:
if( _IsTargetModel( INDEXED_GLOBALS ) ) return( FALSE );
if( op1->n.class == N_MEMORY ) return( TRUE );
break;
case V_RESLOC:
if( _IsTargetModel( INDEXED_GLOBALS ) ) return( FALSE );
if( result->n.class == N_MEMORY ) return( TRUE );
break;
case V_GOOD_CLR:
if( op1 == result ) return( TRUE );
/* On P6 architecture, 'and' will cause a partial register stall with
* horrible performance implications. Always use movzx.
*/
if( !_CPULevel( CPU_486 ) || _CPULevel( CPU_686 ) ) break;
if( OptForSize > 50 ) break;
if( result->n.class == N_REGISTER ) {
if( HW_Ovlap( result->r.reg, HW_BP ) ) break;
}
return( TRUE );
case V_P5_FXCH:
if( !_CPULevel( CPU_586 ) ) return( FALSE );
if( OptForSize <= 50 ) return( TRUE );
break;
case V_CYP_SEX:
if( !_CPULevel( CPU_586 ) ) return( FALSE );
if( OptForSize > 50 ) return( FALSE );
op1 = ins->operands[0];
{
type_length backup;
type_length new_off;
backup = WORD_SIZE - op1->n.size;
switch( op1->n.class ) {
case N_TEMP:
return( TRUE );
case N_MEMORY:
new_off = op1->v.offset - backup;
if( new_off >= 0 ) return( TRUE );
if( ins->num_operands > NumOperands( ins ) ) return( FALSE );
return( TRUE );
case N_INDEXED:
new_off = op1->i.constant - backup;
if( new_off >= 0 ) return( TRUE );
if( ins->num_operands > NumOperands( ins ) ) return( FALSE );
if( op1->i.base == NULL ) return( FALSE );
return( TRUE );
default:
break;
}
}
break;
case V_NEGATE:
if( ins->head.opcode == OP_NEGATE ) return( TRUE );
break;
case V_CONSTTEMP:
{
int i;
for( i = ins->num_operands-1; i >= 0; --i ) {
op1 = ins->operands[i];
if( op1->n.class == N_TEMP
&& (op1->t.temp_flags & CONST_TEMP ) ) return( TRUE );
}
return( FALSE );
}
case V_SWAP_GOOD_386:
if( !_CPULevel( CPU_386 ) ) return( FALSE );
return( OtherVerify( V_SWAP_GOOD, ins, op1, op2, result ) );
case V_INTCOMP:
if( ins->result != NULL && ins->type_class != FS ) return( FALSE );
if( ins->head.opcode == OP_CMP_EQUAL ) return( TRUE );
if( ins->head.opcode == OP_CMP_NOT_EQUAL ) return( TRUE );
#if _TARGET & _TARG_80386
// rINTCOMP reductions for 16-bit need work to handle < and >
// comparisons - not worth it for now - BBB Apr 24, 1995
if( ins->type_class != FS ) return( FALSE );
if( ins->operands[ 1 ]->n.class == N_CONSTANT &&
ins->operands[ 1 ]->c.const_type == CONS_ABSOLUTE &&
CFTest( ins->operands[ 1 ]->c.value ) > 0 ) return( TRUE );
#endif
return( FALSE );
default:
return( OtherVerify( kind, ins, op1, op2, result ) );
}
return( FALSE );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?