2
$Id: cpupara.pas,v 1.38 2004/03/15 14:39:56 mazen Exp $
3
Copyright (c) 1998-2002 by Florian Klaempfl
5
Calling conventions for the SPARC
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.
20
*****************************************************************************}
32
symconst,symbase,symtype,symdef,paramgr,cgbase;
35
TSparcParaManager=class(TParaManager)
36
function copy_value_on_stack(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
37
function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
38
function get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override;
39
function get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
40
{Returns a structure giving the information on the storage of the parameter
41
(which must be an integer parameter)
42
@param(nr Parameter number of routine, starting from 1)}
43
function getintparaloc(calloption : tproccalloption; nr : longint) : tparalocation;override;
44
procedure allocparaloc(list: taasmoutput; const loc: tparalocation);override;
45
procedure freeparaloc(list: taasmoutput; const loc: tparalocation);override;
46
function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
47
function create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargspara):longint;override;
48
procedure splitparaloc64(const locpara:tparalocation;var loclopara,lochipara:tparalocation);override;
50
procedure init_values(var curintreg :tsuperregister; var cur_stack_offset: aWord);
51
function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; firstpara: tparaitem;
52
var curintreg: tsuperregister; var cur_stack_offset: aword):longint;
61
function TSparcParaManager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
67
function tsparcparamanager.get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;
69
result:=[RS_F0..RS_F31];
73
function TSparcParaManager.GetIntParaLoc(calloption : tproccalloption; nr : longint) : tparalocation;
76
InternalError(2002100806);
77
FillChar(GetIntParaLoc,SizeOf(TParaLocation),0);
78
result.lochigh:=LOC_INVALID;
82
{ The six first parameters are passed into registers }
86
register:=newreg(R_INTREGISTER,(RS_O0+nr),R_SUBWHOLE);
89
{ The other parameters are passed on the stack }
92
reference.index:=NR_STACK_POINTER_REG;
93
reference.offset:=92+(nr-6)*4;
100
function getparaloc(p : tdef) : tcgloc;
103
{ Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
104
if push_addr_param for the def is true
108
getparaloc:=LOC_REGISTER;
110
getparaloc:=LOC_FPUREGISTER;
112
getparaloc:=LOC_REGISTER;
114
getparaloc:=LOC_REGISTER;
116
getparaloc:=LOC_REGISTER;
118
getparaloc:=LOC_REGISTER;
120
getparaloc:=LOC_REFERENCE;
123
getparaloc:=LOC_REFERENCE
125
getparaloc:=LOC_REGISTER;
127
if is_shortstring(p) or is_longstring(p) then
128
getparaloc:=LOC_REFERENCE
130
getparaloc:=LOC_REGISTER;
132
if (po_methodpointer in tprocvardef(p).procoptions) then
133
getparaloc:=LOC_REFERENCE
135
getparaloc:=LOC_REGISTER;
137
getparaloc:=LOC_REGISTER;
139
getparaloc:=LOC_REFERENCE;
141
if is_smallset(p) then
142
getparaloc:=LOC_REGISTER
144
getparaloc:=LOC_REFERENCE;
146
getparaloc:=LOC_REFERENCE;
147
{ avoid problems with errornous definitions }
149
getparaloc:=LOC_REGISTER;
151
internalerror(2002071001);
154
function tsparcparamanager.copy_value_on_stack(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
160
{ true if a parameter is too large to copy and only the address is pushed }
161
function tsparcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
164
{ var,out always require address }
165
if varspez in [vs_var,vs_out] then
175
push_addr_param:=true;
177
result:=is_object(def);
179
result:=(tstringdef(def).string_typ in [st_shortstring,st_longstring]);
181
result:=(po_methodpointer in tprocvardef(def).procoptions);
183
result:=(tsetdef(def).settype<>smallset);
188
procedure TSparcParaManager.init_values(var curintreg: tsuperregister; var cur_stack_offset: aWord);
191
cur_stack_offset:=92;
195
function TSparcParaManager.create_paraloc_info(p:TAbstractProcDef; side: tcallercallee):longint;
197
paraloc : tparalocation;
198
stack_offset : aWord;
199
nextintreg : tsuperregister;
203
init_values(NextIntReg,stack_offset);
204
{ Nested procedures have the parent framepoint in o0 }
205
if p.parast.symtablelevel>normal_function_level then
207
result := create_paraloc_info_intern(p,side,TParaItem(p.para.First),NextIntReg,stack_offset);
210
fillchar(paraloc,sizeof(tparalocation),0);
211
paraloc.size:=def_cgsize(p.rettype.def);
212
paraloc.Alignment:= std_param_align;
213
{ Return in FPU register? }
214
if p.rettype.def.deftype=floatdef then
216
paraloc.loc:=LOC_FPUREGISTER;
217
paraloc.register:=NR_FPU_RESULT_REG;
220
{ Return in register? }
221
if not ret_in_param(p.rettype.def,p.proccalloption) then
223
paraloc.loc:=LOC_REGISTER;
225
if paraloc.size in [OS_64,OS_S64] then
227
paraloc.lochigh:=LOC_REGISTER;
228
if side=callerside then
229
paraloc.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
231
paraloc.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
232
if side=callerside then
233
paraloc.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
235
paraloc.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
240
if side=callerside then
241
paraloc.register:=NR_FUNCTION_RESULT_REG
243
paraloc.register:=NR_FUNCTION_RETURN_REG;
248
paraloc.loc:=LOC_REFERENCE;
250
p.funcret_paraloc[side]:=paraloc;
251
{ Size on stack is not used }
257
function TSparcParaManager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; firstpara: tparaitem;
258
var curintreg: tsuperregister; var cur_stack_offset: aword):longint;
261
nextintreg : tsuperregister;
263
paraloc : tparalocation;
269
nextintreg := curintreg;
270
stack_offset := cur_stack_offset;
272
while assigned(hp) do
274
fillchar(paraloc,sizeof(paraloc),0);
275
paraloc.Alignment:= std_param_align;
276
if push_addr_param(hp.paratyp,hp.paratype.def,p.proccalloption) or (hp.paratyp in [vs_var,vs_out]) then
277
paraloc.size:=OS_ADDR
280
paraloc.size:=def_cgSize(hp.paratype.def);
281
if paraloc.size=OS_NO then
282
paraloc.size:=OS_ADDR;
284
is_64bit:=(paraloc.size in [OS_64,OS_S64,OS_F64]);
285
if NextIntReg<=RS_O5-ord(is_64bit) then
287
paraloc.loc:=LOC_REGISTER;
291
paraloc.registerhigh:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
292
paraloc.lochigh:=LOC_REGISTER;
295
paraloc.registerlow:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
300
paraloc.loc:=LOC_REFERENCE;
301
{ Low part need to be in O5 if still available }
302
if NextIntReg<=RS_O5 then
304
paraloc.low_in_reg:=true;
305
paraloc.lowreg:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
308
paraloc.reference.index:=NR_STACK_POINTER_REG;
309
paraloc.reference.offset:=stack_offset;
311
(not paraloc.low_in_reg) then
316
hp.paraloc[side]:=paraloc;
317
if side = calleeside then
319
{ update callee paraloc and use Ix registers instead
321
if hp.paraloc[calleeside].loc=LOC_REGISTER then
325
setsupreg(hp.paraloc[calleeside].registerhigh,getsupreg(hp.paraloc[calleeside].registerhigh)+(RS_I0-RS_O0));
326
setsupreg(hp.paraloc[calleeside].registerlow,getsupreg(hp.paraloc[calleeside].registerlow)+(RS_I0-RS_O0));
330
if hp.paraloc[calleeside].low_in_reg then
331
setsupreg(hp.paraloc[calleeside].lowreg,getsupreg(hp.paraloc[calleeside].lowreg)+(RS_I0-RS_O0));
332
setsupreg(hp.paraloc[calleeside].reference.index,getsupreg(hp.paraloc[calleeside].reference.index)+(RS_I0-RS_O0));
335
hp:=TParaItem(hp.Next);
342
procedure tsparcparamanager.allocparaloc(list: taasmoutput; const loc: tparalocation);
344
if (loc.loc=LOC_REFERENCE) and
345
(loc.low_in_reg) then
346
cg.GetExplicitRegister(list,loc.lowreg);
347
inherited allocparaloc(list,loc);
351
procedure tsparcparamanager.freeparaloc(list: taasmoutput; const loc: tparalocation);
353
if (loc.loc=LOC_REFERENCE) and
354
(loc.low_in_reg) then
355
cg.UnGetRegister(list,loc.lowreg);
356
inherited freeparaloc(list,loc);
359
procedure tsparcparamanager.splitparaloc64(const locpara:tparalocation;var loclopara,lochipara:tparalocation);
361
{ Word 0 is in register, word 1 is in reference }
362
if (locpara.loc=LOC_REFERENCE) and locpara.low_in_reg then
366
if locpara.size=OS_S64 then
367
lochipara.size:=OS_S32
369
lochipara.size:=OS_32;
370
lochipara.low_in_reg:=false;
373
loclopara.size:=OS_32;
374
loclopara.loc:=LOC_REGISTER;
375
loclopara.register:=locpara.lowreg;
378
inherited splitparaloc64(locpara,loclopara,lochipara);
380
function TSparcParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargspara):longint;
382
cur_stack_offset: aword;
383
parasize, l: longint;
384
curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
386
paraloc: tparalocation;
388
init_values(curintreg,cur_stack_offset);
389
firstfloatreg:=curfloatreg;
391
result := create_paraloc_info_intern(p,callerside,tparaitem(p.para.first),curintreg,cur_stack_offset);
392
if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
393
{ just continue loading the parameters in the registers }
394
result := create_paraloc_info_intern(p,callerside,tparaitem(varargspara.first),curintreg,cur_stack_offset)
397
hp := tparaitem(varargspara.first);
398
parasize := cur_stack_offset;
399
while assigned(hp) do
401
paraloc.size:=def_cgsize(hp.paratype.def);
402
paraloc.lochigh:=LOC_INVALID;
403
paraloc.loc:=LOC_REFERENCE;
404
paraloc.alignment:=4;
405
paraloc.reference.index:=NR_STACK_POINTER_REG;
406
l:=push_size(hp.paratyp,hp.paratype.def,p.proccalloption);
407
paraloc.reference.offset:=parasize;
408
parasize:=parasize+l;
409
hp.paraloc[callerside]:=paraloc;
410
hp:=tparaitem(hp.next);
414
if curfloatreg<>firstfloatreg then
415
include(varargspara.varargsinfo,va_uses_float_reg);
419
ParaManager:=TSparcParaManager.create;
422
$Log: cpupara.pas,v $
423
Revision 1.38 2004/03/15 14:39:56 mazen
424
* make sparc para manager quite similar to ppc one to help
426
+ Add support to var args in registers. need to be verfied as it
427
was just copying ppc's one
429
Revision 1.37 2004/03/09 13:05:49 mazen
430
+ give location for 64bit to fix IE 200402061
432
Revision 1.36 2004/02/25 14:25:47 mazen
433
* fix compile problem for sparc
435
Revision 1.35 2003/11/10 19:05:50 peter
436
* fixed alias/colouring > 255
438
Revision 1.34 2003/10/24 11:25:32 mazen
439
-unused units removed from uses clause
440
*fix related to rg which was removed
442
Revision 1.33 2003/10/08 21:16:27 olle
443
* changed to symbolic const for alignment
444
+ alignment set for function result
446
Revision 1.32 2003/10/08 14:11:36 mazen
447
+ Alignement field added to TParaLocation (=4 as 32 bits archs)
449
Revision 1.31 2003/10/01 20:34:50 peter
450
* procinfo unit contains tprocinfo
451
* cginfo renamed to cgbase
452
* moved cgmessage to verbose
453
* fixed ppc and sparc compiles
455
Revision 1.30 2003/09/14 21:35:15 peter
456
* new volatile registers proc
458
Revision 1.29 2003/09/14 19:19:05 peter
461
Revision 1.28 2003/09/03 15:55:01 peter
462
* NEWRA branch merged
464
Revision 1.27.2.1 2003/08/31 21:08:16 peter
465
* first batch of sparc fixes
467
Revision 1.27 2003/08/11 21:18:20 peter
468
* start of sparc support for newra
470
Revision 1.26 2003/07/08 21:25:00 peter
473
Revision 1.25 2003/07/06 22:10:56 peter
474
* big endian first allocates high
476
Revision 1.24 2003/07/06 17:58:22 peter
477
* framepointer fixes for sparc
478
* parent framepointer code more generic
480
Revision 1.23 2003/07/05 20:11:41 jonas
481
* create_paraloc_info() is now called separately for the caller and
485
Revision 1.22 2003/07/02 22:18:04 peter
486
* paraloc splitted in callerparaloc,calleeparaloc
487
* sparc calling convention updates
489
Revision 1.21 2003/06/17 16:36:59 peter
492
Revision 1.20 2003/06/09 21:44:14 mazen
493
* fix compile problem related to modification
494
of the declareation of GetIntParaLoc in the
495
ancestor's declaration
497
Revision 1.19 2003/06/01 21:38:06 peter
498
* getregisterfpu size parameter added
499
* op_const_reg size parameter added
502
Revision 1.18 2003/05/31 01:00:51 peter
505
Revision 1.17 2003/05/30 23:57:08 peter
507
* accumulator removed, splitted in function_return_reg (called) and
508
function_result_reg (caller)
510
Revision 1.16 2003/04/23 13:35:39 peter
513
Revision 1.15 2003/04/23 12:35:35 florian
514
* fixed several issues with powerpc
515
+ applied a patch from Jonas for nested function calls (PowerPC only)
518
Revision 1.14 2003/01/08 18:43:58 daniel
519
* Tregister changed into a record
521
Revision 1.13 2003/01/05 21:32:35 mazen
522
* fixing several bugs compiling the RTL
524
Revision 1.12 2002/11/25 19:21:49 mazen
525
* fixed support of nSparcInline
527
Revision 1.11 2002/11/25 17:43:28 peter
528
* splitted defbase in defutil,symutil,defcmp
529
* merged isconvertable and is_equal into compare_defs(_ext)
530
* made operator search faster by walking the list only once
532
Revision 1.10 2002/11/18 17:32:01 peter
533
* pass proccalloption to ret_in_xxx and push_xxx functions
535
Revision 1.9 2002/11/03 20:22:40 mazen
536
* parameter handling updated
538
Revision 1.8 2002/10/13 21:46:07 mazen
539
* assembler output format fixed
541
Revision 1.7 2002/10/10 19:57:51 mazen
542
* Just to update repsitory
544
Revision 1.6 2002/10/10 15:10:39 mazen
545
* Internal error fixed, but usually i386 parameter model used
547
Revision 1.5 2002/10/09 13:52:19 mazen
548
just incase some one wolud help me debugging that\!
550
Revision 1.4 2002/10/08 21:02:22 mazen
551
* debugging register allocation
553
Revision 1.3 2002/10/07 20:33:05 mazen
554
word alignement modified in g_stack_frame
556
Revision 1.2 2002/10/04 21:57:42 mazen
557
* register allocation for parameters now done in cpupara, but InternalError(200109223) in cgcpu.pas:1053 is still not fixed du to location_force problem in ncgutils.pas:419
559
Revision 1.1 2002/08/21 13:30:07 mazen
560
*** empty log message ***
562
Revision 1.2 2002/07/11 14:41:34 florian
563
* start of the new generic parameter handling
565
Revision 1.1 2002/07/07 09:44:32 florian
566
* powerpc target fixed, very simple units can be compiled