axpsplit.c

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

C
703
字号
/****************************************************************************
*
*                            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:  Alpha AXP specific instruction splitting.
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "vergen.h"
#include "tables.h"
#include "pattern.h"
#include "rtclass.h"
#include "zoiks.h"
#include "model.h"
#include "procdef.h"
#include <assert.h>

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  hw_reg_set      StackReg(void);
extern  hw_reg_set      ScratchReg(void);
extern  hw_reg_set      ReturnAddrReg(void);

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  void            UpdateLive( instruction *, instruction * );
extern  name            *OffsetMem( name *, type_length, type_class_def );

extern  type_length     TypeClassSize[];
extern  type_class_def  Unsigned[];
extern  type_length     MaxStack;
extern  proc_def        *CurrProc;

extern  instruction     *rLOAD_1( instruction *ins ) {
/****************************************************/

    name                *temp_1;
    name                *temp_2;
    instruction         *new_ins;
    instruction         *first_ins;
    name                *mem;

    // assert( ins->operands[ 0 ]->n.class == N_INDEXED );
    assert( ins->result->n.class == N_REGISTER );
    assert( ins->type_class == I1 || ins->type_class == U1 );

    mem = OffsetMem( ins->operands[ 0 ], 0, U8 );
    temp_2 = AllocTemp( U8 );
    temp_1 = AllocTemp( I8 );
    // ldq_u x(rn) -> temp_1
    // lda x(rn) -> temp_2
    // extbl temp_1, temp_2 -> r1
    first_ins = MakeUnary( OP_LOAD_UNALIGNED, mem, temp_1, I8 );
    PrefixIns( ins, first_ins );
    new_ins = MakeUnary( OP_LA, mem, temp_2, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_EXTRACT_LOW, temp_1, temp_2, temp_1, I8, U1, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeConvert( temp_1, ins->result, ins->type_class, I8 );
    ReplIns( ins, new_ins );
    UpdateLive( first_ins, new_ins );
    return( first_ins );
}

extern  instruction     *rSTORE_1( instruction *ins ) {
/*****************************************************/

    name                *temp_1;
    name                *temp_2;
    name                *temp_3;
    name                *index;
    name                *byte_loc;
    instruction         *first_ins;
    instruction         *new_ins;

    // assert( ins->result->n.class == N_INDEXED );
    assert( ins->operands[ 0 ]->n.class == N_REGISTER );
    assert( ins->type_class == I1 || ins->type_class == U1 );

    temp_1 = AllocTemp( U8 );
    temp_2 = AllocTemp( U8 );
    temp_3 = AllocTemp( U8 );
    index = OffsetMem( ins->result, 0, U8 );
    byte_loc = ins->operands[ 0 ];
    // expansion for mov r1 -> x(r2) is:
    // lda x(r2) -> temp_1
    // ldq_u x(r2) -> temp_2
    // insbl r1, temp_1 -> temp_3
    // mskbl temp_2, temp_1 -> temp_2
    // or temp_2, temp_3 -> temp_2
    // stq_u temp_2 -> x(r2)
    first_ins = MakeUnary( OP_LA, index, temp_1, U8 );
    PrefixIns( ins, first_ins );
    new_ins = MakeConvert( byte_loc, temp_3, U8, ins->type_class );
    PrefixIns( ins, new_ins );
    new_ins = MakeUnary( OP_LOAD_UNALIGNED, index, temp_2, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_INSERT_LOW, temp_3, temp_1, temp_3, U8, U1, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_MASK_LOW, temp_2, temp_1, temp_2, U8, U1, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeBinary( OP_OR, temp_2, temp_3, temp_2, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeUnary( OP_STORE_UNALIGNED, temp_2, index, U8 );
    ReplIns( ins, new_ins );
    UpdateLive( first_ins, new_ins );
    return( first_ins );
}

extern  instruction     *rLOAD_2( instruction *ins ) {
/****************************************************/

    instruction         *first_ins;
    instruction         *new_ins;
    name                *temp;
    name                *mem;
    // name             *new_mem;
    name                *result;

    assert( ins->result->n.class == N_REGISTER );
    assert( ins->operands[ 0 ]->n.class == N_INDEXED || ins->operands[ 0 ]->n.class == N_TEMP );
    // FIXME: This assumes shorts are two-byte aligned
    // Microsoft appears to be using some evil alternate scheme.
    mem = OffsetMem( ins->operands[ 0 ], 0, U8 );
    result = AllocTemp( U8 );
    temp = AllocTemp( U8 );
    // mov U2 k(rn) -> rm expands to:
    // ldq_u    k(rn) -> rm
    // lea              k(rn) -> temp
    // extwl    rm, temp, rm
    first_ins = MakeUnary( OP_LOAD_UNALIGNED, mem, result, U8 );
    PrefixIns( ins, first_ins );
    new_ins = MakeUnary( OP_LA, mem, temp, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_EXTRACT_LOW, result, temp, result, U8, U2, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeConvert( result, ins->result, ins->type_class, U8 );
    ReplIns( ins, new_ins );
    UpdateLive( first_ins, new_ins );
    return( first_ins );
}

extern  instruction     *rLOAD_2U( instruction *ins ) {
/*****************************************************/

    name                *mem;
    name                *new_mem;
    name                *result;
    name                *temp;
    name                *addr;
    instruction         *first_ins;
    instruction         *new_ins;

    mem = OffsetMem( ins->operands[ 0 ], 0, U8 );
    new_mem = OffsetMem( ins->operands[ 0 ], 1, U8 );
    result = AllocTemp( U8 );
    temp = AllocTemp( U8 );
    addr = AllocTemp( U8 );
    first_ins = MakeUnary( OP_LOAD_UNALIGNED, mem, result, U8 );
    PrefixIns( ins, first_ins );
    new_ins = MakeUnary( OP_LOAD_UNALIGNED, new_mem, temp, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeUnary( OP_LA, mem, addr, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_EXTRACT_LOW, result, addr, result, U8, U2, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_EXTRACT_HIGH, temp, addr, temp, U8, U2, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeBinary( OP_OR, temp, result, result, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeConvert( result, ins->result, ins->type_class, U8 );
    ReplIns( ins, new_ins );
    UpdateLive( first_ins, new_ins );
    return( first_ins );
}

extern  instruction     *rSTORE_2( instruction *ins ) {
/*****************************************************/

    name                *temp_1;
    name                *temp_2;
    name                *addr;
    name                *index;
    name                *src;
    instruction         *first_ins;
    instruction         *new_ins;

    assert( ins->operands[ 0 ]->n.class == N_REGISTER );
    // assert( ins->result->n.class == N_INDEXED );
    assert( ins->type_class == U2 || ins->type_class == I2 );

    // mov rm -> x(rn) goes to:
    //          lea     x(rn) -> addr
    //          ldq_u   x(rn) -> temp_1
    //          inswl   rm, addr, temp_2
    //          mskwl   temp_1, addr, temp_1
    //          or      temp_1, temp_2, temp_1
    //          stq_u   temp_1, x(rn)
    temp_1 = AllocTemp( U8 );
    temp_2 = AllocTemp( U8 );
    addr = AllocTemp( U8 );
    index = OffsetMem( ins->result, 0, U8 );
    src = ins->operands[ 0 ];
    first_ins = MakeUnary( OP_LA, index, addr, U8 );
    PrefixIns( ins, first_ins );
    new_ins = MakeUnary( OP_LOAD_UNALIGNED, index, temp_1, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeConvert( src, temp_2, U8, ins->type_class );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_INSERT_LOW, temp_2, addr, temp_2, U8, U2, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_MASK_LOW, temp_1, addr, temp_1, U8, U2, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeBinary( OP_OR, temp_1, temp_2, temp_1, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeUnary( OP_STORE_UNALIGNED, temp_1, index, U8 );
    ReplIns( ins, new_ins );
    UpdateLive( first_ins, new_ins );
    return( first_ins );
}

extern  instruction     *rSTORE_2U( instruction *ins ) {
/******************************************************/

    name                *mem;
    name                *new_mem;
    name                *result;
    name                *temp;
    name                *value;
    name                *low;
    name                *high;
    name                *addr;
    instruction         *first_ins;
    instruction         *new_ins;


    mem = OffsetMem( ins->result, 0, U8 );
    new_mem = OffsetMem( ins->result, 1, U8 );
    addr = AllocTemp( U8 );
    result = AllocTemp( U8 );
    temp = AllocTemp( U8 );
    high = AllocTemp( U8 );
    low = AllocTemp( U8 );
    value = AllocTemp( U8 );
    first_ins = MakeConvert( ins->operands[ 0 ], value, U8, ins->type_class );
    PrefixIns( ins, first_ins );
    new_ins = MakeUnary( OP_LA, mem, addr, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeUnary( OP_LOAD_UNALIGNED, new_mem, high, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeUnary( OP_LOAD_UNALIGNED, mem, low, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_INSERT_HIGH, value, addr, temp, U8, U2, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_INSERT_LOW, value, addr, result, U8, U2, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_MASK_HIGH, high, addr, high, U8, U2, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_MASK_LOW, low, addr, low, U8, U2, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeBinary( OP_OR, high, temp, high, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeBinary( OP_OR, low, result, low, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeUnary( OP_STORE_UNALIGNED, high, new_mem, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeUnary( OP_STORE_UNALIGNED, low, mem, U8 );
    ReplIns( ins, new_ins );
    UpdateLive( first_ins, new_ins );
    return( first_ins );
}

extern  instruction     *rLOAD_4U( instruction *ins ) {
/*****************************************************/

    instruction         *first_ins;
    instruction         *new_ins;
    name                *mem_1;
    name                *mem_2;
    name                *temp_1;
    name                *temp_2;
    name                *temp_3;

    mem_1 = OffsetMem( ins->operands[ 0 ], 0, U8 );
    mem_2 = OffsetMem( ins->operands[ 0 ], 3, U8 );
    temp_1 = AllocTemp( U8 );
    temp_2 = AllocTemp( U8 );
    temp_3 = AllocTemp( U8 );
    first_ins = MakeUnary( OP_LOAD_UNALIGNED, mem_1, temp_1, U8 );
    PrefixIns( ins, first_ins );
    new_ins = MakeUnary( OP_LOAD_UNALIGNED, mem_2, temp_2, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeUnary( OP_LA, mem_1, temp_3, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_EXTRACT_LOW, temp_1, temp_3, temp_1, U8, U4, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_EXTRACT_HIGH, temp_2, temp_3, temp_2, U8, U4, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeBinary( OP_OR, temp_1, temp_2, temp_1, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeConvert( temp_1, ins->result, ins->type_class, U8 );
    ReplIns( ins, new_ins );
    UpdateLive( first_ins, new_ins );
    return( first_ins );
}

⌨️ 快捷键说明

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