s37split.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 943 行 · 第 1/2 页
C
943 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "standard.h"
#include "coderep.h"
#include "typedef.h"
#include "opcodes.h"
#include "pattern.h"
#include "regset.h"
#include "model.h"
#include "vergen.h"
#include "zoiks.h"
#include "conflict.h"
#include "cfloat.h"
#include "s37split.def"
extern instruction *MakeBinary(opcode_defs,name*,name*,name*,type_class_def);
extern instruction *MakeMove(name*,name*,type_class_def);
extern instruction *MoveConst(unsigned_32 ,name *,type_class_def );
extern instruction *MakeUnary(opcode_defs,name*,name*,type_class_def);
extern instruction *MakeConvert(name*,name*,type_class_def,type_class_def);
extern name *AllocIntConst(int);
extern name *AllocS32Const(signed_32);
extern name *AllocConst(pointer);
extern cfloat *CFCnvU32F(unsigned_32);
extern name *AllocTemp(type_class_def);
extern name *SAllocTemp(type_class_def,type_length);
extern name *TempOffset(name*,type_length,type_class_def);
extern void PrefixIns(instruction*,instruction*);
extern void ReplIns(instruction*,instruction*);
extern void SuffixIns(instruction*,instruction*);
extern name *AllocAddrConst(name*,int,constant_class,type_class_def);
extern void ChangeType(instruction*,type_class_def);
extern name *ScaleIndex(name*,name*,type_length,type_class_def,type_length,int,i_flags);
extern name *AllocRegName(hw_reg_set);
extern conflict_node *GiveRegister(conflict_node*,bool);
extern conflict_node *NameConflict(instruction*,name*);
extern hw_reg_set LowReg(hw_reg_set);
extern void MarkPossible(instruction*,name*,reg_set_index);
extern void UpdateLive(instruction*,instruction*);
extern name *STempOffset(name*,type_length,type_class_def,type_length);
extern memory_name *SAllocMemory(pointer,type_length,cg_class,type_class_def,type_length);
extern void DoNothing(instruction*);
extern name *IndexToTemp(instruction*,name*);
extern conflict_node *IndexSplit(instruction*,name*);
extern instruction *rMOVRESREG(instruction*);
extern instruction *rLOADOP2(instruction*);
extern instruction *rSWAPCMP(instruction*);
extern instruction *rSWAPOPS(instruction*);
extern instruction *rUSEREGISTER(instruction*);
extern instruction *rDOCVT(instruction*);
extern instruction *rOP1REG(instruction*);
extern instruction *rOP1RESTEMP(instruction*);
extern instruction *rOP1MEM(instruction*);
extern instruction *rOP2MEM(instruction*);
extern instruction *rFORCERESMEM(instruction*);
extern instruction *rMOVEINDEX(instruction*);
extern instruction *rMAKEADD(instruction*);
extern instruction *rMAKEMOVE(instruction*);
extern instruction *rMAKENEG(instruction*);
extern instruction *rMAKESUB(instruction*);
extern instruction *rMOVOP2(instruction*);
extern reg_list *RegSets[];
extern op_regs RegList[];
extern byte OptForSize;
extern opcode_entry MVCL[];
extern opcode_entry MVC[];
extern opcode_entry NC[];
extern opcode_entry OC[];
extern opcode_entry XC[];
extern opcode_entry CLC[];
extern opcode_entry Mul4G[];
extern opcode_entry Mul4I2G[];
extern opcode_entry Add4I2G[];
extern opcode_entry Sub4I2G[];
extern opcode_entry Mod4G[];
extern opcode_entry Div4G[];
extern opcode_entry S4to8G[];
extern opcode_entry S1to4G[];
extern opcode_entry S2to4G[];
extern opcode_entry Z1to4G[];
extern opcode_entry Z2to4G[];
extern opcode_entry CNormF[];
extern type_length TypeClassSize[];
extern instruction *(* ReduceTab[])() = {
/***************************************/
rMOVRESREG,
rLOADOP2,
rSWAPCMP,
rSWAPOPS,
rUSEREGISTER,
rPREPMUL,
rPREPDIV,
rDOCVT,
rPREPCONV8,
rCLRMOV8,
rCLRMOV,
rMOVEXT,
rOP1REG,
rPREPS1TO4,
rPREPS2TO4,
rPREPZ1TO4,
rPREPZ2TO4,
rMOVEADDR,
rBIN2INT,
rUN2INT,
rSIDE2INT,
rNEGDEC,
rNOT2XOR,
rOP1RESTEMP,
rPREPMOD,
rOP1MEM,
rOP2MEM,
rFORCERESMEM,
rMVCL,
rMOVEINDEX,
rMAKEADD,
rMAKEMOVE,
rMAKENEG,
rMAKESUB,
rMOVOP2,
rMAKEAND,
rTEST1,
rSTOD,
rDTOS,
rPREPI4I2,
rPREPITOD,
rPREPUTOD,
rMEMDOWN,
rMVC,
rXC,
rCLC,
NULL
};
extern name *HighPart( name *tosplit, type_class_def class ) {
/*************************************************************/
class = class; tosplit = tosplit;
return( NULL );
}
extern name *LowPart( name *tosplit, type_class_def class ) {
/*************************************************************/
class = class; tosplit = tosplit;
return( NULL );
}
extern void CheckCC( instruction *ins1, instruction *ins ) {
/*********************************************************/
ins1 = ins1; ins = ins;
}
extern bool UnChangeable( instruction *ins ) {
/************************************************/
return( ins->table == MVCL );
}
static instruction *rPREPMUL( instruction *ins ) {
/***********************************************/
instruction *ins1;
instruction *ins2;
name *name1;
name *low;
name1 = SAllocTemp( XX, 8 );
low = TempOffset( name1, WORD_SIZE, WD );
ins1 = MakeMove( ins->operands[0], low, WD );
ins->operands[0] = low;
PrefixIns( ins, ins1 );
ins2 = MakeMove( low, ins->result, WD );
ins->result = name1;
SuffixIns( ins, ins2 );
ins->table = Mul4G;
ins->u.gen_table = NULL;
_SetTrue( NameConflict( ins, name1 ), NEVER_TOO_GREEDY );
return( ins1 );
}
static instruction *rPREPI4I2( instruction *ins ) {
/**********************************************
If you I4 op I2 is handled then send to a I4I2 table
*/
if( ins->head.opcode == OP_MUL ){
ins->table = Mul4I2G;
}else if( ins->head.opcode == OP_ADD ){
ins->table = Add4I2G;
}else if( ins->head.opcode == OP_SUB ){
ins->table = Sub4I2G;
}else{
Zoiks( ZOIKS_019 );
ins->table = NULL;
}
ins->u.gen_table = NULL;
return( ins );
}
static instruction *PrepModDiv( instruction *ins, int off, opcode_entry *tbl ) {
/******************************************************************************/
instruction *ins1;
instruction *ins2;
name *name1;
name *low;
name1 = SAllocTemp( XX, 8 );
ins1 = MakeConvert( ins->operands[0], name1, XX, ins->type_class );
ins->operands[0] = name1;
PrefixIns( ins, ins1 );
low = TempOffset( name1, off, WD );
ins2 = MakeMove( low, ins->result, WD );
ins->result = name1;
SuffixIns( ins, ins2 );
ins->table = tbl;
_SetTrue( NameConflict( ins, name1 ), NEVER_TOO_GREEDY );
return( ins1 );
}
static instruction *rPREPDIV( instruction *ins ) {
/***********************************************/
return( PrepModDiv( ins, WORD_SIZE, Div4G ) );
}
static instruction *rPREPMOD( instruction *ins ) {
/***********************************************/
return( PrepModDiv( ins, 0, Mod4G ) );
}
static instruction *rPREPCONV8( instruction *ins ) {
/**************************************************/
instruction *ins1;
name *high;
high = TempOffset( ins->result, 0, WD );
ins1 = MakeMove( ins->operands[0], high, WD );
ins->operands[0] = high;
PrefixIns( ins, ins1 );
ins->table = S4to8G; /* set to gen table */
return( ins1 );
}
static instruction *rCLRMOV8( instruction *ins ) {
/**************************************************/
/* change a CONV to a clear high word move U4 to low */
instruction *ins1;
instruction *ins2;
name *high;
name *low;
high = TempOffset( ins->result, 0, WD );
ins1 = MakeMove( AllocIntConst( 0 ), high, WD );
PrefixIns( ins, ins1 );
low = TempOffset( ins->result, WORD_SIZE, WD );
ins2 = MakeMove( ins->operands[0], low, WD );
ReplIns( ins, ins2 );
return( ins1 );
}
static instruction *rCLRMOV( instruction *ins ) {
/**************************************************/
/* Assume unsigned CONV clear result then move value in */
instruction *ins1;
instruction *ins2;
ins1 = MakeMove( AllocIntConst( 0 ), ins->result, ins->type_class );
PrefixIns( ins, ins1 );
ins2 = MakeMove( ins->operands[0], ins->result, ins->base_type_class );
ReplIns( ins, ins2 );
return( ins1 );
}
static instruction *rMOVEXT( instruction *ins ) {
/**************************************************/
/* Assume CONV move then extend in */
instruction *ins1;
instruction *ins2;
int shift;
ins1 = MakeMove( ins->operands[0], ins->result, ins->base_type_class );
PrefixIns( ins, ins1 );
shift = (ins->result->n.size - ins->operands[0]->n.size)*8;
/* mjc a bit sys dependent */
ins2 = MakeBinary( OP_RSHIFT, ins->result, AllocIntConst( shift ),
ins->result, ins->type_class );
ReplIns( ins, ins2 );
return( ins1 );
}
static instruction *PrepCnvUp( instruction *ins, opcode_entry *table ) {
/**********************************************************************/
name *temp;
instruction *new_ins;
temp = AllocTemp( WD );
new_ins = MakeMove( temp, ins->result, WD );
ins->result = temp;
SuffixIns( ins, new_ins );
ins->table = table;
ins->u.gen_table = NULL;
_SetTrue( NameConflict( ins, temp ), NEVER_TOO_GREEDY );
return( ins );
}
static instruction *rPREPS1TO4( instruction *ins ) {
/*************************************************/
return( PrepCnvUp( ins, S1to4G ) );
}
static instruction *rPREPS2TO4( instruction *ins ) {
/*************************************************/
return( PrepCnvUp( ins, S2to4G ) );
}
static instruction *rPREPZ1TO4( instruction *ins ) {
/*************************************************/
return( PrepCnvUp( ins, Z1to4G ) );
}
static instruction *rPREPZ2TO4( instruction *ins ) {
/*************************************************/
#if 0
name *temp;
instruction *new_ins;
temp = ins->operands[0];
if( temp->n.class == N_TEMP ){
ins = rOP1MEM(ins);
}
if( temp->n.class == N_REGISTER ){
temp = AllocTemp( U2 );
temp->v.usage |= USE_MEMORY | NEEDS_MEMORY;
new_ins = MakeMove( ins->operands[0], temp, U2 );
ins->operands[ 0 ] = temp;
PrefixIns( ins, new_ins );
temp->v.usage |= USE_MEMORY | NEEDS_MEMORY;
new_ins = ins;
}
#endif
ins = PrepCnvUp( ins, Z2to4G );
return( ins );
}
extern name *FArea = NULL;
static name *InitItoF( void ) {
/************************************************
Add the ItoF work area used by converion routines
*/
extern block *HeadBlock;
instruction *start;
instruction *ins;
name *low;
name *dwork;
start = HeadBlock->ins.hd.next;
dwork = SAllocTemp( FD, 8 );
dwork->v.usage |= USE_MEMORY | NEEDS_MEMORY;
low = TempOffset( dwork, 0, WD );
ins = MoveConst( 0x4E000000, low, WD );
PrefixIns( start, ins );
return( dwork );
}
static name *ItoFArea( void ){
if( FArea == NULL ){
FArea = InitItoF();
}
return( FArea );
}
static instruction *rPREPITOD( instruction *ins ) {
/*************************************************
CONV FD I4 op1 -> result =>
XOR op1 0X80000000 ->temp
MOV 0x4E000000 -> high part of FD in mem
MOV temp -> low
MOV FD -> temp FD
SUB TEMP - (FD)0X80000000 ->result
*/
instruction *ins1;
instruction *ins2;
name *dwork;
name *ipart;
name *temp;
name *theconst;
temp = AllocTemp( WD );
theconst = AllocConst( CFCnvU32F(0x80000000 ) );
ins1 = MakeBinary( OP_XOR, ins->operands[0],
theconst,
temp, WD );
ins->operands[0] = temp;
PrefixIns( ins, ins1 );
#if 0 /* if we haven't pre-allocated a work area */
dwork = SAllocTemp( FD, 8 );
dwork->v.usage |= USE_MEMORY | NEEDS_MEMORY;
ipart = TempOffset( dwork, 0, WD );
ins2 = MoveConst( 0x4E000000, ipart, WD );
PrefixIns( ins, ins2 );
#else
dwork = ItoFArea();
#endif
ipart = TempOffset( dwork, WORD_SIZE, WD );
ins2 = MakeMove( temp, ipart, WD );
ins->operands[0] = ipart;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?