* more MIPS code of David Zhang integrated

git-svn-id: trunk@14228 -
This commit is contained in:
florian 2009-11-20 14:46:45 +00:00
parent 2ef18ba527
commit 0c8546f94c
13 changed files with 1588 additions and 373 deletions

14
.gitattributes vendored
View File

@ -234,15 +234,21 @@ 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/aoptcpu.pas svneol=native#text/plain
compiler/mips/aoptcpub.pas svneol=native#text/plain
compiler/mips/aoptcpud.pas svneol=native#text/plain
compiler/mips/cgcpu.pas svneol=native#text/plain
compiler/mips/cpubase.pas svneol=native#text/plain
compiler/mips/cpugas.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/cpunode.pas svneol=native#text/plain
compiler/mips/cpupara.pas svneol=native#text/plain
compiler/mips/cpupi.pas svneol=native#text/plain
compiler/mips/itcpugas.pas svneol=native#text/plain
compiler/mips/mipsreg.dat svneol=native#text/plain
compiler/mips/ncpuadd.pas svneol=native#text/plain
compiler/mips/opcode.inc svneol=native#text/plain
compiler/mips/rgcpu.pas svneol=native#text/pascal
compiler/mips/rgcpu.pas svneol=native#text/plain
compiler/mips/rmipscon.inc svneol=native#text/plain
compiler/mips/rmipsdwf.inc svneol=native#text/plain
compiler/mips/rmipsgas.inc svneol=native#text/plain

View File

@ -3067,7 +3067,7 @@ unit cgcpu;
begin
{ restore int registers and return }
list.concat(taicpu.op_reg_reg(A_MOV, NR_STACK_POINTER_REG, NR_R11));
reference_reset(ref,4);
ref.index:=NR_STACK_POINTER_REG;
list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,regs),PF_DB));
@ -3195,7 +3195,7 @@ unit cgcpu;
tmpreg:=getintregister(list,OS_ADDR);
list.concat(taicpu.op_reg_reg(A_MOV, tmpreg, NR_R15));
ref.base := tmpreg;
end;

View File

@ -1,7 +1,7 @@
{
Copyright (c) 2003 by Florian Klaempfl
Copyright (c) 1999-2009 by Mazen Neifer and David Zhang
Contains the assembler object for MIPS
Contains the assembler object 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
@ -26,314 +26,424 @@ unit aasmcpu;
interface
uses
cclasses,aasmtai,aasmdata,
aasmbase,globtype,globals,verbose,
cpubase,cpuinfo,cgbase,cgutils;
cclasses,
globtype, globals, verbose,
aasmbase, aasmtai,
cgbase, cgutils, cpubase, cpuinfo;
const
{ "mov reg,reg" source operand number }
O_MOV_SOURCE = 1;
{ "mov reg,reg" source operand number }
O_MOV_DEST = 0;
const
{ "mov reg,reg" source operand number }
O_MOV_SOURCE = 0;
{ "mov reg,reg" source operand number }
O_MOV_DEST = 1;
type
taicpu = class(tai_cpu_abstract)
constructor op_none(op : tasmop);
type
taicpu = class(tai_cpu_abstract)
delayslot_annulled: boolean; { conditinal opcode with ,a }
constructor op_none(op: tasmop);
constructor op_reg(op : tasmop;_op1 : tregister);
constructor op_const(op : tasmop;_op1 : longint);
constructor op_reg(op: tasmop; _op1: tregister);
constructor op_const(op: tasmop; _op1: longint);
constructor op_ref(op: tasmop; const _op1: treference);
constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
constructor op_reg_reg(op: tasmop; _op1, _op2: tregister);
constructor op_reg_ref(op: tasmop; _op1: tregister; const _op2: treference);
constructor op_reg_const(op: tasmop; _op1: tregister; _op2: longint);
constructor op_ref_regset(op:tasmop; _op1: treference; _op2: tcpuregisterset);
constructor op_reg_reg_reg(op: tasmop; _op1, _op2, _op3: tregister);
constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
{ SFM/LFM }
constructor op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
constructor op_reg_reg_ref(op: tasmop; _op1, _op2: tregister; const _op3: treference);
constructor op_reg_reg_const(op: tasmop; _op1, _op2: tregister; _op3: aint);
{ this is for Jmp instructions }
constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
{ this is for Jmp instructions }
constructor op_sym(op: tasmop; _op1: tasmsymbol);
constructor op_reg_reg_sym(op: tasmop; _op1, _op2: tregister; _op3: tasmsymbol);
constructor op_reg_sym(op: tasmop; _op1: tregister; _op2: tasmsymbol);
constructor op_sym_ofs(op: tasmop; _op1: tasmsymbol; _op1ofs: longint);
constructor op_sym(op : tasmop;_op1 : tasmsymbol);
constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
{ register allocation }
function is_same_reg_move(regtype: Tregistertype): boolean; override;
function is_same_reg_move(regtype: Tregistertype):boolean; override;
{ register spilling code }
function spilling_get_operation_type(opnr: longint): topertype; override;
end;
function spilling_get_operation_type(opnr: longint): topertype;override;
end;
tai_align = class(tai_align_abstract)
{ nothing to add }
end;
tai_align = class(tai_align_abstract)
{ nothing to add }
end;
function spilling_create_load(const ref:treference;r:tregister): tai;
function spilling_create_store(r:tregister; const ref:treference): tai;
procedure InitAsm;
procedure DoneAsm;
procedure InitAsm;
procedure DoneAsm;
function spilling_create_load(const ref: treference; r: tregister): taicpu;
function spilling_create_store(r: tregister; const ref: treference): taicpu;
implementation
uses
cutils,rgobj,itcpugas;
{*****************************************************************************
taicpu Constructors
*****************************************************************************}
constructor taicpu.op_none(op : tasmop);
begin
inherited create(op);
end;
constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
begin
inherited create(op);
ops:=1;
loadreg(0,_op1);
end;
constructor taicpu.op_none(op: tasmop);
begin
inherited Create(op);
end;
constructor taicpu.op_const(op : tasmop;_op1 : longint);
begin
inherited create(op);
ops:=1;
loadconst(0,aint(_op1));
end;
constructor taicpu.op_reg(op: tasmop; _op1: tregister);
begin
inherited Create(op);
ops := 1;
loadreg(0, _op1);
end;
constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
begin
inherited create(op);
ops:=2;
loadreg(0,_op1);
loadreg(1,_op2);
end;
constructor taicpu.op_ref(op: tasmop; const _op1: treference);
begin
inherited Create(op);
ops := 1;
loadref(0, _op1);
end;
constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
begin
inherited create(op);
ops:=2;
loadreg(0,_op1);
loadconst(1,aint(_op2));
end;
constructor taicpu.op_const(op: tasmop; _op1: longint);
begin
inherited Create(op);
ops := 1;
loadconst(0, _op1);
end;
constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
begin
inherited create(op);
ops:=2;
loadreg(0,_op1);
loadref(1,_op2);
end;
constructor taicpu.op_reg_reg(op: tasmop; _op1, _op2: tregister);
begin
inherited Create(op);
ops := 2;
loadreg(0, _op1);
loadreg(1, _op2);
end;
constructor taicpu.op_reg_const(op: tasmop; _op1: tregister; _op2: longint);
begin
inherited Create(op);
ops := 2;
loadreg(0, _op1);
loadconst(1, _op2);
end;
constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
begin
inherited create(op);
ops:=3;
loadreg(0,_op1);
loadreg(1,_op2);
loadreg(2,_op3);
end;
constructor taicpu.op_reg_ref(op: tasmop; _op1: tregister; const _op2: treference);
begin
inherited Create(op);
ops := 2;
loadreg(0, _op1);
loadref(1, _op2);
end;
constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
begin
inherited create(op);
ops:=3;
loadreg(0,_op1);
loadreg(1,_op2);
loadconst(2,aint(_op3));
end;
constructor taicpu.op_reg_reg_reg(op: tasmop; _op1, _op2, _op3: tregister);
begin
inherited Create(op);
ops := 3;
loadreg(0, _op1);
loadreg(1, _op2);
loadreg(2, _op3);
end;
constructor taicpu.op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
begin
inherited create(op);
ops:=3;
loadreg(0,_op1);
loadconst(1,_op2);
loadref(2,_op3);
end;
constructor taicpu.op_reg_reg_ref(op: tasmop; _op1, _op2: tregister; const _op3: treference);
begin
inherited create(op);
ops := 3;
loadreg(0, _op1);
loadreg(1, _op2);
loadref(2, _op3);
end;
constructor taicpu.op_reg_reg_const(op: tasmop; _op1, _op2: tregister; _op3: aint);
begin
inherited create(op);
ops := 3;
loadreg(0, _op1);
loadreg(1, _op2);
loadconst(2, _op3);
end;
constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
begin
inherited create(op);
ops:=3;
loadreg(0,_op1);
loadreg(1,_op2);
loadsymbol(0,_op3,_op3ofs);
end;
constructor taicpu.op_sym(op: tasmop; _op1: tasmsymbol);
begin
inherited Create(op);
is_jmp := op in [A_J, A_BEQI, A_BNEI, A_BLTI, A_BLEI, A_BGTI, A_BGEI,
A_BLTUI, A_BLEUI, A_BGTUI, A_BGEUI,
A_BEQ, A_BNE, A_BLT, A_BLE, A_BGT, A_BGE,
A_BLTU, A_BLEU, A_BGTU, A_BGEU
];
ops := 1;
loadsymbol(0, _op1, 0);
end;
constructor taicpu.op_reg_reg_sym(op: tasmop; _op1, _op2: tregister; _op3: tasmsymbol);
begin
inherited create(op);
is_jmp := op in [A_J,
A_BEQI, A_BNEI, A_BLTI, A_BLEI, A_BGTI, A_BGEI, A_BLTUI, A_BLEUI,
A_BGTUI, A_BGEUI,
A_BEQ, A_BNE, A_BLT, A_BLE, A_BGT, A_BGE, A_BLTU, A_BLEU, A_BGTU, A_BGEU];
ops := 3;
loadreg(0, _op1);
loadreg(1, _op2);
loadsymbol(2, _op3, 0);
end;
constructor taicpu.op_reg_sym(op: tasmop; _op1: tregister; _op2: tasmsymbol);
begin
inherited create(op);
is_jmp := op in [A_J,
A_BEQI, A_BNEI, A_BLTI, A_BLEI, A_BGTI, A_BGEI, A_BLTUI, A_BLEUI,
A_BGTUI, A_BGEUI,
A_BEQ, A_BNE, A_BLT, A_BLE, A_BGT, A_BGE, A_BLTU, A_BLEU, A_BGTU, A_BGEU, A_BGTZ];
ops := 2;
loadreg(0, _op1);
loadsymbol(1, _op2, 0);
end;
constructor taicpu.op_sym_ofs(op: tasmop; _op1: tasmsymbol; _op1ofs: longint);
begin
inherited Create(op);
ops := 1;
loadsymbol(0, _op1, _op1ofs);
end;
constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
begin
inherited create(op);
ops:=3;
loadreg(0,_op1);
loadreg(1,_op2);
loadref(2,_op3);
end;
constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
begin
inherited create(op);
condition:=cond;
ops:=1;
loadsymbol(0,_op1,0);
end;
constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
begin
inherited create(op);
ops:=1;
loadsymbol(0,_op1,0);
end;
constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
begin
inherited create(op);
ops:=1;
loadsymbol(0,_op1,_op1ofs);
end;
constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
begin
inherited create(op);
ops:=2;
loadreg(0,_op1);
loadsymbol(1,_op2,_op2ofs);
end;
constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
begin
inherited create(op);
ops:=2;
loadsymbol(0,_op1,_op1ofs);
loadref(1,_op2);
end;
{ ****************************** newra stuff *************************** }
function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
begin
{ allow the register allocator to remove unnecessary moves }
result:=(((opcode=A_MOVE) and (regtype = R_INTREGISTER)) or
((opcode=A_MOVF) and (regtype = R_FPUREGISTER))
) and
(condition=C_None) and
(ops=2) and
(oper[0]^.typ=top_reg) and
(oper[1]^.typ=top_reg) and
(oper[0]^.reg=oper[1]^.reg);
end;
function spilling_create_load(const ref:treference;r:tregister): tai;
begin
case getregtype(r) of
R_INTREGISTER :
result:=taicpu.op_reg_ref(A_LDR,r,ref);
R_FPUREGISTER :
{ use lfm because we don't know the current internal format
and avoid exceptions
}
result:=taicpu.op_reg_const_ref(A_LFM,r,1,ref);
else
internalerror(200401041);
end;
end;
function spilling_create_store(r:tregister; const ref:treference): tai;
begin
case getregtype(r) of
R_INTREGISTER :
result:=taicpu.op_reg_ref(A_STR,r,ref);
R_FPUREGISTER :
{ use sfm because we don't know the current internal format
and avoid exceptions
}
result:=taicpu.op_reg_const_ref(A_SFM,r,1,ref);
else
internalerror(200401041);
end;
end;
function taicpu.is_same_reg_move(regtype: Tregistertype): boolean;
begin
Result := (
((opcode = A_MOVE) and (regtype = R_INTREGISTER)) or
((regtype = R_FPUREGISTER) and (opcode in [A_MOV_S, A_MOV_D]))
) and
(oper[0]^.reg = oper[1]^.reg);
end;
function taicpu.spilling_get_operation_type(opnr: longint): topertype;
type
op_write_set_type = set of TAsmOp;
const
op_write_set: op_write_set_type =
[A_NEG,
A_NEGU,
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_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_MFLO,
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_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_LDC1,
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_SEQ,
A_SGE,
A_SGEU,
A_SGT,
A_SGTU,
A_SLE,
A_SLEU,
A_SNE];
begin
case opcode of
A_ADC,A_ADD,A_AND,
A_EOR,A_CLZ,
A_LDR,A_LDRB,A_LDRD,A_LDRBT,A_LDRH,A_LDRSB,
A_LDRSH,A_LDRT,
A_MOV,A_MVN,A_MLA,A_MUL,
A_ORR,A_RSB,A_RSC,A_SBC,A_SUB,
A_SWP,A_SWPB,
A_LDF,A_FLT,A_FIX,
A_ADF,A_DVF,A_FDV,A_FML,
A_RFS,A_RFC,A_RDF,
A_RMF,A_RPW,A_RSF,A_SUF,A_ABS,A_ACS,A_ASN,A_ATN,A_COS,
A_EXP,A_LOG,A_LGN,A_MVF,A_MNF,A_FRD,A_MUF,A_POL,A_RND,A_SIN,A_SQT,A_TAN,
A_LFM:
if opnr=0 then
result:=operand_write
else
result:=operand_read;
A_BIC,A_BKPT,A_B,A_BL,A_BLX,A_BX,
A_CMN,A_CMP,A_TEQ,A_TST,
A_CMF,A_CMFE,A_WFS,A_CNF:
result:=operand_read;
A_SMLAL,A_UMLAL:
if opnr in [0,1] then
result:=operand_readwrite
else
result:=operand_read;
A_SMULL,A_UMULL:
if opnr in [0,1] then
result:=operand_write
else
result:=operand_read;
A_STR,A_STRB,A_STRBT,A_STRD,
A_STRH,A_STRT,A_STF,A_SFM:
{ important is what happens with the involved registers }
if opnr=0 then
result := operand_read
else
{ check for pre/post indexed }
result := operand_read;
result := operand_read;
if opcode in op_write_set then
if opnr = 0 then
result := operand_write;
end;
function spilling_create_load(const ref: treference; r: tregister): taicpu;
begin
case getregtype(r) of
R_INTREGISTER :
result:=taicpu.op_reg_ref(A_LW,r,ref);
R_FPUREGISTER :
begin
case getsubreg(r) of
R_SUBFS :
result:=taicpu.op_reg_ref(A_LWC1,r,ref);
R_SUBFD :
result:=taicpu.op_reg_ref(A_LDC1,r,ref);
else
internalerror(200401042);
end;
end
else
internalerror(200403151);
internalerror(200401041);
end;
end;
procedure InitAsm;
function spilling_create_store(r: tregister; const ref: treference): taicpu;
begin
case getregtype(r) of
R_INTREGISTER :
result:=taicpu.op_reg_ref(A_SW,r,ref);
R_FPUREGISTER :
begin
case getsubreg(r) of
R_SUBFS :
result:=taicpu.op_reg_ref(A_SWC1,r,ref);
R_SUBFD :
result:=taicpu.op_reg_ref(A_SDC1,r,ref);
else
internalerror(200401042);
end;
end
else
internalerror(200401041);
end;
end;
procedure DoneAsm;
begin
end;
procedure InitAsm;
begin
end;
procedure DoneAsm;
begin
end;
begin
cai_cpu := taicpu;
cai_align := tai_align;
end.

41
compiler/mips/aoptcpu.pas Normal file
View File

@ -0,0 +1,41 @@
{
Copyright (c) 1998-2004 by Jonas Maebe
This unit calls the optimization procedures to optimize the assembler
code for sparc
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 aoptcpu;
{$i fpcdefs.inc}
Interface
uses
cpubase, aoptobj, aoptcpub, aopt;
Type
TCpuAsmOptimizer = class(TAsmOptimizer)
End;
Implementation
begin
casmoptimizer:=TCpuAsmOptimizer;
end.

119
compiler/mips/aoptcpub.pas Normal file
View File

@ -0,0 +1,119 @@
{
Copyright (c) 1998-2009 by Jonas Maebe and David Zhang
This unit contains several types and constants necessary for the
optimizer to work on the MIPSEL architecture
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 aoptcpub; { Assembler OPTimizer CPU specific Base }
{$i fpcdefs.inc}
{ enable the following define if memory references can have both a base and }
{ index register in 1 operand }
{$define RefsHaveIndexReg}
{ enable the following define if memory references can have a scaled index }
{ define RefsHaveScale}
{ enable the following define if memory references can have a segment }
{ override }
{ define RefsHaveSegment}
Interface
Uses
cpubase,aasmcpu,AOptBase;
Type
{ type of a normal instruction }
TInstr = Taicpu;
PInstr = ^TInstr;
{ ************************************************************************* }
{ **************************** TCondRegs ********************************** }
{ ************************************************************************* }
{ Info about the conditional registers }
TCondRegs = Object
Constructor Init;
Destructor Done;
End;
{ ************************************************************************* }
{ **************************** TAoptBaseCpu ******************************* }
{ ************************************************************************* }
TAoptBaseCpu = class(TAoptBase)
End;
{ ************************************************************************* }
{ ******************************* Constants ******************************* }
{ ************************************************************************* }
Const
{ the maximum number of things (registers, memory, ...) a single instruction }
{ changes }
MaxCh = 3;
{ the maximum number of operands an instruction has }
MaxOps = 3;
{Oper index of operand that contains the source (reference) with a load }
{instruction }
LoadSrc = 0;
{Oper index of operand that contains the destination (register) with a load }
{instruction }
LoadDst = 1;
{Oper index of operand that contains the source (register) with a store }
{instruction }
StoreSrc = 0;
{Oper index of operand that contains the destination (reference) with a load }
{instruction }
StoreDst = 1;
aopt_uncondjmp = A_J;
aopt_condjmp = A_BEQ;
Implementation
{ ************************************************************************* }
{ **************************** TCondRegs ********************************** }
{ ************************************************************************* }
Constructor TCondRegs.init;
Begin
End;
Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
Begin
End;
End.

View File

@ -0,0 +1,36 @@
{
Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
Development Team
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 aoptcpud;
{$i fpcdefs.inc}
interface
uses
aoptda;
type
TAOptDFACpu = class(TAOptDFA)
end;
implementation
end.

View File

@ -101,7 +101,7 @@ type
procedure a_op64_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64; setflags: boolean; var ovloc: tlocation); override;
end;
procedure create_codegen;
implementation
@ -336,20 +336,20 @@ begin
(ref.offset > simm16hi) then
begin
tmpreg := GetIntRegister(list, OS_INT);
reference_reset(tmpref);
reference_reset(tmpref,sizeof(aint));
tmpref.symbol := ref.symbol;
tmpref.offset := ref.offset;
tmpref.refaddr := addr_hi;
tmpref.refaddr := addr_high;
list.concat(taicpu.op_reg_ref(A_LUI, tmpreg, tmpref));
if (ref.offset = 0) and (ref.index = NR_NO) and
(ref.base = NR_NO) then
begin
ref.refaddr := addr_lo;
ref.refaddr := addr_low;
end
else
begin
{ Load the low part is left }
tmpref.refaddr := addr_lo;
tmpref.refaddr := addr_low;
list.concat(taicpu.op_reg_reg_ref(A_ADDIU, tmpreg, tmpreg, tmpref));
ref.offset := 0;
{ symbol is loaded }
@ -405,7 +405,7 @@ begin
assigned(ref.symbol) then
begin
tmpreg := GetIntRegister(list, OS_INT);
reference_reset(tmpref);
reference_reset(tmpref,sizeof(aint));
tmpref.symbol := ref.symbol;
tmpref.refaddr := addr_pic;
if not (pi_needs_got in current_procinfo.flags) then
@ -435,14 +435,14 @@ begin
tmpreg1 := GetIntRegister(list, OS_INT);
if assigned(ref.symbol) then
begin
reference_reset(tmpref);
reference_reset(tmpref,sizeof(aint));
tmpref.symbol := ref.symbol;
tmpref.offset := ref.offset;
tmpref.refaddr := addr_hi;
tmpref.refaddr := addr_high;
list.concat(taicpu.op_reg_ref(A_LUI, tmpreg1, tmpref));
{ Load the low part }
tmpref.refaddr := addr_lo;
tmpref.refaddr := addr_low;
list.concat(taicpu.op_reg_reg_ref(A_ADDIU, tmpreg1, tmpreg1, tmpref));
{ symbol is loaded }
ref.symbol := nil;
@ -554,7 +554,7 @@ begin
begin
if (Index = NR_SP) and (Offset < Target_info.first_parm_offset) then
InternalError(2002081104);
reference_reset_base(ref, index, offset);
reference_reset_base(ref, index, offset, sizeof(aint));
end;
a_load_const_ref(list, size, a, ref);
end;
@ -581,7 +581,7 @@ begin
begin
if (Index = NR_SP) and (Offset < Target_info.first_parm_offset) then
InternalError(2002081104);
reference_reset_base(ref, index, offset);
reference_reset_base(ref, index, offset, sizeof(aint));
end;
tmpreg := GetIntRegister(list, OS_INT);
a_load_ref_reg(list, sz, sz, r, tmpreg);
@ -607,7 +607,7 @@ begin
a_loadaddr_ref_reg(list, r, Register);
LOC_REFERENCE:
begin
reference_reset(ref);
reference_reset(ref,sizeof(aint));
ref.base := reference.index;
ref.offset := reference.offset;
tmpreg := GetAddressRegister(list);
@ -635,7 +635,7 @@ begin
a_load_ref_reg(list, hloc^.size, hloc^.size, href, hloc^.Register);
LOC_REFERENCE:
begin
reference_reset_base(href2, hloc^.reference.index, hloc^.reference.offset);
reference_reset_base(href2, hloc^.reference.index, hloc^.reference.offset, sizeof(aint));
a_load_ref_ref(list, hloc^.size, hloc^.size, href, href2);
end;
else
@ -651,16 +651,16 @@ procedure TCgMPSel.a_paramfpu_reg(list: tasmlist; size: tcgsize; const r: tregis
var
href: treference;
begin
tg.GetTemp(list, TCGSize2Size[size], tt_normal, href);
a_loadfpu_reg_ref(list, size, r, href);
tg.GetTemp(list, TCGSize2Size[size], sizeof(aint), tt_normal, href);
a_loadfpu_reg_ref(list, size, size, r, href);
a_paramfpu_ref(list, size, href, paraloc);
tg.Ungettemp(list, href);
end;
procedure TCgMPSel.a_call_name(list: tasmlist; const s: string);
procedure TCgMPSel.a_call_name(list: tasmlist; const s: string; weak: boolean);
begin
list.concat(taicpu.op_sym(A_JAL, objectlibrary.newasmsymbol(s, AB_EXTERNAL, AT_FUNCTION)));
list.concat(taicpu.op_sym(A_JAL,current_asmdata.RefAsmSymbol(s)));
{ Delay slot }
list.concat(taicpu.op_none(A_NOP));
end;
@ -827,7 +827,7 @@ begin
begin
tmpreg := r; //GetIntRegister(list, OS_ADDR);
r_used := true;
reference_reset(tmpref);
reference_reset(tmpref,sizeof(aint));
tmpref.symbol := href.symbol;
tmpref.refaddr := addr_pic;
if not (pi_needs_got in current_procinfo.flags) then
@ -858,13 +858,13 @@ begin
hreg := r
else
hreg := GetAddressRegister(list);
reference_reset(tmpref);
reference_reset(tmpref,sizeof(aint));
tmpref.symbol := href.symbol;
tmpref.offset := href.offset;
tmpref.refaddr := addr_hi;
tmpref.refaddr := addr_high;
list.concat(taicpu.op_reg_ref(A_LUI, hreg, tmpref));
{ Only the low part is left }
tmpref.refaddr := addr_lo;
tmpref.refaddr := addr_low;
list.concat(taicpu.op_reg_reg_ref(A_ADDIU, hreg, hreg, tmpref));
if href.base <> NR_NO then
begin
@ -880,8 +880,7 @@ begin
else
{ At least small offset, maybe base and maybe index }
if (href.offset >= simm16lo) and
(href.offset <= simm16hi)
then
(href.offset <= simm16hi) then
begin
if href.index <> NR_NO then { Both base and index }
begin
@ -903,8 +902,8 @@ begin
begin
list.concat(taicpu.op_reg_reg_const(A_ADDIU, r, href.base, href.offset));
end
else { only offset, can be generated by absolute }
else
{ only offset, can be generated by absolute }
a_load_const_reg(list, OS_ADDR, href.offset, r);
end
else
@ -920,10 +919,10 @@ var
begin
if reg1 <> reg2 then
begin
instr := taicpu.op_reg_reg(fpumovinstr[size], reg2, reg1);
instr := taicpu.op_reg_reg(fpumovinstr[tosize], reg2, reg1);
list.Concat(instr);
{ Notify the register allocator that we have written a move instruction so
it can try to eliminate it. }
{ Notify the register allocator that we have written a move instruction so
it can try to eliminate it. }
add_move_instruction(instr);
end;
end;
@ -934,15 +933,11 @@ var
tmpref: treference;
tmpreg: tregister;
begin
case size of
case tosize of
OS_F32:
begin
handle_load_store_fpu(list, False, A_LWC1, reg, ref);
end;
OS_F64:
begin
handle_load_store_fpu(list, False, A_LDC1, reg, ref);
end
else
InternalError(2007042701);
end;
@ -953,15 +948,11 @@ var
tmpref: treference;
tmpreg: tregister;
begin
case size of
case tosize of
OS_F32:
begin
handle_load_store_fpu(list, True, A_SWC1, reg, ref);
end;
OS_F64:
begin
handle_load_store_fpu(list, True, A_SDC1, reg, ref);
end
else
InternalError(2007042702);
end;
@ -1237,59 +1228,58 @@ begin
list.concat(taicpu.op_reg_const(A_LI, tmpreg, a));
end;
case cmp_op of
OC_EQ: { equality comparison }
list.concat(taicpu.op_reg_reg_sym(A_BEQ, reg, tmpreg, l));
OC_GT: { greater than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BGT, reg, tmpreg, l));
OC_LT: { less than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BLT, reg, tmpreg, l));
OC_GTE: { greater or equal than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BGE, reg, tmpreg, l));
OC_LTE: { less or equal than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BLE, reg, tmpreg, l));
OC_NE: { not equal }
list.concat(taicpu.op_reg_reg_sym(A_BNE, reg, tmpreg, l));
OC_BE: { less or equal than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BLEU, reg, tmpreg, l));
OC_B: { less than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BLTU, reg, tmpreg, l));
OC_AE: { greater or equal than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BGEU, reg, tmpreg, l));
OC_A: { greater than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BGTU, reg, tmpreg, l));
else
internalerror(200701071);
end;{ case }
OC_EQ: { equality comparison }
list.concat(taicpu.op_reg_reg_sym(A_BEQ, reg, tmpreg, l));
OC_GT: { greater than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BGT, reg, tmpreg, l));
OC_LT: { less than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BLT, reg, tmpreg, l));
OC_GTE: { greater or equal than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BGE, reg, tmpreg, l));
OC_LTE: { less or equal than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BLE, reg, tmpreg, l));
OC_NE: { not equal }
list.concat(taicpu.op_reg_reg_sym(A_BNE, reg, tmpreg, l));
OC_BE: { less or equal than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BLEU, reg, tmpreg, l));
OC_B: { less than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BLTU, reg, tmpreg, l));
OC_AE: { greater or equal than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BGEU, reg, tmpreg, l));
OC_A: { greater than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BGTU, reg, tmpreg, l));
else
internalerror(200701071);
end;
list.Concat(TAiCpu.Op_none(A_NOP));
end;
procedure TCgMPSel.a_cmp_reg_reg_label(list: tasmlist; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);
begin
case cmp_op of
OC_EQ: { equality comparison }
list.concat(taicpu.op_reg_reg_sym(A_BEQ, reg2, reg1, l));
OC_GT: { greater than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BGT, reg2, reg1, l));
OC_LT: { less than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BLT, reg2, reg1, l));
OC_GTE: { greater or equal than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BGE, reg2, reg1, l));
OC_LTE: { less or equal than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BLE, reg2, reg1, l));
OC_NE: { not equal }
list.concat(taicpu.op_reg_reg_sym(A_BNE, reg2, reg1, l));
OC_BE: { less or equal than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BLEU, reg2, reg1, l));
OC_B: { less than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BLTU, reg2, reg1, l));
OC_AE: { greater or equal than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BGEU, reg2, reg1, l));
OC_A: { greater than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BGTU, reg2, reg1, l));
else
internalerror(200701072);
OC_EQ: { equality comparison }
list.concat(taicpu.op_reg_reg_sym(A_BEQ, reg2, reg1, l));
OC_GT: { greater than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BGT, reg2, reg1, l));
OC_LT: { less than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BLT, reg2, reg1, l));
OC_GTE: { greater or equal than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BGE, reg2, reg1, l));
OC_LTE: { less or equal than (signed) }
list.concat(taicpu.op_reg_reg_sym(A_BLE, reg2, reg1, l));
OC_NE: { not equal }
list.concat(taicpu.op_reg_reg_sym(A_BNE, reg2, reg1, l));
OC_BE: { less or equal than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BLEU, reg2, reg1, l));
OC_B: { less than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BLTU, reg2, reg1, l));
OC_AE: { greater or equal than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BGEU, reg2, reg1, l));
OC_A: { greater than (unsigned) }
list.concat(taicpu.op_reg_reg_sym(A_BGTU, reg2, reg1, l));
else
internalerror(200701072);
end;{ case }
list.Concat(TAiCpu.Op_none(A_NOP));
end;
@ -1297,7 +1287,7 @@ end;
procedure TCgMPSel.a_jmp_always(List: tasmlist; l: TAsmLabel);
begin
List.Concat(TAiCpu.op_sym(A_J, objectlibrary.newasmsymbol(l.Name, AB_EXTERNAL, AT_FUNCTION)));
List.Concat(TAiCpu.op_sym(A_J,l));
{ Delay slot }
list.Concat(TAiCpu.Op_none(A_NOP));
end;
@ -1305,7 +1295,7 @@ end;
procedure TCgMPSel.a_jmp_name(list: tasmlist; const s: string);
begin
List.Concat(TAiCpu.op_sym(A_J, objectlibrary.newasmsymbol(s, AB_EXTERNAL, AT_FUNCTION)));
List.Concat(TAiCpu.op_sym(A_J, current_asmdata.RefAsmSymbol(s)));
{ Delay slot }
list.Concat(TAiCpu.Op_none(A_NOP));
end;
@ -1410,9 +1400,9 @@ var
localsize: aint;
begin
localsize := cgcpu_calc_stackframe_size;
if paramanager.ret_in_param(current_procinfo.procdef.rettype.def, current_procinfo.procdef.proccalloption) then
if paramanager.ret_in_param(current_procinfo.procdef.returndef, current_procinfo.procdef.proccalloption) then
begin
reference_reset(hr);
reference_reset(hr,sizeof(aint));
hr.offset := 12;
hr.refaddr := addr_full;
if nostackframe then
@ -1488,7 +1478,7 @@ begin
paramanager.freeparaloc(list, paraloc1);
alloccpuregisters(list, R_INTREGISTER, paramanager.get_volatile_registers_int(pocall_default));
alloccpuregisters(list, R_FPUREGISTER, paramanager.get_volatile_registers_fpu(pocall_default));
a_call_name(list, 'FPC_MOVE');
a_call_name(list, 'FPC_MOVE', false);
dealloccpuregisters(list, R_FPUREGISTER, paramanager.get_volatile_registers_fpu(pocall_default));
dealloccpuregisters(list, R_INTREGISTER, paramanager.get_volatile_registers_int(pocall_default));
paraloc3.done;
@ -1511,8 +1501,8 @@ begin
g_concatcopy_move(list, Source, dest, len)
else
begin
reference_reset(src);
reference_reset(dst);
reference_reset(src,sizeof(aint));
reference_reset(dst,sizeof(aint));
{ load the address of source into src.base }
src.base := GetAddressRegister(list);
a_loadaddr_ref_reg(list, Source, src.base);
@ -1532,7 +1522,7 @@ begin
a_load_const_reg(list, OS_INT, Count, countreg);
{ explicitely allocate R_O0 since it can be used safely here }
{ (for holding date that's being copied) }
objectlibrary.getlabel(lab);
current_asmdata.getjumplabel(lab);
a_label(list, lab);
list.concat(taicpu.op_reg_ref(A_LW, tmpreg1, src));
list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst));
@ -1595,8 +1585,8 @@ begin
g_concatcopy_move(list, Source, dest, len)
else
begin
reference_reset(src);
reference_reset(dst);
reference_reset(src,sizeof(aint));
reference_reset(dst,sizeof(aint));
{ load the address of source into src.base }
src.base := GetAddressRegister(list);
a_loadaddr_ref_reg(list, Source, src.base);
@ -1615,7 +1605,7 @@ begin
a_load_const_reg(list, OS_INT, len, countreg);
{ explicitely allocate R_O0 since it can be used safely here }
{ (for holding date that's being copied) }
objectlibrary.getlabel(lab);
current_asmdata.getjumplabel(lab);
a_label(list, lab);
list.concat(taicpu.op_reg_ref(A_LBU, tmpreg1, src));
list.concat(taicpu.op_reg_ref(A_SB, tmpreg1, dst));
@ -1646,7 +1636,7 @@ procedure TCgMPSel.g_intf_wrapper(list: tasmlist; procdef: tprocdef; const label
var
href: treference;
begin
reference_reset_base(href, NR_R2, 0); { return value }
reference_reset_base(href, NR_R2, 0, sizeof(aint)); { return value }
cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_R24);
end;
@ -1658,7 +1648,7 @@ procedure TCgMPSel.g_intf_wrapper(list: tasmlist; procdef: tprocdef; const label
if (procdef.extnumber=$ffff) then
Internalerror(200006139);
{ call/jmp vmtoffs(%eax) ; method offs }
reference_reset_base(href, NR_R24, procdef._class.vmtmethodoffset(procdef.extnumber));
reference_reset_base(href, NR_R24, procdef._class.vmtmethodoffset(procdef.extnumber), sizeof(aint));
cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_R24);
list.concat(taicpu.op_reg(A_JR, NR_R24));
end;
@ -1694,7 +1684,7 @@ begin
op_onr24methodaddr;
end
else
list.concat(taicpu.op_sym(A_B, objectlibrary.newasmsymbol(procdef.mangledname, AB_EXTERNAL, AT_FUNCTION)));
list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname)));
{ Delay slot }
list.Concat(TAiCpu.Op_none(A_NOP));
@ -1966,7 +1956,10 @@ begin
end;
begin
cg := TCgMPSel.Create;
cg64 := TCg64MPSel.Create;
procedure create_codegen;
begin
cg:=TCgMPSel.Create;
cg64:=TCg64MPSel.Create;
end;
end.

View File

@ -296,11 +296,21 @@ unit cpubase;
}
std_param_align = 4;
{*****************************************************************************
CPU Dependent Constants
*****************************************************************************}
const
simm16lo = -32768;
simm16hi = 32767;
{*****************************************************************************
Helpers
*****************************************************************************}
function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
{ Returns the tcgsize corresponding with the size of reg.}
function reg_cgsize(const reg: tregister) : tcgsize;
function cgsize2subreg(regtype: tregistertype; s:tcgsize):tsubregister;
@ -309,6 +319,10 @@ unit cpubase;
function std_regnum_search(const s:string):Tregister;
function std_regname(r:Tregister):string;
var
STK2_dummy: aint;
STK2_Localsize: aint;
implementation
uses
@ -386,6 +400,12 @@ unit cpubase;
end;
function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
begin
result := c1 = c2;
end;
function std_regnum_search(const s:string):Tregister;
begin
result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
@ -404,4 +424,7 @@ unit cpubase;
end;
begin
STK2_dummy := 10;
STK2_Localsize := 0;
end.

246
compiler/mips/cpugas.pas Normal file
View File

@ -0,0 +1,246 @@
{
Copyright (c) 1999-2009 by Florian Klaempfl and David Zhang
This unit implements an asmoutput class for MIPS assembly syntax
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 cpugas;
{$i fpcdefs.inc}
interface
uses
cpubase,
aasmtai, aasmcpu, assemble, aggas;
type
TGasMIPSEL = class(TGnuAssembler)
procedure WriteInstruction(hp: Tai); override;
end;
implementation
uses
cutils, systems,
verbose, itcpugas, cgbase, cgutils;
function GetReferenceString(var ref: TReference): string;
begin
GetReferenceString := '';
with ref do
begin
if (base = NR_NO) and (index = NR_NO) then
begin
if assigned(symbol) then
GetReferenceString := symbol.Name;
if offset > 0 then
GetReferenceString := GetReferenceString + '+' + ToStr(offset)
else if offset < 0 then
GetReferenceString := GetReferenceString + ToStr(offset);
case refaddr of
addr_hi:
GetReferenceString := '%hi(' + GetReferenceString + ')';
addr_lo:
GetReferenceString := '%lo(' + GetReferenceString + ')';
end;
end
else
begin
{$ifdef extdebug}
if assigned(symbol) and
not(refaddr in [addr_pic,addr_lo]) then
internalerror(2003052601);
{$endif extdebug}
if base <> NR_NO then
GetReferenceString := GetReferenceString + '(' + gas_regname(base) + ')';
if index = NR_NO then
begin
if offset <> 0 then
GetReferenceString := ToStr(offset) + GetReferenceString;
if assigned(symbol) then
begin
if refaddr = addr_lo then
GetReferenceString := '%lo(' + symbol.Name + ')' + GetReferenceString
else
GetReferenceString := symbol.Name + {'+' +} GetReferenceString;
end;
end
else
begin
{$ifdef extdebug}
if (Offset<>0) or assigned(symbol) then
internalerror(2003052603);
{$endif extdebug}
GetReferenceString := GetReferenceString + '(' + gas_regname(index) + ')';
end;
end;
end;
end;
function getopstr(const Oper: TOper): string;
begin
with Oper do
case typ of
top_reg:
getopstr := gas_regname(reg);
top_const:
getopstr := tostr(longint(val));
top_ref:
if (oper.ref^.refaddr in [addr_no, addr_pic]) or ((oper.ref^.refaddr = addr_lo) and ((oper.ref^.base <> NR_NO) or
(oper.ref^.index <> NR_NO))) then
getopstr := getreferencestring(ref^)
else
getopstr := getreferencestring(ref^);
else
internalerror(10001);
end;
end;
function getopstr_4(const Oper: TOper): string;
var
tmpref: treference;
begin
with Oper do
case typ of
top_ref:
begin
tmpref := ref^;
Inc(tmpref.offset, 4);
getopstr_4 := getreferencestring(tmpref);
end;
else
internalerror(2007050403);
end;
end;
procedure TGasMIPSEL.WriteInstruction(hp: Tai);
var
Op: TAsmOp;
s,s1: string;
i: integer;
tmpfpu: string;
tmpfpu_len: longint;
begin
if hp.typ <> ait_instruction then
exit;
op := taicpu(hp).opcode;
case op of
A_P_STK2:
begin
s1 := getopstr(taicpu(hp).oper[2]^);
STK2_LocalSize := align(STK2_LocalSize, 8);
if s1[1] = '-' then
str(-STK2_LocalSize, s1)
else
str(STK2_LocalSize, s1);
s := #9 + std_op2str[A_ADDIU] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[1]^) + ',' + s1;
AsmWriteLn(s);
end;
A_P_FRAME:
begin
end;
A_P_SET_MACRO:
begin
s := #9 + '.set' + #9 + 'macro';
AsmWriteLn(s);
end;
A_P_SET_REORDER:
begin
s := #9 + '.set' + #9 + 'reorder';
AsmWriteLn(s);
end;
A_P_SET_NOMACRO:
begin
s := #9 + '.set' + #9 + 'nomacro';
AsmWriteLn(s);
end;
A_P_SET_NOREORDER:
begin
s := #9 + '.set' + #9 + 'noreorder';
AsmWriteLn(s);
end;
A_P_SW:
begin
s := #9 + std_op2str[A_SW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
AsmWriteLn(s);
end;
A_P_LW:
begin
s := #9 + std_op2str[A_LW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
AsmWriteLn(s);
end;
A_LDC1:
begin
tmpfpu := getopstr(taicpu(hp).oper[0]^);
s := #9 + std_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
AsmWriteLn(s);
tmpfpu_len := length(tmpfpu);
tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
s := #9 + std_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
AsmWriteLn(s);
end;
A_SDC1:
begin
tmpfpu := getopstr(taicpu(hp).oper[0]^);
s := #9 + std_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
AsmWriteLn(s);
tmpfpu_len := length(tmpfpu);
tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
s := #9 + std_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
AsmWriteLn(s);
end;
else
begin
s := #9 + std_op2str[op] + cond2str[taicpu(hp).condition];
if taicpu(hp).delayslot_annulled then
s := s + ',a';
if taicpu(hp).ops > 0 then
begin
s := s + #9 + getopstr(taicpu(hp).oper[0]^);
for i := 1 to taicpu(hp).ops - 1 do
s := s + ',' + getopstr(taicpu(hp).oper[i]^);
end;
AsmWriteLn(s);
end;
end;
end;
const
as_MIPSEL_as_info: tasminfo =
(
id: as_gas;
idtxt: 'AS';
asmbin: 'as';
asmcmd: '-mips2 -W -EL -o $OBJ $ASM';
supported_target: system_any;
flags: [af_allowdirect, af_needar, af_smartlink_sections];
labelprefix: '.L';
comment: '# ';
);
begin
RegisterAssembler(as_MIPSEL_as_info, TGasMIPSEL);
end.

41
compiler/mips/cpunode.pas Normal file
View File

@ -0,0 +1,41 @@
{******************************************************************************
Copyright (c) 2000 by Florian Klaempfl
Includes the MIPS code generator
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 CpuNode;
{$I fpcdefs.inc}
interface
{ This unit is used to define the specific CPU implementations. All needed
actions are included in the INITALIZATION part of these units. This explains
the behaviour of such a unit having just a USES clause! }
implementation
uses
{ generic nodes }
ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgopt,ncgmat,ncgobjc,
{ to be able to only parts of the generic code,
the processor specific nodes must be included
after the generic one (FK)
}
ncpuadd,ncpucall,ncpumat,ncpuinln,ncpucnv,ncpuset;
end.

598
compiler/mips/ncpuadd.pas Normal file
View File

@ -0,0 +1,598 @@
{
Copyright (c) 2000-2009 by Florian Klaempfl and David Zhang
Code generation for add nodes on the FVM32
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 ncpuadd;
{$i fpcdefs.inc}
interface
uses
node, ncgadd, cpubase, aasmbase, cgbase;
type
tmipsaddnode = class(tcgaddnode)
private
function cmp64_lt(left_reg, right_reg: TRegister64): TRegister;
function cmp64_le(left_reg, right_reg: TRegister64): TRegister;
function cmp64_eq(left_reg, right_reg: TRegister64): TRegister;
function cmp64_ne(left_reg, right_reg: TRegister64): TRegister;
function cmp64_ltu(left_reg, right_reg: TRegister64): TRegister;
function cmp64_leu(left_reg, right_reg: TRegister64): TRegister;
function GetRes_register(unsigned: boolean; this_reg, left_reg, right_reg: TRegister): TRegister;
function GetRes64_register(unsigned: boolean; {this_reg,} left_reg, right_reg: TRegister64): TRegister;
protected
procedure second_addfloat; override;
procedure second_cmpfloat; override;
procedure second_cmpboolean; override;
procedure second_cmpsmallset; override;
procedure second_cmp64bit; override;
procedure second_cmpordinal; override;
end;
implementation
uses
systems,
cutils, verbose,
paramgr,
aasmtai, aasmcpu, aasmdata,
defutil,
{cgbase,} cgcpu, cgutils,
cpupara,
ncon, nset, nadd,
ncgutil, cgobj;
{*****************************************************************************
tmipsaddnode
*****************************************************************************}
function tmipsaddnode.GetRes_register(unsigned: boolean; this_reg, left_reg, right_reg: TRegister): TRegister;
var
tmp_asm_op: tasmop;
begin
case NodeType of
equaln:
tmp_asm_op := A_SEQ;
unequaln:
tmp_asm_op := A_SNE;
else
if not (unsigned) then
begin
if nf_swapped in flags then
case NodeType of
ltn:
tmp_asm_op := A_SGT;
lten:
tmp_asm_op := A_SGE;
gtn:
tmp_asm_op := A_SLT;
gten:
tmp_asm_op := A_SLE;
end
else
case NodeType of
ltn:
tmp_asm_op := A_SLT;
lten:
tmp_asm_op := A_SLE;
gtn:
tmp_asm_op := A_SGT;
gten:
tmp_asm_op := A_SGE;
end;
end
else
begin
if nf_swapped in Flags then
case NodeType of
ltn:
tmp_asm_op := A_SGTU;
lten:
tmp_asm_op := A_SGEU;
gtn:
tmp_asm_op := A_SLTU;
gten:
tmp_asm_op := A_SLEU;
end
else
case NodeType of
ltn:
tmp_asm_op := A_SLTU;
lten:
tmp_asm_op := A_SLEU;
gtn:
tmp_asm_op := A_SGTU;
gten:
tmp_asm_op := A_SGEU;
end;
end;
end;
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(tmp_asm_op, this_reg, left_reg, right_reg));
GetRes_register := this_reg;
end;
function tmipsaddnode.cmp64_eq(left_reg, right_reg: TRegister64): TRegister;
var
lfcmp64_L4: tasmlabel;
begin
objectlibrary.getlabel(lfcmp64_L4);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, left_reg.reghi, right_reg.reghi, lfcmp64_L4));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_sym(A_BNE, left_reg.reglo, right_reg.reglo, lfcmp64_L4));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4);
cmp64_eq := NR_TCR10;
end;
function tmipsaddnode.cmp64_ne(left_reg, right_reg: TRegister64): TRegister;
var
lfcmp64_L4: tasmlabel;
begin
objectlibrary.getlabel(lfcmp64_L4);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, left_reg.reghi, right_reg.reghi, lfcmp64_L4));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_sym(A_BNE, left_reg.reglo, right_reg.reglo, lfcmp64_L4));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4);
cmp64_ne := NR_TCR10;
end;
function tmipsaddnode.cmp64_lt(left_reg, right_reg: TRegister64): TRegister;
var
lfcmp64_L4, lfcmp64_L5: tasmlabel;
begin
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
objectlibrary.getlabel(lfcmp64_L4);
objectlibrary.getlabel(lfcmp64_L5);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLT, NR_TCR11, left_reg.reghi, right_reg.reghi));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, left_reg.reghi, right_reg.reghi, lfcmp64_L4));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, left_reg.reglo, right_reg.reglo));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_B, lfcmp64_L4));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L5);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4);
cmp64_lt := NR_TCR10;
end;
function tmipsaddnode.cmp64_le(left_reg, right_reg: TRegister64): TRegister;
var
lfcmp64_L4, lfcmp64_L5: tasmlabel;
begin
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
objectlibrary.getlabel(lfcmp64_L4);
objectlibrary.getlabel(lfcmp64_L5);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLT, NR_TCR11, right_reg.reghi, left_reg.reghi));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, right_reg.reghi, left_reg.reghi, lfcmp64_L5));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, right_reg.reglo, left_reg.reglo));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L5);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4);
cmp64_le := NR_TCR10;
end;
function tmipsaddnode.cmp64_ltu(left_reg, right_reg: TRegister64): TRegister;
var
lfcmp64_L4, lfcmp64_L5: tasmlabel;
begin
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
objectlibrary.getlabel(lfcmp64_L4);
objectlibrary.getlabel(lfcmp64_L5);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, left_reg.reghi, right_reg.reghi));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, left_reg.reghi, right_reg.reghi, lfcmp64_L4));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, left_reg.reglo, right_reg.reglo));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_B, lfcmp64_L4));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L5);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4);
cmp64_ltu := NR_TCR10;
end;
function tmipsaddnode.cmp64_leu(left_reg, right_reg: TRegister64): TRegister;
var
lfcmp64_L4, lfcmp64_L5: tasmlabel;
begin
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
objectlibrary.getlabel(lfcmp64_L4);
objectlibrary.getlabel(lfcmp64_L5);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, right_reg.reghi, left_reg.reghi));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, right_reg.reghi, left_reg.reghi, lfcmp64_L5));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, right_reg.reglo, left_reg.reglo));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L5);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4);
cmp64_leu := NR_TCR10;
end;
function tmipsaddnode.GetRes64_register(unsigned: boolean; //this_reg: TRegister;
left_reg, right_reg: TRegister64): TRegister;
var
tmpreg: TRegister;
lfcmp64_L4, lfcmp_L5: tasmlabel;
begin
case NodeType of
equaln:
begin
GetRes64_register := cmp64_eq(left_reg, right_reg);
end;
unequaln:
GetRes64_register := cmp64_ne(left_reg, right_reg);
else
if not (unsigned) then
begin
if nf_swapped in flags then
case NodeType of
ltn:
GetRes64_register := cmp64_lt(right_reg, left_reg);
lten:
GetRes64_register := cmp64_le(right_reg, left_reg);
gtn:
GetRes64_register := cmp64_lt(left_reg, right_reg);
gten:
GetRes64_register := cmp64_le(left_reg, right_reg);
end
else
case NodeType of
ltn:
GetRes64_register := cmp64_lt(left_reg, right_reg);
lten:
GetRes64_register := cmp64_le(left_reg, right_reg);
gtn:
GetRes64_register := cmp64_lt(right_reg, left_reg);
gten:
GetRes64_register := cmp64_le(right_reg, left_reg);
end;
end
else
begin
if nf_swapped in Flags then
case NodeType of
ltn:
GetRes64_register := cmp64_ltu(right_reg, left_reg);
lten:
GetRes64_register := cmp64_leu(right_reg, left_reg);
gtn:
GetRes64_register := cmp64_ltu(left_reg, right_reg);
gten:
GetRes64_register := cmp64_leu(left_reg, right_reg);
end
else
case NodeType of
ltn:
GetRes64_register := cmp64_ltu(left_reg, right_reg);
lten:
GetRes64_register := cmp64_leu(left_reg, right_reg);
gtn:
GetRes64_register := cmp64_ltu(right_reg, left_reg);
gten:
GetRes64_register := cmp64_leu(right_reg, left_reg);
end;
end;
end;
end;
procedure tmipsaddnode.second_addfloat;
var
op: TAsmOp;
begin
pass_left_right;
if (nf_swapped in flags) then
swapleftright;
{ force fpureg as location, left right doesn't matter
as both will be in a fpureg }
location_force_fpureg(current_asmdata.CurrAsmList, left.location, True);
location_force_fpureg(current_asmdata.CurrAsmList, right.location, (left.location.loc <> LOC_CFPUREGISTER));
location_reset(location, LOC_FPUREGISTER, def_cgsize(resultdef));
if left.location.loc <> LOC_CFPUREGISTER then
location.Register := left.location.Register
else
location.Register := right.location.Register;
case nodetype of
addn:
begin
if location.size = OS_F64 then
op := A_ADD_D
else
op := A_ADD_S;
end;
muln:
begin
if location.size = OS_F64 then
op := A_MUL_D
else
op := A_MUL_S;
end;
subn:
begin
if location.size = OS_F64 then
op := A_SUB_D
else
op := A_SUB_S;
end;
slashn:
begin
if location.size = OS_F64 then
op := A_DIV_D
else
op := A_DIV_S;
end;
else
internalerror(200306014);
end;
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
location.Register, left.location.Register, right.location.Register));
end;
procedure tmipsaddnode.second_cmpfloat;
var
op: tasmop;
lfcmptrue, lfcmpfalse: tasmlabel;
begin
pass_left_right;
if nf_swapped in flags then
swapleftright;
{ force fpureg as location, left right doesn't matter
as both will be in a fpureg }
location_force_fpureg(current_asmdata.CurrAsmList, left.location, True);
location_force_fpureg(current_asmdata.CurrAsmList, right.location, True);
location_reset(location, LOC_REGISTER, OS_INT);
location.Register := NR_TCR0;
case NodeType of
equaln:
begin
if left.location.size = OS_F64 then
op := A_C_EQ_D
else
op := A_C_EQ_S;
objectlibrary.getlabel(lfcmpfalse);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1F, lfcmpfalse)); //lfcmpfalse
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
cg.a_label(current_asmdata.CurrAsmList, lfcmpfalse);
end;
unequaln:
begin
if left.location.size = OS_F64 then
op := A_C_EQ_D
else
op := A_C_EQ_S;
objectlibrary.getlabel(lfcmpfalse);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1F, lfcmpfalse));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
cg.a_label(current_asmdata.CurrAsmList, lfcmpfalse);
end;
ltn:
begin
if left.location.size = OS_F64 then
op := A_C_LT_D
else
op := A_C_LT_S;
objectlibrary.getlabel(lfcmptrue);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
cg.a_label(current_asmdata.CurrAsmList, lfcmptrue);
end;
lten:
begin
if left.location.size = OS_F64 then
op := A_C_LE_D
else
op := A_C_LE_S;
objectlibrary.getlabel(lfcmptrue);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
cg.a_label(current_asmdata.CurrAsmList, lfcmptrue);
end;
gtn:
begin
if left.location.size = OS_F64 then
op := A_C_LT_D
else
op := A_C_LT_S;
objectlibrary.getlabel(lfcmptrue);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, right.location.Register, left.location.Register));
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
cg.a_label(current_asmdata.CurrAsmList, lfcmptrue);
end;
gten:
begin
if left.location.size = OS_F64 then
op := A_C_LE_D
else
op := A_C_LE_S;
objectlibrary.getlabel(lfcmptrue);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, right.location.Register, left.location.Register));
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
cg.a_label(current_asmdata.CurrAsmList, lfcmptrue);
end;
end; {case}
end;
procedure tmipsaddnode.second_cmpboolean;
var
tmp_right_reg: TRegister;
begin
pass_left_right;
force_reg_left_right(True, True);
tmp_right_reg := NR_NO;
if right.location.loc = LOC_CONSTANT then
begin
tmp_right_reg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, tmp_right_reg, right.location.Value));
end
else
begin
tmp_right_reg := right.location.Register;
end;
location_reset(location, LOC_REGISTER, OS_INT);
location.Register := GetRes_register(True, NR_TCR0, left.location.Register, tmp_right_reg);
end;
procedure tmipsaddnode.second_cmpsmallset;
var
tmp_right_reg: TRegister;
begin
pass_left_right;
force_reg_left_right(True, True);
tmp_right_reg := NR_NO;
if right.location.loc = LOC_CONSTANT then
begin
tmp_right_reg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, tmp_right_reg, right.location.Value));
end
else
begin
tmp_right_reg := right.location.Register;
end;
location_reset(location, LOC_REGISTER, OS_INT);
location.Register := GetRes_register(True, NR_TCR0, left.location.Register, tmp_right_reg);
end;
procedure tmipsaddnode.second_cmp64bit;
var
unsigned : boolean;
tmp_left_reg: TRegister;
begin
pass_left_right;
force_reg_left_right(false,false);
unsigned:=not(is_signed(left.resultdef)) or
not(is_signed(right.resultdef));
location_reset(location, LOC_REGISTER, OS_INT);
location.Register := GetRes64_register(unsigned, {NR_TCR0, }left.location.register64, right.location.register64); // NR_TCR0;
end;
procedure tmipsaddnode.second_cmpordinal;
var
unsigned: boolean;
tmp_right_reg: TRegister;
begin
pass_left_right;
force_reg_left_right(True, True);
unsigned := not (is_signed(left.resultdef)) or not (is_signed(right.resultdef));
tmp_right_reg := NR_NO;
if right.location.loc = LOC_CONSTANT then
begin
tmp_right_reg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, tmp_right_reg, right.location.Value));
end
else
begin
tmp_right_reg := right.location.Register;
end;
location_reset(location, LOC_REGISTER, OS_INT);
location.Register := getres_register(unsigned, NR_TCR0, left.location.Register, tmp_right_reg);
end;
begin
caddnode := tmipsaddnode;
end.

View File

@ -488,8 +488,10 @@ implementation
hregister:=cg.getintregister(list,OS_INT);
{ load value in low register }
case l.loc of
{$ifdef cpuflags}
LOC_FLAGS :
cg.g_flags2reg(list,OS_INT,l.resflags,hregister);
{$endif cpuflags}
LOC_JUMP :
begin
cg.a_label(list,current_procinfo.CurrTrueLabel);
@ -574,8 +576,10 @@ implementation
hregister := l.register;
{ load value in new register }
case l.loc of
{$ifdef cpuflags}
LOC_FLAGS :
cg.g_flags2reg(list,dst_size,l.resflags,hregister);
{$endif cpuflags}
LOC_JUMP :
begin
cg.a_label(list,current_procinfo.CurrTrueLabel);

View File

@ -1805,10 +1805,9 @@ unit rgobj;
end;
procedure Trgobj.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
var ins:Taicpu;
procedure trgobj.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
var
ins:Taicpu;
begin
ins:=spilling_create_load(spilltemp,tempreg);
add_cpu_interferences(ins);
@ -1817,9 +1816,8 @@ unit rgobj;
procedure Trgobj.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
var ins:Taicpu;
var
ins:Taicpu;
begin
ins:=spilling_create_store(tempreg,spilltemp);
add_cpu_interferences(ins);