mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 05:08:06 +02:00
* more MIPS code of David Zhang integrated
git-svn-id: trunk@14228 -
This commit is contained in:
parent
2ef18ba527
commit
0c8546f94c
14
.gitattributes
vendored
14
.gitattributes
vendored
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
41
compiler/mips/aoptcpu.pas
Normal 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
119
compiler/mips/aoptcpub.pas
Normal 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.
|
36
compiler/mips/aoptcpud.pas
Normal file
36
compiler/mips/aoptcpud.pas
Normal 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.
|
@ -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.
|
||||
|
@ -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
246
compiler/mips/cpugas.pas
Normal 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
41
compiler/mips/cpunode.pas
Normal 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
598
compiler/mips/ncpuadd.pas
Normal 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.
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user