rscsplit.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,383 行 · 第 1/4 页
C
1,383 行
/****************************************************************************
*
* 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: RISC instruction spliting reductions.
*
****************************************************************************/
#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "vergen.h"
#include "tables.h"
#include "pattern.h"
#include "rtclass.h"
#include "system.h"
#include "zoiks.h"
#include "model.h"
#include "regset.h"
#include "cfloat.h"
#include <assert.h>
extern instruction *rMOVRESREG(instruction*);
extern instruction *rSWAPOPS(instruction*);
extern instruction *rDOCVT(instruction*);
extern instruction *rOP1REG(instruction*);
extern instruction *rOP2REG(instruction*);
extern instruction *rMOVOP1TEMP(instruction*);
extern instruction *rMOVOP2TEMP(instruction*);
extern instruction *rMOVRESTEMP(instruction*);
extern instruction *rPUSHTOMOV(instruction*);
extern instruction *rPOPTOMOV(instruction*);
extern instruction *rOP1MEM(instruction*);
extern instruction *rOP2MEM(instruction*);
extern instruction *rCONSTLOAD(instruction*);
extern instruction *rSWAPCMP(instruction*);
extern instruction *rSIMPCMP(instruction*);
extern instruction *rDOSET(instruction*);
extern instruction *rDOLOAD(instruction*);
extern instruction *rDOSTORE(instruction*);
extern instruction *rOP1CMEM(instruction*);
extern instruction *rOP2CMEM(instruction*);
extern instruction *rMAKECALL(instruction*);
extern instruction *rDOTEST(instruction*);
extern instruction *rCHANGETYPE(instruction*);
extern instruction *rMOVEXX(instruction*);
extern instruction *rFORCERESMEM(instruction*);
extern instruction *rMOVEINDEX(instruction*);
extern instruction *rBIN2INT(instruction*);
extern instruction *rBIN2QUAD(instruction*);
extern instruction *rSHR(instruction*);
extern instruction *rLOAD_1(instruction*);
extern instruction *rLOAD_2(instruction*);
extern instruction *rLOAD_2U(instruction*);
extern instruction *rLOAD_4U(instruction*);
extern instruction *rLOAD_8U(instruction*);
extern instruction *rSTORE_1(instruction*);
extern instruction *rSTORE_2(instruction*);
extern instruction *rSTORE_2U(instruction*);
extern instruction *rSTORE_4U(instruction*);
extern instruction *rSTORE_8U(instruction*);
extern instruction *rMOVEXX_8(instruction*);
extern instruction *rMOVEXX_4(instruction*);
extern instruction *rMOD2DIV(instruction*);
extern instruction *rALLOCA(instruction*);
extern instruction *rM_SIMPCMP( instruction * );
extern instruction *rSPLITOP( instruction * );
extern instruction *rSPLITMOVE( instruction * );
extern instruction *rSPLITCMP( instruction * );
extern instruction *rSPLITNEG( instruction * );
extern instruction *rSPLITUNARY( instruction * );
extern instruction *rSEX_4TO8( instruction * );
extern instruction *rCLRHI_4( instruction * );
extern instruction *rMOVELOW( instruction * );
extern hw_reg_set StackReg( void );
extern hw_reg_set ReturnAddrReg( void );
extern hw_reg_set SavedRegs( void );
extern name *AllocMemory(pointer,type_length,cg_class,type_class_def);
extern name *AllocIndex(name*,name*,type_length,type_class_def);
extern name *AllocS32Const(signed_32);
extern name *AllocRegName(hw_reg_set);
extern name *AllocTemp(type_class_def);
extern name *AllocAddrConst(name*,int,constant_class,type_class_def);
extern name *ScaleIndex(name*,name*,type_length,type_class_def,type_length,int,i_flags);
extern name *STempOffset(name*,type_length,type_class_def,type_length);
extern name *DeAlias( name * );
extern void SuffixIns(instruction*,instruction*);
extern void PrefixIns(instruction*,instruction*);
extern void ReplIns(instruction*,instruction*);
extern label_handle RTLabel(int);
extern void ChangeType(instruction*,type_class_def);
extern void FreeIns( instruction * );
extern instruction *MakeNary(opcode_defs,name*,name*,name*,type_class_def,type_class_def,int);
extern instruction *MakeBinary(opcode_defs,name*,name*,name*,type_class_def);
extern instruction *MakeMove(name*,name*,type_class_def);
extern instruction *MakeConvert(name*,name*,type_class_def,type_class_def);
extern instruction *MakeUnary(opcode_defs,name*,name*,type_class_def);
extern instruction *MakeCondition(opcode_defs,name*,name*,int,int,type_class_def);
extern instruction *NewIns( int );
extern name *GenFloat( name *, type_class_def );
extern opcode_entry *OpcodeTable( table_def );
extern void UpdateLive( instruction *, instruction * );
extern hw_reg_set ReturnAddrReg();
extern hw_reg_set FirstReg( reg_set_index );
extern type_length TypeClassSize[];
extern type_class_def Unsigned[];
extern type_class_def HalfClass[];
extern opcode_entry *CodeTable( instruction * );
extern name *AllocConst( pointer );
extern name *AllocIntConst( int );
extern name *AllocUIntConst( uint );
extern name *AddrConst( name *, int, constant_class );
extern name *AllocU64Const( unsigned_32, unsigned_32 );
extern hw_reg_set Low16Reg( hw_reg_set regs );
extern hw_reg_set Low32Reg( hw_reg_set regs );
extern hw_reg_set Low64Reg( hw_reg_set regs );
extern hw_reg_set High16Reg( hw_reg_set regs );
extern hw_reg_set High32Reg( hw_reg_set regs );
extern hw_reg_set High64Reg( hw_reg_set regs );
extern constant_defn *GetFloat( name *, type_class_def );
extern name *TempOffset( name *, type_length, type_class_def );
extern void HalfType( instruction * );
extern bool SameThing( name *, name * );
extern instruction *(* ReduceTab[])() = {
/***************************************/
#undef _R_
#define _R_( x, f ) f
#include "r.h"
};
static instruction *PromoteOperand( instruction *ins ) {
/***********************************************************/
name *temp;
instruction *new_ins;
if( _IsFloating( ins->type_class ) ) {
if( ins->type_class == FS ) {
temp = AllocTemp( FD );
new_ins = MakeConvert( ins->operands[ 0 ], temp, ins->type_class, FD );
ins->operands[ 0 ] = temp;
PrefixIns( ins, new_ins );
UpdateLive( new_ins, ins );
return( new_ins );
}
} else {
if( ins->type_class < U8 ) {
temp = AllocTemp( U8 );
new_ins = MakeConvert( ins->operands[ 0 ], temp, ins->type_class, U8 );
ins->operands[ 0 ] = temp;
PrefixIns( ins, new_ins );
UpdateLive( new_ins, ins );
return( new_ins );
}
}
return( NULL );
}
extern instruction *rDOSET( instruction *ins ) {
/***************************************************/
instruction *new;
switch( ins->head.opcode ) {
case OP_SET_NOT_EQUAL:
// FIXME: This is correct but stupid
ins->head.opcode = OP_SET_EQUAL;
new = MakeBinary( OP_SET_EQUAL, ins->result, AllocS32Const( 0 ), ins->result, ins->type_class );
SuffixIns( ins, new );
break;
case OP_SET_GREATER:
ins->head.opcode = OP_SET_LESS_EQUAL;
rSWAPOPS( ins );
break;
case OP_SET_GREATER_EQUAL:
ins->head.opcode = OP_SET_LESS;
rSWAPOPS( ins );
break;
case OP_SET_LESS:
case OP_SET_LESS_EQUAL:
case OP_SET_EQUAL:
break;
default:
_Zoiks( ZOIKS_120 );
}
switch( TypeClassSize[ ins->type_class ] ) {
case 4:
ins->table = OpcodeTable( BIN4 );
break;
case 8:
ins->table = OpcodeTable( BIN8 );
break;
default:
ins->table = OpcodeTable( BIN4 );
_Zoiks( ZOIKS_120 );
}
return( ins );
}
extern instruction *rSIMPCMP( instruction *ins )
/****************************************************
* Simplify a comparison instruction for a platform that can't perform
* arbitrary reg/reg comparisons.
*/
{
instruction *new;
opcode_defs opcode;
bool reverse;
reverse = FALSE;
assert( ins->result == NULL );
switch( ins->head.opcode ) {
case OP_CMP_NOT_EQUAL:
reverse = TRUE;
/* fall through */
case OP_CMP_EQUAL:
opcode = OP_SET_EQUAL;
break;
case OP_CMP_GREATER:
reverse = TRUE;
/* fall through */
case OP_CMP_LESS_EQUAL:
opcode = OP_SET_LESS_EQUAL;
break;
case OP_CMP_GREATER_EQUAL:
reverse = TRUE;
/* fall through */
case OP_CMP_LESS:
opcode = OP_SET_LESS;
break;
}
ins->result = AllocTemp( ins->type_class );
switch( ins->type_class ) {
case I4:
case U4:
ins->table = OpcodeTable( BIN4 );
break;
case I8:
case U8:
ins->table = OpcodeTable( BIN8 );
break;
case FS:
ins->table = OpcodeTable( FBINS );
break;
case FD:
case FL:
ins->table = OpcodeTable( FBIND );
break;
default:
_Zoiks( ZOIKS_096 );
}
ins->head.opcode = opcode;
opcode = OP_CMP_NOT_EQUAL;
if( reverse ) {
opcode = OP_CMP_EQUAL;
}
new = MakeCondition( opcode, ins->result, AllocS32Const( 0 ), _TrueIndex( ins ), _FalseIndex( ins ), ins->type_class );
SuffixIns( ins, new );
return( new );
}
extern instruction *rDOTEST( instruction *ins ) {
/****************************************************/
instruction *first;
instruction *last;
name *temp;
opcode_defs opcode;
temp = AllocTemp( ins->type_class );
switch( ins->head.opcode ) {
case OP_BIT_TEST_TRUE:
opcode = OP_CMP_NOT_EQUAL;
break;
case OP_BIT_TEST_FALSE:
opcode = OP_CMP_EQUAL;
break;
default:
opcode = OP_CMP_EQUAL;
_Zoiks( ZOIKS_120 );
}
first = MakeBinary( OP_AND, ins->operands[ 0 ],
ins->operands[ 1 ], temp, ins->type_class );
PrefixIns( ins, first );
last = MakeCondition( opcode, temp, AllocS32Const( 0 ),
_TrueIndex( ins ), _FalseIndex( ins ), ins->type_class );
ReplIns( ins, last );
UpdateLive( first, last );
return( first );
}
extern instruction *rPUSHTOMOV( instruction *ins ) {
/*******************************************************/
instruction *new_ins;
instruction *first_ins;
instruction *prom_ins;
name *stack_reg;
type_class_def push_class;
push_class = U8;
if( _IsFloating( ins->type_class ) ) {
push_class = FD;
}
prom_ins = PromoteOperand( ins );
stack_reg = AllocRegName( StackReg() );
first_ins = MakeBinary( OP_SUB, stack_reg, AllocS32Const( TypeClassSize[ push_class ] ), stack_reg, WD );
PrefixIns( ins, first_ins );
new_ins = MakeMove( ins->operands[ 0 ], AllocIndex( stack_reg, NULL, 0, push_class ), push_class );
ReplIns( ins, new_ins );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?