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