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 + -
显示快捷键?