mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-12 23:09:40 +02:00
* started to integrate the code of David Zhang's MIPS code from fpc-mips on sf into fpc trunk
git-svn-id: trunk@14219 -
This commit is contained in:
parent
79ec403774
commit
e5ebb2a26e
5
.gitattributes
vendored
5
.gitattributes
vendored
@ -234,10 +234,15 @@ compiler/m68k/ra68k.pas svneol=native#text/plain
|
||||
compiler/m68k/ra68kmot.pas svneol=native#text/plain
|
||||
compiler/m68k/rgcpu.pas svneol=native#text/plain
|
||||
compiler/mips/aasmcpu.pas svneol=native#text/plain
|
||||
compiler/mips/cgcpu.pas svneol=native#text/pascal
|
||||
compiler/mips/cpubase.pas svneol=native#text/plain
|
||||
compiler/mips/cpuinfo.pas svneol=native#text/plain
|
||||
compiler/mips/cpupara.pas svneol=native#text/pascal
|
||||
compiler/mips/cpupi.pas svneol=native#text/pascal
|
||||
compiler/mips/itcpugas.pas svneol=native#text/plain
|
||||
compiler/mips/mipsreg.dat svneol=native#text/plain
|
||||
compiler/mips/opcode.inc svneol=native#text/plain
|
||||
compiler/mips/rgcpu.pas svneol=native#text/pascal
|
||||
compiler/mips/rmipscon.inc svneol=native#text/plain
|
||||
compiler/mips/rmipsdwf.inc svneol=native#text/plain
|
||||
compiler/mips/rmipsgas.inc svneol=native#text/plain
|
||||
|
@ -70,7 +70,7 @@ interface
|
||||
addr_full,
|
||||
addr_pic,
|
||||
addr_pic_no_got
|
||||
{$IF defined(POWERPC) or defined(POWERPC64) or defined(SPARC)}
|
||||
{$IF defined(POWERPC) or defined(POWERPC64) or defined(SPARC) or defined(MIPS)}
|
||||
,
|
||||
addr_low, // bits 48-63
|
||||
addr_high, // bits 32-47
|
||||
|
@ -326,6 +326,7 @@ unit cgobj;
|
||||
|
||||
procedure a_jmp_name(list : TAsmList;const s : string); virtual; abstract;
|
||||
procedure a_jmp_always(list : TAsmList;l: tasmlabel); virtual; abstract;
|
||||
{$ifdef cpuflags}
|
||||
procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); virtual; abstract;
|
||||
|
||||
{# Depending on the value to check in the flags, either sets the register reg to one (if the flag is set)
|
||||
@ -333,6 +334,7 @@ unit cgobj;
|
||||
}
|
||||
procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister); virtual; abstract;
|
||||
procedure g_flags2ref(list: TAsmList; size: TCgSize; const f: tresflags; const ref:TReference); virtual;
|
||||
{$endif cpuflags}
|
||||
|
||||
{
|
||||
This routine tries to optimize the op_const_reg/ref opcode, and should be
|
||||
@ -3463,6 +3465,7 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
{$ifdef cpuflags}
|
||||
procedure tcg.g_flags2ref(list: TAsmList; size: TCgSize; const f: tresflags; const ref:TReference);
|
||||
|
||||
var
|
||||
@ -3472,6 +3475,7 @@ implementation
|
||||
g_flags2reg(list,size,f,tmpreg);
|
||||
a_load_reg_ref(list,size,size,tmpreg,ref);
|
||||
end;
|
||||
{$endif cpuflags}
|
||||
|
||||
|
||||
procedure tcg.g_maybe_testself(list : TAsmList;reg:tregister);
|
||||
|
@ -80,7 +80,9 @@ unit cgutils;
|
||||
loc : TCGLoc;
|
||||
size : TCGSize;
|
||||
case TCGLoc of
|
||||
{$ifdef cpuflags}
|
||||
LOC_FLAGS : (resflags : tresflags);
|
||||
{$endif cpuflags}
|
||||
LOC_CONSTANT : (
|
||||
case longint of
|
||||
{$ifdef FPC_BIG_ENDIAN}
|
||||
|
@ -120,6 +120,15 @@
|
||||
{$define cpunodefaultint}
|
||||
{$endif avr}
|
||||
|
||||
{$ifdef mips}
|
||||
{$define cpu32bitalu}
|
||||
{$define cpu32bitaddr}
|
||||
{ $define cpuflags}
|
||||
{$define cputargethasfixedstack}
|
||||
{$define cpurequiresproperalignment}
|
||||
{$define cpumm}
|
||||
{$endif mips}
|
||||
|
||||
{$IFDEF MACOS}
|
||||
{$DEFINE USE_FAKE_SYSUTILS}
|
||||
{$ENDIF MACOS}
|
||||
|
@ -401,6 +401,11 @@ interface
|
||||
optimizecputype : cpuinfo.cpu_avr;
|
||||
fputype : fpu_none;
|
||||
{$endif avr}
|
||||
{$ifdef mips}
|
||||
cputype : cpu_mips32;
|
||||
optimizecputype : cpu_mips32;
|
||||
fputype : fpu_mips2;
|
||||
{$endif mips}
|
||||
asmmode : asmmode_standard;
|
||||
interfacetype : it_interfacecom;
|
||||
defproccall : pocall_default;
|
||||
|
1972
compiler/mips/cgcpu.pas
Normal file
1972
compiler/mips/cgcpu.pas
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
{
|
||||
Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
|
||||
|
||||
Contains the base types for the ARM
|
||||
Contains the base types for MIPS
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -43,28 +43,7 @@ unit cpubase;
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
TAsmOp=(A_ABS_D,A_ABS_S,A_ADD,A_ADD_D,A_ADD_S,A_ADDI,A_ADDIU,A_ADDU,
|
||||
A_AND,A_ANDI,A_BC1F,A_BC1FL,A_BC1T,A_BC1TL,A_BC2F,A_BC2FL,
|
||||
A_BC2T,A_BC2TL,A_BEQ,A_BEQL,A_BGEZ,A_BGEZAL,A_BGEZALL,A_BGEZL,
|
||||
A_BGTZ,A_BGTZL,A_BLEZ,A_BLEZL,A_BLTZ,A_BLTZAL,A_BLTZALL,A_BLTZL,
|
||||
A_BNE,A_BNEL,A_BREAK,A_C_cond_D,A_C_cond_S,A_CACHE,A_CEIL_W_D,A_CEIL_W_S,
|
||||
A_CFC1,A_CFC2,A_CLO,A_CLZ,A_COP2,A_CTC1,A_CTC2,A_CVT_D_S,
|
||||
A_CVT_D_W,A_CVT_S_D,A_CVT_S_W,A_CVT_W_D,A_CVT_W_S,A_DIV,A_DIV_D,A_DIV_S,
|
||||
A_DIVU,A_ERET,A_FLOOR_W_D,A_FLOOR_W_S,A_J,A_JAL,A_JALR,A_JR,
|
||||
A_LB,A_LBU,A_LDC1,A_LDC2,A_LH,A_LHU,A_LL,A_LUI,
|
||||
A_LW,A_LWC1,A_LWC2,A_LWL,A_LWR,A_MADD,A_MADDU,A_MFC0,
|
||||
A_MFC1,A_MFC2,A_MFHI,A_MFLO,A_MOV_D,A_MOV_S,A_MOVF,A_MOVF_D,
|
||||
A_MOVF_S,A_MOVN,A_MOVN_D,A_MOVN_S,A_MOVT,A_MOVT_D,A_MOVT_S,A_MOVZ,
|
||||
A_MOVZ_D,A_MOVZ_S,A_MSUB,A_MSUBU,A_MTC0,A_MTC1,A_MTC2,A_MTHI,
|
||||
A_MTLO,A_MUL,A_MUL_D,A_MUL_S,A_MULT,A_MULTU,A_NEG_D,A_NEG_S,
|
||||
A_NOR,A_OR,A_ORI,A_PREF,A_ROUND_W_D,A_ROUND_W_S,A_SB,A_SC,
|
||||
A_SDC1,A_SDC2,A_SH,A_SLL,A_SLLV,A_SLT,A_SLTI,A_SLTIU,
|
||||
A_SLTU,A_SQRT_D,A_SQRT_S,A_SRA,A_SRAV,A_SRL,A_SRLV,A_SSNOP,
|
||||
A_SUB,A_SUB_D,A_SUB_S,A_SUBU,A_SW,A_SWC1,A_SWC2,A_SWL,
|
||||
A_SWR,A_SYNC,A_SYSCALL,A_TEQ,A_TEQI,A_TGE,A_TGEI,A_TGEIU,
|
||||
A_TGEU,A_TLBP,A_TLBR,A_TLBWI,A_TLBWR,A_TLT,A_TLTI,A_TLTIU,
|
||||
A_TLTU,A_TNE,A_TNEI,A_TRUNC_W_D,A_TRUNC_W_S,A_WAIT,A_XOR,A_XORI
|
||||
);
|
||||
TAsmOp=({$i opcode.inc});
|
||||
|
||||
{ This should define the array of instructions as string }
|
||||
op2strtable=array[tasmop] of string[11];
|
||||
@ -126,94 +105,28 @@ unit cpubase;
|
||||
type
|
||||
totherregisterset = set of tregisterindex;
|
||||
|
||||
{*****************************************************************************
|
||||
Instruction post fixes
|
||||
*****************************************************************************}
|
||||
type
|
||||
{ ARM instructions load/store and arithmetic instructions
|
||||
can have several instruction post fixes which are collected
|
||||
in this enumeration
|
||||
}
|
||||
TOpPostfix = (PF_None,
|
||||
{ update condition flags
|
||||
or floating point single }
|
||||
PF_S,
|
||||
{ floating point size }
|
||||
PF_D,PF_E,PF_P,PF_EP,
|
||||
{ load/store }
|
||||
PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T,
|
||||
{ multiple load/store address modes }
|
||||
PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA
|
||||
);
|
||||
|
||||
TRoundingMode = (RM_None,RM_P,RM_M,RM_Z);
|
||||
|
||||
const
|
||||
cgsize2fpuoppostfix : array[OS_NO..OS_F128] of toppostfix = (
|
||||
PF_E,
|
||||
PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,
|
||||
PF_S,PF_D,PF_E,PF_None,PF_None);
|
||||
|
||||
oppostfix2str : array[TOpPostfix] of string[2] = ('',
|
||||
's',
|
||||
'd','e','p','ep',
|
||||
'b','sb','bt','h','sh','t',
|
||||
'ia','ib','da','db','fd','fa','ed','ea');
|
||||
|
||||
roundingmode2str : array[TRoundingMode] of string[1] = ('',
|
||||
'p','m','z');
|
||||
|
||||
{*****************************************************************************
|
||||
Conditions
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
TAsmCond=(C_None,
|
||||
C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
|
||||
C_GE,C_LT,C_GT,C_LE,C_AL,C_NV
|
||||
C_EQ, C_NE, C_LT, C_LE, C_GT, C_GE, C_LTU, C_LEU, C_GTU, C_GEU,
|
||||
C_FEQ, {Equal}
|
||||
C_FNE, {Not Equal}
|
||||
C_FGT, {Greater}
|
||||
C_FLT, {Less}
|
||||
C_FGE, {Greater or Equal}
|
||||
C_FLE {Less or Equal}
|
||||
|
||||
);
|
||||
|
||||
const
|
||||
cond2str : array[TAsmCond] of string[2]=('',
|
||||
'eq','ne','cs','cc','mi','pl','vs','vc','hi','ls',
|
||||
'ge','lt','gt','le','al','nv'
|
||||
cond2str : array[TAsmCond] of string[3]=('',
|
||||
'eq','ne','lt','le','gt','ge','ltu','leu','gtu','geu',
|
||||
'feq','fne','fgt','flt','fge','fle'
|
||||
);
|
||||
|
||||
uppercond2str : array[TAsmCond] of string[2]=('',
|
||||
'EQ','NE','CS','CC','MI','PL','VS','VC','HI','LS',
|
||||
'GE','LT','GT','LE','AL','NV'
|
||||
);
|
||||
|
||||
inverse_cond : array[TAsmCond] of TAsmCond=(C_None,
|
||||
C_NE,C_EQ,C_CC,C_CS,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI,
|
||||
C_LT,C_GE,C_LE,C_GT,C_None,C_None
|
||||
);
|
||||
|
||||
{*****************************************************************************
|
||||
Flags
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
TResFlags = (F_EQ,F_NE,F_CS,F_CC,F_MI,F_PL,F_VS,F_VC,F_HI,F_LS,
|
||||
F_GE,F_LT,F_GT,F_LE);
|
||||
|
||||
{*****************************************************************************
|
||||
Operands
|
||||
*****************************************************************************}
|
||||
|
||||
taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED);
|
||||
tshiftmode = (SM_None,SM_LSL,SM_LSR,SM_ASR,SM_ROR,SM_RRX);
|
||||
|
||||
tupdatereg = (UR_None,UR_Update);
|
||||
|
||||
pshifterop = ^tshifterop;
|
||||
|
||||
tshifterop = record
|
||||
shiftmode : tshiftmode;
|
||||
rs : tregister;
|
||||
shiftimm : byte;
|
||||
end;
|
||||
|
||||
{*****************************************************************************
|
||||
Constants
|
||||
*****************************************************************************}
|
||||
@ -224,7 +137,7 @@ unit cpubase;
|
||||
{ Constant defining possibly all registers which might require saving }
|
||||
ALL_OTHERREGISTERS = [];
|
||||
|
||||
general_superregisters = [RS_R0..RS_PC];
|
||||
general_superregisters = [RS_R0..RS_R31];
|
||||
|
||||
{ Table of registers which can be allocated by the code generator
|
||||
internally, when generating the code.
|
||||
@ -238,7 +151,7 @@ unit cpubase;
|
||||
{ passing on ABI's that define this) }
|
||||
{ c_countusableregsxxx = amount of registers in the usableregsxxx set }
|
||||
|
||||
maxintregs = 15;
|
||||
maxintregs = 31;
|
||||
{ to determine how many registers to use for regvars }
|
||||
maxintscratchregs = 3;
|
||||
usableregsint = [RS_R4..RS_R10];
|
||||
@ -300,44 +213,61 @@ unit cpubase;
|
||||
Generic Register names
|
||||
*****************************************************************************}
|
||||
|
||||
{ Stack pointer register }
|
||||
NR_STACK_POINTER_REG = NR_R13;
|
||||
RS_STACK_POINTER_REG = RS_R13;
|
||||
{ Frame pointer register }
|
||||
RS_FRAME_POINTER_REG = RS_R11;
|
||||
NR_FRAME_POINTER_REG = NR_R11;
|
||||
{ Register for addressing absolute data in a position independant way,
|
||||
such as in PIC code. The exact meaning is ABI specific. For
|
||||
further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
|
||||
}
|
||||
NR_PIC_OFFSET_REG = NR_R9;
|
||||
STK2_PTR = NR_R23;
|
||||
NR_GP = NR_R28;
|
||||
NR_SP = NR_R29;
|
||||
NR_S8 = NR_R30;
|
||||
NR_FP = NR_R30;
|
||||
NR_RA = NR_R31;
|
||||
|
||||
RS_GP = RS_R28;
|
||||
RS_SP = RS_R29;
|
||||
RS_S8 = RS_R30;
|
||||
RS_FP = RS_R30;
|
||||
RS_RA = RS_R31;
|
||||
|
||||
{# Stack pointer register }
|
||||
NR_STACK_POINTER_REG = NR_SP;
|
||||
RS_STACK_POINTER_REG = RS_SP;
|
||||
{# Frame pointer register }
|
||||
NR_FRAME_POINTER_REG = NR_FP;
|
||||
RS_FRAME_POINTER_REG = RS_FP;
|
||||
|
||||
NR_RETURN_ADDRESS_REG = NR_R7;
|
||||
{ the return_result_reg, is used inside the called function to store its return
|
||||
value when that is a scalar value otherwise a pointer to the address of the
|
||||
result is placed inside it }
|
||||
|
||||
{ Results are returned in this register (32-bit values) }
|
||||
NR_FUNCTION_RETURN_REG = NR_R0;
|
||||
RS_FUNCTION_RETURN_REG = RS_R0;
|
||||
NR_FUNCTION_RETURN_REG = NR_R2;
|
||||
RS_FUNCTION_RETURN_REG = RS_R2;
|
||||
{ Low part of 64bit return value }
|
||||
NR_FUNCTION_RETURN64_LOW_REG = NR_R0;
|
||||
RS_FUNCTION_RETURN64_LOW_REG = RS_R0;
|
||||
NR_FUNCTION_RETURN64_LOW_REG = NR_R2;
|
||||
RS_FUNCTION_RETURN64_LOW_REG = RS_R2;
|
||||
{ High part of 64bit return value }
|
||||
NR_FUNCTION_RETURN64_HIGH_REG = NR_R1;
|
||||
RS_FUNCTION_RETURN64_HIGH_REG = RS_R1;
|
||||
NR_FUNCTION_RETURN64_HIGH_REG = NR_R3;
|
||||
RS_FUNCTION_RETURN64_HIGH_REG = RS_R3;
|
||||
{ The value returned from a function is available in this register }
|
||||
NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
|
||||
RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
|
||||
NR_FUNCTION_RESULT_REG = NR_R2;
|
||||
RS_FUNCTION_RESULT_REG = RS_R2;
|
||||
{ The lowh part of 64bit value returned from a function }
|
||||
NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
|
||||
RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
|
||||
NR_FUNCTION_RESULT64_LOW_REG = NR_R2;
|
||||
RS_FUNCTION_RESULT64_LOW_REG = RS_R2;
|
||||
{ The high part of 64bit value returned from a function }
|
||||
NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
|
||||
RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
|
||||
NR_FUNCTION_RESULT64_HIGH_REG = NR_R3;
|
||||
RS_FUNCTION_RESULT64_HIGH_REG = RS_R3;
|
||||
|
||||
NR_FPU_RESULT_REG = NR_F0;
|
||||
|
||||
NR_MM_RESULT_REG = NR_NO;
|
||||
|
||||
NR_RETURN_ADDRESS_REG = NR_FUNCTION_RETURN_REG;
|
||||
NR_TCR0 = NR_R15;
|
||||
NR_TCR1 = NR_R3;
|
||||
|
||||
NR_TCR10 = NR_R20;
|
||||
NR_TCR11 = NR_R21;
|
||||
NR_TCR12 = NR_R18;
|
||||
NR_TCR13 = NR_R19;
|
||||
|
||||
{ Offset where the parent framepointer is pushed }
|
||||
PARENT_FRAMEPOINTER_OFFSET = 0;
|
||||
|
||||
{*****************************************************************************
|
||||
GCC /ABI linking information
|
||||
@ -351,12 +281,12 @@ unit cpubase;
|
||||
This value can be deduced from the CALLED_USED_REGISTERS array in the
|
||||
GCC source.
|
||||
}
|
||||
saved_standard_registers : array[0..8] of tsuperregister =
|
||||
(RS_R16,RS_R17,RS_R18,RS_R19,RS_R20,RS_R21,RS_R22,RS_R23,RS_R30);
|
||||
|
||||
saved_standard_registers : array[0..0] of tsuperregister =
|
||||
(RS_NO);
|
||||
|
||||
{ this is only for the generic code which is not used for this architecture }
|
||||
saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
|
||||
|
||||
|
||||
{ Required parameter alignment when calling a routine declared as
|
||||
stdcall and cdecl. The alignment value should be the one defined
|
||||
by GCC or the target ABI.
|
||||
@ -373,17 +303,12 @@ unit cpubase;
|
||||
|
||||
{ Returns the tcgsize corresponding with the size of reg.}
|
||||
function reg_cgsize(const reg: tregister) : tcgsize;
|
||||
function cgsize2subreg(s:Tcgsize):Tsubregister;
|
||||
function cgsize2subreg(regtype: tregistertype; s:tcgsize):tsubregister;
|
||||
function is_calljmp(o:tasmop):boolean;
|
||||
procedure inverse_flags(var f: TResFlags);
|
||||
function flags_to_cond(const f: TResFlags) : TAsmCond;
|
||||
function findreg_by_number(r:Tregister):tregisterindex;
|
||||
function std_regnum_search(const s:string):Tregister;
|
||||
function std_regname(r:Tregister):string;
|
||||
|
||||
procedure shifterop_reset(var so : tshifterop);
|
||||
function is_pc(const r : tregister) : boolean;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
@ -404,21 +329,27 @@ unit cpubase;
|
||||
);
|
||||
|
||||
|
||||
function cgsize2subreg(s:Tcgsize):Tsubregister;
|
||||
function cgsize2subreg(regtype: tregistertype; s:tcgsize):tsubregister;
|
||||
begin
|
||||
cgsize2subreg:=R_SUBWHOLE;
|
||||
if s in [OS_64,OS_S64] then
|
||||
cgsize2subreg:=R_SUBQ
|
||||
else
|
||||
cgsize2subreg:=R_SUBWHOLE;
|
||||
end;
|
||||
|
||||
|
||||
function reg_cgsize(const reg: tregister): tcgsize;
|
||||
const subreg2cgsize:array[Tsubregister] of Tcgsize =
|
||||
(OS_NO,OS_8,OS_8,OS_16,OS_32,OS_64,OS_NO,OS_NO,OS_NO);
|
||||
begin
|
||||
case getregtype(reg) of
|
||||
R_INTREGISTER :
|
||||
reg_cgsize:=OS_32;
|
||||
R_FPUREGISTER :
|
||||
reg_cgsize:=OS_F80;
|
||||
begin
|
||||
if getsubreg(reg)=R_SUBFD then
|
||||
result:=OS_F64
|
||||
else
|
||||
result:=OS_F32;
|
||||
end;
|
||||
else
|
||||
internalerror(200303181);
|
||||
end;
|
||||
@ -435,29 +366,21 @@ unit cpubase;
|
||||
end;
|
||||
|
||||
|
||||
procedure inverse_flags(var f: TResFlags);
|
||||
function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
|
||||
const
|
||||
inv_flags: array[TResFlags] of TResFlags =
|
||||
(F_NE,F_EQ,F_CC,F_CS,F_PL,F_MI,F_VC,F_VS,F_LS,F_HI,
|
||||
F_LT,F_GE,F_LE,F_GT);
|
||||
inverse: array[TAsmCond] of TAsmCond=(C_None,
|
||||
C_EQ, C_NE, C_LT, C_LE, C_GT, C_GE, C_LTU, C_LEU, C_GTU, C_GEU,
|
||||
C_FEQ, {Equal}
|
||||
C_FNE, {Not Equal}
|
||||
C_FGT, {Greater}
|
||||
C_FLT, {Less}
|
||||
C_FGE, {Greater or Equal}
|
||||
C_FLE {Less or Equal}
|
||||
|
||||
);
|
||||
begin
|
||||
f:=inv_flags[f];
|
||||
end;
|
||||
|
||||
|
||||
function flags_to_cond(const f: TResFlags) : TAsmCond;
|
||||
const
|
||||
flag_2_cond: array[F_EQ..F_LE] of TAsmCond =
|
||||
(C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
|
||||
C_GE,C_LT,C_GT,C_LE);
|
||||
begin
|
||||
if f>high(flag_2_cond) then
|
||||
internalerror(200112301);
|
||||
result:=flag_2_cond[f];
|
||||
end;
|
||||
|
||||
|
||||
function findreg_by_number(r:Tregister):tregisterindex;
|
||||
result := inverse[c];
|
||||
end; function findreg_by_number(r:Tregister):tregisterindex;
|
||||
begin
|
||||
result:=rgBase.findreg_by_number_table(r,regnumber_index);
|
||||
end;
|
||||
@ -481,15 +404,4 @@ unit cpubase;
|
||||
end;
|
||||
|
||||
|
||||
procedure shifterop_reset(var so : tshifterop);
|
||||
begin
|
||||
FillChar(so,sizeof(so),0);
|
||||
end;
|
||||
|
||||
|
||||
function is_pc(const r : tregister) : boolean;
|
||||
begin
|
||||
is_pc:=(r=NR_R15);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -32,13 +32,10 @@ Type
|
||||
{ possible supported processors for this target }
|
||||
tcputype =
|
||||
(cpu_none,
|
||||
mips32
|
||||
cpu_mips32
|
||||
);
|
||||
|
||||
tfputype =
|
||||
(fpu_none,
|
||||
fpu_fpu
|
||||
);
|
||||
tfputype =(fpu_none,fpu_soft,fpu_mips2,fpu_mips3);
|
||||
|
||||
Const
|
||||
{# Size of native extended floating point type }
|
||||
@ -63,7 +60,8 @@ Const
|
||||
);
|
||||
|
||||
fputypestr : array[tfputype] of string[6] = ('',
|
||||
'FPU'
|
||||
'SOFT',
|
||||
'FPU_MIPS2','FPU_MIPS3'
|
||||
);
|
||||
|
||||
{ Supported optimizations, only used for information }
|
||||
|
342
compiler/mips/cpupara.pas
Normal file
342
compiler/mips/cpupara.pas
Normal file
@ -0,0 +1,342 @@
|
||||
{
|
||||
Copyright (c) 1998-2002 by Florian Klaempfl and David Zhang
|
||||
|
||||
Calling conventions for the MIPSEL
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*****************************************************************************}
|
||||
unit cpupara;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
globtype,
|
||||
cclasses,
|
||||
aasmtai,
|
||||
cpubase,cpuinfo,
|
||||
symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase;
|
||||
|
||||
type
|
||||
TMIPSELParaManager=class(TParaManager)
|
||||
function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
|
||||
function get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override;
|
||||
function get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
|
||||
{Returns a structure giving the information on the storage of the parameter
|
||||
(which must be an integer parameter)
|
||||
@param(nr Parameter number of routine, starting from 1)}
|
||||
procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override;
|
||||
function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
|
||||
function create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override;
|
||||
private
|
||||
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||
procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
|
||||
var intparareg,parasize:longint);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
cutils,verbose,systems,
|
||||
defutil,
|
||||
cgutils,cgobj;
|
||||
|
||||
type
|
||||
tparasupregs = array[0..5] of tsuperregister;
|
||||
pparasupregs = ^tparasupregs;
|
||||
const
|
||||
paraoutsupregs : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9);
|
||||
parainsupregs : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9);
|
||||
|
||||
|
||||
function TMIPSELParaManager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
|
||||
begin
|
||||
result:=[RS_R16..RS_R23];
|
||||
end;
|
||||
|
||||
|
||||
function tMIPSELparamanager.get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;
|
||||
begin
|
||||
result:=[RS_F0..RS_F31];
|
||||
end;
|
||||
|
||||
|
||||
procedure TMIPSELParaManager.GetIntParaLoc(calloption : tproccalloption; nr : longint;var cgpara : tcgpara);
|
||||
var
|
||||
paraloc : pcgparalocation;
|
||||
begin
|
||||
if nr<1 then
|
||||
InternalError(2002100806);
|
||||
cgpara.reset;
|
||||
cgpara.size:=OS_INT;
|
||||
cgpara.intsize:=tcgsize2size[OS_INT];
|
||||
cgpara.alignment:=std_param_align;
|
||||
paraloc:=cgpara.add_location;
|
||||
with paraloc^ do
|
||||
begin
|
||||
{ The six first parameters are passed into registers } {MIPS first four}
|
||||
dec(nr);
|
||||
if nr<6 then //MIPSEL nr<6
|
||||
begin
|
||||
loc:=LOC_REGISTER;
|
||||
register:=newreg(R_INTREGISTER,(RS_R4+nr),R_SUBWHOLE);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ The other parameters are passed on the stack }
|
||||
loc:=LOC_REFERENCE;
|
||||
reference.index:=NR_STACK_POINTER_REG;
|
||||
reference.offset:=92+(nr-6)*4;
|
||||
end;
|
||||
size:=OS_INT;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ true if a parameter is too large to copy and only the address is pushed }
|
||||
function tMIPSELparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
|
||||
begin
|
||||
result:=false;
|
||||
{ var,out always require address }
|
||||
if varspez in [vs_var,vs_out] then
|
||||
begin
|
||||
result:=true;
|
||||
exit;
|
||||
end;
|
||||
case def.typ of
|
||||
recorddef,
|
||||
arraydef,
|
||||
variantdef,
|
||||
formaldef :
|
||||
push_addr_param:=true;
|
||||
objectdef :
|
||||
result:=is_object(def);
|
||||
stringdef :
|
||||
result:=(tstringdef(def).stringtype in [st_shortstring,st_longstring]);
|
||||
procvardef :
|
||||
result:=(po_methodpointer in tprocvardef(def).procoptions);
|
||||
setdef :
|
||||
result:=not(is_smallset(def));
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure tMIPSELparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||
var
|
||||
retcgsize : tcgsize;
|
||||
begin
|
||||
{ Constructors return self instead of a boolean }
|
||||
if (p.proctypeoption=potype_constructor) then
|
||||
retcgsize:=OS_ADDR
|
||||
else
|
||||
retcgsize:=def_cgsize(p.returndef);
|
||||
|
||||
location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
{ void has no location }
|
||||
if is_void(p.returndef) then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_VOID;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ Return in FPU register? }
|
||||
if p.returndef.typ=floatdef then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_FPUREGISTER;
|
||||
p.funcretloc[side].register:=NR_FPU_RESULT_REG;
|
||||
if retcgsize=OS_F64 then
|
||||
setsubreg(p.funcretloc[side].register,R_SUBFD);
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
end
|
||||
else
|
||||
{ Return in register? }
|
||||
if not ret_in_param(p.returndef,p.proccalloption) then
|
||||
begin
|
||||
{$ifndef cpu64bit}
|
||||
if retcgsize in [OS_64,OS_S64] then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
{ high }
|
||||
if side=callerside then
|
||||
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
|
||||
else
|
||||
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
|
||||
{ low }
|
||||
if side=callerside then
|
||||
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
|
||||
else
|
||||
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
|
||||
end
|
||||
else
|
||||
{$endif cpu64bit}
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
if side=callerside then
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
|
||||
else
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REFERENCE;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
param_offset:array[0..20] of ^Aint;
|
||||
|
||||
procedure tMIPSELparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
|
||||
var intparareg,parasize:longint);
|
||||
var
|
||||
paraloc : pcgparalocation;
|
||||
i : integer;
|
||||
hp : tparavarsym;
|
||||
paracgsize : tcgsize;
|
||||
hparasupregs : pparasupregs;
|
||||
paralen : longint;
|
||||
begin
|
||||
if side=callerside then
|
||||
hparasupregs:=@paraoutsupregs
|
||||
else
|
||||
hparasupregs:=@parainsupregs;
|
||||
for i:=0 to paras.count-1 do
|
||||
begin
|
||||
|
||||
param_offset[i] := Nil;
|
||||
hp:=tparavarsym(paras[i]);
|
||||
{ currently only support C-style array of const,
|
||||
there should be no location assigned to the vararg array itself }
|
||||
if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
|
||||
is_array_of_const(hp.vardef) then
|
||||
begin
|
||||
paraloc:=hp.paraloc[side].add_location;
|
||||
{ hack: the paraloc must be valid, but is not actually used }
|
||||
paraloc^.loc:=LOC_REGISTER;
|
||||
paraloc^.register:=NR_R0;
|
||||
paraloc^.size:=OS_ADDR;
|
||||
break;
|
||||
end;
|
||||
|
||||
if push_addr_param(hp.varspez,hp.vardef,p.proccalloption) then
|
||||
paracgsize:=OS_ADDR
|
||||
else
|
||||
begin
|
||||
paracgsize:=def_cgSize(hp.vardef);
|
||||
if paracgsize=OS_NO then
|
||||
paracgsize:=OS_ADDR;
|
||||
end;
|
||||
hp.paraloc[side].reset;
|
||||
hp.paraloc[side].size:=paracgsize;
|
||||
hp.paraloc[side].Alignment:=std_param_align;
|
||||
paralen:=tcgsize2size[paracgsize];
|
||||
hp.paraloc[side].intsize:=paralen;
|
||||
while paralen>0 do
|
||||
begin
|
||||
paraloc:=hp.paraloc[side].add_location;
|
||||
{ Floats are passed in int registers,
|
||||
We can allocate at maximum 32 bits per register }
|
||||
if paracgsize in [OS_64,OS_S64,OS_F32,OS_F64] then
|
||||
paraloc^.size:=OS_32
|
||||
else
|
||||
paraloc^.size:=paracgsize;
|
||||
{ ret in param? }
|
||||
if vo_is_funcret in hp.varoptions then
|
||||
begin
|
||||
paraloc^.loc:=LOC_REFERENCE;
|
||||
if side=callerside then
|
||||
begin
|
||||
paraloc^.reference.index := NR_STACK_POINTER_REG;
|
||||
paraloc^.reference.offset:=target_info.first_parm_offset{1000}-12 - parasize;
|
||||
end
|
||||
else
|
||||
begin
|
||||
paraloc^.reference.index := NR_FRAME_POINTER_REG;
|
||||
paraloc^.reference.offset:=target_info.first_parm_offset{1000}-4 - parasize;
|
||||
param_offset[i] := @paraloc^.reference.offset;
|
||||
end;
|
||||
inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
|
||||
end
|
||||
else if (intparareg<=high(tparasupregs)) then
|
||||
begin
|
||||
paraloc^.loc:=LOC_REGISTER;
|
||||
paraloc^.register:=newreg(R_INTREGISTER,hparasupregs^[intparareg],R_SUBWHOLE);
|
||||
inc(intparareg);
|
||||
end
|
||||
else
|
||||
begin
|
||||
paraloc^.loc:=LOC_REFERENCE;
|
||||
if side=callerside then
|
||||
begin
|
||||
paraloc^.reference.index := {NR_R17;//}NR_STACK_POINTER_REG;
|
||||
paraloc^.reference.offset:=target_info.first_parm_offset{1000}-12 - parasize;
|
||||
end
|
||||
else
|
||||
begin
|
||||
paraloc^.reference.index := {NR_R18;//}NR_FRAME_POINTER_REG;
|
||||
paraloc^.reference.offset:=target_info.first_parm_offset{1000}-4 - parasize;
|
||||
param_offset[i] := @paraloc^.reference.offset;
|
||||
end;
|
||||
{ Parameters are aligned at 4 bytes }
|
||||
inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
|
||||
end;
|
||||
dec(paralen,tcgsize2size[paraloc^.size]);
|
||||
end;
|
||||
end;
|
||||
for i:=0 to paras.count-1 do
|
||||
begin
|
||||
if (side = calleeside) and (param_offset[i] <> nil) then
|
||||
param_offset[i]^ := param_offset[i]^ + parasize - 8;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function TMIPSELParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
|
||||
var
|
||||
intparareg,
|
||||
parasize : longint;
|
||||
begin
|
||||
intparareg:=0;
|
||||
parasize:=0;
|
||||
{ calculate the registers for the normal parameters }
|
||||
create_paraloc_info_intern(p,callerside,p.paras,intparareg,parasize);
|
||||
{ append the varargs }
|
||||
create_paraloc_info_intern(p,callerside,varargspara,intparareg,parasize);
|
||||
result:=parasize;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
function tMIPSELparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
|
||||
var
|
||||
intparareg,
|
||||
parasize : longint;
|
||||
begin
|
||||
intparareg:=0;
|
||||
parasize:=0;
|
||||
create_paraloc_info_intern(p,side,p.paras,intparareg,parasize);
|
||||
{ Create Function result paraloc }
|
||||
create_funcretloc_info(p,side);
|
||||
{ We need to return the size allocated on the stack }
|
||||
result:=parasize;
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
ParaManager:=TMIPSELParaManager.create;
|
||||
end.
|
76
compiler/mips/cpupi.pas
Normal file
76
compiler/mips/cpupi.pas
Normal file
@ -0,0 +1,76 @@
|
||||
{
|
||||
Copyright (c) 2002-2009 by Florian Klaempfl and David Zhang
|
||||
|
||||
This unit contains the CPU specific part of tprocinfo
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
****************************************************************************
|
||||
}
|
||||
unit cpupi;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
cutils,
|
||||
procinfo,cpuinfo,
|
||||
psub;
|
||||
|
||||
type
|
||||
TMIPSProcInfo=class(tcgprocinfo)
|
||||
public
|
||||
constructor create(aparent:tprocinfo);override;
|
||||
function calc_stackframe_size:longint;override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
systems,globals,
|
||||
tgobj,paramgr,symconst;
|
||||
|
||||
constructor tmipsprocinfo.create(aparent:tprocinfo);
|
||||
begin
|
||||
inherited create(aparent);
|
||||
maxpushedparasize:=0;
|
||||
end;
|
||||
|
||||
|
||||
function TMIPSProcInfo.calc_stackframe_size:longint;
|
||||
begin
|
||||
{
|
||||
Stackframe layout:
|
||||
%fp
|
||||
<locals>
|
||||
<temp>
|
||||
<arguments 6-n for calling>
|
||||
%sp+92
|
||||
<space for arguments 0-5> \
|
||||
<return pointer for calling> | included in first_parm_offset
|
||||
<register window save area for calling> /
|
||||
%sp
|
||||
|
||||
Alignment must be the max available, as doubles require
|
||||
8 byte alignment
|
||||
}
|
||||
result:=Align(tg.direction*tg.lasttemp+maxpushedparasize+target_info.first_parm_offset,current_settings.alignment.localalignmax);
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
cprocinfo:=TMIPSProcInfo;
|
||||
end.
|
241
compiler/mips/opcode.inc
Normal file
241
compiler/mips/opcode.inc
Normal file
@ -0,0 +1,241 @@
|
||||
A_NONE,
|
||||
A_P_STK2,
|
||||
A_P_LW,
|
||||
A_P_SET_NOREORDER,
|
||||
A_P_SET_NOMACRO,
|
||||
A_P_SET_MACRO,
|
||||
A_P_SET_REORDER,
|
||||
A_P_FRAME,
|
||||
A_P_MASK,
|
||||
A_P_FMASK,
|
||||
A_P_SW,
|
||||
A_SPARC8UNIMP,
|
||||
A_NOP,
|
||||
A_NOT,
|
||||
A_NEG,
|
||||
A_NEGU,
|
||||
A_B,
|
||||
A_LI,
|
||||
A_DLI,
|
||||
A_LA,
|
||||
A_MOVE,
|
||||
A_LB,
|
||||
A_LBU,
|
||||
A_LH,
|
||||
A_LHU,
|
||||
A_LW,
|
||||
A_LWU,
|
||||
A_LWL,
|
||||
A_LWR,
|
||||
A_LD,
|
||||
A_LDL,
|
||||
A_LDR,
|
||||
A_LL,
|
||||
A_LLD,
|
||||
A_SB,
|
||||
A_SH,
|
||||
A_SW,
|
||||
A_SWL,
|
||||
A_SWR,
|
||||
A_SD,
|
||||
A_SDL,
|
||||
A_SDR,
|
||||
A_SC,
|
||||
A_SCD,
|
||||
A_SYNC,
|
||||
A_ADDI,
|
||||
A_DADDI,
|
||||
A_ADDIU,
|
||||
A_DADDIU,
|
||||
A_SLTI,
|
||||
A_SLTIU,
|
||||
A_ANDI,
|
||||
A_ORI,
|
||||
A_XORI,
|
||||
A_LUI,
|
||||
A_DNEG,
|
||||
A_DNEGU,
|
||||
A_ADD,
|
||||
A_DADD,
|
||||
A_ADDU,
|
||||
A_DADDU,
|
||||
A_SUB,
|
||||
A_DSUB,
|
||||
A_SUBU,
|
||||
A_DSUBU,
|
||||
A_SLT,
|
||||
A_SLTU,
|
||||
A_AND,
|
||||
A_OR,
|
||||
A_XOR,
|
||||
A_NOR,
|
||||
A_MUL,
|
||||
A_MULO,
|
||||
A_MULOU,
|
||||
A_DMUL,
|
||||
A_DMULO,
|
||||
A_DMULOU,
|
||||
A_DIV,
|
||||
A_DIVU,
|
||||
A_DDIV,
|
||||
A_DDIVU,
|
||||
A_REM,
|
||||
A_REMU,
|
||||
A_DREM,
|
||||
A_DREMU,
|
||||
A_MULT,
|
||||
A_DMULT,
|
||||
A_MULTU,
|
||||
A_DMULTU,
|
||||
A_MFHI,
|
||||
A_MTHI,
|
||||
A_MFLO,
|
||||
A_MTLO,
|
||||
A_MULTG,
|
||||
A_DMULTG,
|
||||
A_MULTUG,
|
||||
A_DMULTUG,
|
||||
A_DIVG,
|
||||
A_DDIVG,
|
||||
A_DIVUG,
|
||||
A_DDIVUG,
|
||||
A_MODG,
|
||||
A_DMODG,
|
||||
A_MODUG,
|
||||
A_DMODUG,
|
||||
A_J,
|
||||
A_JAL,
|
||||
A_JR,
|
||||
A_JALR,
|
||||
A_BEQ,
|
||||
A_BNE,
|
||||
A_BLEZ,
|
||||
A_BGTZ,
|
||||
A_BLTZ,
|
||||
A_BGEZ,
|
||||
A_BLTZAL,
|
||||
A_BGEZAL,
|
||||
A_BEQL,
|
||||
A_BNEL,
|
||||
A_BLEZL,
|
||||
A_BGTZL,
|
||||
A_BLTZL,
|
||||
A_BGEZL,
|
||||
A_BLTZALL,
|
||||
A_BGEZALL,
|
||||
A_SLL,
|
||||
A_SRL,
|
||||
A_SRA,
|
||||
A_SLLV,
|
||||
A_SRLV,
|
||||
A_SRAV,
|
||||
A_DSLL,
|
||||
A_DSRL,
|
||||
A_DSRA,
|
||||
A_DSLLV,
|
||||
A_DSRLV,
|
||||
A_DSRAV,
|
||||
A_DSLL32,
|
||||
A_DSRL32,
|
||||
A_DSRA32,
|
||||
A_LWC1,
|
||||
A_SWC1,
|
||||
A_LDC1,
|
||||
A_SDC1,
|
||||
A_MTC1,
|
||||
A_MFC1,
|
||||
A_DMTC1,
|
||||
A_DMFC1,
|
||||
A_CTC1,
|
||||
A_CFC1,
|
||||
A_ADD_S,
|
||||
A_ADD_D,
|
||||
A_SUB_S,
|
||||
A_SUB_D,
|
||||
A_MUL_S,
|
||||
A_MUL_D,
|
||||
A_DIV_S,
|
||||
A_DIV_D,
|
||||
A_ABS_S,
|
||||
A_ABS_D,
|
||||
A_NEG_S,
|
||||
A_NEG_D,
|
||||
A_SQRT_S,
|
||||
A_SQRT_D,
|
||||
A_MOV_S,
|
||||
A_MOV_D,
|
||||
A_CVT_S_D,
|
||||
A_CVT_S_W,
|
||||
A_CVT_S_L,
|
||||
A_CVT_D_S,
|
||||
A_CVT_D_W,
|
||||
A_CVT_D_L,
|
||||
A_CVT_W_S,
|
||||
A_CVT_W_D,
|
||||
A_CVT_L_S,
|
||||
A_CVT_L_D,
|
||||
A_ROUND_W_S,
|
||||
A_ROUND_W_D,
|
||||
A_ROUND_L_S,
|
||||
A_ROUND_L_D,
|
||||
A_TRUNC_W_S,
|
||||
A_TRUNC_W_D,
|
||||
A_TRUNC_L_S,
|
||||
A_TRUNC_L_D,
|
||||
A_CEIL_W_S,
|
||||
A_CEIL_W_D,
|
||||
A_CEIL_L_S,
|
||||
A_CEIL_L_D,
|
||||
A_FLOOR_W_S,
|
||||
A_FLOOR_W_D,
|
||||
A_FLOOR_L_S,
|
||||
A_FLOOR_L_D,
|
||||
A_BC1T,
|
||||
A_BC1F,
|
||||
A_BC1TL,
|
||||
A_BC1FL,
|
||||
A_C_EQ_D,
|
||||
A_C_EQ_S,
|
||||
A_C_LE_D,
|
||||
A_C_LE_S,
|
||||
A_C_LT_D,
|
||||
A_C_LT_S,
|
||||
A_BEQI,
|
||||
A_BNEI,
|
||||
A_BLTI,
|
||||
A_BLEI,
|
||||
A_BGTI,
|
||||
A_BGEI,
|
||||
A_BLTUI,
|
||||
A_BLEUI,
|
||||
A_BGTUI,
|
||||
A_BGEUI,
|
||||
A_BLT,
|
||||
A_BLE,
|
||||
A_BGT,
|
||||
A_BGE,
|
||||
A_BLTU,
|
||||
A_BLEU,
|
||||
A_BGTU,
|
||||
A_BGEU,
|
||||
A_SEQ,
|
||||
A_SGE,
|
||||
A_SGEU,
|
||||
A_SGT,
|
||||
A_SGTU,
|
||||
A_SLE,
|
||||
A_SLEU,
|
||||
A_SNE,
|
||||
A_SYSCALL,
|
||||
A_ADD64SUB,
|
||||
A_SUB64SUB,
|
||||
A_MUL64SUB,
|
||||
A_DIV64SUB,
|
||||
A_NEG64SUB,
|
||||
A_NOT64SUB,
|
||||
A_OR64SUB,
|
||||
A_SAR64SUB,
|
||||
A_SHL64SUB,
|
||||
A_SHR64SUB,
|
||||
A_XOR64SUB,
|
||||
A_END_DEF
|
165
compiler/mips/rgcpu.pas
Normal file
165
compiler/mips/rgcpu.pas
Normal file
@ -0,0 +1,165 @@
|
||||
{
|
||||
Copyright (c) 1998-2009 by Florian Klaempfl and David Zhang
|
||||
|
||||
This unit implements the register allocator for MIPLEL
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
****************************************************************************
|
||||
}
|
||||
|
||||
unit rgcpu;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
aasmbase,aasmcpu,aasmtai,aasmdata,
|
||||
cgbase,cgutils,
|
||||
cpubase,
|
||||
rgobj;
|
||||
|
||||
type
|
||||
trgcpu=class(trgobj)
|
||||
procedure add_constraints(reg:tregister);override;
|
||||
function get_spill_subreg(r : tregister) : tsubregister;override;
|
||||
procedure do_spill_read(list:tasmlist;pos:tai;const spilltemp:treference;tempreg:tregister);override;
|
||||
procedure do_spill_written(list:tasmlist;pos:tai;const spilltemp:treference;tempreg:tregister);override;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
globtype,
|
||||
verbose,cutils,
|
||||
cgobj;
|
||||
|
||||
procedure trgcpu.add_constraints(reg:tregister);
|
||||
var
|
||||
supreg,i : Tsuperregister;
|
||||
begin
|
||||
case getsubreg(reg) of
|
||||
{ Let 64bit floats conflict with all odd float regs }
|
||||
R_SUBFD:
|
||||
begin
|
||||
supreg:=getsupreg(reg);
|
||||
i:=RS_F1;
|
||||
while (i<=RS_F31) do
|
||||
begin
|
||||
add_edge(supreg,i);
|
||||
inc(i,2);
|
||||
end;
|
||||
end;
|
||||
{ Let 64bit ints conflict with all odd int regs }
|
||||
R_SUBQ:
|
||||
begin
|
||||
supreg:=getsupreg(reg);
|
||||
i:=RS_R1;
|
||||
while (i<=RS_R31) do
|
||||
begin
|
||||
add_edge(supreg,i);
|
||||
inc(i,2);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function trgcpu.get_spill_subreg(r : tregister) : tsubregister;
|
||||
begin
|
||||
if getregtype(r)=R_FPUREGISTER then
|
||||
result:=getsubreg(r)
|
||||
else
|
||||
result:=defaultsub;
|
||||
end;
|
||||
|
||||
|
||||
procedure trgcpu.do_spill_read(list:tasmlist;pos:tai;const spilltemp:treference;tempreg:tregister);
|
||||
var
|
||||
helpins : tai;
|
||||
tmpref : treference;
|
||||
helplist : tasmlist;
|
||||
hreg : tregister;
|
||||
begin
|
||||
if abs(spilltemp.offset)>4095 then
|
||||
begin
|
||||
helplist:=tasmlist.create;
|
||||
|
||||
if getregtype(tempreg)=R_INTREGISTER then
|
||||
hreg:=tempreg
|
||||
else
|
||||
hreg:=cg.getintregister(helplist,OS_ADDR);
|
||||
|
||||
reference_reset(tmpref,sizeof(aint));
|
||||
tmpref.offset:=spilltemp.offset;
|
||||
tmpref.refaddr:=addr_high;
|
||||
helplist.concat(taicpu.op_reg_ref(A_LUI,hreg,tmpref));
|
||||
|
||||
tmpref.refaddr:=addr_low;
|
||||
helplist.concat(taicpu.op_reg_reg_ref(A_ADDIU,hreg,hreg,tmpref));
|
||||
helplist.concat(taicpu.op_reg_reg_reg(A_ADDU,hreg,hreg,spilltemp.base));
|
||||
|
||||
reference_reset_base(tmpref,hreg,0,sizeof(aint));
|
||||
|
||||
helpins:=spilling_create_load(tmpref,tempreg);
|
||||
helplist.concat(helpins);
|
||||
list.insertlistafter(pos,helplist)
|
||||
end
|
||||
else
|
||||
inherited do_spill_read(list,pos,spilltemp,tempreg);
|
||||
end;
|
||||
|
||||
|
||||
procedure trgcpu.do_spill_written(list:tasmlist;pos:tai;const spilltemp:treference;tempreg:tregister);
|
||||
var
|
||||
helpins : tai;
|
||||
tmpref : treference;
|
||||
helplist : tasmlist;
|
||||
hreg : tregister;
|
||||
begin
|
||||
if abs(spilltemp.offset)>4095 then
|
||||
begin
|
||||
helplist:=tasmlist.create;
|
||||
|
||||
if getregtype(tempreg)=R_INTREGISTER then
|
||||
hreg:=getregisterinline(helplist,R_SUBWHOLE)
|
||||
else
|
||||
hreg:=cg.getintregister(helplist,OS_ADDR);
|
||||
|
||||
reference_reset(tmpref,sizeof(aint));
|
||||
tmpref.offset:=spilltemp.offset;
|
||||
tmpref.refaddr:=addr_high;
|
||||
helplist.concat(taicpu.op_reg_ref(A_LUI,hreg,tmpref));
|
||||
|
||||
tmpref.refaddr:=addr_low;
|
||||
helplist.concat(taicpu.op_reg_reg_ref(A_ADDIU,hreg,hreg,tmpref));
|
||||
helplist.concat(taicpu.op_reg_reg_reg(A_ADDU,hreg,hreg,spilltemp.base));
|
||||
|
||||
reference_reset_base(tmpref,hreg,0,sizeof(aint));
|
||||
|
||||
helpins:=spilling_create_store(tempreg,tmpref);
|
||||
helplist.concat(helpins);
|
||||
if getregtype(tempreg)=R_INTREGISTER then
|
||||
ungetregisterinline(helplist,hreg);
|
||||
|
||||
list.insertlistafter(pos,helplist)
|
||||
end
|
||||
else
|
||||
inherited do_spill_written(list,pos,spilltemp,tempreg);
|
||||
end;
|
||||
|
||||
end.
|
Loading…
Reference in New Issue
Block a user