mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-01 16:22:47 +02:00
+ full JVM implementation for add-nodes and mat-nodes, except for
u64bit division/mod, and no overflow checking for divisions (none yet for add nodes either, but that has to be implemented in hlcgcpu rather than in the add-nodes themselves) git-svn-id: branches/jvmbackend@18331 -
This commit is contained in:
parent
e9f1856a61
commit
f250d5d494
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -218,7 +218,9 @@ compiler/jvm/cputarg.pas svneol=native#text/plain
|
||||
compiler/jvm/hlcgcpu.pas svneol=native#text/plain
|
||||
compiler/jvm/itcpujas.pas svneol=native#text/plain
|
||||
compiler/jvm/jvmreg.dat svneol=native#text/plain
|
||||
compiler/jvm/njvmadd.pas svneol=native#text/plain
|
||||
compiler/jvm/njvmcal.pas svneol=native#text/plain
|
||||
compiler/jvm/njvmmat.pas svneol=native#text/plain
|
||||
compiler/jvm/rgcpu.pas svneol=native#text/plain
|
||||
compiler/jvm/rjvmcon.inc svneol=native#text/plain
|
||||
compiler/jvm/rjvmnor.inc svneol=native#text/plain
|
||||
|
@ -32,7 +32,7 @@ implementation
|
||||
uses
|
||||
ncgbas,ncgflw,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,
|
||||
ncgadd, ncgcal,ncgmat,ncginl,
|
||||
njvmcal
|
||||
njvmadd,njvmcal,njvmmat
|
||||
{ ncpuadd,ncpucall,ncpumat,ncpuinln,ncpucnv,ncpuset, }
|
||||
{ this not really a node }
|
||||
{ rgcpu},tgcpu;
|
||||
|
249
compiler/jvm/njvmadd.pas
Normal file
249
compiler/jvm/njvmadd.pas
Normal file
@ -0,0 +1,249 @@
|
||||
{
|
||||
Copyright (c) 2000-2011 by Florian Klaempfl and Jonas Maebe
|
||||
|
||||
Code generation for add nodes on the JVM
|
||||
|
||||
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 njvmadd;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
cgbase,
|
||||
node,ncgadd,cpubase;
|
||||
|
||||
type
|
||||
|
||||
{ njvmadd }
|
||||
|
||||
tjvmaddnode = class(tcgaddnode)
|
||||
protected
|
||||
function pass_1: tnode;override;
|
||||
|
||||
function cmpnode2signedtopcmp: TOpCmp;
|
||||
|
||||
procedure second_generic_compare;
|
||||
|
||||
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,procinfo,
|
||||
aasmtai,aasmdata,aasmcpu,defutil,
|
||||
hlcgobj,hlcgcpu,cgutils,
|
||||
cpupara,
|
||||
ncon,nset,nadd,
|
||||
cgobj;
|
||||
|
||||
{*****************************************************************************
|
||||
tjvmaddnode
|
||||
*****************************************************************************}
|
||||
|
||||
function tjvmaddnode.pass_1: tnode;
|
||||
begin
|
||||
result:=inherited pass_1;
|
||||
if expectloc=LOC_FLAGS then
|
||||
expectloc:=LOC_JUMP;
|
||||
end;
|
||||
|
||||
|
||||
function tjvmaddnode.cmpnode2signedtopcmp: TOpCmp;
|
||||
begin
|
||||
case nodetype of
|
||||
gtn: result:=OC_GT;
|
||||
gten: result:=OC_GTE;
|
||||
ltn: result:=OC_LT;
|
||||
lten: result:=OC_LTE;
|
||||
equaln: result:=OC_EQ;
|
||||
unequaln: result:=OC_NE;
|
||||
else
|
||||
internalerror(2011010412);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure tjvmaddnode.second_generic_compare;
|
||||
begin
|
||||
pass_left_right;
|
||||
if (nf_swapped in flags) then
|
||||
swapleftright;
|
||||
location_reset(location,LOC_JUMP,OS_NO);
|
||||
|
||||
if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
|
||||
hlcg.a_cmp_loc_reg_label(current_asmdata.CurrAsmList,left.resultdef,cmpnode2signedtopcmp,left.location,right.location.register,current_procinfo.CurrTrueLabel)
|
||||
else case left.location.loc of
|
||||
LOC_REGISTER,LOC_CREGISTER:
|
||||
hlcg.a_cmp_reg_loc_label(current_asmdata.CurrAsmList,left.resultdef,cmpnode2signedtopcmp,left.location.register,right.location,current_procinfo.CurrTrueLabel);
|
||||
LOC_REFERENCE,LOC_CREFERENCE:
|
||||
hlcg.a_cmp_ref_loc_label(current_asmdata.CurrAsmList,left.resultdef,cmpnode2signedtopcmp,left.location.reference,right.location,current_procinfo.CurrTrueLabel);
|
||||
LOC_CONSTANT:
|
||||
hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,left.resultdef,cmpnode2signedtopcmp,left.location.value,right.location,current_procinfo.CurrTrueLabel);
|
||||
else
|
||||
internalerror(2011010413);
|
||||
end;
|
||||
hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
|
||||
end;
|
||||
|
||||
|
||||
procedure tjvmaddnode.second_addfloat;
|
||||
var
|
||||
op : TAsmOp;
|
||||
begin
|
||||
pass_left_right;
|
||||
if (nf_swapped in flags) then
|
||||
swapleftright;
|
||||
|
||||
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
|
||||
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location);
|
||||
|
||||
location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
|
||||
location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
|
||||
|
||||
case nodetype of
|
||||
addn :
|
||||
begin
|
||||
if location.size=OS_F64 then
|
||||
op:=a_dadd
|
||||
else
|
||||
op:=a_fadd;
|
||||
end;
|
||||
muln :
|
||||
begin
|
||||
if location.size=OS_F64 then
|
||||
op:=a_dmul
|
||||
else
|
||||
op:=a_fmul;
|
||||
end;
|
||||
subn :
|
||||
begin
|
||||
if location.size=OS_F64 then
|
||||
op:=a_dsub
|
||||
else
|
||||
op:=a_fsub;
|
||||
end;
|
||||
slashn :
|
||||
begin
|
||||
if location.size=OS_F64 then
|
||||
op:=a_ddiv
|
||||
else
|
||||
op:=a_fdiv;
|
||||
end;
|
||||
else
|
||||
internalerror(2011010402);
|
||||
end;
|
||||
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_none(op));
|
||||
thlcgjvm(hlcg).decstack(1+ord(location.size=OS_F64));
|
||||
{ could be optimized in the future by keeping the results on the stack,
|
||||
if we add code to swap the operands when necessary (a_swap for
|
||||
singles, store/load/load for doubles since there is no swap for
|
||||
2-slot elements -- also adjust expectloc in that case! }
|
||||
thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
|
||||
end;
|
||||
|
||||
|
||||
procedure tjvmaddnode.second_cmpfloat;
|
||||
var
|
||||
op : tasmop;
|
||||
begin
|
||||
pass_left_right;
|
||||
if (nf_swapped in flags) then
|
||||
swapleftright;
|
||||
location_reset(location,LOC_JUMP,OS_NO);
|
||||
|
||||
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
|
||||
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location);
|
||||
|
||||
{ compares two floating point values and puts 1/0/-1 on stack depending
|
||||
on whether value1 >/=/< value2 }
|
||||
if left.location.size=OS_F64 then
|
||||
op:=a_dcmpl
|
||||
else
|
||||
op:=a_fcmpl;
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_none(op));
|
||||
thlcgjvm(hlcg).decstack((1+ord(left.location.size=OS_F64))*2-1);
|
||||
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcmp2if[cmpnode2signedtopcmp],current_procinfo.CurrTrueLabel));
|
||||
thlcgjvm(hlcg).decstack(1);
|
||||
hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
|
||||
end;
|
||||
|
||||
|
||||
procedure tjvmaddnode.second_cmpboolean;
|
||||
begin
|
||||
second_generic_compare;
|
||||
end;
|
||||
|
||||
|
||||
procedure tjvmaddnode.second_cmpsmallset;
|
||||
begin
|
||||
if (nodetype in [equaln,unequaln]) then
|
||||
begin
|
||||
second_generic_compare;
|
||||
exit;
|
||||
end;
|
||||
case nodetype of
|
||||
lten,gten:
|
||||
begin
|
||||
pass_left_right;
|
||||
If (not(nf_swapped in flags) and
|
||||
(nodetype=lten)) or
|
||||
((nf_swapped in flags) and
|
||||
(nodetype=gten)) then
|
||||
swapleftright;
|
||||
location_reset(location,LOC_JUMP,OS_NO);
|
||||
// now we have to check whether left >= right:
|
||||
// (right and not(left)=0)
|
||||
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
|
||||
thlcgjvm(hlcg).a_op_reg_stack(current_asmdata.CurrAsmList,OP_NOT,left.resultdef,NR_NO);
|
||||
thlcgjvm(hlcg).a_op_loc_stack(current_asmdata.CurrAsmList,OP_AND,right.resultdef,right.location);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_ifeq,current_procinfo.CurrTrueLabel));
|
||||
thlcgjvm(hlcg).decstack(1);
|
||||
hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
|
||||
end;
|
||||
else
|
||||
internalerror(2011010414);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure tjvmaddnode.second_cmp64bit;
|
||||
begin
|
||||
second_generic_compare;
|
||||
end;
|
||||
|
||||
|
||||
procedure tjvmaddnode.second_cmpordinal;
|
||||
begin
|
||||
second_generic_compare;
|
||||
end;
|
||||
|
||||
begin
|
||||
caddnode:=tjvmaddnode;
|
||||
end.
|
199
compiler/jvm/njvmmat.pas
Normal file
199
compiler/jvm/njvmmat.pas
Normal file
@ -0,0 +1,199 @@
|
||||
{
|
||||
Copyright (c) 1998-2011 by Florian Klaempfl and Jonas Maebe
|
||||
|
||||
Generate JVM code for math nodes
|
||||
|
||||
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 njvmmat;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
node,nmat,ncgmat;
|
||||
|
||||
type
|
||||
tjvmmoddivnode = class(tmoddivnode)
|
||||
procedure pass_generate_code;override;
|
||||
end;
|
||||
|
||||
tjvmshlshrnode = class(tshlshrnode)
|
||||
procedure pass_generate_code;override;
|
||||
end;
|
||||
|
||||
tjvmnotnode = class(tcgnotnode)
|
||||
procedure second_boolean;override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
globtype,systems,constexp,
|
||||
cutils,verbose,globals,
|
||||
symconst,symdef,
|
||||
aasmbase,aasmcpu,aasmtai,aasmdata,
|
||||
defutil,
|
||||
cgbase,cgobj,pass_2,procinfo,
|
||||
ncon,
|
||||
cpubase,
|
||||
hlcgobj,hlcgcpu,cgutils;
|
||||
|
||||
{*****************************************************************************
|
||||
tjvmmoddivnode
|
||||
*****************************************************************************}
|
||||
|
||||
procedure tjvmmoddivnode.pass_generate_code;
|
||||
var
|
||||
op: topcg;
|
||||
isu32int: boolean;
|
||||
begin
|
||||
secondpass(left);
|
||||
secondpass(right);
|
||||
location_reset(location,LOC_REGISTER,left.location.size);
|
||||
location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
|
||||
|
||||
|
||||
if nodetype=divn then
|
||||
begin
|
||||
{ TODO: overflow checking in case of high(longint) or high(int64) div -1 }
|
||||
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
|
||||
if is_signed(resultdef) then
|
||||
op:=OP_IDIV
|
||||
else
|
||||
op:=OP_DIV;
|
||||
thlcgjvm(hlcg).a_op_loc_stack(current_asmdata.CurrAsmList,op,right.resultdef,right.location)
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ must be handled via a helper }
|
||||
if torddef(resultdef).ordtype=u64bit then
|
||||
internalerror(2011010416);
|
||||
if (torddef(resultdef).ordtype<>u32bit) then
|
||||
begin
|
||||
isu32int:=false;
|
||||
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
|
||||
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location);
|
||||
end
|
||||
else
|
||||
begin
|
||||
isu32int:=true;
|
||||
if left.location.loc=LOC_CONSTANT then
|
||||
thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,s64inttype,left.location.value,R_INTREGISTER)
|
||||
else
|
||||
begin
|
||||
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
|
||||
thlcgjvm(hlcg).resize_stack_int_val(current_asmdata.CurrAsmList,OS_32,OS_S64,false);
|
||||
end;
|
||||
if right.location.loc=LOC_CONSTANT then
|
||||
thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,s64inttype,right.location.value,R_INTREGISTER)
|
||||
else
|
||||
begin
|
||||
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location);
|
||||
thlcgjvm(hlcg).resize_stack_int_val(current_asmdata.CurrAsmList,OS_32,OS_S64,false);
|
||||
end;
|
||||
end;
|
||||
if isu32int or
|
||||
(torddef(resultdef).ordtype=s64bit) then
|
||||
begin
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_lrem));
|
||||
thlcgjvm(hlcg).decstack(2);
|
||||
end
|
||||
else
|
||||
begin
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_irem));
|
||||
thlcgjvm(hlcg).decstack(1);
|
||||
end;
|
||||
if isu32int then
|
||||
thlcgjvm(hlcg).resize_stack_int_val(current_asmdata.CurrAsmList,OS_S64,OS_32,false);
|
||||
end;
|
||||
thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
tjvmshlshrnode
|
||||
*****************************************************************************}
|
||||
|
||||
procedure tjvmshlshrnode.pass_generate_code;
|
||||
var
|
||||
op : topcg;
|
||||
begin
|
||||
secondpass(left);
|
||||
secondpass(right);
|
||||
location_reset(location,LOC_REGISTER,left.location.size);
|
||||
location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
|
||||
|
||||
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
|
||||
if nodetype=shln then
|
||||
op:=OP_SHL
|
||||
else
|
||||
op:=OP_SHR;
|
||||
thlcgjvm(hlcg).a_op_loc_stack(current_asmdata.CurrAsmList,op,right.resultdef,right.location);
|
||||
thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
tjvmnotnode
|
||||
*****************************************************************************}
|
||||
|
||||
procedure tjvmnotnode.second_boolean;
|
||||
var
|
||||
hl : tasmlabel;
|
||||
begin
|
||||
{ if the location is LOC_JUMP, we do the secondpass after the
|
||||
labels are allocated
|
||||
}
|
||||
if left.expectloc=LOC_JUMP then
|
||||
begin
|
||||
hl:=current_procinfo.CurrTrueLabel;
|
||||
current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
|
||||
current_procinfo.CurrFalseLabel:=hl;
|
||||
secondpass(left);
|
||||
hlcg.maketojumpbool(current_asmdata.CurrAsmList,left);
|
||||
hl:=current_procinfo.CurrTrueLabel;
|
||||
current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
|
||||
current_procinfo.CurrFalseLabel:=hl;
|
||||
location.loc:=LOC_JUMP;
|
||||
end
|
||||
else
|
||||
begin
|
||||
secondpass(left);
|
||||
case left.location.loc of
|
||||
LOC_REGISTER, LOC_CREGISTER,
|
||||
LOC_REFERENCE, LOC_CREFERENCE:
|
||||
begin
|
||||
location_reset(location,LOC_REGISTER,left.location.size);
|
||||
location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
|
||||
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
|
||||
thlcgjvm(hlcg).a_op_reg_stack(current_asmdata.CurrAsmList,OP_NOT,left.resultdef,NR_NO);
|
||||
thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
|
||||
end;
|
||||
else
|
||||
internalerror(2011010417);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
cmoddivnode:=tjvmmoddivnode;
|
||||
cshlshrnode:=tjvmshlshrnode;
|
||||
cnotnode:=tjvmnotnode;
|
||||
end.
|
Loading…
Reference in New Issue
Block a user