2
$Id: nppcadd.pas,v 1.43 2004/03/18 16:19:03 peter Exp $
3
Copyright (c) 2000-2002 by Florian Klaempfl and Jonas Maebe
5
Code generation for add nodes on the PowerPC
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
****************************************************************************
30
node,nadd,ncgadd,cpubase;
33
tppcaddnode = class(tcgaddnode)
34
function pass_1: tnode; override;
35
procedure pass_2;override;
37
procedure pass_left_and_right;
38
procedure load_left_right(cmpop, load_constants: boolean);
39
function getresflags : tresflags;
40
procedure emit_compare(unsigned : boolean);
41
procedure second_addfloat;override;
42
procedure second_addboolean;override;
43
procedure second_addsmallset;override;
45
procedure second_addmmx;override;
47
procedure second_add64bit;override;
54
cutils,verbose,globals,
55
symconst,symdef,paramgr,
56
aasmbase,aasmtai,aasmcpu,defutil,htypechk,
57
cgbase,cpuinfo,pass_1,pass_2,regvars,
60
ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
63
{*****************************************************************************
65
*****************************************************************************}
67
function tppcaddnode.pass_1: tnode;
69
if (nodetype in [equaln,unequaln]) and
70
is_64bit(left.resulttype.def) then
75
expectloc := LOC_FLAGS;
76
calcregisters(self,2,0,0);
79
result := inherited pass_1;
83
{*****************************************************************************
85
*****************************************************************************}
87
procedure tppcaddnode.pass_left_and_right;
92
{ calculate the operator which is more difficult }
95
{ in case of constant put it to the left }
96
if (left.nodetype=ordconstn) then
101
{ are too few registers free? }
102
if location.loc=LOC_FPUREGISTER then
103
pushedfpu:=maybe_pushfpu(exprasmlist,right.registersfpu,left.location)
109
tmpreg := cg.getfpuregister(exprasmlist,left.location.size);
110
cg.a_loadfpu_loc_reg(exprasmlist,left.location,tmpreg);
111
location_reset(left.location,LOC_FPUREGISTER,left.location.size);
112
left.location.register := tmpreg;
117
procedure tppcaddnode.load_left_right(cmpop, load_constants: boolean);
119
procedure load_node(var n: tnode);
121
case n.location.loc of
125
location.register := n.location.register;
126
if is_64bit(n.resulttype.def) then
127
location.registerhigh := n.location.registerhigh;
129
LOC_REFERENCE,LOC_CREFERENCE:
131
location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
134
location.register := n.location.register;
135
if is_64bit(n.resulttype.def) then
136
location.registerhigh := n.location.registerhigh;
141
if load_constants then
143
location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
145
location.register := n.location.register;
146
if is_64bit(n.resulttype.def) then
147
location.registerhigh := n.location.registerhigh;
157
(location.register = NR_NO) then
159
location.register := cg.getintregister(exprasmlist,OS_INT);
160
if is_64bit(resulttype.def) then
161
location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
166
function tppcaddnode.getresflags : tresflags;
168
if (left.resulttype.def.deftype <> floatdef) then
173
equaln : result.flag:=F_EQ;
174
unequaln : result.flag:=F_NE;
176
if nf_swaped in flags then
178
ltn : result.flag:=F_GT;
179
lten : result.flag:=F_GE;
180
gtn : result.flag:=F_LT;
181
gten : result.flag:=F_LE;
185
ltn : result.flag:=F_LT;
186
lten : result.flag:=F_LE;
187
gtn : result.flag:=F_GT;
188
gten : result.flag:=F_GE;
194
procedure tppcaddnode.emit_compare(unsigned: boolean);
200
// get the constant on the right if there is one
201
if (left.location.loc = LOC_CONSTANT) then
203
// can we use an immediate, or do we have to load the
204
// constant in a register first?
205
if (right.location.loc = LOC_CONSTANT) then
208
if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.valueqword)<>0) and ((hi(right.location.valueqword)<>$ffffffff) or unsigned) then
209
internalerror(2002080301);
211
if (nodetype in [equaln,unequaln]) then
213
(right.location.value > high(word))) or
215
(longint(right.location.value) < low(smallint)) or
216
(longint(right.location.value) > high(smallint))) then
217
{ we can then maybe use a constant in the 'othersigned' case
218
(the sign doesn't matter for // equal/unequal)}
219
unsigned := not unsigned;
222
((right.location.value) <= high(word))) or
224
(longint(right.location.value) >= low(smallint)) and
225
(longint(right.location.value) <= high(smallint))) then
230
tmpreg := cg.getintregister(exprasmlist,OS_INT);
231
cg.a_load_const_reg(exprasmlist,OS_INT,
232
aword(right.location.value),tmpreg);
237
location.loc := LOC_FLAGS;
238
location.resflags := getresflags;
250
if (right.location.loc = LOC_CONSTANT) then
252
exprasmlist.concat(taicpu.op_reg_const(op,
253
left.location.register,longint(right.location.value)))
256
exprasmlist.concat(taicpu.op_reg_reg(op,
257
left.location.register,tmpreg));
258
cg.ungetregister(exprasmlist,tmpreg);
261
exprasmlist.concat(taicpu.op_reg_reg(op,
262
left.location.register,right.location.register));
266
{*****************************************************************************
268
*****************************************************************************}
270
procedure tppcaddnode.second_addboolean;
278
{ calculate the operator which is more difficult }
282
if (torddef(left.resulttype.def).typ=bool8bit) or
283
(torddef(right.resulttype.def).typ=bool8bit) then
286
if (torddef(left.resulttype.def).typ=bool16bit) or
287
(torddef(right.resulttype.def).typ=bool16bit) then
292
if (cs_full_boolean_eval in aktlocalswitches) or
293
(nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
295
if left.nodetype in [ordconstn,realconstn] then
298
isjump:=(left.expectloc=LOC_JUMP);
302
objectlibrary.getlabel(truelabel);
304
objectlibrary.getlabel(falselabel);
307
if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
308
location_force_reg(exprasmlist,left.location,cgsize,false);
314
else if left.location.loc=LOC_JUMP then
315
internalerror(2003122901);
317
isjump:=(right.expectloc=LOC_JUMP);
321
objectlibrary.getlabel(truelabel);
323
objectlibrary.getlabel(falselabel);
326
if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
327
location_force_reg(exprasmlist,right.location,cgsize,false);
333
else if right.location.loc=LOC_JUMP then
334
internalerror(200312292);
336
cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
338
{ set result location }
340
location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
342
location_reset(location,LOC_FLAGS,OS_NO);
344
load_left_right(cmpop,false);
346
if (left.location.loc = LOC_CONSTANT) then
354
if (right.location.loc <> LOC_CONSTANT) then
355
exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,
356
left.location.register,right.location.register))
358
exprasmlist.concat(taicpu.op_reg_const(A_CMPLWI,
359
left.location.register,longint(right.location.value)));
360
location.resflags := getresflags;
372
internalerror(200203247);
375
if right.location.loc <> LOC_CONSTANT then
376
cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
377
left.location.register,right.location.register,
380
cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
381
aword(right.location.value),left.location.register,
388
// just to make sure we free the right registers
394
location_reset(location,LOC_JUMP,OS_NO);
399
objectlibrary.getlabel(truelabel);
401
maketojumpbool(exprasmlist,left,lr_load_regvars);
402
cg.a_label(exprasmlist,truelabel);
408
objectlibrary.getlabel(falselabel);
410
maketojumpbool(exprasmlist,left,lr_load_regvars);
411
cg.a_label(exprasmlist,falselabel);
415
internalerror(200403181);
418
maketojumpbool(exprasmlist,right,lr_load_regvars);
423
release_reg_left_right;
427
{*****************************************************************************
429
*****************************************************************************}
431
procedure tppcaddnode.second_addfloat;
455
internalerror(200403182);
458
// get the operands in the correct order, there are no special cases
459
// here, everything is register-based
460
if nf_swaped in flags then
463
// put both operands in a register
464
location_force_fpureg(exprasmlist,right.location,true);
465
location_force_fpureg(exprasmlist,left.location,true);
467
// initialize de result
470
location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
471
if left.location.loc = LOC_FPUREGISTER then
472
location.register := left.location.register
473
else if right.location.loc = LOC_FPUREGISTER then
474
location.register := right.location.register
476
location.register := cg.getfpuregister(exprasmlist,location.size);
480
location_reset(location,LOC_FLAGS,OS_NO);
481
location.resflags := getresflags;
484
// emit the actual operation
487
exprasmlist.concat(taicpu.op_reg_reg_reg(op,
488
location.register,left.location.register,
489
right.location.register))
493
exprasmlist.concat(taicpu.op_reg_reg_reg(op,
494
newreg(R_SPECIALREGISTER,location.resflags.cr,R_SUBNONE),left.location.register,right.location.register))
497
release_reg_left_right;
500
{*****************************************************************************
502
*****************************************************************************}
504
procedure tppcaddnode.second_addsmallset;
513
{ when a setdef is passed, it has to be a smallset }
514
if ((left.resulttype.def.deftype=setdef) and
515
(tsetdef(left.resulttype.def).settype<>smallset)) or
516
((right.resulttype.def.deftype=setdef) and
517
(tsetdef(right.resulttype.def).settype<>smallset)) then
518
internalerror(200203301);
521
cmpop:=nodetype in [equaln,unequaln,lten,gten];
523
{ set result location }
525
location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
527
location_reset(location,LOC_FLAGS,OS_NO);
529
load_left_right(cmpop,false);
532
(location.register = NR_NO) then
533
location.register := cg.getintregister(exprasmlist,OS_INT);
538
if (nf_swaped in flags) and (left.nodetype=setelementn) then
540
{ are we adding set elements ? }
541
if right.nodetype=setelementn then
543
{ no range support for smallsets! }
544
if assigned(tsetelementnode(right).right) then
545
internalerror(43244);
546
if (right.location.loc = LOC_CONSTANT) then
547
cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
548
aword(1 shl aword(right.location.value)),
549
left.location.register,location.register)
552
tmpreg := cg.getintregister(exprasmlist,OS_INT);
553
cg.a_load_const_reg(exprasmlist,OS_INT,1,tmpreg);
554
cg.a_op_reg_reg(exprasmlist,OP_SHL,OS_INT,
555
right.location.register,tmpreg);
556
if left.location.loc <> LOC_CONSTANT then
557
cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_INT,tmpreg,
558
left.location.register,location.register)
560
cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
561
aword(left.location.value),tmpreg,location.register);
562
cg.ungetregister(exprasmlist,tmpreg);
576
if (not(nf_swaped in flags)) then
577
if (right.location.loc=LOC_CONSTANT) then
578
right.location.value := not(right.location.value)
581
else if (left.location.loc=LOC_CONSTANT) then
582
left.location.value := not(left.location.value)
590
if left.location.loc = LOC_CONSTANT then
592
tmpreg := cg.getintregister(exprasmlist,OS_INT);
593
cg.a_load_const_reg(exprasmlist,OS_INT,
594
aword(left.location.value),tmpreg);
595
exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
596
location.register,tmpreg,right.location.register));
597
cg.ungetregister(exprasmlist,tmpreg);
600
exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
601
location.register,left.location.register,
602
right.location.register));
613
If (not(nf_swaped in flags) and
614
(nodetype = lten)) or
615
((nf_swaped in flags) and
616
(nodetype = gten)) then
618
// now we have to check whether left >= right
619
tmpreg := cg.getintregister(exprasmlist,OS_INT);
620
if left.location.loc = LOC_CONSTANT then
622
cg.a_op_const_reg_reg(exprasmlist,OP_AND,OS_INT,
623
not(left.location.value),right.location.register,tmpreg);
624
exprasmlist.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0));
625
// the two instructions above should be folded together by
626
// the peepholeoptimizer
630
if right.location.loc = LOC_CONSTANT then
632
cg.a_load_const_reg(exprasmlist,OS_INT,
633
aword(right.location.value),tmpreg);
634
exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
635
tmpreg,left.location.register));
638
exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
639
right.location.register,left.location.register));
641
cg.ungetregister(exprasmlist,tmpreg);
642
location.resflags.cr := RS_CR0;
643
location.resflags.flag := F_EQ;
647
internalerror(2002072701);
652
// these are all commutative operations
653
if (left.location.loc = LOC_CONSTANT) then
655
if (right.location.loc = LOC_CONSTANT) then
656
cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
657
aword(right.location.value),left.location.register,
660
cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
661
right.location.register,left.location.register,
665
release_reg_left_right;
668
{*****************************************************************************
670
*****************************************************************************}
672
procedure tppcaddnode.second_add64bit;
682
procedure emit_cmp64_hi;
685
oldleft, oldright: tlocation;
687
// put the high part of the location in the low part
688
location_copy(oldleft,left.location);
689
location_copy(oldright,right.location);
690
if left.location.loc = LOC_CONSTANT then
691
left.location.valueqword := left.location.valueqword shr 32
693
left.location.registerlow := left.location.registerhigh;
694
if right.location.loc = LOC_CONSTANT then
695
right.location.valueqword := right.location.valueqword shr 32
697
right.location.registerlow := right.location.registerhigh;
699
// and call the normal emit_compare
700
emit_compare(unsigned);
701
location_copy(left.location,oldleft);
702
location_copy(right.location,oldright);
706
procedure emit_cmp64_lo;
713
procedure firstjmp64bitcmp;
716
oldnodetype: tnodetype;
719
load_all_regvars(exprasmlist);
721
{ the jump the sequence is a little bit hairy }
725
cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
726
{ cheat a little bit for the negative test }
727
toggleflag(nf_swaped);
728
cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
729
toggleflag(nf_swaped);
733
oldnodetype:=nodetype;
734
if nodetype=lten then
738
cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
739
{ cheat for the negative test }
744
cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
745
nodetype:=oldnodetype;
749
nodetype := unequaln;
750
cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
755
cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
761
procedure secondjmp64bitcmp;
764
{ the jump the sequence is a little bit hairy }
768
{ the comparison of the low dword always has }
769
{ to be always unsigned! }
770
cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
771
cg.a_jmp_always(exprasmlist,falselabel);
775
nodetype := unequaln;
776
cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
777
cg.a_jmp_always(exprasmlist,truelabel);
782
cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
783
cg.a_jmp_always(exprasmlist,falselabel);
790
tempreg64: tregister64;
798
unsigned:=((left.resulttype.def.deftype=orddef) and
799
(torddef(left.resulttype.def).typ=u64bit)) or
800
((right.resulttype.def.deftype=orddef) and
801
(torddef(right.resulttype.def).typ=u64bit));
826
{ should be handled in pass_1 (JM) }
827
internalerror(200109051);
830
internalerror(2002072705);
834
location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
836
load_left_right(cmpop,(cs_check_overflow in aktlocalswitches) and
837
(nodetype in [addn,subn]));
839
if not(cs_check_overflow in aktlocalswitches) or
840
not(nodetype in [addn,subn]) then
853
// instead of doing a complicated compare, do
854
// (left.hi xor right.hi) or (left.lo xor right.lo)
855
// (somewhate optimized so that no superfluous 'mr's are
857
if (left.location.loc = LOC_CONSTANT) then
859
if (right.location.loc = LOC_CONSTANT) then
861
if left.location.loc = LOC_REGISTER then
863
tempreg64.reglo := left.location.registerlow;
864
tempreg64.reghi := left.location.registerhigh;
868
if (aword(right.location.valueqword) <> 0) then
869
tempreg64.reglo := cg.getintregister(exprasmlist,OS_32)
871
tempreg64.reglo := left.location.registerlow;
872
if ((right.location.valueqword shr 32) <> 0) then
873
tempreg64.reghi := cg.getintregister(exprasmlist,OS_32)
875
tempreg64.reghi := left.location.registerhigh;
878
if (aword(right.location.valueqword) <> 0) then
879
{ negative values can be handled using SUB, }
880
{ positive values < 65535 using XOR. }
881
if (longint(right.location.valueqword) >= -32767) and
882
(longint(right.location.valueqword) < 0) then
883
cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
884
aword(right.location.valueqword),
885
left.location.registerlow,tempreg64.reglo)
887
cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
888
aword(right.location.valueqword),
889
left.location.registerlow,tempreg64.reglo);
891
if ((right.location.valueqword shr 32) <> 0) then
892
if (longint(right.location.valueqword shr 32) >= -32767) and
893
(longint(right.location.valueqword shr 32) < 0) then
894
cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
895
aword(right.location.valueqword shr 32),
896
left.location.registerhigh,tempreg64.reghi)
898
cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
899
aword(right.location.valueqword shr 32),
900
left.location.registerhigh,tempreg64.reghi);
904
tempreg64.reglo := cg.getintregister(exprasmlist,OS_INT);
905
tempreg64.reghi := cg.getintregister(exprasmlist,OS_INT);
906
cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,
907
left.location.register64,right.location.register64,
911
cg.a_reg_alloc(exprasmlist,NR_R0);
912
exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR_,NR_R0,
913
tempreg64.reglo,tempreg64.reghi));
914
cg.a_reg_dealloc(exprasmlist,NR_R0);
915
if (tempreg64.reglo <> left.location.registerlow) then
916
cg.ungetregister(exprasmlist,tempreg64.reglo);
917
if (tempreg64.reghi <> left.location.registerhigh) then
918
cg.ungetregister(exprasmlist,tempreg64.reghi);
920
location_reset(location,LOC_FLAGS,OS_NO);
921
location.resflags := getresflags;
925
if (location.registerlow = NR_NO) then
927
location.registerlow := cg.getintregister(exprasmlist,OS_INT);
928
location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
931
if (left.location.loc = LOC_CONSTANT) then
933
if (right.location.loc = LOC_CONSTANT) then
934
cg64.a_op64_const_reg_reg(exprasmlist,op,right.location.valueqword,
935
left.location.register64,location.register64)
937
cg64.a_op64_reg_reg_reg(exprasmlist,op,right.location.register64,
938
left.location.register64,location.register64);
942
if (nf_swaped in flags) then
945
if left.location.loc <> LOC_CONSTANT then
947
if (location.registerlow = NR_NO) then
949
location.registerlow := cg.getintregister(exprasmlist,OS_INT);
950
location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
952
if right.location.loc <> LOC_CONSTANT then
954
cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
955
right.location.register64,left.location.register64,
959
cg64.a_op64_const_reg_reg(exprasmlist,OP_SUB,
960
right.location.valueqword,left.location.register64,
963
else if ((left.location.valueqword shr 32) = 0) then
965
if (location.registerlow = NR_NO) then
967
location.registerlow := cg.getintregister(exprasmlist,OS_INT);
968
location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
970
if (int64(left.location.valueqword) >= low(smallint)) and
971
(int64(left.location.valueqword) <= high(smallint)) then
974
exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
975
location.registerlow,right.location.registerlow,
976
aword(left.location.value)));
981
location_force_reg(exprasmlist,left.location,
983
exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBC,
984
location.registerlow,left.location.registerlow,
985
right.location.registerlow));
987
exprasmlist.concat(taicpu.op_reg_reg(A_SUBFZE,
988
location.registerhigh,right.location.registerhigh));
990
else if (aword(left.location.valueqword) = 0) then
992
// (const32 shl 32) - reg64
993
if (location.registerlow = NR_NO) then
995
location.registerlow := cg.getintregister(exprasmlist,OS_INT);
996
location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
998
exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
999
location.registerlow,right.location.registerlow,0));
1000
left.location.valueqword := left.location.valueqword shr 32;
1001
location_force_reg(exprasmlist,left.location,OS_32,true);
1002
exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBFE,
1003
location.registerhigh,right.location.registerhigh,
1004
left.location.register));
1009
location_force_reg(exprasmlist,left.location,
1010
def_cgsize(left.resulttype.def),false);
1011
if (left.location.loc = LOC_REGISTER) then
1012
location.register64 := left.location.register64
1013
else if (location.registerlow = NR_NO) then
1015
location.registerlow := cg.getintregister(exprasmlist,OS_INT);
1016
location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
1018
cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
1019
right.location.register64,left.location.register64,
1020
location.register64);
1024
internalerror(2002072803);
1029
if is_signed(resulttype.def) then
1043
internalerror(2002072806);
1061
exprasmlist.concat(taicpu.op_reg_reg_reg(op1,location.registerlow,
1062
left.location.registerlow,right.location.registerlow));
1063
exprasmlist.concat(taicpu.op_reg_reg_reg(op2,location.registerhigh,
1064
right.location.registerhigh,left.location.registerhigh));
1065
if not(is_signed(resulttype.def)) then
1066
if nodetype = addn then
1067
exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.registerhigh,left.location.registerhigh))
1069
exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.registerhigh,location.registerhigh));
1070
cg.g_overflowcheck(exprasmlist,location,resulttype.def);
1073
{ set result location }
1074
{ (emit_compare sets it to LOC_FLAGS for compares, so set the }
1075
{ real location only now) (JM) }
1077
not(nodetype in [equaln,unequaln]) then
1078
location_reset(location,LOC_JUMP,OS_NO);
1080
release_reg_left_right;
1085
{*****************************************************************************
1087
*****************************************************************************}
1089
{$ifdef SUPPORT_MMX}
1090
procedure ti386addnode.second_addmmx;
1095
hregister : tregister;
1097
pass_left_and_right;
1100
mmxbase:=mmx_type(left.resulttype.def);
1104
if (cs_mmx_saturation in aktlocalswitches) then
1111
mmxs16bit,mmxfixed16:
1122
mmxs16bit,mmxu16bit,mmxfixed16:
1124
mmxs32bit,mmxu32bit:
1132
mmxs16bit,mmxu16bit:
1140
if (cs_mmx_saturation in aktlocalswitches) then
1147
mmxs16bit,mmxfixed16:
1158
mmxs16bit,mmxu16bit,mmxfixed16:
1160
mmxs32bit,mmxu32bit:
1172
internalerror(200403183);
1175
{ left and right no register? }
1176
{ then one must be demanded }
1177
if (left.location.loc<>LOC_MMXREGISTER) then
1179
if (right.location.loc=LOC_MMXREGISTER) then
1181
location_swap(left.location,right.location);
1182
toggleflag(nf_swaped);
1186
{ register variable ? }
1187
if (left.location.loc=LOC_CMMXREGISTER) then
1189
hregister:=rg.getregistermm(exprasmlist);
1190
emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
1194
if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
1195
internalerror(200203245);
1197
location_release(exprasmlist,left.location);
1199
hregister:=rg.getregistermm(exprasmlist);
1200
emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
1203
location_reset(left.location,LOC_MMXREGISTER,OS_NO);
1204
left.location.register:=hregister;
1208
{ at this point, left.location.loc should be LOC_MMXREGISTER }
1209
if right.location.loc<>LOC_MMXREGISTER then
1211
if (nodetype=subn) and (nf_swaped in flags) then
1213
if right.location.loc=LOC_CMMXREGISTER then
1215
emit_reg_reg(A_MOVQ,S_NO,right.location.register,R_MM7);
1216
emit_reg_reg(op,S_NO,left.location.register,R_MM7);
1217
emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
1221
if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
1222
internalerror(200203247);
1223
emit_ref_reg(A_MOVQ,S_NO,right.location.reference,R_MM7);
1224
emit_reg_reg(op,S_NO,left.location.register,R_MM7);
1225
emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
1226
location_release(exprasmlist,right.location);
1231
if (right.location.loc=LOC_CMMXREGISTER) then
1233
emit_reg_reg(op,S_NO,right.location.register,left.location.register);
1237
if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
1238
internalerror(200203246);
1239
emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
1240
location_release(exprasmlist,right.location);
1246
{ right.location=LOC_MMXREGISTER }
1247
if (nodetype=subn) and (nf_swaped in flags) then
1249
emit_reg_reg(op,S_NO,left.location.register,right.location.register);
1250
location_swap(left.location,right.location);
1251
toggleflag(nf_swaped);
1255
emit_reg_reg(op,S_NO,right.location.register,left.location.register);
1259
location_freetemp(exprasmlist,right.location);
1260
location_release(exprasmlist,right.location);
1263
location_freetemp(exprasmlist,left.location);
1264
location_release(exprasmlist,left.location);
1266
set_result_location(cmpop,true);
1268
{$endif SUPPORT_MMX}
1271
{*****************************************************************************
1273
*****************************************************************************}
1275
procedure tppcaddnode.pass_2;
1276
{ is also being used for xor, and "mul", "sub, or and comparative }
1285
{ true, if unsigned types are compared }
1289
{ to make it more readable, string and set (not smallset!) have their
1291
case left.resulttype.def.deftype of
1294
{ handling boolean expressions }
1295
if is_boolean(left.resulttype.def) and
1296
is_boolean(right.resulttype.def) then
1301
{ 64bit operations }
1302
else if is_64bit(left.resulttype.def) then
1310
internalerror(2002072402);
1315
{ normalsets are already handled in pass1 }
1316
if (tsetdef(left.resulttype.def).settype<>smallset) then
1317
internalerror(200109041);
1323
{$ifdef SUPPORT_MMX}
1324
if is_mmx_able_array(left.resulttype.def) then
1329
{$endif SUPPORT_MMX}
1339
cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
1340
unsigned:=not(is_signed(left.resulttype.def)) or
1341
not(is_signed(right.resulttype.def));
1343
pass_left_and_right;
1345
{ Convert flags to register first }
1346
{ can any of these things be in the flags actually?? (JM) }
1348
if (left.location.loc = LOC_FLAGS) or
1349
(right.location.loc = LOC_FLAGS) then
1350
internalerror(2002072602);
1352
{ set result location }
1354
location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
1356
location_reset(location,LOC_FLAGS,OS_NO);
1358
load_left_right(cmpop, (cs_check_overflow in aktlocalswitches) and
1359
(nodetype in [addn,subn,muln]));
1361
if (location.register = NR_NO) and
1363
location.register := cg.getintregister(exprasmlist,OS_INT);
1365
if not(cs_check_overflow in aktlocalswitches) or
1367
(nodetype in [orn,andn,xorn]) then
1370
addn, muln, xorn, orn, andn:
1387
if (left.location.loc = LOC_CONSTANT) then
1389
if (right.location.loc <> LOC_CONSTANT) then
1390
cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
1391
left.location.register,right.location.register,
1394
cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
1395
aword(right.location.value),left.location.register,
1400
if (nf_swaped in flags) then
1402
if left.location.loc <> LOC_CONSTANT then
1403
if right.location.loc <> LOC_CONSTANT then
1404
cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
1405
right.location.register,left.location.register,
1408
cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
1409
aword(right.location.value),left.location.register,
1412
if (longint(left.location.value) >= low(smallint)) and
1413
(longint(left.location.value) <= high(smallint)) then
1415
exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
1416
location.register,right.location.register,
1417
longint(left.location.value)));
1421
tmpreg := cg.getintregister(exprasmlist,OS_INT);
1422
cg.a_load_const_reg(exprasmlist,OS_INT,
1423
aword(left.location.value),tmpreg);
1424
cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
1425
right.location.register,tmpreg,location.register);
1426
cg.ungetregister(exprasmlist,tmpreg);
1429
ltn,lten,gtn,gten,equaln,unequaln :
1431
emit_compare(unsigned);
1436
// overflow checking is on and we have an addn, subn or muln
1438
if is_signed(resulttype.def) then
1448
internalerror(2002072601);
1450
exprasmlist.concat(taicpu.op_reg_reg_reg(op,location.register,
1451
left.location.register,right.location.register));
1452
cg.g_overflowcheck(exprasmlist,location,resulttype.def);
1459
exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD,location.register,
1460
left.location.register,right.location.register));
1461
exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.register,left.location.register));
1462
cg.g_overflowcheck(exprasmlist,location,resulttype.def);
1466
exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUB,location.register,
1467
left.location.register,right.location.register));
1468
exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.register,location.register));
1469
cg.g_overflowcheck(exprasmlist,location,resulttype.def);
1473
{ calculate the upper 32 bits of the product, = 0 if no overflow }
1474
exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULHWU_,location.register,
1475
left.location.register,right.location.register));
1476
{ calculate the real result }
1477
exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULLW,location.register,
1478
left.location.register,right.location.register));
1479
{ g_overflowcheck generates a OC_AE instead of OC_EQ :/ }
1480
objectlibrary.getlabel(hl);
1481
tcgppc(cg).a_jmp_cond(exprasmlist,OC_EQ,hl);
1482
cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
1483
cg.a_label(exprasmlist,hl);
1489
release_reg_left_right;
1493
caddnode:=tppcaddnode;
1496
$Log: nppcadd.pas,v $
1497
Revision 1.43 2004/03/18 16:19:03 peter
1498
* fixed operator overload allowing for pointer-string
1499
* replaced some type_e_mismatch with more informational messages
1501
Revision 1.42 2004/01/06 21:37:41 peter
1502
* fixed too long ie number
1504
Revision 1.41 2003/12/29 11:35:19 jonas
1505
* hopefully fixed tb0454
1507
Revision 1.40 2003/12/09 20:39:43 jonas
1508
* forgot call to cg.g_overflowcheck() in nppcadd
1509
* fixed overflow flag definition
1510
* fixed cg.g_overflowcheck() for signed numbers (jump over call to
1511
FPC_OVERFLOW if *no* overflow instead of if overflow :)
1513
Revision 1.39 2003/12/08 21:18:44 jonas
1514
* fixed usigned overflow checking
1516
Revision 1.38 2003/10/17 14:52:07 peter
1519
Revision 1.37 2003/10/17 01:22:08 florian
1520
* compilation of the powerpc compiler fixed
1522
Revision 1.36 2003/10/01 20:34:49 peter
1523
* procinfo unit contains tprocinfo
1524
* cginfo renamed to cgbase
1525
* moved cgmessage to verbose
1526
* fixed ppc and sparc compiles
1528
Revision 1.35 2003/09/03 19:39:16 peter
1529
* removed empty cga unit
1531
Revision 1.34 2003/09/03 19:35:24 peter
1532
* powerpc compiles again
1534
Revision 1.33 2003/06/14 22:32:43 jonas
1535
* ppc compiles with -dnewra, haven't tried to compile anything with it
1538
Revision 1.32 2003/06/04 11:58:58 jonas
1539
* calculate localsize also in g_return_from_proc since it's now called
1540
before g_stackframe_entry (still have to fix macos)
1541
* compilation fixes (cycle doesn't work yet though)
1543
Revision 1.31 2003/06/01 21:38:06 peter
1544
* getregisterfpu size parameter added
1545
* op_const_reg size parameter added
1548
Revision 1.30 2003/05/30 18:49:14 jonas
1549
* fixed problem where sometimes no register was allocated for the result
1550
of an addnode when using regvars
1552
Revision 1.29 2003/04/27 11:55:34 jonas
1553
* fixed overflow checking form of 64bit add instruction
1555
Revision 1.28 2003/04/27 11:06:06 jonas
1556
* fixed 64bit "const - reg/ref" bugs
1558
Revision 1.27 2003/04/24 22:29:58 florian
1559
* fixed a lot of PowerPC related stuff
1561
Revision 1.26 2003/04/23 22:18:01 peter
1562
* fixes to get rtl compiled
1564
Revision 1.25 2003/04/23 12:35:35 florian
1565
* fixed several issues with powerpc
1566
+ applied a patch from Jonas for nested function calls (PowerPC only)
1569
Revision 1.24 2003/03/11 21:46:24 jonas
1570
* lots of new regallocator fixes, both in generic and ppc-specific code
1571
(ppc compiler still can't compile the linux system unit though)
1573
Revision 1.23 2003/03/10 18:11:41 olle
1574
* changed ungetregister to ungetregisterint in tppcaddnode.clear_left_right
1576
Revision 1.22 2003/02/19 22:00:16 daniel
1577
* Code generator converted to new register notation
1578
- Horribily outdated todo.txt removed
1580
Revision 1.21 2003/01/08 18:43:58 daniel
1581
* Tregister changed into a record
1583
Revision 1.20 2002/11/25 17:43:27 peter
1584
* splitted defbase in defutil,symutil,defcmp
1585
* merged isconvertable and is_equal into compare_defs(_ext)
1586
* made operator search faster by walking the list only once
1588
Revision 1.19 2002/10/21 18:08:05 jonas
1589
* some range errors fixed
1591
Revision 1.18 2002/09/08 14:14:49 jonas
1592
* more optimizations for 64bit compares
1594
Revision 1.17 2002/09/07 22:15:48 jonas
1595
* fixed optimized 64 compares
1597
Revision 1.16 2002/09/04 19:42:45 jonas
1598
* fixed bugs in 64bit operations (registers weren't always allocated for
1600
* optimized 'const64 - reg64/mem64'
1601
* optimized equaln/unequaln with 64bit values (change them to
1602
'(left.hi xor right.hi) or (left.lo xor right.lo)' so there are less
1603
branches and the result can be returned in the flags this way. Could
1604
be done for the i386 too probably.
1606
Revision 1.15 2002/08/31 21:30:46 florian
1607
* fixed several problems caused by Jonas' commit :)
1609
Revision 1.14 2002/08/31 19:26:20 jonas
1610
* fixed 64bit comparisons
1612
Revision 1.13 2002/08/17 22:09:47 florian
1613
* result type handling in tcgcal.pass_2 overhauled
1614
* better tnode.dowrite
1615
* some ppc stuff fixed
1617
Revision 1.12 2002/08/14 18:41:48 jonas
1618
- remove valuelow/valuehigh fields from tlocation, because they depend
1619
on the endianess of the host operating system -> difficult to get
1620
right. Use lo/hi(location.valueqword) instead (remember to use
1621
valueqword and not value!!)
1623
Revision 1.11 2002/08/11 14:32:32 peter
1624
* renamed current_library to objectlibrary
1626
Revision 1.10 2002/08/11 13:24:18 peter
1627
* saving of asmsymbols in ppu supported
1628
* asmsymbollist global is removed and moved into a new class
1629
tasmlibrarydata that will hold the info of a .a file which
1630
corresponds with a single module. Added librarydata to tmodule
1631
to keep the library info stored for the module. In the future the
1632
objectfiles will also be stored to the tasmlibrarydata class
1633
* all getlabel/newasmsymbol and friends are moved to the new class
1635
Revision 1.9 2002/08/11 11:40:16 jonas
1636
* some overflow checking fixes
1638
Revision 1.8 2002/08/11 06:14:40 florian
1639
* fixed powerpc compilation problems
1641
Revision 1.7 2002/08/10 17:15:31 jonas
1642
* various fixes and optimizations
1644
Revision 1.6 2002/08/06 20:55:24 florian
1645
* first part of ppc calling conventions fix
1647
Revision 1.5 2002/08/05 08:58:54 jonas
1648
* fixed compilation problems
1650
Revision 1.4 2002/08/04 12:57:56 jonas
1651
* more misc. fixes, mostly constant-related
1653
Revision 1.3 2002/07/28 16:02:49 jonas
1654
+ 64 bit operations (badly tested), everything is implemented now!
1657
Revision 1.2 2002/07/27 20:00:59 jonas
1658
+ second_addboolean(), second_addfloat() and second_addsmallset()
1659
(64bit stuff is all that's left to do)
1661
Revision 1.1 2002/07/26 12:31:57 jonas
1662
+ intial implementation of add nodes, only integer/enumeration/pointer/...
1663
handling is finished