blob: e547fc15b1b4ee7aeed7aa68f0cb5193eca5e483 [file] [log] [blame]
PulkoMandy17fc7592022-07-28 18:27:54 +02001/* Code generator for a PPC RISC cpu with 32 general purpose, */
2/* 32 floating point and 8 condition code registers. */
3
4#include "supp.h"
5
6static char FILE_[]=__FILE__;
7
8#include "dwarf2.c"
9
10/* Public data that MUST be there. */
11
12/* Name and copyright. */
13char cg_copyright[]="vbcc code-generator for PPC V0.7 (c) in 1997-2022 by Volker Barthelmann";
14
15/* Commandline-flags the code-generator accepts */
16int g_flags[MAXGF]={STRINGFLAG,STRINGFLAG,0,0,0,0,
17 0,0,0,0,0,
18 0,0,0,0,0,0,
19 0,0,0};
20char *g_flags_name[MAXGF]={"cpu","fpu","const-in-data","sd","merge-constants","fsub-zero",
21 "elf","amiga-align","no-regnames","no-peephole","setccs",
22 "use-lmw","poweropen","sc","madd","eabi","gas",
23 "no-align-args","conservative-sr","use-commons",
24 "baserel32os4","baserel32mos","oldlibcalls"};
25union ppi g_flags_val[MAXGF];
26
27/* Alignment-requirements for all types in bytes. */
28zmax align[MAX_TYPE+1];
29
30/* Alignment that is sufficient for every object. */
31zmax maxalign;
32
33/* CHAR_BIT for the target machine. */
34zmax char_bit;
35
36/* Tabelle fuer die Groesse der einzelnen Typen */
37zmax sizetab[MAX_TYPE+1];
38
39/* Minimum and Maximum values each type can have. */
40/* Must be initialized in init_cg(). */
41zmax t_min[MAX_TYPE+1];
42zumax t_max[MAX_TYPE+1];
43zumax tu_max[MAX_TYPE+1];
44
45/* Names of all registers. */
46char *regnames[MAXR+1]={"noreg",
47 "r0","r1","r2","r3","r4","r5","r6","r7",
48 "r8","r9","r10","r11","r12","r13","r14","r15",
49 "r16","r17","r18","r19","r20","r21","r22","r23",
50 "r24","r25","r26","r27","r28","r29","r30","r31",
51 "f0","f1","f2","f3","f4","f5","f6","f7",
52 "f8","f9","f10","f11","f12","f13","f14","f15",
53 "f16","f17","f18","f19","f20","f21","f22","f23",
54 "f24","f25","f26","f27","f28","f29","f30","f31",
55 "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7",
56 "cnt",
57 "r3/r4","r5/r6","r7/r8","r9/r10",
58 "r14/r15","r16/r17","r18/r19","r20/r21",
59 "r22/r23","r24/r25","r26/r27","r28/r29","r30/r31",
60 "lr"};
61
62/* The Size of each register in bytes. */
63zmax regsize[MAXR+1];
64
65/* Type which can store each register. */
66struct Typ *regtype[MAXR+1];
67
68/* regsa[reg]!=0 if a certain register is allocated and should */
69/* not be used by the compiler pass. */
70int regsa[MAXR+1];
71
72/* Specifies which registers may be scratched by functions. */
73int regscratch[MAXR+1]={0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
74 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
75 1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
76 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
77 1,1,0,0,0,1,1,1,1,
78 1,1,1,1,
79 0,0,0,0,0,0,0,0,0};
80
81int reg_prio[MAXR+1]={0,0,0,0,19,20,21,22,23,24,25,26,27,28,0,1,2,
82 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
83 0,1,2,3,4,5,6,7,8,9,10,11,12,13,0,0,
84 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
85 1,1,0,0,0,1,1,1,1,
86 19,21,23,25,
87 1,3,5,7,9,11,13,15,17};
88
89struct reg_handle empty_reg_handle={0,0};
90
91/* Names of target-specific variable attributes. */
92char *g_attr_name[]={"__far","__near","__chip","__saveds","__rfi","__saveall",
93 "__syscall","__nosave","__brel",0};
94#define FAR 1
95#define NEAR 2
96#define CHIP 4
97#define SAVEDS 8
98#define RFI 16
99#define SAVEALL 32
100#define SYSCALL 64
101#define NOSAVE 128
102#define BREL 256
103
104/****************************************/
105/* Private data and functions. */
106/****************************************/
107
108#define SMALLDATA (g_flags[3]&USEDFLAG)
109#define POWEROPEN (g_flags[12]&USEDFLAG)
110#define STORMC (g_flags[13]&USEDFLAG)
111#define EABI (g_flags[15]&USEDFLAG)
112#define GAS (g_flags[16]&USEDFLAG)
113#define NOALIGNARGS (g_flags[17]&USEDFLAG)
114#define CONSERVATIVE_SR (g_flags[18]&USEDFLAG)
115#define USE_COMMONS (g_flags[19]&USEDFLAG)
116#define BASERELOS4 (g_flags[20]&USEDFLAG)
117#define BASERELMOS (g_flags[21]&USEDFLAG)
118#define OLDLIBCALLS (g_flags[22]&USEDFLAG)
119
120
121static char *mregnames[MAXR+1];
122
123static char *ret="\tblr\n";
124
125static long malign[MAX_TYPE+1]= {1,1,2,4,4,8,4,8,8,1,4,1,1,1,4,1};
126static long msizetab[MAX_TYPE+1]={1,1,2,4,4,8,4,8,8,0,4,0,0,0,4,0};
127
128static struct Typ ltyp={LONG},lltyp={LLONG},ldbl={DOUBLE},lchar={CHAR};
129
130static char *marray[]={"__section(x,y)=__vattr(\"section(\"#x\",\"#y\")\")",
131 "__PPC__",
132 "__aos4libcall=__attr(\"aos4libcall;\")",
133 "__linearvarargs=__attr(\"linearvarargs;\")",
134 "__interrupt=__rfi __saveall",
135 0};
136
137const int r4=5,r5=6,r6=7,r3r4=74,r5r6=75;
138
139
140static int r0=1; /* special register */
141static int r2=3; /* reserved or toc */
142static int r3=4; /* return value */
143static int sp=2; /* Stackpointer */
144static int fp=2; /* Framepointer */
145static int vlafp=32; /* Framepointer to use with vlas */
146static int sd=14; /* SmallDataPointer */
147static int sd2=3; /* SmallData2 (eabi) */
148static int t1=12,t2=13,t3=1; /* Temporaries used by code generator */
149static int f1=45,f2=46,f3=33; /* Temporaries used by code generator */
150static int cr0=65; /* Default condition-code-register */
151static int ctr=73; /* ctr */
152static int lr=87; /* link register */
153static int bp32os4=3; /* baserel32 pointer for Amiga OS4 */
154static int bp32mos=14; /* baserel32 pointer for MorphOS */
155
156#define DATA 0
157#define BSS 1
158#define CODE 2
159#define RODATA 3
160#define TOC 4
161#define SDATA 5
162#define SDATA2 6
163#define SBSS 7
164#define SPECIAL 8
165
166#if HAVE_OSEK
167/* removed */
168/* removed */
169#endif
170
171static long stack;
172static int stack_valid;
173static long tmpoff; /* offset for additional temporaries, upper end! */
174static int lastlabel,exit_label;
175static int sdp;
176static int q1loaded,q2loaded;
177static int section=-1,newobj,crsave;
178static char *codename="\t.text\n\t.align\t2\n",
179 *dataname="\t.data\n\t.align\t2\n",
180 *bssname="",
181 *rodataname="\t.section\t.rodata\n\t.align\t2\n",
182 *tocname="\t.tocd\n\t.align\t2\n",
183 *sdataname="\t.section\t\".sdata\",\"aw\"\n\t.align\t2\n",
184 *sdata2name="\t.section\t\".sdata2\",\"a\"\n\t.align\t2\n",
185 *sbssname="\t.section\t\".sbss\",\"auw\"\n\t.align\t2\n";
186
187static char *labprefix="l",*idprefix="_",*tocprefix="@_";
188static long frameoffset,pushed,maxpushed,framesize,localoffset,minframe=8;
189static void emit_obj(FILE *f,struct obj *p,int t);
190
191static int all_regs;
192
193struct StatFPtrList {
194 struct StatFPtrList *next;
195 struct Var *vptr;
196};
197static struct StatFPtrList *firstfptr = NULL;
198
199void title(FILE *f)
200{
201 static int done;
202 extern char *inname; /*grmpf*/
203 if(!done&&f){
204 done=1;
205 emit(f,"\t.file\t\"%s\"\n",inname);
206 }
207}
208
209static long real_offset(struct obj *o)
210{
211 long off;
212 if(zm2l(o->v->offset)>=0){
213 return zm2l(o->v->offset)+frameoffset+zm2l(o->val.vmax);
214 }else{
215 return framesize+minframe-zm2l(o->v->offset)-zm2l(maxalign)+zm2l(o->val.vmax);
216 }
217}
218static long hi(long off)
219{
220 zmax zm=l2zm(off),r=zmrshift(zm,l2zm(16L));
221 if(!zmeqto(zmand(zm,l2zm(32768L)),l2zm(0L))) r=zmadd(r,l2zm(1L));
222 return zm2l(zs2zm(zm2zs(zmand(r,l2zm(65535L)))));
223}
224static long lo(long off)
225{
226 return zm2l(zs2zm(zm2zs(zmand(l2zm(off),l2zm(65535L)))));
227}
228static struct fpconstlist {
229 struct fpconstlist *next;
230 int label,typ;
231 union atyps val;
232} *firstfpc;
233
234static int addfpconst(struct obj *o,int t)
235{
236 struct fpconstlist *p=firstfpc;
237 t&=NQ;
238 if(t==LDOUBLE) t=DOUBLE;
239 if(g_flags[4]&USEDFLAG){
240 for(p=firstfpc;p;p=p->next){
241 if(t==p->typ){
242 eval_const(&p->val,t);
243 if(t==FLOAT&&zldeqto(vldouble,zf2zld(o->val.vfloat))) return p->label;
244 if(t==DOUBLE&&zldeqto(vldouble,zd2zld(o->val.vdouble))) return p->label;
245 }
246 }
247 }
248 p=mymalloc(sizeof(struct fpconstlist));
249 p->next=firstfpc;
250 p->label=++label;
251 p->typ=t;
252 p->val=o->val;
253 firstfpc=p;
254 return p->label;
255}
256
257#define REG_IND 1
258#define IMM_IND 2
259#define UPDATE 64
260
261static struct obj *cam(int flags,int base,long offset)
262/* Initializes an addressing-mode structure and returns a pointer to */
263/* that object. Will not survive a second call! */
264{
265 static struct obj obj;
266 static struct AddressingMode am;
267 obj.am=&am;
268 am.flags=flags;
269 am.base=base;
270 am.offset=offset;
271 return &obj;
272}
273
274static char *ldts[]={"","bz","ha","wz","wz","wz","fs","fd","fd","","wz"};
275static char *ldtu[]={"","bz","hz","wz","wz","wz","??","??","??","??","??"};
276static char *sdts[]={"","b","h","w","w","w","fs","fd","fd","","w"};
277static char *sdtu[]={"","b","h","w","w","w","??","??","??","??","??"};
278
279#define ldt(t) ((t&UNSIGNED)?ldtu[t&NQ]:ldts[t&NQ])
280#define sdt(t) ((t&UNSIGNED)?sdtu[t&NQ]:sdts[t&NQ])
281
282static int special_section(FILE *f,struct Var *v)
283{
284 char *sec;
285 if(!v->vattr) return 0;
286 sec=strstr(v->vattr,"section(");
287 if(!sec) return 0;
288 sec+=strlen("section(");
289 emit(f,"\t.section\t");
290 while(*sec&&*sec!=')') emit_char(f,*sec++);
291 emit(f,"\n");
292 if(f) section=SPECIAL;
293 return 1;
294}
295
296static int use_sd(int t)
297/* Shall the object of type t be addressed in small-data-mode? */
298{
299 int r=0;
300 if(ISFUNC(t)) return 0;
301 if(g_flags[3]&USEDFLAG)
302 r=sd;
303 else if(STORMC&&(t&NQ)<=POINTER)
304 r=sd;
305 else if(EABI&&ISSCALAR(t)){
306 if(t&CONST)
307 r=sd2;
308 else
309 r=sd;
310 }
311 return r;
312}
313
314static void load_address(FILE *f,int r,struct obj *o,int typ)
315/* Generates code to load the address of a variable into register r. */
316{
317 BSET(regs_modified,r);
318 if(!(o->flags&VAR))
319 ierror(0);
320 if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
321 long off=real_offset(o);
322 if(off<=32767){
323 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[fp],off);
324 }else{
325 if(r==r0){
326 BSET(regs_modified,t2);
327 emit(f,"\taddis\t%s,%s,%ld\n",mregnames[t2],mregnames[fp],hi(off));
328 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[t2],lo(off));
329 }else{
330 emit(f,"\taddis\t%s,%s,%ld\n",mregnames[r],mregnames[fp],hi(off));
331 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[r],lo(off));
332 }
333 }
334 }else{
335 if((sdp=use_sd(o->v->vtyp->flags))&&!(o->v->tattr&FAR)
336 &&zmleq(l2zm(0L),o->val.vmax)&&!zmleq(szof(o->v->vtyp),o->val.vmax)){
337 emit(f,"\tla\t%s,",mregnames[r]);
338 emit_obj(f,o,typ);
339 if(GAS)
340 emit(f,"@sda21(0)\n");
341 else
342 emit(f,"(%s)\n",mregnames[sdp]);
343 }else{
344 if(POWEROPEN){
345 zmax offset=o->val.vmax;
346 if(f){
347 if((o->v->vtyp->flags&NQ)==FUNKT&&o->v->storage_class==STATIC){
348 /* check if static function pointer was already created in TOC */
349 struct StatFPtrList **oldsfp=&firstfptr;
350 struct StatFPtrList *sfp=firstfptr;
351 while(sfp){
352 if(sfp->vptr==o->v) break;
353 oldsfp=&sfp->next;
354 sfp=sfp->next;
355 }
356 if(!sfp){
357 *oldsfp=sfp=mymalloc(sizeof(struct StatFPtrList));
358 sfp->next=NULL;
359 sfp->vptr=o->v;
360 }
361 }
362 emit(f,"\tl%s\t%s,%s",ldt(LONG),mregnames[r],tocprefix);
363 o->val.vmax=l2zm(0L);emit_obj(f,o,POINTER);o->val.vmax=offset;
364 emit(f,"(%s)\n",mregnames[r2]);
365 if(hi(zm2l(offset))) emit(f,"\taddis\t%s,%s,%ld\n",mregnames[r],mregnames[r],hi(zm2l(offset)));
366 if(lo(zm2l(offset))) emit(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[r],lo(zm2l(offset)));
367 }
368 }else{
369 if(BASERELOS4){
370 emit(f,"\taddis\t%s,%s,",mregnames[r],mregnames[bp32os4]);
371 emit_obj(f,o,typ);emit(f,"@brel@ha\n");
372 emit(f,"\taddi\t%s,%s,",mregnames[r],mregnames[r]);
373 emit_obj(f,o,typ);emit(f,"@brel@l\n");
374 }else if(BASERELMOS){
375 emit(f,"\taddis\t%s,%s,",mregnames[r],mregnames[bp32mos]);
376 emit_obj(f,o,typ);emit(f,"@drel@ha\n");
377 emit(f,"\taddi\t%s,%s,",mregnames[r],mregnames[r]);
378 emit_obj(f,o,typ);emit(f,"@drel@l\n");
379 }else{
380 emit(f,"\tlis\t%s,",mregnames[r]);
381 emit_obj(f,o,typ);emit(f,"@ha\n");
382 emit(f,"\taddi\t%s,%s,",mregnames[r],mregnames[r]);
383 emit_obj(f,o,typ);emit(f,"@l\n");
384 }
385 }
386 }
387 }
388}
389static void load_reg(FILE *f,int r,struct obj *o,int typ,int tmp)
390/* Generates code to load a memory object into register r. tmp is a */
391/* general purpose register which may be used. tmp can be r. */
392{
393 typ&=NU;
394 BSET(regs_modified,r);
395 if(o->flags&KONST){
396 long l;
397 eval_const(&o->val,typ);
398 if(ISFLOAT(typ)){
399 int lab;
400 if((g_flags[5]&USEDFLAG)&&zldeqto(vldouble,d2zld(0.0))){
401 emit(f,"\tfsub\t%s,%s,%s\n",mregnames[r],mregnames[r],mregnames[r]);
402 return;
403 }
404 lab=addfpconst(o,typ);
405 if(sdp=use_sd(typ)){
406 if(GAS)
407 emit(f,"\tl%s\t%s,%s%d@sda21(0)\n",ldt(typ),mregnames[r],labprefix,lab);
408 else
409 emit(f,"\tl%s\t%s,%s%d(%s)\n",ldt(typ),mregnames[r],labprefix,lab,mregnames[sdp]);
410 }else{
411 BSET(regs_modified,tmp);
412 if(POWEROPEN){
413 emit(f,"\tl%s\t%s,%s%s%ld(%s)\n",ldt(LONG),mregnames[tmp],tocprefix,labprefix,(long)lab,mregnames[r2]);
414 emit(f,"\tl%s\t%s,0(%s)\n",ldt(typ),mregnames[r],mregnames[tmp]);
415 }else{
416 emit(f,"\tlis\t%s,%s%d@ha\n",mregnames[tmp],labprefix,lab);
417 emit(f,"\tl%s\t%s,%s%d@l(%s)\n",ldt(typ),mregnames[r],labprefix,lab,mregnames[tmp]);
418 }
419 }
420 return;
421 }
422 if(r==1) ierror(0);
423 l=hi(zm2l(vmax));
424 if(l){
425 emit(f,"\tlis\t%s,%ld\n",mregnames[r],l);
426 l=lo(zm2l(vmax));
427 if(l)
428 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[r],l);
429 }else{
430 emit(f,"\tli\t%s,%ld\n",mregnames[r],lo(vmax));
431 }
432 return;
433 }
434 if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
435 if(o->flags&VARADR){
436 load_address(f,r,o,POINTER);
437 }else{
438 if((sdp=use_sd(o->v->vtyp->flags))&&!(o->v->tattr&FAR)){
439 emit(f,"\tl%s\t%s,",ldt(typ),mregnames[r]);
440 emit_obj(f,o,typ);
441 if(GAS)
442 emit(f,"@sda21(0)\n");
443 else
444 emit(f,"(%s)\n",mregnames[sdp]);
445 }else{
446 BSET(regs_modified,tmp);
447 if(POWEROPEN){
448 zmax offset=o->val.vmax;
449 emit(f,"\tl%s\t%s,%s",ldt(LONG),mregnames[tmp],tocprefix);
450 o->val.vmax=l2zm(0L);emit_obj(f,o,POINTER);o->val.vmax=offset;
451 emit(f,"(%s)\n",mregnames[r2]);
452 if(hi(zm2l(offset))) emit(f,"\taddis\t%s,%s,%ld\n",mregnames[tmp],mregnames[tmp],hi(zm2l(offset)));
453 emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(typ),mregnames[r],lo(zm2l(offset)),mregnames[tmp]);
454 }else{
455 if(BASERELOS4){
456 emit(f,"\taddis\t%s,%s,",mregnames[tmp],mregnames[bp32os4]);
457 emit_obj(f,o,typ);emit(f,"@brel@ha\n");
458 emit(f,"\tl%s\t%s,",ldt(typ),mregnames[r]);
459 emit_obj(f,o,typ);emit(f,"@brel@l(%s)\n",mregnames[tmp]);
460 }else if(BASERELMOS){
461 emit(f,"\taddis\t%s,%s,",mregnames[tmp],mregnames[bp32mos]);
462 emit_obj(f,o,typ);emit(f,"@drel@ha\n");
463 emit(f,"\tl%s\t%s,",ldt(typ),mregnames[r]);
464 emit_obj(f,o,typ);emit(f,"@drel@l(%s)\n",mregnames[tmp]);
465 }else{
466 emit(f,"\tlis\t%s,",mregnames[tmp]);
467 emit_obj(f,o,typ);emit(f,"@ha\n");
468 emit(f,"\tl%s\t%s,",ldt(typ),mregnames[r]);
469 emit_obj(f,o,typ);emit(f,"@l(%s)\n",mregnames[tmp]);
470 }
471 }
472 }
473 }
474 }else{
475 if((o->flags&(DREFOBJ|REG))==REG){
476 if(r!=o->reg)
477 emit(f,"\t%smr\t%s,%s\n",r>=33?"f":"",mregnames[r],mregnames[o->reg]);
478 }else if(!o->am&&(o->flags&(DREFOBJ|REG))==(REG|DREFOBJ)){
479 emit(f,"\tl%s\t%s,0(%s)\n",ldt(typ),mregnames[r],mregnames[o->reg]);
480 }else if(!o->am){
481 long off=real_offset(o);
482 if(off<=32767){
483 emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(typ),mregnames[r],off,mregnames[fp]);
484 }else{
485 BSET(regs_modified,tmp);
486 emit(f,"\taddis\t%s,%s,%ld\n",mregnames[tmp],mregnames[fp],hi(off));
487 emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(typ),mregnames[r],lo(zm2l(off)),mregnames[tmp]);
488 }
489 }else{
490 emit(f,"\tl%s%s%s\t%s,",ldt(typ),(o->am->flags&UPDATE)?"u":"",(o->am->flags&REG_IND)?"x":"",mregnames[r]);
491 emit_obj(f,o,typ);emit(f,"\n");
492 }
493 }
494}
495
496static void store_reg(FILE *f,int r,struct obj *o,int typ)
497/* Generates code to store register r into memory object o. */
498{
499 int tmp;
500 typ&=NQ;
501 if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
502 int tmp=t1;
503 if(tmp==r) tmp=t2;
504 if((sdp=use_sd(o->v->vtyp->flags))&&!(o->v->tattr&FAR)){
505 emit(f,"\tst%s\t%s,",sdt(typ),mregnames[r]);
506 emit_obj(f,o,typ);
507 if(GAS)
508 emit(f,"@sda21(0)\n");
509 else
510 emit(f,"(%s)\n",mregnames[sdp]);
511 return;
512 }else{
513 BSET(regs_modified,tmp);
514 if(POWEROPEN){
515 zmax offset=o->val.vmax;
516 emit(f,"\tl%s\t%s,%s",ldt(LONG),mregnames[tmp],tocprefix);
517 o->val.vmax=l2zm(0L);emit_obj(f,o,POINTER);o->val.vmax=offset;
518 emit(f,"(%s)\n",mregnames[r2]);
519 if(hi(zm2l(offset))) emit(f,"\taddis\t%s,%s,%ld\n",mregnames[tmp],mregnames[tmp],hi(zm2l(offset)));
520 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(typ),mregnames[r],lo(zm2l(offset)),mregnames[tmp]);
521 return;
522 }else{
523 if(BASERELOS4){
524 emit(f,"\taddis\t%s,%s,",mregnames[tmp],mregnames[bp32os4]);
525 emit_obj(f,o,typ);emit(f,"@brel@ha\n");
526 emit(f,"\tst%s\t%s,",sdt(typ),mregnames[r]);
527 emit_obj(f,o,typ);emit(f,"@brel@l(%s)\n",mregnames[tmp]);
528 }else if(BASERELMOS){
529 emit(f,"\taddis\t%s,%s,",mregnames[tmp],mregnames[bp32mos]);
530 emit_obj(f,o,typ);emit(f,"@drel@ha\n");
531 emit(f,"\tst%s\t%s,",sdt(typ),mregnames[r]);
532 emit_obj(f,o,typ);emit(f,"@drel@l(%s)\n",mregnames[tmp]);
533 }else{
534 emit(f,"\tlis\t%s,",mregnames[tmp]);
535 emit_obj(f,o,typ);emit(f,"@ha\n");
536 emit(f,"\tst%s\t%s,",sdt(typ),mregnames[r]);
537 emit_obj(f,o,typ);emit(f,"@l(%s)\n",mregnames[tmp]);
538 }
539 return;
540 }
541 }
542 }
543 if(!(o->flags&DREFOBJ)&&!o->am){
544 long off=real_offset(o);
545 if(r==t1) tmp=t2; else tmp=t1;
546 if(off<=32767){
547 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(typ),mregnames[r],off,mregnames[fp]);
548 }else{
549
550 BSET(regs_modified,tmp);
551 emit(f,"\taddis\t%s,%s,%ld\n",mregnames[tmp],mregnames[fp],hi(off));
552 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(typ),mregnames[r],lo(off),mregnames[tmp]);
553 }
554 }else{
555 if(!o->am){
556 emit(f,"\tst%s\t%s,",sdt(typ),mregnames[r]);
557 emit_obj(f,o,typ);emit(f,"\n");
558 }else{
559 emit(f,"\tst%s%s%s\t%s,",sdt(typ),(o->am->flags&UPDATE)?"u":"",(o->am->flags&REG_IND)?"x":"",mregnames[r]);
560 emit_obj(f,o,typ);emit(f,"\n");
561 }
562 }
563}
564
565static long pof2(zumax x)
566/* Yields log2(x)+1 oder 0. */
567{
568 zumax p;int ln=1;
569 p=ul2zum(1L);
570 while(ln<=32&&zumleq(p,x)){
571 if(zumeqto(x,p)) return ln;
572 ln++;p=zumadd(p,p);
573 }
574 return 0;
575}
576
577#if 1
578static char *dct[]={"","byte","2byte","4byte","4byte","4byte","4byte","4byte","4byte"};
579#else
580static char *dct[]={"","byte","short","long","long","long","long","long","long"};
581#endif
582static struct IC *do_refs(FILE *,struct IC *);
583static void pr(FILE *,struct IC *);
584static void function_top(FILE *,struct Var *,long);
585static void function_bottom(FILE *f,struct Var *,long);
586
587#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
588
589static int q1reg,q2reg,zreg;
590
591static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
592static char *logicals[]={"or","xor","and"};
593static char *record[]={"","."};
594static char *arithmetics[]={"slw","srw","add","sub","mullw","divw","mod"};
595static char *isimm[]={"","i"};
596
597static struct IC *do_refs(FILE *f,struct IC *p)
598/* Does some pre-processing like fetching operands from memory to */
599/* registers etc. */
600{
601 int typ,typ1,reg,c=abs(p->code);
602
603 q1loaded=q2loaded=0;
604
605 /* cannot use q1typ, because p->code may have been negated */
606 if(c==CONVERT)
607 typ=p->typf2;
608 else
609 typ=p->typf;
610
611 if((typ&NQ)==POINTER) typ=UNSIGNED|LONG;
612
613 if((c==SUB||c==SUBIFP)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&(typ&NQ)<=LLONG){
614 eval_const(&p->q2.val,typ);
615 if(zmleq(vmax,l2zm(32768L))&&zmleq(l2zm(-32767L),vmax)){
616 union atyps val;
617 if(c==SUB){
618 if(p->code==SUB) p->code=c=ADD; else p->code=c=-ADD;
619 }else{
620 if(p->code==SUBIFP) p->code=c=ADDI2P; else p->code=c=-ADDI2P;
621 }
622 c=abs(c);
623 val.vmax=zmsub(l2zm(0L),vmax);
624 eval_const(&val,MAXINT);
625 insert_const(&p->q2.val,typ);
626 p->typf=typ=(typ&~UNSIGNED);
627 }
628 }
629
630 q1reg=q2reg=zreg=0;
631 if(p->q1.flags&REG) q1reg=p->q1.reg;
632 if(p->q2.flags&REG) q2reg=p->q2.reg;
633 if((p->z.flags&(REG|DREFOBJ))==REG) zreg=p->z.reg;
634
635 if((p->q1.flags&(KONST|DREFOBJ))==KONST){
636 eval_const(&p->q1.val,typ);
637 if(ISFLOAT(typ)) reg=f1; else reg=t1;
638 if(c==ASSIGN&&zreg) reg=zreg;
639 if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
640 if(c!=SUB||(typ&NQ)>LONG||!zmleq(vmax,l2zm(32767L))||!zmleq(l2zm(-32768L),vmax)){
641 load_reg(f,reg,&p->q1,typ,t1);
642 q1reg=reg;
643 q1loaded=1;
644 }
645 }else if(c!=ADDRESS){
646 if(ISFLOAT(typ)) reg=f1; else reg=t1;
647 if((c==ASSIGN||(c==CONVERT&&ISINT(p->typf2)))&&zreg>=1&&zreg<=32) reg=zreg;
648 if((c==ASSIGN||(c==CONVERT&&ISFLOAT(p->typf2)))&&zreg>=33&&zreg<=64) reg=zreg;
649 if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
650 if(p->q1.am){
651 load_reg(f,reg,&p->q1,typ,t1);
652 q1reg=reg;
653 q1loaded=1;
654 }else{
655 if(p->q1.flags&&!q1reg){
656 if(p->q1.flags&DREFOBJ) {typ1=POINTER;reg=t1;} else typ1=typ;
657 if((typ1&NQ)<=POINTER){
658 int m=p->q1.flags;
659 p->q1.flags&=~DREFOBJ;
660 load_reg(f,reg,&p->q1,typ1,t1);
661 p->q1.flags=m;
662 q1reg=reg;
663 q1loaded=1;
664 }
665 }
666 if((p->q1.flags&DREFOBJ)&&(typ&NQ)<=POINTER){
667 if(ISFLOAT(typ)) reg=f1; else reg=t1;
668 if((c==ASSIGN||(c==CONVERT&&ISINT(p->typf2)))&&zreg>=1&&zreg<=32) reg=zreg;
669 if((c==ASSIGN||(c==CONVERT&&ISFLOAT(p->typf2)))&&zreg>=33&&zreg<=64) reg=zreg;
670 if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
671 if(p->q1.am)
672 load_reg(f,reg,&p->q1,typ,t1);
673 else
674 load_reg(f,reg,cam(IMM_IND,q1reg,0),typ,t1);
675 q1reg=reg;
676 q1loaded=1;
677 }
678 }
679 }
680 /* cannot use q2typ (see above) */
681 typ=p->typf;
682 if((p->q2.flags&(KONST|DREFOBJ))==KONST){
683 eval_const(&p->q2.val,typ);
684 if(ISFLOAT(typ)) reg=f2; else reg=t2;
685 if(ISFLOAT(typ)||c==DIV||c==SUB||c==MOD){
686 load_reg(f,reg,&p->q2,typ,t2);
687 q2reg=reg;
688 q2loaded=1;
689 }else{
690 if((c>=OR&&c<=AND)||(c==COMPARE&&(typ&UNSIGNED))){
691 if(!zumleq(vumax,ul2zum(65535UL))){
692 load_reg(f,reg,&p->q2,typ,t2);
693 q2reg=reg;
694 q2loaded=1;
695 }
696 }else{
697 if(!zmleq(vmax,l2zm(32767L))||!zmleq(l2zm(-32768L),vmax)){
698 load_reg(f,reg,&p->q2,typ,t2);
699 q2reg=reg;
700 q2loaded=1;
701 }
702 }
703 }
704 }else{
705 if(p->q2.am){
706 if(ISFLOAT(typ)) reg=f2; else reg=t2;
707 load_reg(f,reg,&p->q2,typ,t2);
708 q2reg=reg;
709 q2loaded=1;
710 }else{
711 if(p->q2.flags&&!q2reg){
712 if((p->q2.flags&DREFOBJ)) typ1=POINTER; else typ1=typ;
713 if(ISFLOAT(typ1)) reg=f2; else reg=t2;
714 if((typ1&NQ)<=POINTER){
715 int m=p->q2.flags;
716 p->q2.flags&=~DREFOBJ;
717 load_reg(f,reg,&p->q2,typ1,t2);
718 p->q2.flags=m;
719 q2reg=reg;
720 q2loaded=1;
721 }
722 }
723 if((p->q2.flags&DREFOBJ)&&(typ&NQ)<=POINTER){
724 if(ISFLOAT(typ)) reg=f2; else reg=t2;
725 if(p->q2.am)
726 load_reg(f,reg,&p->q2,typ,t2);
727 else
728 load_reg(f,reg,cam(IMM_IND,q2reg,0),typ,t2);
729 q2reg=reg;
730 q2loaded=1;
731 }
732 }
733 }
734 if(p->z.am||(p->z.flags&&!isreg(z))){
735 typ=p->typf;
736 if(c!=ADDRESS&&ISFLOAT(typ)) zreg=f3; else zreg=t3;
737 }
738 if(q1reg){p->q1.flags=REG;p->q1.reg=q1reg;p->q1.am=0;}
739 if(q2reg){p->q2.flags=REG;p->q2.reg=q2reg;p->q2.am=0;}
740 return p;
741}
742static void pr(FILE *f,struct IC *p)
743 /* Writes the destination register to the real destination if necessary. */
744{
745 int typ=p->typf;
746 if(p->code==ADDRESS) typ=POINTER;
747 if(p->z.flags){
748 if(zreg>=74&&zreg<=86){printf("c=%d\n",p->code); ierror(0);}
749 if(p->z.am){
750 store_reg(f,zreg,&p->z,typ);
751 }else if(!isreg(z)){
752 if(p->z.flags&DREFOBJ){
753 if(p->z.flags&REG){
754 if(p->z.am)
755 store_reg(f,zreg,&p->z,typ);
756 else
757 store_reg(f,zreg,cam(IMM_IND,p->z.reg,0),typ);
758 }else{
759 int r;
760 if(t1==zreg) r=t2; else r=t1;
761 load_reg(f,r,&p->z,POINTER,r);
762 store_reg(f,zreg,cam(IMM_IND,r,0),typ);
763 }
764 }else{
765 store_reg(f,zreg,&p->z,typ);
766 }
767 }else{
768 if(p->z.reg!=zreg)
769 emit(f,"\t%smr\t%s,%s\n",(zreg>=33&&zreg<=64)?"f":"",mregnames[p->z.reg],mregnames[zreg]);
770 }
771 }
772}
773static int dwarf2_regnumber(int r)
774{
775 if(r==0) ierror(0);
776 if(r<=32)
777 return r-1;
778 else if(r<=64)
779 return r+6;
780 else
781 ierror(0);
782}
783static zmax dwarf2_fboffset(struct Var *v)
784{
785 struct obj o;
786 if(!v||(v->storage_class!=AUTO&&v->storage_class!=REGISTER)) ierror(0);
787 o.flags=VAR;
788 o.v=v;
789 o.val.vmax=l2zm(0L);
790 return l2zm(real_offset(&o));
791}
792static void dwarf2_print_frame_location(FILE *f,struct Var *v)
793{
794 struct obj o;
795 o.flags=REG;
796 o.reg=sp;
797 o.val.vmax=l2zm(0L);
798 o.v=0;
799 dwarf2_print_location(f,&o);
800}
801static void emit_obj(FILE *f,struct obj *p,int t)
802/* Prints an object. */
803{
804 if(p->am){
805 if(p->am->flags&REG_IND) emit(f,"%s,%s",mregnames[p->am->offset],mregnames[p->am->base]);
806 if(p->am->flags&IMM_IND) emit(f,"%ld(%s)",p->am->offset,mregnames[p->am->base]);
807 return;
808 }
809 /* if(p->flags&DREFOBJ) emit(f,"(");*/
810 if(p->flags&VAR) {
811 if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
812 if(p->flags&REG){
813 emit(f,"%s",mregnames[p->reg]);
814 }else{
815 emit(f,"%ld(%s)",real_offset(p),mregnames[fp]);
816 }
817 }else{
818 if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,MAXINT);emit(f,"+");}
819 if(p->v->storage_class==STATIC){
820 emit(f,"%s%ld",labprefix,zm2l(p->v->offset));
821 }else{
822 emit(f,"%s%s",idprefix,p->v->identifier);
823 }
824 }
825 }
826 if((p->flags&REG)&&!(p->flags&VAR)) emit(f,"%s",mregnames[p->reg]);
827 if(p->flags&KONST){
828 emitval(f,&p->val,t&NU);
829 }
830 /* if(p->flags&DREFOBJ) emit(f,")");*/
831}
832static int exists_freereg(struct IC *p,int reg)
833/* Test if there is a sequence of FREEREGs containing FREEREG reg. */
834{
835 while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
836 if(p->code==FREEREG&&p->q1.reg==reg) return 1;
837 p=p->next;
838 }
839 return 0;
840}
841
842static size_t lsize;
843static bvtype *once,*twice;
844
845static void peephole(struct IC *p)
846/* Try to use addressing modes */
847{
848 int c,c2,r,cnt,maxlabel,uselr=0;struct IC *p2;struct AddressingMode *am;
849 if(cross_module){
850 lastlabel=0;
851 for(p2=p;p2;p2=p2->next){
852 if(p2->code>=LABEL&&p2->code<=BRA){
853 if(!lastlabel||p2->typf<lastlabel) lastlabel=p2->typf;
854 if(p->typf>maxlabel) maxlabel=p->typf;
855 }
856 }
857 }else{
858 maxlabel=label; /*FIXME*/
859 }
860 /*lsize=((label-lastlabel+1+7)/CHAR_BIT)*CHAR_BIT;*/
861 lsize=BVSIZE(label-lastlabel+1);
862 once=mymalloc(lsize);
863 twice=mymalloc(lsize);
864 memset(once,0,lsize);
865 memset(twice,0,lsize);
866 for(;p;p=p->next){
867 c=p->code;
868 if(c==CALL){
869 if(p->call_list==0){
870 uselr=1;
871 }else{
872 int i;
873 for(i=0;i<p->call_cnt;i++)
874 if(!p->call_list[i].v->fi||
875 !p->call_list[i].v->fi->inline_asm||
876 !(p->call_list[i].v->fi->flags&ALL_REGS)||
877 BTST(p->call_list[i].v->fi->regs_modified,lr))
878 uselr=1;
879 }
880 }
881 if((q1typ(p)&NQ)==LLONG&&(c==MULT||c==DIV||c==MOD||c==LSHIFT||c==RSHIFT)) uselr=1;
882 if(c==CONVERT&&(q1typ(p)&NQ)==LLONG&&ISFLOAT(ztyp(p)&NQ)) uselr=1;
883 if(c==CONVERT&&(ztyp(p)&NQ)==LLONG&&ISFLOAT(q1typ(p)&NQ)) uselr=1;
884 if(c!=FREEREG&&c!=ALLOCREG&&(c!=SETRETURN||!isreg(q1)||p->q1.reg!=p->z.reg)) exit_label=0;
885 if(c==LABEL) exit_label=p->typf;
886 /* Test which labels are jumped to more than once. */
887 if((c>=BEQ&&c<=BRA)&&p->typf-lastlabel>=lsize*CHAR_BIT){
888 printf("lsize=%lu p->typf=%d lastlabel=%d\n",lsize,p->typf,lastlabel);
889 ierror(0);
890 }
891 if(c>=BEQ&&c<=BRA){
892 if(BTST(once,p->typf-lastlabel))
893 BSET(twice,p->typf-lastlabel);
894 else
895 BSET(once,p->typf-lastlabel);
896 }
897 /* Try test-opt */
898 if(c==TEST&&!(p->q1.flags&DREFOBJ)){
899 for(p2=p->prev;p2;p2=p2->prev){
900 c2=p2->code;
901 if(c2==NOP||c2==ALLOCREG||c2==FREEREG) continue;
902 if(c2==CALL||(c2>=LABEL&&c2<=BRA)) break;
903 if((p2->z.flags&DREFOBJ)&&(p->q1.flags&(REG|DREFOBJ))!=REG) break;
904 if(p->q1.flags==p2->z.flags&&p->q1.am==p2->z.am){
905 if(!(p->q1.flags&VAR)||(p->q1.v==p2->z.v&&zmeqto(p->q1.val.vmax,p2->z.val.vmax))){
906 if(!(p->q1.flags&REG)||p->q1.reg==p2->z.reg){
907 if(p->z.flags==0||(isreg(z)&&p->z.reg==cr0)){
908 if(p->typf==p2->typf&&(!(p->typf&UNSIGNED)||!multiple_ccs)){
909 p2->ext.setcc=1;
910 }
911 break;
912 }
913 }
914 }
915 }
916 }
917 }
918 /* Try update */
919 if((c==ADDI2P||c==SUBIFP)&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg){
920 if((p->q2.flags&(KONST|DREFOBJ))==KONST){
921 eval_const(&p->q2.val,p->typf);
922 if(c==SUBIFP) vmax=zmsub(l2zm(0L),vmax);
923 if(zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))){
924 struct obj *o;
925 r=p->q1.reg;cnt=0;o=0;
926 for(p2=p->next;p2;p2=p2->next){
927 c2=p2->code;
928 if(c2==NOP||c2==ALLOCREG||c2==FREEREG) continue;
929 if((c2==CALL/*&&regscratch[r]*/)||(c2>=LABEL&&c2<=BRA)) break;
930 if((p2->q1.flags&(DREFOBJ|REG))==REG&&p2->q1.reg==r) break;
931 if((p2->q2.flags&(DREFOBJ|REG))==REG&&p2->q2.reg==r) break;
932 if((p2->z.flags&(DREFOBJ|REG))==REG&&p2->z.reg==r) break;
933 if((p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r) cnt|=1;
934 if((p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r) cnt|=2;
935 if((p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r) cnt|=4;
936 if((cnt&3)==3) break;
937 if(cnt){
938 if(cnt&1){
939 if((q1typ(p2)&NQ)==LLONG) break;
940 o=&p2->q1;
941 }else if(cnt&2){
942 if((q2typ(p2)&NQ)==LLONG) break;
943 o=&p2->q2;
944 }else{
945 if((ztyp(p2)&NQ)==LLONG) break;
946 o=&p2->z;
947 }
948 if(p2->code==ASSIGN&&((p2->typf&NQ)>POINTER||!zmeqto(p2->q2.val.vmax,sizetab[p2->typf&NQ])))
949 break;
950 o->am=am=mymalloc(sizeof(*am));
951 o->am->flags=(IMM_IND|UPDATE);
952 o->am->base=r;
953 o->am->offset=zm2l(vmax);
954 p->code=c=NOP;
955 break;
956 }
957 }
958 }
959 }
960 }
961 /* Try const(reg) */
962#ifndef oldpeep
963 if((c==ADDI2P||c==SUBIFP)&&isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
964 int base;zmax of;struct obj *o;
965 eval_const(&p->q2.val,p->typf);
966 if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
967 if(zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))){
968 r=p->z.reg;
969 if(isreg(q1)) base=p->q1.reg; else base=r;
970 o=0;
971 for(p2=p->next;p2;p2=p2->next){
972 c2=p2->code;
973 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
974 if(c2!=FREEREG&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r) break;
975 if(c2!=FREEREG&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==r) break;
976 if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/){
977 if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
978 if(o) break;
979 o=&p2->q1;
980 }
981 if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
982 if(o) break;
983 o=&p2->q2;
984 }
985 if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
986 if(o) break;
987 o=&p2->z;
988 }
989 }
990 if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG){
991 int m;
992 if(c2==FREEREG)
993 m=p2->q1.reg;
994 else
995 m=p2->z.reg;
996 if(m==r){
997 if(o){
998 o->am=am=mymalloc(sizeof(*am));
999 am->flags=IMM_IND;
1000 am->base=base;
1001 am->offset=zm2l(of);
1002 if(isreg(q1)){
1003 p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
1004 }else{
1005 p->code=c=ASSIGN;p->q2.flags=0;
1006 p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ];
1007 }
1008 }
1009 break;
1010 }
1011 if(c2!=FREEREG&&m==base) break;
1012 continue;
1013 }
1014 }
1015 }
1016 }
1017#else
1018 if((c==ADDI2P||c==SUBIFP)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&isreg(z)){
1019 int base;zmax of;
1020 p2=p->next;
1021 while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
1022 if(p2) c2=p2->code; else c2=0;
1023 eval_const(&p->q2.val,p->typf);
1024 if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
1025 r=p->z.reg;
1026 if(isreg(q1)) base=p->q1.reg; else base=r;
1027 if(c2&&zmleq(l2zm(-32768L),of)&&zmleq(of,l2zm(32767L))&&c2!=CALL&&(c2<LABEL||c2>BRA)
1028 &&(c2!=ASSIGN||((p2->typf&NQ)<=POINTER&&zmeqto(p2->q2.val.vmax,sizetab[p2->typf&NQ])))
1029 &&c2!=ADDRESS&&(((p2->z.flags&(DREFOBJ|REG))==REG&&p2->z.reg==r&&p2->q2.flags==0)||exists_freereg(p2->next,r))){
1030 if(((p2->q1.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=r)
1031 &&((p2->q2.flags&(REG|DREFOBJ))!=REG||p2->q2.reg!=r)){
1032 cnt=0;
1033 if((p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
1034 p2->q1.am=am=mymalloc(sizeof(*am));
1035 p2->q1.am->flags=IMM_IND;
1036 p2->q1.am->base=base;
1037 p2->q1.am->offset=zm2l(of);
1038 cnt++;
1039 }
1040 if((p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
1041 p2->q2.am=am=mymalloc(sizeof(*am));
1042 p2->q2.am->flags=IMM_IND;
1043 p2->q2.am->base=base;
1044 p2->q2.am->offset=zm2l(of);
1045 cnt++;
1046 }
1047 if((p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
1048 p2->z.am=am=mymalloc(sizeof(*am));
1049 p2->z.am->flags=IMM_IND;
1050 p2->z.am->base=base;
1051 p2->z.am->offset=zm2l(of);
1052 cnt++;
1053 }
1054 if(isreg(q1)){
1055 p->code=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
1056 }else{
1057 p->code=ASSIGN;p->q2.flags=0;
1058 }
1059 if(cnt==1&&((p2->q1.flags&(DREFOBJ|REG))!=REG||p2->q1.reg!=base)
1060 &&((p2->q2.flags&(DREFOBJ|REG))!=REG||p2->q2.reg!=base)
1061 &&((p2->z.flags&(DREFOBJ|REG))!=REG||p2->z.reg!=base) ){
1062 /* Can we use update? */
1063 p2=p2->next;
1064 while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
1065 if(p2){
1066 c2=p2->code;
1067 if(c2==ADDI2P||c2==SUBIFP){
1068 if((p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==base
1069 &&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==base
1070 &&(p2->q2.flags&(KONST|DREFOBJ))==KONST ){
1071 eval_const(&p2->q2.val,p2->typf);
1072 if(c2==SUBIFP) vmax=zmsub(l2zm(0L),vmax);
1073 if(zmeqto(vmax,of)){
1074 am->flags|=UPDATE;
1075 p2->code=NOP;
1076 }
1077 }
1078 }
1079 }
1080 }
1081 continue;
1082 }
1083 }
1084 }
1085#endif
1086 /* Try reg,reg */
1087#ifndef oldpeep
1088 if(c==ADDI2P&&isreg(q2)&&isreg(z)&&(isreg(q1)||p->q2.reg!=p->z.reg)){
1089 int base,idx;struct obj *o;
1090 r=p->z.reg;idx=p->q2.reg;
1091 if(isreg(q1)) base=p->q1.reg; else base=r;
1092 o=0;
1093 for(p2=p->next;p2;p2=p2->next){
1094 c2=p2->code;
1095 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
1096 if(c2!=FREEREG&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r) break;
1097 if(c2!=FREEREG&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==r) break;
1098 if((p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==idx&&idx!=r) break;
1099
1100 if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/){
1101 if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
1102 if(o||(q1typ(p2)&NQ)==LLONG) break;
1103 o=&p2->q1;
1104 }
1105 if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
1106 if(o||(q2typ(p2)&NQ)==LLONG) break;
1107 o=&p2->q2;
1108 }
1109 if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
1110 if(o||(ztyp(p2)&NQ)==LLONG) break;
1111 o=&p2->z;
1112 }
1113 }
1114 if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG){
1115 int m;
1116 if(c2==FREEREG)
1117 m=p2->q1.reg;
1118 else
1119 m=p2->z.reg;
1120 if(m==r){
1121 if(o){
1122 o->am=am=mymalloc(sizeof(*am));
1123 am->flags=REG_IND;
1124 am->base=base;
1125 am->offset=idx;
1126 if(isreg(q1)){
1127 p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
1128 }else{
1129 p->code=c=ASSIGN;p->q2.flags=0;
1130 p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ];
1131 }
1132 }
1133 break;
1134 }
1135 if(c2!=FREEREG&&m==base) break;
1136 continue;
1137 }
1138 }
1139 }
1140#else
1141 if(c==ADDI2P&&isreg(q2)&&isreg(z)&&p->q2.reg!=p->z.reg){
1142 int base,idx;
1143 p2=p->next;
1144 while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
1145 if(p2) c2=p2->code; else c2=0;
1146 r=p->z.reg;idx=p->q2.reg;
1147 if(isreg(q1)) base=p->q1.reg; else base=r;
1148 if(c2&&c2!=CALL&&(c2<LABEL||c2>BRA)
1149 &&(c2!=ASSIGN||((p2->typf&NQ)<=POINTER&&zmeqto(p2->q2.val.vmax,sizetab[p2->typf&NQ])))
1150 &&c2!=ADDRESS&&exists_freereg(p2->next,r)){
1151 if(((p2->q1.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=r)
1152 &&((p2->q2.flags&(REG|DREFOBJ))!=REG||p2->q2.reg!=r) ){
1153 cnt=0;
1154 if((p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
1155 p2->q1.am=am=mymalloc(sizeof(*am));
1156 p2->q1.am->flags=REG_IND;
1157 p2->q1.am->base=base;
1158 p2->q1.am->offset=idx;
1159 cnt++;
1160 }
1161 if((p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
1162 p2->q2.am=am=mymalloc(sizeof(*am));
1163 p2->q2.am->flags=REG_IND;
1164 p2->q2.am->base=base;
1165 p2->q2.am->offset=idx;
1166 cnt++;
1167 }
1168 if((p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
1169 p2->z.am=am=mymalloc(sizeof(*am));
1170 p2->z.am->flags=REG_IND;
1171 p2->z.am->base=base;
1172 p2->z.am->offset=idx;
1173 cnt++;
1174 }
1175 if(isreg(q1)){
1176 p->code=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
1177 }else{
1178 p->code=ASSIGN;p->q2.flags=0;
1179 }
1180 if(cnt==1&&((p2->q1.flags&(DREFOBJ|REG))!=REG||p2->q1.reg!=base)
1181 &&((p2->q2.flags&(DREFOBJ|REG))!=REG||p2->q2.reg!=base)
1182 &&((p2->z.flags&(DREFOBJ|REG))!=REG||p2->z.reg!=base) ){
1183 /* Can we use update? */
1184 p2=p2->next;
1185 while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
1186 if(p2){
1187 c2=p2->code;
1188 if(c2==ADDI2P){
1189 if((p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==base
1190 &&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==base
1191 &&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==idx){
1192 am->flags|=UPDATE;
1193 p2->code=NOP;
1194 }
1195 }
1196 }
1197 }
1198 continue;
1199 }
1200 }
1201 }
1202#endif
1203 }
1204 if(!uselr) function_calls=0;
1205}
1206
1207static void toc_entry(FILE *f,struct Var *v)
1208/* Create a toc-entry. */
1209{
1210 if(!use_sd(v->vtyp->flags)||(v->tattr&FAR)){
1211 if(v->storage_class==STATIC&&!ISFUNC(v->vtyp->flags)){
1212 emit(f,tocname);
1213 emit(f,"%s%s%ld:\n",tocprefix,labprefix,zm2l(v->offset));
1214 emit(f,"\t.long\t%s%ld\n",labprefix,zm2l(v->offset));
1215 }else{
1216 if(!ISFUNC(v->vtyp->flags)){
1217 emit(f,tocname);
1218 emit(f,"%s%s%s:\n",tocprefix,idprefix,v->identifier);
1219 emit(f,"\t.long\t%s%s\n",idprefix,v->identifier);
1220 }
1221 if(v->storage_class==EXTERN)
1222 emit(f,"\t.global\t%s%s%s\n",tocprefix,idprefix,v->identifier);
1223 }
1224 if(f) section=TOC;
1225 }
1226}
1227
1228static int savereg(struct Var *v,int i)
1229{
1230 if(v->tattr&(SYSCALL|NOSAVE)) return 0;
1231 if(vlas&&i==fp) return 1;
1232 if((i==sd&&(v->tattr&SAVEDS))||(regused[i]&&!regscratch[i]&&!regsa[i])
1233 ||((v->tattr&SAVEALL)&&i<=32&&(regscratch[i]||i==t1||i==t2||i==t3)&&((!v->fi)||(!(v->fi->flags&ALL_REGS))||BTST(v->fi->regs_modified,i)) ))
1234 return 1;
1235 return 0;
1236}
1237
1238static int stmw,stme;
1239
1240static void function_top(FILE *f,struct Var *v,long offset)
1241/* Generates function top. */
1242{
1243 int i,preg;long of;
1244 if(POWEROPEN) toc_entry(f,v);
1245 if(mregnames[1]!=regnames[1]) emit(f,"#vsc elf\n");
1246 if(g_flags[0]&USEDFLAG) emit(f,"#vsc cpu %s\n",g_flags_val[0].p);
1247 if(g_flags[1]&USEDFLAG) emit(f,"#vsc fpu %s\n",g_flags_val[1].p);
1248 if(!special_section(f,v)&&section!=CODE){emit(f,codename);if(f) section=CODE;}
1249 if(!GAS) emit(f,"\t.sdreg\t%s\n",mregnames[sd]);
1250 if(!optsize) emit(f,"\t.align\t4\n");
1251 if(v->storage_class==EXTERN){
1252 if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC)
1253 emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
1254 emit(f,"%s%s:\n",idprefix,v->identifier);
1255 }else
1256 emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
1257 frameoffset=minframe+maxpushed;
1258 framesize=frameoffset+offset;
1259 stme=0;
1260 for(i=1;i<=64;i++){
1261 if(savereg(v,i)){
1262 if(i<=32) framesize+=4; else framesize+=8;
1263 if(i<=32&&stme==0) stme=i;
1264 }else{
1265 if(i<=32) stme=0;
1266 }
1267 }
1268 if(stme==32||!(g_flags[11]&USEDFLAG)) stme=0;
1269 for(crsave=0,i=65;i<=72;i++)
1270 if((regused[i]&&!regscratch[i]&&!regsa[i])) crsave=1;
1271 if(crsave&&!POWEROPEN) framesize+=4;
1272 if(framesize==minframe&&((v->tattr&(SYSCALL))||(function_calls==0&&!crsave))) framesize=frameoffset=0;
1273 if(EABI)
1274 framesize=(framesize+7)/8*8;
1275 else
1276 framesize=(framesize+15)/16*16;
1277 stack=framesize;
1278 stack_valid=1;
1279 if(v->tattr&SYSCALL){
1280 emit(f,"#barrier\n");
1281 emit(f,"\tmtspr\t81,0\n");
1282 emit(f,"#barrier\n");
1283 emit(f,"\tstwu\t%s,-4(%s)\n",mregnames[t1],mregnames[sp]);
1284 emit(f,"\tmflr\t%s\n",mregnames[t1]);
1285 emit(f,"\tstwu\t%s,-4(%s)\n",mregnames[t1],mregnames[sp]);
1286 emit(f,"\tbl\t%s__syscall_init\n",idprefix);
1287 /*FIXME: das koennte man evtl. noch sparen */
1288 emit(f,"\taddi\t%s,%s,-8\n",mregnames[sp],mregnames[sp]);
1289 }else if(v->tattr&NOSAVE){
1290 /* nothing */
1291 }else if(function_calls||(stack_check&&framesize)){
1292 emit(f,"\tmflr\t%s\n",mregnames[t1]);
1293 BSET(regs_modified,t1);
1294 }
1295 if(stack_check&&framesize){
1296 BSET(regs_modified,t2);
1297 if(framesize<=32767){
1298 emit(f,"\tli\t%s,%ld\n",mregnames[t2],framesize);
1299 }else{
1300 emit(f,"\tlis\t%s,%ld\n",mregnames[t2],hi(framesize));
1301 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[t2],lo(framesize));
1302 }
1303 emit(f,"\tbl\t%s__stack_check\n",idprefix);
1304 if(!function_calls){
1305 emit(f,"\tmtlr\t%s\n",mregnames[t1]);
1306 BSET(regs_modified,lr);
1307 }
1308 }
1309 if(function_calls&&!(v->tattr&(SYSCALL|NOSAVE))&&framesize>=32760){
1310 if(POWEROPEN)
1311 emit(f,"\tst%s\t%s,8(%s)\n",sdt(LONG),mregnames[t1],mregnames[sp]);
1312 else
1313 emit(f,"\tst%s\t%s,4(%s)\n",sdt(LONG),mregnames[t1],mregnames[sp]);
1314 }
1315 of=minframe+maxpushed+offset;
1316 if(framesize!=0){
1317 if(framesize<=32767){
1318 emit(f,"\tstwu\t%s,-%ld(%s)\n",mregnames[sp],framesize,mregnames[sp]);
1319 preg=sp;
1320 }else{
1321 BSET(regs_modified,t1);
1322 BSET(regs_modified,t2);
1323 emit(f,"\tmr\t%s,%s\n",mregnames[t2],mregnames[sp]);
1324 emit(f,"\tlis\t%s,%ld\n",mregnames[t1],hi(-framesize));
1325 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t1],mregnames[t1],lo(-framesize));
1326 emit(f,"\tstwux\t%s,%s,%s\n",mregnames[sp],mregnames[sp],mregnames[t1]);
1327 preg=t2;of-=framesize;
1328 }
1329 }
1330 if(crsave&&!(v->tattr&NOSAVE)){
1331 BSET(regs_modified,t3);
1332 if(POWEROPEN){
1333 emit(f,"\tmfcr\t%s\n\tst%s\t%s,4(%s)\n",mregnames[t3],sdt(LONG),mregnames[t3],mregnames[preg]);
1334 }else{
1335 emit(f,"\tmfcr\t%s\n\tst%s\t%s,%ld(%s)\n",mregnames[t3],sdt(LONG),mregnames[t3],of,mregnames[preg]);
1336 of+=4;
1337 }
1338 }
1339 for(i=1;i<=64;i++){
1340 if(savereg(v,i)){
1341 if(i<=32){
1342 if(i==stme){
1343 emit(f,"\tstmw\t%s,%ld(%s)\n",mregnames[stme],of,mregnames[preg]);
1344 of+=(32-stme+1)*4;
1345 i=32;
1346 }else{
1347 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(LONG),mregnames[i],of,mregnames[preg]);
1348 of+=4;
1349 }
1350 }else{
1351 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(DOUBLE),mregnames[i],of,mregnames[preg]);
1352 of+=8;
1353 }
1354 }
1355 }
1356 if(function_calls&&!(v->tattr&(SYSCALL|NOSAVE))&&framesize<32760){
1357 if(POWEROPEN)
1358 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(LONG),mregnames[t1],framesize+8,mregnames[sp]);
1359 else
1360 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(LONG),mregnames[t1],framesize+4,mregnames[sp]);
1361 }
1362 if((v->tattr&SAVEDS)&&(SMALLDATA||BASERELMOS||POWEROPEN)){
1363 if(POWEROPEN){
1364 emit(f,"\t.global\t%s__getr2\n",idprefix);
1365 if(!function_calls)
1366 emit(f,"\tmflr\t%s\n",mregnames[t2]);
1367 emit(f,"\tbl\t%s__getr2\n",idprefix);
1368 if(!function_calls){
1369 emit(f,"\tmtlr\t%s\n",mregnames[t2]);
1370 BSET(regs_modified,lr);
1371 }
1372 }else{
1373 if(BASERELMOS){
1374 emit(f,"\t.global\t%s__restore_r13\n",idprefix);
1375 emit(f,"\tbl\t%s__restore_r13\n",idprefix);
1376 }else{
1377 emit(f,"\tlis\t%s,%s_SDA_BASE_@ha\n",mregnames[sd],idprefix);
1378 emit(f,"\taddi\t%s,%s,%s_SDA_BASE_@l\n",mregnames[sd],mregnames[sd],idprefix);
1379 }
1380 }
1381 }
1382 if(v->tattr&BREL){
1383 if(BASERELOS4){
1384 emit(f,"\t.global\t%s__baserel_get_addr\n",idprefix);
1385 emit(f,"\tbl\t%s__baserel_get_addr\n",idprefix);
1386 }
1387 }
1388 if(vlas){
1389 emit(f,"\tmr\t%s,%s\n",mregnames[fp],mregnames[sp]);
1390 emit(f,"\t.set\t____fo,%ld\n",frameoffset);
1391 }
1392}
1393static void function_bottom(FILE *f,struct Var *v,long offset)
1394/* Generates function bottom. */
1395{
1396 int i,preg;long of;
1397 if(v->tattr&SYSCALL){
1398 emit(f,"\tb\t%s__dispatch\n",idprefix);
1399 }else{
1400 of=minframe+maxpushed+offset;
1401 if(framesize<=32767){
1402 preg=sp;
1403 }else{
1404 emit(f,"\tlwz\t%s,0(%s)\n",mregnames[t2],mregnames[sp]);
1405 preg=t2;of-=framesize;
1406 }
1407 if(crsave&&!(v->tattr&NOSAVE)){
1408 if(POWEROPEN){
1409 emit(f,"\tl%s\t%s,8(%s)\n\tmtcr\t%s\n",ldt(LONG),mregnames[t1],mregnames[preg],mregnames[t1]);
1410 }else{
1411 emit(f,"\tl%s\t%s,%ld(%s)\n\tmtcr\t%s\n",ldt(LONG),mregnames[t1],of,mregnames[preg],mregnames[t1]);
1412 of+=4;
1413 }
1414 }
1415 if(function_calls&&!(v->tattr&NOSAVE)&&framesize<32760){
1416 BSET(regs_modified,lr);
1417 if(POWEROPEN)
1418 emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(LONG),mregnames[t1],framesize+8,mregnames[sp]);
1419 else
1420 emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(LONG),mregnames[t1],framesize+4,mregnames[sp]);
1421 }
1422 for(i=1;i<=64;i++){
1423 if(savereg(v,i)){
1424 if(i<=32){
1425 if(i==stme){
1426 emit(f,"\tlmw\t%s,%ld(%s)\n",mregnames[stme],of,mregnames[preg]);
1427 of+=(32-stme+1)*4;
1428 i=32;
1429 }else{
1430 emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(LONG),mregnames[i],of,mregnames[preg]);
1431 of+=4;
1432 }
1433 }else{
1434 emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(DOUBLE),mregnames[i],of,mregnames[preg]);
1435 of+=8;
1436 }
1437 }
1438 }
1439 if(framesize){
1440 if(framesize<=32767)
1441 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[sp],mregnames[sp],framesize);
1442 else
1443 emit(f,"\tmr\t%s,%s\n",mregnames[sp],mregnames[preg]);
1444 }
1445 if(function_calls&&!(v->tattr&NOSAVE)){
1446 if(framesize<32760){
1447 emit(f,"\tmtlr\t%s\n",mregnames[t1]);
1448 }else{
1449 BSET(regs_modified,lr);
1450 if(POWEROPEN)
1451 emit(f,"\tl%s\t%s,8(%s)\n\tmtlr\t%s\n",ldt(LONG),mregnames[t1],mregnames[sp],mregnames[t1]);
1452 else
1453 emit(f,"\tl%s\t%s,4(%s)\n\tmtlr\t%s\n",ldt(LONG),mregnames[t1],mregnames[sp],mregnames[t1]);
1454 }
1455 }
1456 emit(f,ret);
1457 }
1458 if(v->storage_class==EXTERN){
1459 emit(f,"\t.type\t%s%s,@function\n",idprefix,v->identifier);
1460 emit(f,"\t.size\t%s%s,$-%s%s\n",idprefix,v->identifier,idprefix,v->identifier);
1461 }else{
1462 emit(f,"\t.type\t%s%ld,@function\n",labprefix,zm2l(v->offset));
1463 emit(f,"\t.size\t%s%ld,$-%s%ld\n",labprefix,zm2l(v->offset),labprefix,zm2l(v->offset));
1464 }
1465 if(all_regs&&v->fi) v->fi->flags|=ALL_REGS;
1466}
1467
1468static int balign(struct obj *o)
1469/* Liefert die unteren 2 Bits des Objekts. 1 wenn unklar. */
1470{
1471 int sc;
1472 if(o->flags&DREFOBJ) return 1;
1473 if(o->am) ierror(0);
1474 if(!(o->flags&VAR)) ierror(0);
1475 sc=o->v->storage_class;
1476 if(sc==EXTERN||sc==STATIC){
1477 /* Alle statischen Daten werden vom cg auf 32bit alignt. */
1478 return zm2l(zmand(o->val.vmax,l2zm(3L)));
1479 }
1480 if(sc==AUTO||sc==REGISTER){
1481 zmax of=o->v->offset;
1482 if(!zmleq(l2zm(0L),of))
1483 of=zmsub(l2zm(0L),zmadd(of,maxalign));
1484 return zm2l(zmand(zmadd(of,o->val.vmax),l2zm(3L)));
1485 }
1486 ierror(0);
1487}
1488
1489/* load hiword of a long long object */
1490static void load_hword(FILE *f,int r,struct obj *o,int t,int tmp)
1491{
1492 struct rpair rp;
1493 BSET(regs_modified,r);
1494 if(o->flags&KONST){
1495 static struct obj cobj;
1496 cobj.flags=KONST;
1497 eval_const(&o->val,t);
1498 vumax=zumand(zumrshift(vumax,ul2zum(32UL)),ul2zum(0xffffffff));
1499 cobj.val.vulong=zum2zul(vumax);
1500 load_reg(f,r,&cobj,UNSIGNED|LONG,tmp);
1501 }else if(!o->am&&(o->flags&DREFOBJ)){
1502 if(!(o->flags&REG)) ierror(0);
1503 emit(f,"\tlwz\t%s,0(%s)\n",mregnames[r],mregnames[o->reg]);
1504 }else if(!o->am&&(o->flags&REG)){
1505 struct rpair rp;
1506 if(!reg_pair(o->reg,&rp))
1507 ierror(0);
1508 if(rp.r1!=r)
1509 emit(f,"\tmr\t%s,%s\n",mregnames[r],mregnames[rp.r1]);
1510 }else{
1511 load_reg(f,r,o,UNSIGNED|LONG,tmp);
1512 }
1513}
1514
1515/* load loword of a long long object */
1516static void load_lword(FILE *f,int r,struct obj *o,int t,int tmp)
1517{
1518 struct rpair rp;
1519 BSET(regs_modified,r);
1520 if(o->flags&KONST){
1521 static struct obj cobj;
1522 cobj.flags=KONST;
1523 eval_const(&o->val,t);
1524 vumax=zumand(vumax,ul2zum(0xffffffff));
1525 cobj.val.vulong=zum2zul(vumax);
1526 load_reg(f,r,&cobj,UNSIGNED|LONG,tmp);
1527 }else if(o->am){
1528 if(o->am->flags!=IMM_IND) ierror(0);
1529 o->am->offset+=4;
1530 load_reg(f,r,o,UNSIGNED|LONG,tmp);
1531 o->am->offset-=4;
1532 }else if(o->flags&DREFOBJ){
1533 if(!(o->flags&REG)) ierror(0);
1534 emit(f,"\tlwz\t%s,4(%s)\n",mregnames[r],mregnames[o->reg]);
1535 }else if(o->flags&REG){
1536 if(!reg_pair(o->reg,&rp)) ierror(0);
1537 if(rp.r2!=r)
1538 emit(f,"\tmr\t%s,%s\n",mregnames[r],mregnames[rp.r2]);
1539 }else{
1540 o->val.vmax=zmadd(o->val.vmax,l2zm(4L));
1541 load_reg(f,r,o,UNSIGNED|LONG,tmp);
1542 o->val.vmax=zmsub(o->val.vmax,l2zm(4L));
1543 }
1544}
1545/* store hiword of a long long object */
1546static void store_hword(FILE *f,int r,struct obj *o)
1547{
1548 struct rpair rp;
1549 if(!o->am&&(o->flags&DREFOBJ)){
1550 if(!(o->flags&REG)) ierror(0);
1551 emit(f,"\tstw\t%s,0(%s)\n",mregnames[r],mregnames[o->reg]);
1552 }else if(!o->am&&(o->flags&REG)){
1553 if(!reg_pair(o->reg,&rp)) ierror(0);
1554 if(rp.r1!=r)
1555 emit(f,"\tmr\t%s,%s\n",mregnames[rp.r1],mregnames[r]);
1556 }else{
1557 store_reg(f,r,o,UNSIGNED|LONG);
1558 }
1559}
1560
1561/* store loword of a long long object */
1562static void store_lword(FILE *f,int r,struct obj *o)
1563{
1564 struct rpair rp;
1565 if(o->am){
1566 if(o->am->flags!=IMM_IND) ierror(0);
1567 o->am->offset+=4;
1568 store_reg(f,r,o,UNSIGNED|LONG);
1569 o->am->offset-=4;
1570 }else if(o->flags&DREFOBJ){
1571 if(!(o->flags&REG)) ierror(0);
1572 emit(f,"\tstw\t%s,4(%s)\n",mregnames[r],mregnames[o->reg]);
1573 }else if(o->flags&REG){
1574 if(!reg_pair(o->reg,&rp)) ierror(0);
1575 if(rp.r2!=r)
1576 emit(f,"\tmr\t%s,%s\n",mregnames[rp.r2],mregnames[r]);
1577 }else{
1578 o->val.vmax=zmadd(o->val.vmax,l2zm(4L));
1579 store_reg(f,r,o,UNSIGNED|LONG);
1580 o->val.vmax=zmsub(o->val.vmax,l2zm(4L));
1581 }
1582}
1583/* if object cannot be dereferenced with a single load, load its address
1584 in register r (!=r0) and modify the object */
1585static void create_loadable(FILE *f,struct obj *o,int r)
1586{
1587 struct rpair rp;
1588 if(o->am) return;
1589 if((o->flags&(REG|DREFOBJ))==DREFOBJ){
1590 o->flags&=~DREFOBJ;
1591 load_reg(f,r,o,POINTER,r);
1592 o->flags|=(REG|DREFOBJ);
1593 o->reg=r;
1594 }
1595 if((o->flags&(VAR|REG))==VAR){
1596 if((o->v->storage_class==STATIC||o->v->storage_class==EXTERN)&&(!use_sd(o->v->vtyp->flags)||(o->v->tattr&FAR))){
1597 load_address(f,r,o,POINTER);
1598 o->reg=r;
1599 o->flags=(REG|DREFOBJ);
1600 }
1601 if((o->v->storage_class==AUTO||o->v->storage_class==REGISTER)&&real_offset(o)>32760){
1602 load_address(f,r,o,POINTER);
1603 o->reg=r;
1604 o->flags=(REG|DREFOBJ);
1605 }
1606 }
1607}
1608
1609static int get_reg()
1610{
1611 int i;
1612 for(i=2;i<=32;i++){
1613 if(!regs[i]&&(regscratch[i]||regused[i]))
1614 break;
1615 }
1616 if(i<=32){
1617 BSET(regs_modified,i);
1618 return i;
1619 }
1620 return 0;
1621}
1622
1623static int handle_llong(FILE *f,struct IC *p)
1624{
1625 int c=p->code,t,savemask=0;char *libfuncname;
1626 int msp;long mtmpoff;
1627
1628 t=(ztyp(p)&NU);
1629
1630 if(c==ADDRESS) return 0;
1631
1632
1633 if(c==GETRETURN){
1634 create_loadable(f,&p->z,t1);
1635 if(!reg_pair(p->q1.reg,&rp)) ierror(0);
1636 store_hword(f,rp.r1,&p->z);
1637 store_lword(f,rp.r2,&p->z);
1638 p->z.flags=0;
1639 return 1;
1640 }
1641
1642 if(c==SETRETURN){
1643 create_loadable(f,&p->q1,t1);
1644 if(!reg_pair(p->z.reg,&rp)) ierror(0);
1645 load_hword(f,rp.r1,&p->q1,q1typ(p),t2);
1646 load_lword(f,rp.r2,&p->q1,q1typ(p),t2);
1647 p->z.flags=0;
1648 return 1;
1649 }
1650
1651 if(c==CONVERT&&(q1typ(p)&NQ)==LLONG&&(ztyp(p)&NQ)==LLONG){
1652 p->code=c=ASSIGN;
1653 p->q2.val.vmax=sizetab[LLONG];
1654 }
1655
1656 if(c==ASSIGN||c==PUSH){
1657 int r;
1658 create_loadable(f,&p->q1,t1);
1659 if(c==ASSIGN){
1660 create_loadable(f,&p->z,t2);
1661 }else{
1662 pushed=(pushed+3)/4*4;
1663 if(align_arguments)
1664 pushed=(pushed+7)/8*8;
1665 }
1666 if(isreg(z)){
1667 if(!reg_pair(p->z.reg,&rp)) ierror(0);
1668 load_hword(f,rp.r1,&p->q1,q1typ(p),t1);
1669 }else{
1670 if(isreg(q1)){
1671 if(!reg_pair(p->q1.reg,&rp)) ierror(0);
1672 r=rp.r1;
1673 }else{
1674 if(p->q1.flags&KONST)
1675 r=t1;
1676 else
1677 r=t3;
1678 load_hword(f,r,&p->q1,q1typ(p),t1);
1679 }
1680 if(c==ASSIGN){
1681 store_hword(f,r,&p->z);
1682 }else{
1683 emit(f,"\tstw\t%s,%ld(%s)\n",mregnames[r],pushed+minframe,mregnames[sp]);
1684 pushed+=4;
1685 }
1686 }
1687 if(isreg(z)){
1688 if(!reg_pair(p->z.reg,&rp)) ierror(0);
1689 load_lword(f,rp.r2,&p->q1,q1typ(p),t1);
1690 }else{
1691 if(isreg(q1)){
1692 if(!reg_pair(p->q1.reg,&rp)) ierror(0);
1693 r=rp.r2;
1694 }else{
1695 if(p->q1.flags&KONST)
1696 r=t1;
1697 else
1698 r=t3;
1699 load_lword(f,r,&p->q1,q1typ(p),t1);
1700 }
1701 if(c==ASSIGN){
1702 store_lword(f,r,&p->z);
1703 }else{
1704 emit(f,"\tstw\t%s,%ld(%s)\n",mregnames[r],pushed+minframe,mregnames[sp]);
1705 pushed+=4;
1706 }
1707 }
1708 p->z.flags=0;
1709 return 1;
1710 }
1711
1712 if(c==CONVERT&&(t&NQ)<LLONG){
1713 if(isreg(q1)){
1714 if(!reg_pair(p->q1.reg,&rp)) ierror(0);
1715 zreg=rp.r2;
1716 }else{
1717 int r;
1718 if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==DREFOBJ)
1719 create_loadable(f,&p->q1,t1);
1720 if(isreg(z))
1721 r=p->z.reg;
1722 else
1723 r=t1;
1724 load_lword(f,r,&p->q1,q1typ(p),t2);
1725 zreg=r;
1726 }
1727 return 1;
1728 }
1729 if(c==CONVERT&&(q1typ(p)&NQ)<LLONG){
1730 int zl,zh,told=q1typ(p);
1731 if(isreg(z)){
1732 if(!reg_pair(p->z.reg,&rp)) ierror(0);
1733 zh=rp.r1;
1734 zl=rp.r2;
1735 }else{
1736 zl=t2;
1737 zh=t3;
1738 }
1739 if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==DREFOBJ)
1740 create_loadable(f,&p->q1,t1);
1741 load_reg(f,zl,&p->q1,q1typ(p),t1);
1742 if(told&UNSIGNED){
1743 if((told&NQ)==CHAR)
1744 emit(f,"\tclrlwi\t%s,%s,24\n",mregnames[zl],mregnames[zl]);
1745 if((told&NQ)==SHORT)
1746 emit(f,"\tclrlwi\t%s,%s,16\n",mregnames[zl],mregnames[zl]);
1747 emit(f,"\tli\t%s,0\n",mregnames[zh]);
1748 }else{
1749 if((told&NQ)==CHAR)
1750 emit(f,"\textsb\t%s,%s\n",mregnames[zl],mregnames[zl]);
1751 if((told&NQ)==SHORT)
1752 emit(f,"\textsh\t%s,%s\n",mregnames[zl],mregnames[zl]);
1753 emit(f,"\tsrawi\t%s,%s,31\n",mregnames[zh],mregnames[zl]);
1754 }
1755 create_loadable(f,&p->z,t1);
1756 store_lword(f,zl,&p->z);
1757 store_hword(f,zh,&p->z);
1758 p->z.flags=0;
1759 return 1;
1760 }
1761
1762 if(c==TEST){
1763 p->code=c=COMPARE;
1764 if(p->typf&UNSIGNED)
1765 p->q2.val.vullong=zum2zull(ul2zum(0UL));
1766 else
1767 p->q2.val.vllong=zm2zll(l2zm(0L));
1768 p->q2.flags=KONST;
1769 }
1770
1771 if(c==KOMPLEMENT){
1772 p->code=c=XOR;
1773 p->q2.flags=KONST;
1774 if(p->typf&UNSIGNED)
1775 p->q2.val.vullong=tu_max[LLONG];
1776 else
1777 p->q2.val.vllong=l2zm(-1L);
1778 }
1779 if(c==MINUS){
1780 p->code=c=SUB;
1781 p->q2=p->q1;
1782 p->q1.flags=KONST;
1783 p->q1.am=0;
1784 if(p->typf&UNSIGNED)
1785 p->q1.val.vullong=ul2zum(0UL);
1786 else
1787 p->q1.val.vllong=l2zm(0L);
1788 }
1789
1790 switch_IC(p);
1791
1792 if(c==COMPARE){
1793 int l1,l2,h1,h2,tmp,falselab=++label,c;
1794 zumax lo,uhi;zmax shi;
1795 char *sh;
1796 struct IC *b;
1797 if(multiple_ccs)
1798 ierror(0); /* still needed? */
1799 else
1800 p->z.reg=cr0;
1801 b=p->next;
1802 while(b->code==ALLOCREG||b->code==FREEREG) b=b->next;
1803 c=b->code;
1804 if(c<BEQ||c>BGT) ierror(0);
1805 if(p->typf&UNSIGNED)
1806 sh="cmplw";
1807 else
1808 sh="cmpw";
1809 if((c==BNE||c==BEQ)&&(p->q2.flags&KONST)&&p->z.reg==cr0){
1810 eval_const(&p->q2.val,q2typ(p));
1811 if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))){
1812 if(isreg(q1)){
1813 if(!reg_pair(p->q1.reg,&rp)) ierror(0);
1814 emit(f,"\tor.\t%s,%s,%s\n",mregnames[t1],mregnames[rp.r1],mregnames[rp.r2]);
1815 }else{
1816 create_loadable(f,&p->q1,t1);
1817 load_lword(f,t3,&p->q1,q1typ(p),t2);
1818 load_hword(f,t1,&p->q1,q1typ(p),t2);
1819 emit(f,"\tor.\t%s,%s,%s\n",mregnames[t3],mregnames[t3],mregnames[t1]);
1820 }
1821 return 1;
1822 }
1823 }
1824 h1=h2=l1=l2=0;
1825 if(isreg(q1)){
1826 if(!reg_pair(p->q1.reg,&rp)) ierror(0);
1827 h1=rp.r1;
1828 l1=rp.r2;
1829 }else{
1830 create_loadable(f,&p->q1,t1);
1831 h1=l1=t3;
1832 }
1833 if(isreg(q2)){
1834 if(!reg_pair(p->q2.reg,&rp)) ierror(0);
1835 h2=rp.r1;
1836 l2=rp.r2;
1837 }else if(p->q2.flags&KONST){
1838 eval_const(&p->q2.val,q2typ(p));
1839 lo=zumrshift(zumlshift(vumax,ul2zum(32UL)),ul2zum(32UL));
1840 if(zumleq(lo,ul2zum(65535L)))
1841 l2=-1;
1842 if(p->typf&UNSIGNED){
1843 uhi=zumrshift(vumax,ul2zum(32UL));
1844 if(zumleq(uhi,ul2zum(65535L)))
1845 h2=-1;
1846 }else{
1847 shi=zmrshift(vmax,l2zm(32L));
1848 if(zmleq(shi,l2zm(32767L))&&zmleq(l2zm(-32768L),shi))
1849 h2=-1;
1850 }
1851 }
1852 if(h2==0||l2==0){
1853 if(!(p->q1.flags&REG)||p->q1.reg!=t1){
1854 create_loadable(f,&p->q2,t1);
1855 }else if(tmp=get_reg()){
1856 create_loadable(f,&p->q2,tmp);
1857 }
1858 if(h2==0) h2=t2;
1859 if(l2==0) l2=t2;
1860 }
1861 load_hword(f,h1,&p->q1,q1typ(p),0);
1862 if(h2==-1){
1863 emit(f,"\t%si\t%s,%s,",sh,mregnames[p->z.reg],mregnames[h1]);
1864 if(p->typf&UNSIGNED)
1865 emitzum(f,uhi);
1866 else
1867 emitzm(f,shi);
1868 emit(f,"\n");
1869 }else{
1870 load_hword(f,h2,&p->q2,q2typ(p),t2);
1871 emit(f,"\t%s\t%s,%s,%s\n",sh,mregnames[p->z.reg],mregnames[h1],mregnames[h2]);
1872 }
1873 if(c==BGT||c==BGE){
1874 emit(f,"\tbgt\t%s,%s%d\n",mregnames[p->z.reg],labprefix,b->typf);
1875 emit(f,"\tblt\t%s,%s%d\n",mregnames[p->z.reg],labprefix,falselab);
1876 }else if(c==BLT||c==BLE){
1877 emit(f,"\tblt\t%s,%s%d\n",mregnames[p->z.reg],labprefix,b->typf);
1878 emit(f,"\tbgt\t%s,%s%d\n",mregnames[p->z.reg],labprefix,falselab);
1879 }else if(c!=BNE){
1880 emit(f,"\tbne\t%s,%s%d\n",mregnames[p->z.reg],labprefix,falselab);
1881 }else{
1882 emit(f,"\tbne\t%s,%s%d\n",mregnames[p->z.reg],labprefix,b->typf);
1883 }
1884
1885 load_lword(f,l1,&p->q1,q1typ(p),t1);
1886 if(l2==-1){
1887 emit(f,"\tcmplwi\t%s,%s,",mregnames[p->z.reg],mregnames[l1]);
1888 emitzm(f,lo);
1889 emit(f,"\n");
1890 }else{
1891 load_lword(f,l2,&p->q2,q2typ(p),t2);
1892 emit(f,"\tcmplw\t%s,%s,%s\n",mregnames[p->z.reg],mregnames[l1],mregnames[l2]);
1893 }
1894 emit(f,"\tb%s\t%s,%s%d\n",ccs[c-BEQ],mregnames[p->z.reg],labprefix,b->typf);
1895 emit(f,"%s%d:\n",labprefix,falselab);
1896 b->code=NOP;
1897
1898 return 1;
1899 }
1900
1901 if(c==ADD||c==SUB||c==AND||c==OR||c==XOR){
1902 /*FIXME: q2==z, q1reg+q2reg=zreg */
1903 int zl,zh,l1,l2,h1,h2,tmp;
1904 char *sl,*sh;
1905 if(c==ADD){
1906 sl="addc";
1907 sh="adde";
1908 }else if(c==SUB){
1909 /* there is no subc, therefore we always use reverse order */
1910 sl="subfc";
1911 sh="subfe";
1912 }else if(c==AND){
1913 sl=sh="and";
1914 }else if(c==OR){
1915 sl=sh="or";
1916 }else if(c==XOR){
1917 sl=sh="xor";
1918 }else
1919 ierror(0);
1920 l1=l2=h1=h2=zl=zh=0;
1921 create_loadable(f,&p->q1,t1);
1922 if(isreg(q1)){
1923 if(!reg_pair(p->q1.reg,&rp)) ierror(0);
1924 h1=rp.r1;
1925 l1=rp.r2;
1926 }else{
1927 create_loadable(f,&p->q1,t1);
1928 l1=t3;
1929 h1=t1;
1930 }
1931 if(isreg(q2)){
1932 if(!reg_pair(p->q2.reg,&rp)) ierror(0);
1933 h2=rp.r1;
1934 l2=rp.r2;
1935 }else if(p->q2.flags&KONST){
1936 /* check for immediates */
1937 if(c==OR||c==XOR){
1938 /* or and xor can always be done using (x)ori and (x)oris */
1939 h2=l2=-1;
1940 }
1941 if(c==ADD){
1942 zmax tmp;
1943 eval_const(&p->q2.val,q2typ(p));
1944 tmp=zmrshift(vmax,l2zm(32L));
1945 /* there are addze and addme instructions */
1946 if(zmeqto(tmp,l2zm(0L))||zmeqto(tmp,l2zm(-1L)))
1947 h2=-1;
1948 /* addic supports 16bit signed values */
1949 tmp=zmrshift(zmlshift(vmax,l2zm(32L)),l2zm(32L));
1950 if(zmleq(tmp,l2zm(32767L))&&zmleq(l2zm(-32768L),tmp))
1951 l2=-1;
1952 }
1953 if(c==SUB){
1954 zmax tmp;
1955 eval_const(&p->q2.val,q2typ(p));
1956 tmp=zmrshift(vmax,l2zm(32L));
1957 /* there are addze and addme instructions */
1958 if(zmeqto(tmp,l2zm(0L))||zmeqto(tmp,l2zm(1L)))
1959 h2=-1;
1960 /* addic supports 16bit signed values */
1961 tmp=zmrshift(zmlshift(vmax,l2zm(32L)),l2zm(32L));
1962 if(zmleq(tmp,l2zm(32768L))&&zmleq(l2zm(-32767L),tmp))
1963 l2=-1;
1964 }
1965 }
1966 if(!l2||!h2){
1967 if(!(p->q1.flags&REG)||p->q1.reg!=t1){
1968 create_loadable(f,&p->q2,t1);
1969 }else if(tmp=get_reg()){
1970 create_loadable(f,&p->q2,tmp);
1971 }
1972 if(h2==0) h2=t2;
1973 if(l2==0) l2=t2;
1974 }
1975 if(isreg(z)&&(!isreg(q2)||p->z.reg!=p->q2.reg)){
1976 if(!reg_pair(p->z.reg,&rp)) ierror(0);
1977 zh=rp.r1;
1978 zl=rp.r2;
1979 }else{
1980 zl=t3;
1981 zh=t1;
1982 }
1983 if((p->q1.flags&KONST)&&l1==t3){
1984 load_lword(f,t2,&p->q1,q1typ(p),0);
1985 emit(f,"\tmr\t%s,%s\n",mregnames[t3],mregnames[t2]);
1986 BSET(regs_modified,t3);
1987 }else
1988 load_lword(f,l1,&p->q1,q1typ(p),0);
1989 if(l2!=-1){
1990 load_lword(f,l2,&p->q2,q2typ(p),t2);
1991 emit(f,"\t%s\t%s,%s,%s\n",sl,mregnames[zl],mregnames[l2],mregnames[l1]);
1992 }else{
1993 eval_const(&p->q2.val,q2typ(p));
1994 if(c==ADD||c==SUB){
1995 if(c==SUB) vmax=zmsub(l2zm(0L),vmax);
1996 vmax=zmrshift(zmlshift(vmax,l2zm(32L)),l2zm(32L));
1997 emit(f,"\taddic\t%s,%s,",mregnames[zl],mregnames[l1]);
1998 emitzm(f,vmax);
1999 emit(f,"\n");
2000 }else if(c==OR||c==XOR){
2001 zumax tmp;
2002 if(zumeqto(zumand(vumax,ul2zum(0xffffffffUL)),ul2zum(0xffffffffUL))){
2003 if(c==XOR)
2004 emit(f,"\tnor\t%s,%s,%s\n",mregnames[zl],mregnames[l1],mregnames[l1]);
2005 else
2006 emit(f,"\tli\t%s,-1\n",mregnames[zl]);
2007 }else{
2008 tmp=zumand(vumax,ul2zum(0xffffUL));
2009 if(!zumeqto(tmp,ul2zum(0UL))){
2010 emit(f,"\t%si\t%s,%s,",sl,mregnames[zl],mregnames[l1]);
2011 emitzum(f,tmp);
2012 emit(f,"\n");
2013 l1=zl;
2014 }
2015 tmp=zumand(zumrshift(vumax,ul2zum(16UL)),ul2zum(0xffff));
2016 if(!zumeqto(tmp,ul2zum(0UL))){
2017 emit(f,"\t%sis\t%s,%s,",sl,mregnames[zl],mregnames[l1]);
2018 emitzum(f,tmp);
2019 emit(f,"\n");
2020 l1=zl;
2021 }
2022 if(l1!=zl)
2023 emit(f,"\tmr\t%s,%s\n",mregnames[zl],mregnames[l1]);
2024 }
2025 }else
2026 ierror(0);
2027 }
2028 if(h2!=-1){
2029 load_hword(f,h2,&p->q2,q2typ(p),t2);
2030 load_hword(f,h1,&p->q1,q1typ(p),0);
2031 emit(f,"\t%s\t%s,%s,%s\n",sh,mregnames[zh],mregnames[h2],mregnames[h1]);
2032 }else{
2033 load_hword(f,h1,&p->q1,q1typ(p),0);
2034 eval_const(&p->q2.val,q2typ(p));
2035 if(c==ADD||c==SUB){
2036 if(c==SUB) vmax=zmsub(l2zm(0L),vmax);
2037 vmax=zmrshift(vmax,l2zm(32L));
2038 if(zmeqto(vmax,l2zm(0L))){
2039 emit(f,"\taddze\t%s,%s\n",mregnames[zh],mregnames[h1]);
2040 }else if(zmeqto(vmax,l2zm(-1L))){
2041 emit(f,"\taddme\t%s,%s\n",mregnames[zh],mregnames[h1]);
2042 }else
2043 ierror(0);
2044 }else if(c==OR||c==XOR){
2045 zumax tmp;
2046 if(zumeqto(zumand(zumrshift(vumax,ul2zum(32L)),ul2zum(0xffffffffUL)),ul2zum(0xffffffffUL))){
2047 if(c==XOR)
2048 emit(f,"\tnor\t%s,%s,%s\n",mregnames[zh],mregnames[h1],mregnames[h1]);
2049 else
2050 emit(f,"\tli\t%s,-1\n",mregnames[zh]);
2051 }else{
2052 tmp=zumand(zumrshift(vumax,ul2zum(32UL)),ul2zum(0xffffUL));
2053 if(!zumeqto(tmp,ul2zum(0UL))){
2054 emit(f,"\t%si\t%s,%s,",sl,mregnames[zh],mregnames[h1]);
2055 emitzum(f,tmp);
2056 emit(f,"\n");
2057 h1=zh;
2058 }
2059 tmp=zumand(zumrshift(vumax,ul2zum(48UL)),ul2zum(0xffff));
2060 if(!zumeqto(tmp,ul2zum(0UL))){
2061 emit(f,"\t%sis\t%s,%s,",sl,mregnames[zh],mregnames[h1]);
2062 emitzum(f,tmp);
2063 emit(f,"\n");
2064 h1=zh;
2065 }
2066 if(h1!=zh)
2067 emit(f,"\tmr\t%s,%s\n",mregnames[zh],mregnames[h1]);
2068 }
2069 }
2070 }
2071 if(p->z.flags){
2072 create_loadable(f,&p->z,t2);
2073 store_lword(f,zl,&p->z);
2074 store_hword(f,zh,&p->z);
2075 p->z.flags=0;
2076 }
2077 return 1;
2078 }
2079
2080 create_loadable(f,&p->q1,t1);
2081
2082 if(tmpoff>=32768&&(regs[r3]||regs[r4]||regs[r5]||regs[r6])){
2083 emit(f,"\taddis\t%s,%s,%ld\n",mregnames[t2],mregnames[sp],hi(tmpoff));
2084 if(lo(tmpoff)) emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[t2],lo(tmpoff));
2085 msp=t2;
2086 mtmpoff=0;
2087 }else{
2088 msp=sp;
2089 mtmpoff=tmpoff;
2090 }
2091
2092 if(regs[r3]){ emit(f,"\tstw\t%s,%ld(%s)\n",mregnames[r3],mtmpoff-4,mregnames[msp]);savemask|=1;}
2093 if(regs[r4]){ emit(f,"\tstw\t%s,%ld(%s)\n",mregnames[r4],mtmpoff-8,mregnames[msp]);savemask|=2;}
2094 if(regs[r5]) {emit(f,"\tstw\t%s,%ld(%s)\n",mregnames[r5],mtmpoff-12,mregnames[msp]);savemask|=4;}
2095 if(regs[r6]) {emit(f,"\tstw\t%s,%ld(%s)\n",mregnames[r6],mtmpoff-16,mregnames[msp]);savemask|=8;}
2096
2097 if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q1.reg>=r3&&p->q1.reg<=r6){
2098 emit(f,"\tmr\t%s,%s\n",mregnames[t1],mregnames[p->q1.reg]);
2099 p->q1.reg=t1;
2100 }
2101 if((p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q2.reg>=r3&&p->q2.reg<=r6){
2102 emit(f,"\tmr\t%s,%s\n",mregnames[t2],mregnames[p->q2.reg]);
2103 p->q2.reg=t2;
2104 }
2105
2106 if((q1typ(p)&NQ)==LLONG){
2107 if(p->q1.am&&p->q1.am->base==r3){
2108 if(p->q1.am->flags==REG_IND&&p->q1.am->offset==r4) ierror(0);
2109 load_lword(f,r4,&p->q1,q1typ(p),0);
2110 load_hword(f,r3,&p->q1,q1typ(p),0);
2111 }else{
2112 if(p->q1.am&&p->q1.am->flags==REG_IND&&p->q1.am->offset==r3) ierror(0);
2113 load_hword(f,r3,&p->q1,q1typ(p),0);
2114 load_lword(f,r4,&p->q1,q1typ(p),0);
2115 }
2116 }else{
2117 if(!ISFLOAT(q1typ(p))) ierror(0);
2118 load_reg(f,f1,&p->q1,q1typ(p),0);
2119 }
2120
2121 if(p->q2.flags){
2122 create_loadable(f,&p->q2,t2);
2123 if((q2typ(p)&NQ)==LLONG){
2124 if(isreg(q2)&&p->q2.reg==r3r4){
2125 emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r5],mtmpoff-4,mregnames[msp]);
2126 emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r6],mtmpoff-8,mregnames[msp]);
2127 }else{
2128 if(p->q2.am&&p->q2.am->base==r5){
2129 if(p->q2.am->flags==REG_IND&&p->q2.am->offset==r6) ierror(0);
2130 load_lword(f,r6,&p->q2,q2typ(p),0);
2131 load_hword(f,r5,&p->q2,q2typ(p),0);
2132 }else{
2133 if(p->q2.am&&p->q2.am->flags==REG_IND&&p->q2.am->offset==r5) ierror(0);
2134 load_hword(f,r5,&p->q2,q2typ(p),0);
2135 load_lword(f,r6,&p->q2,q2typ(p),0);
2136 }
2137 }
2138 }else{
2139 if((q2typ(p)&NQ)>=LLONG) ierror(0);
2140 if(isreg(q2)&&p->q2.reg==r3){
2141 emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r5],mtmpoff-4,mregnames[msp]);
2142 }else{
2143 load_reg(f,r5,&p->q2,q2typ(p),0);
2144 }
2145 }
2146 }
2147
2148 if(c==MULT) libfuncname="__mulint64";
2149 else if(c==DIV){
2150 if(t&UNSIGNED)
2151 libfuncname="__divuint64";
2152 else
2153 libfuncname="__divsint64";
2154 }else if(c==MOD){
2155 if(t&UNSIGNED)
2156 libfuncname="__moduint64";
2157 else
2158 libfuncname="__modsint64";
2159 }else if(c==CONVERT){
2160 static char s[32];
2161 if(ISFLOAT(q1typ(p)))
2162 sprintf(s,"__flt%dto%cint64",(q1typ(p)&NQ)==FLOAT?32:64,(ztyp(p)&UNSIGNED)?'u':'s');
2163 else
2164 sprintf(s,"__%cint64toflt%d",(q1typ(p)&UNSIGNED)?'u':'s',(ztyp(p)&NQ)==FLOAT?32:64);
2165 libfuncname=s;
2166 }else if(c==RSHIFT){
2167 if(t&UNSIGNED)
2168 libfuncname="__rshuint64";
2169 else
2170 libfuncname="__rshsint64";
2171 }else if(c==LSHIFT)
2172 libfuncname="__lshint64";
2173 else{
2174 printf("c=%d\n",c);
2175 ierror(0);
2176 }
2177 emit(f,"\t.global\t%s%s\n",idprefix,libfuncname);
2178 emit(f,"\tbl\t%s%s\n",idprefix,libfuncname);
2179 stack_valid=0; /*FIXME*/
2180
2181 if((p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
2182 if((p->z.reg==r3&&(savemask&1))||
2183 (p->z.reg==r4&&(savemask&2))||
2184 (p->z.reg==r5&&(savemask&4))||
2185 (p->z.reg==r6&&(savemask&8))){
2186 if(p->z.reg==r3)
2187 emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[t1],mtmpoff-4,mregnames[msp]);
2188 else if(p->z.reg==r4)
2189 emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[t1],mtmpoff-8,mregnames[msp]);
2190 else if(p->z.reg==r5)
2191 emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[t1],mtmpoff-12,mregnames[msp]);
2192 else if(p->z.reg==r6)
2193 emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[t1],mtmpoff-16,mregnames[msp]);
2194 else
2195 ierror(0);
2196 p->z.reg=t1;
2197 }
2198 }
2199
2200 if((p->z.flags&REG)&&p->z.reg==r3)
2201 savemask&=~1;
2202 if((p->z.flags&REG)&&p->z.reg==r4)
2203 savemask&=~2;
2204 if((p->z.flags&REG)&&p->z.reg==r5)
2205 savemask&=~4;
2206 if((p->z.flags&REG)&&p->z.reg==r6)
2207 savemask&=~8;
2208 if((p->z.flags&REG)&&p->z.reg==r3r4)
2209 savemask&=~3;
2210 if((p->z.flags&REG)&&p->z.reg==r5r6)
2211 savemask&=~12;
2212
2213
2214 if(ISFLOAT(ztyp(p))){
2215 zreg=f1;
2216 }else{
2217 create_loadable(f,&p->z,t1);
2218 store_hword(f,r3,&p->z);
2219 store_lword(f,r4,&p->z);
2220 p->z.flags=0;
2221 }
2222
2223 if(savemask&1)
2224 emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r3],mtmpoff-4,mregnames[msp]);
2225 if(savemask&2)
2226 emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r4],mtmpoff-8,mregnames[msp]);
2227 if(savemask&4)
2228 emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r5],mtmpoff-12,mregnames[msp]);
2229 if(savemask&8)
2230 emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r6],mtmpoff-16,mregnames[msp]);
2231
2232 return 1;
2233}
2234/****************************************/
2235/* End of private data and functions. */
2236/****************************************/
2237
2238
2239int init_cg(void)
2240/* Does necessary initializations for the code-generator. Gets called */
2241/* once at the beginning and should return 0 in case of problems. */
2242{
2243 int i;
2244 /* Initialize some values which cannot be statically initialized */
2245 /* because they are stored in the target's arithmetic. */
2246 maxalign=l2zm(8L);
2247 if(POWEROPEN){
2248 stackalign=l2zm(4L);
2249 align_arguments=0;
2250 }else{
2251 tocname=sdataname;
2252 stackalign=l2zm(4L);
2253 if(NOALIGNARGS)
2254 align_arguments=0;
2255 else
2256 align_arguments=1;
2257 }
2258 char_bit=l2zm(8L);
2259 if(g_flags[7]&USEDFLAG){
2260 malign[INT]=malign[LONG]=malign[LLONG]=malign[POINTER]=malign[FLOAT]=malign[DOUBLE]=malign[LDOUBLE]=2;
2261 }
2262 for(i=0;i<=MAX_TYPE;i++){
2263 sizetab[i]=l2zm(msizetab[i]);
2264 align[i]=l2zm(malign[i]);
2265 }
2266 for(i=0;i<=MAXR;i++) mregnames[i]=regnames[i];
2267 for(i= 1;i<=32;i++){
2268 regsize[i]=l2zm(4L);
2269 regtype[i]=&ltyp;
2270 if(g_flags[8]&USEDFLAG) mregnames[i]++;
2271 }
2272 for(i=33;i<=64;i++){
2273 regsize[i]=l2zm(8L);
2274 regtype[i]=&ldbl;
2275 if(g_flags[8]&USEDFLAG) mregnames[i]++;
2276 }
2277 for(i=65;i<=72;i++){
2278 regsize[i]=l2zm(1L);
2279 regtype[i]=&lchar;
2280 if(g_flags[8]&USEDFLAG) mregnames[i]+=2;
2281 }
2282 for(i=74;i<=86;i++){
2283 regsize[i]=l2zm(8L);
2284 regtype[i]=&lltyp;
2285 }
2286
2287 /* Use multiple ccs. */
2288 multiple_ccs=1;
2289
2290 /* Initialize the min/max-settings. Note that the types of the */
2291 /* host system may be different from the target system and you may */
2292 /* only use the smallest maximum values ANSI guarantees if you */
2293 /* want to be portable. */
2294 /* That's the reason for the subtraction in t_min[INT]. Long could */
2295 /* be unable to represent -2147483648 on the host system. */
2296 t_min[CHAR]=l2zm(-128L);
2297 t_min[SHORT]=l2zm(-32768L);
2298 t_min[INT]=zmsub(l2zm(-2147483647L),l2zm(1L));
2299 t_min[LONG]=t_min(INT);
2300 t_min[LLONG]=zmlshift(l2zm(1L),l2zm(63L));
2301 t_min[MAXINT]=t_min(LLONG);
2302 t_max[CHAR]=ul2zum(127L);
2303 t_max[SHORT]=ul2zum(32767UL);
2304 t_max[INT]=ul2zum(2147483647UL);
2305 t_max[LONG]=t_max(INT);
2306 t_max[LLONG]=zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL));
2307 t_max[MAXINT]=t_max(LLONG);
2308 tu_max[CHAR]=ul2zum(255UL);
2309 tu_max[SHORT]=ul2zum(65535UL);
2310 tu_max[INT]=ul2zum(4294967295UL);
2311 tu_max[LONG]=t_max(UNSIGNED|INT);
2312 tu_max[LLONG]=zumkompl(ul2zum(0UL));
2313 tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
2314
2315 /* Reserve a few registers for use by the code-generator. */
2316 /* This is not optimal but simple. */
2317 if(POWEROPEN){
2318 sd=r2;
2319 }
2320 regsa[t1]=regsa[t2]=regsa[t3]=1;
2321 regsa[f1]=regsa[f2]=regsa[f3]=1;
2322 regsa[sp]=regsa[fp]=regsa[sd]=regsa[r2]=1;
2323 regscratch[t1]=regscratch[t2]=regscratch[t3]=0;
2324 regscratch[f1]=regscratch[f2]=regscratch[f3]=0;
2325 regscratch[sp]=regscratch[fp]=regscratch[sd]=regscratch[r2]=0;
2326
2327 if(g_flags[6]&USEDFLAG) {minframe=8;labprefix=".l";idprefix="";}
2328 if(POWEROPEN) {minframe=24;labprefix="l";idprefix="_";}
2329
2330 if(optsize){
2331 dataname="\t.data\n";
2332 rodataname="\t.section\t.rodata\n";
2333 sdataname="\t.section\t\".sdata\",\"aw\"\n";
2334 sdata2name="\t.section\t\".sdata2\",\"a\"\n";
2335 sbssname="\t.section\t\".sbss\",\"auw\"\n";
2336 }
2337
2338 if(BASERELOS4) bssname="\t.bss\n";
2339
2340 target_macros=marray;
2341
2342 declare_builtin("__mulint64",LLONG,LLONG,r3r4,LLONG,r5r6,1,0);
2343 declare_builtin("__divsint64",LLONG,LLONG,r3r4,LLONG,r5r6,1,0);
2344 declare_builtin("__divuint64",UNSIGNED|LLONG,UNSIGNED|LLONG,r3r4,UNSIGNED|LLONG,r5r6,1,0);
2345 declare_builtin("__modsint64",LLONG,LLONG,r3r4,LLONG,r5r6,1,0);
2346 declare_builtin("__moduint64",UNSIGNED|LLONG,UNSIGNED|LLONG,r3r4,UNSIGNED|LLONG,r5r6,1,0);
2347 declare_builtin("__lshint64",LLONG,LLONG,r3r4,INT,r5,1,0);
2348 declare_builtin("__rshsint64",LLONG,LLONG,r3r4,INT,r5,1,0);
2349 declare_builtin("__rshuint64",LLONG,UNSIGNED|LLONG,r3r4,INT,r5,1,0);
2350
2351 return 1;
2352}
2353
2354void init_db(FILE *f)
2355{
2356 dwarf2_setup(sizetab[POINTER],".byte",".2byte",".4byte",".4byte",labprefix,idprefix,".section");
2357 dwarf2_print_comp_unit_header(f);
2358}
2359
2360int freturn(struct Typ *t)
2361/* Returns the register in which variables of type t are returned. */
2362/* If the value cannot be returned in a register returns 0. */
2363/* A pointer MUST be returned in a register. The code-generator */
2364/* has to simulate a pseudo register if necessary. */
2365{
2366 if(ISFLOAT(t->flags)) return 34; /* f1 */
2367 if(ISSTRUCT(t->flags)||ISUNION(t->flags)) return 0;
2368 if(zmleq(szof(t),l2zm(4L))) return r3;
2369 if((t->flags&NQ)==LLONG) return 74; /* r3/r4 */
2370 return 0;
2371}
2372
2373int reg_pair(int r,struct rpair *p)
2374/* Returns 0 if the register is no register pair. If r */
2375/* is a register pair non-zero will be returned and the */
2376/* structure pointed to p will be filled with the two */
2377/* elements. */
2378{
2379 if(r<74||r>86)
2380 return 0;
2381 switch(r){
2382 case 74: p->r1=4;p->r2=5;return 1;
2383 case 75: p->r1=6;p->r2=7;return 1;
2384 case 76: p->r1=8;p->r2=9;return 1;
2385 case 77: p->r1=10;p->r2=11;return 1;
2386 case 78: p->r1=15;p->r2=16;return 1;
2387 case 79: p->r1=17;p->r2=18;return 1;
2388 case 80: p->r1=19;p->r2=20;return 1;
2389 case 81: p->r1=21;p->r2=22;return 1;
2390 case 82: p->r1=23;p->r2=24;return 1;
2391 case 83: p->r1=25;p->r2=26;return 1;
2392 case 84: p->r1=27;p->r2=28;return 1;
2393 case 85: p->r1=29;p->r2=30;return 1;
2394 case 86: p->r1=31;p->r2=32;return 1;
2395 }
2396 ierror(0);
2397}
2398
2399
2400int cost_savings(struct IC *p,int r,struct obj *o)
2401{
2402 int c=p->code;
2403 if(o->flags&VKONST){
2404 struct obj *co=&o->v->cobj;
2405 int longload;
2406 if(o->flags&DREFOBJ)
2407 return 4;
2408 if(ISFLOAT(p->typf)) return 2;
2409 longload=0;
2410 if((co->flags&VARADR)&&!use_sd(o->v->vtyp->flags))
2411 longload=2;
2412 if(co->flags&KONST){
2413 eval_const(&co->val,p->typf);
2414 if(p->typf&UNSIGNED){
2415 if(!zumleq(vumax,ul2zum(65535UL)))
2416 longload=2;
2417 }else{
2418 if(!zmleq(vmax,l2zm(32767L))||zmleq(vmax,l2zm(-32769L)))
2419 longload=2;
2420 }
2421 }
2422 if(o==&p->q1&&p->code==ASSIGN&&((p->z.flags&DREFOBJ)||p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN))
2423 return longload+2;
2424 else
2425 return longload;
2426 }
2427 if(o->flags&DREFOBJ)
2428 return 4;
2429 if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 3;
2430 if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 3;
2431 return 2;
2432}
2433
2434int regok(int r,int t,int mode)
2435/* Returns 0 if register r cannot store variables of */
2436/* type t. If t==POINTER and mode!=0 then it returns */
2437/* non-zero only if the register can store a pointer */
2438/* and dereference a pointer to mode. */
2439{
2440 if(r==0) return 0;
2441 t&=NQ;
2442 if(t==0){
2443 if(r>=65&&r<=72) return 1; else return 0;
2444 }
2445 if(ISFLOAT(t)&&r>=33&&r<=64) return 1;
2446 if(t==POINTER&&r>=1&&r<=32) return 1;
2447 if(t>=CHAR&&t<=LONG&&r>=1&&r<=32) return 1;
2448 if(t==LLONG&&r>=74&&r<=86) return 1;
2449 return 0;
2450}
2451
2452int dangerous_IC(struct IC *p)
2453/* Returns zero if the IC p can be safely executed */
2454/* without danger of exceptions or similar things. */
2455/* vbcc may generate code in which non-dangerous ICs */
2456/* are sometimes executed although control-flow may */
2457/* never reach them (mainly when moving computations */
2458/* out of loops). */
2459/* Typical ICs that generate exceptions on some */
2460/* machines are: */
2461/* - accesses via pointers */
2462/* - division/modulo */
2463/* - overflow on signed integer/floats */
2464{
2465 int c=p->code;
2466 if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
2467 return 1;
2468 if((c==DIV||c==MOD)&&!(p->q2.flags&KONST))
2469 return 1;
2470 return 0;
2471}
2472
2473int must_convert(int o,int t,int const_expr)
2474/* Returns zero if code for converting np to type t */
2475/* can be omitted. */
2476/* On the PowerPC cpu pointers and 32bit */
2477/* integers have the same representation and can use */
2478/* the same registers. */
2479{
2480 int op=o&NQ,tp=t&NQ;
2481 if((op==INT||op==LONG||op==POINTER)&&(tp==INT||tp==LONG||tp==POINTER))
2482 return 0;
2483 if(op==DOUBLE&&tp==LDOUBLE) return 0;
2484 if(op==LDOUBLE&&tp==DOUBLE) return 0;
2485 if(op==tp) return 0;
2486 return 1;
2487}
2488
2489void gen_ds(FILE *f,zmax size,struct Typ *t)
2490/* This function has to create <size> bytes of storage */
2491/* initialized with zero. */
2492{
2493 title(f);
2494 if(newobj&&section!=TOC&&section!=SBSS&&section!=SPECIAL&&!BASERELOS4)
2495 emit(f,"%ld\n",zm2l(size));
2496 else
2497 emit(f,"\t.space\t%ld\n",zm2l(size));
2498 newobj=0;
2499}
2500
2501void gen_align(FILE *f,zmax align)
2502/* This function has to make sure the next data is */
2503/* aligned to multiples of <align> bytes. */
2504{
2505 title(f);
2506 if(!optsize&&(zm2l(align)<4))
2507 emit(f,"\t.align\t2\n");
2508 else
2509 if(zm2l(align)>1)
2510 emit(f,"\t.align\t%ld\n",pof2(align)-1);
2511}
2512
2513void gen_var_head(FILE *f,struct Var *v)
2514/* This function has to create the head of a variable */
2515/* definition, i.e. the label and information for */
2516/* linkage etc. */
2517{
2518 int constflag;char *sec;
2519 title(f);
2520 if(v->clist) constflag=is_const(v->vtyp);
2521 if(v->storage_class==STATIC){
2522 if(ISFUNC(v->vtyp->flags)) return;
2523 if(!special_section(f,v)){
2524 if(use_sd(v->vtyp->flags)&&!(v->tattr&FAR)){
2525 if(EABI){
2526 if(v->clist&&!constflag&&section!=SDATA){emit(f,sdataname);if(f) section=SDATA;}
2527 if(v->clist&&constflag&&section!=SDATA2){emit(f,sdata2name);if(f) section=SDATA2;}
2528 if(!v->clist&&section!=SBSS){emit(f,sbssname);if(f) section=SBSS;}
2529 }else if (POWEROPEN){
2530 if(section!=TOC){emit(f,tocname);if(f) section=TOC;}
2531 }
2532 else {
2533 if(v->clist&&section!=SDATA){emit(f,sdataname);if(f) section=SDATA;}
2534 if(!v->clist&&section!=SBSS){emit(f,sbssname);if(f) section=SBSS;}
2535 }
2536 }else{
2537 if(BASERELOS4){
2538 if(v->clist&&section!=DATA){emit(f,dataname); if(f) section=DATA;}
2539 }else if(BASERELMOS){
2540 if(v->clist&&section!=SDATA){emit(f,sdataname); if(f) section=SDATA;}
2541 if(!v->clist&&section!=SBSS){emit(f,sbssname); if(f) section=SBSS;}
2542 }else{
2543 if(POWEROPEN) toc_entry(f,v);
2544 if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
2545 if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
2546 if(!USE_COMMONS&&!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
2547 }
2548 }
2549 }
2550 if(v->clist||section==TOC||section==SBSS||section==SPECIAL){
2551 emit(f,"\t.type\t%s%ld,@object\n",labprefix,zm2l(v->offset));
2552 emit(f,"\t.size\t%s%ld,%ld\n",labprefix,zm2l(v->offset),zm2l(szof(v->vtyp)));
2553 gen_align(f,falign(v->vtyp));
2554 emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
2555 }else{
2556 emit(f,"\t.lcomm\t%s%ld,",labprefix,zm2l(v->offset));
2557 newobj=1;
2558 }
2559 }
2560 if(v->storage_class==EXTERN){
2561 emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
2562 if(POWEROPEN&&(!use_sd(v->vtyp->flags)||(v->tattr&FAR)))
2563 emit(f,"\t.global\t%s%s%s\n",tocprefix,idprefix,v->identifier);
2564 if(v->flags&(DEFINED|TENTATIVE)){
2565 if(!special_section(f,v)){
2566 if(use_sd(v->vtyp->flags)&&!(v->tattr&FAR)){
2567 if(EABI){
2568 if(v->clist&&!constflag&&section!=SDATA){emit(f,sdataname);if(f) section=SDATA;}
2569 if(v->clist&&constflag&&section!=SDATA2){emit(f,sdata2name);if(f) section=SDATA2;}
2570 if(!v->clist&&section!=SBSS){emit(f,sbssname);if(f) section=SBSS;}
2571 }else if (POWEROPEN){
2572 if(section!=TOC){emit(f,tocname);if(f) section=TOC;}
2573 }
2574 else {
2575 if(v->clist&&section!=SDATA){emit(f,sdataname);if(f) section=SDATA;}
2576 if(!USE_COMMONS&&!v->clist&&section!=SBSS){emit(f,sbssname);if(f) section=SBSS;}
2577 }
2578 }else{
2579 if(BASERELOS4){
2580 if(v->clist&&section!=DATA){emit(f,dataname); if(f) section=DATA;}
2581 }else if(BASERELMOS){
2582 if(v->clist&&section!=SDATA){emit(f,sdataname); if(f) section=SDATA;}
2583 if(!USE_COMMONS&&!v->clist&&section!=SBSS){emit(f,sbssname); if(f) section=SBSS;}
2584 }else{
2585 if(POWEROPEN) toc_entry(f,v);
2586 if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
2587 if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
2588 if(!USE_COMMONS&&!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
2589 }
2590 }
2591 }
2592 if(v->clist||section==TOC||section==SBSS||section==SPECIAL){
2593 emit(f,"\t.type\t%s%s,@object\n",idprefix,v->identifier);
2594 emit(f,"\t.size\t%s%s,%ld\n",idprefix,v->identifier,zm2l(szof(v->vtyp)));
2595 gen_align(f,falign(v->vtyp));
2596 emit(f,"%s%s:\n",idprefix,v->identifier);
2597 }else{
2598 emit(f,"\t.%scomm\t%s%s,",USE_COMMONS?"":"l",idprefix,v->identifier);
2599 newobj=1;
2600 }
2601 }
2602 }
2603}
2604
2605void gen_dc(FILE *f,int t,struct const_list *p)
2606/* This function has to create static storage */
2607/* initialized with const-list p. */
2608{
2609 title(f);
2610 if((t&NQ)==POINTER) t=UNSIGNED|LONG;
2611 emit(f,"\t.%s\t",dct[t&NQ]);
2612 if(!p->tree){
2613 if(ISFLOAT(t)){
2614 /* auch wieder nicht sehr schoen und IEEE noetig */
2615 unsigned char *ip;
2616 ip=(unsigned char *)&p->val.vdouble;
2617 emit(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
2618 if((t&NQ)!=FLOAT){
2619 emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
2620 }
2621 }else if((t&NQ)==LLONG){
2622 zumax tmp;
2623 eval_const(&p->val,t);
2624 tmp=vumax;
2625 vumax=zumand(zumrshift(vumax,ul2zum(32UL)),ul2zum(0xffffffff));
2626 gval.vulong=zum2zul(vumax);
2627 emitval(f,&gval,UNSIGNED|LONG);
2628 emit(f,",");
2629 vumax=zumand(tmp,ul2zum(0xffffffff));
2630 gval.vulong=zum2zul(vumax);
2631 emitval(f,&gval,UNSIGNED|LONG);
2632 }else{
2633 emitval(f,&p->val,t&NU);
2634 }
2635 }else{
2636 emit_obj(f,&p->tree->o,t&NU);
2637 }
2638 emit(f,"\n");newobj=0;
2639}
2640
2641static void allocreg(int r)
2642{
2643 if(reg_pair(r,&rp)){
2644 regs[rp.r1]=1;
2645 regs[rp.r2]=1;
2646 }
2647 regs[r]=1;
2648}
2649
2650static void freereg(int r)
2651{
2652 if(reg_pair(r,&rp)){
2653 regs[rp.r1]=0;
2654 regs[rp.r2]=0;
2655 }
2656 regs[r]=0;
2657}
2658
2659/* The main code-generation routine. */
2660/* f is the stream the code should be written to. */
2661/* p is a pointer to a doubly linked list of ICs */
2662/* containing the function body to generate code for. */
2663/* v is a pointer to the function. */
2664/* offset is the size of the stackframe the function */
2665/* needs for local variables. */
2666
2667void gen_code(FILE *f,struct IC *p,struct Var *v,zmax offset)
2668/* The main code-generation. */
2669{
2670 int c,t,i,addbuf,varargs=0,fixedgpr,fixedfpr,setcc,ccset;
2671 char *fpp;int fpf;struct IC *m;
2672 long of=(zm2l(offset)+3)/4*4,regbase,vparmos=0;
2673 if(DEBUG&1) printf("gen_code()\n");
2674 for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
2675 if(vlas) fp=vlafp; else fp=sp;
2676 maxpushed=0;addbuf=0;
2677 if(v->tattr&RFI)
2678 ret="\trfi\n";
2679 else
2680 ret="\tblr\n";
2681 if(!v->fi) v->fi=new_fi();
2682 title(f);
2683 for(m=p;m;m=m->next){
2684 c=m->code;t=m->typf&NU;
2685 m->ext.setcc=0;
2686 if(c==ALLOCREG){
2687 allocreg(m->q1.reg);
2688 continue;
2689 }
2690 if(c==FREEREG){
2691 freereg(m->q1.reg);
2692 continue;
2693 }
2694 if(c==COMPARE&&(m->q2.flags&KONST)&&(t&NQ)!=CHAR&&(t&NQ)!=SHORT){
2695 eval_const(&m->q2.val,t);
2696 if(zmeqto(vmax,l2zm(0L))&&zldeqto(vldouble,d2zld(0.0))){
2697 m->q2.flags=0;m->code=c=TEST;
2698 }
2699 }
2700 if((t&NQ)<=LLONG&&(m->q2.flags&KONST)&&(t&NQ)<=LLONG&&(c==MULT||((c==DIV||c==MOD)&&(t&UNSIGNED)))){
2701 eval_const(&m->q2.val,t);
2702 i=pof2(vmax);
2703 if(i){
2704 if(c==MOD){
2705 vmax=zmsub(vmax,l2zm(1L));
2706 m->code=AND;
2707 }else{
2708 vmax=l2zm(i-1);
2709 if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
2710 }
2711 c=m->code;
2712 gval.vmax=vmax;
2713 eval_const(&gval,MAXINT);
2714 if(c==AND){
2715 insert_const(&m->q2.val,t);
2716 }else{
2717 insert_const(&m->q2.val,INT);
2718 m->typf2=INT;
2719 }
2720 }
2721 }
2722 if(addbuf<16){
2723 if((q1typ(m)&NQ)==LLONG&&(c==MULT||c==DIV||c==MOD||c==LSHIFT||c==RSHIFT)) {addbuf=16;function_calls++;}
2724 if(c==CONVERT&&(q1typ(m)&NQ)==LLONG&&ISFLOAT(ztyp(m)&NQ)){addbuf=16;function_calls++;}
2725 if(c==CONVERT&&(ztyp(m)&NQ)==LLONG&&ISFLOAT(q1typ(m)&NQ)){addbuf=16;function_calls++;}
2726 if(addbuf<8){
2727 if(c==CONVERT&&ISFLOAT(m->typf2)&&!ISFLOAT(t)) addbuf=8;
2728 if(c==CONVERT&&!ISFLOAT(m->typf2)&&ISFLOAT(t)) addbuf=8;
2729 }
2730 }
2731 if(c==CALL&&maxpushed<zm2l(m->q2.val.vmax)) maxpushed=zm2l(m->q2.val.vmax);
2732 if(c==CALL&&(m->q1.flags&VAR)&&!strcmp(m->q1.v->identifier,"__va_start")) varargs=1;
2733 }
2734 once=twice=0;
2735 if(!(g_flags[9]&USEDFLAG)) peephole(p);
2736 if(varargs){
2737 fixedgpr=fixedfpr=0;
2738 if(!freturn(v->vtyp->next)) fixedgpr++;
2739 for(i=0;i<v->vtyp->exact->count;i++){
2740 c=(*v->vtyp->exact->sl)[i].styp->flags&NQ;
2741 if(fixedgpr<8&&(c==POINTER||c<=LONG))
2742 fixedgpr++;
2743 else if(fixedgpr<7&&c==LLONG)
2744 fixedgpr=(fixedgpr+3)/2*2;
2745 else if(fixedfpr<8&&ISFLOAT(c))
2746 fixedfpr++;
2747 else{
2748
2749 vparmos+=zm2l(szof((*v->vtyp->exact->sl)[i].styp));
2750 vparmos=(vparmos+zm2l(stackalign)-1)/zm2l(stackalign)*zm2l(stackalign);
2751 }
2752 }
2753 regbase=of;
2754 addbuf+=96;
2755 }
2756 for(c=1;c<=MAXR;c++){
2757 if((!regsa[c])&&regused[c]){
2758 BSET(regs_modified,c);
2759 }
2760 }
2761 of+=addbuf;tmpoff=minframe+maxpushed+of;
2762 function_top(f,v,of);
2763 all_regs=1;
2764 if(varargs){
2765 regbase=frameoffset+regbase;
2766 fpp="";
2767 if(!(g_flags[8]&USEDFLAG)) fpp="r";
2768 for(i=fixedgpr;i<8;i++)
2769 emit(f,"\tstw\t%s%d,%ld(%s)\n",fpp,i+3,regbase+i*4,mregnames[sp]);
2770 if(!(g_flags[8]&USEDFLAG)) fpp="f";
2771 for(i=fixedfpr;i<8;i++)
2772 emit(f,"\tstfd\t%s%d,%ld(%s)\n",fpp,i+1,regbase+32+i*8,mregnames[sp]);
2773 }
2774 pushed=0;ccset=0;
2775 for(;p;pr(f,p),p=p->next){
2776 c=p->code;t=p->typf;
2777 setcc=p->ext.setcc;
2778 if(debug_info)
2779 dwarf2_line_info(f,p);
2780 if(c==NOP) {p->z.flags=0;continue;}
2781 if(c==ALLOCREG){
2782 allocreg(p->q1.reg);
2783 continue;
2784 }
2785 if(c==FREEREG){
2786 freereg(p->q1.reg);
2787 continue;
2788 }
2789 if(c==COMPARE&&(p->q2.flags&KONST)&&(t&NQ)!=LLONG){
2790 struct case_table *ct=calc_case_table(p,JUMP_TABLE_DENSITY);
2791 if(ct&&(ct->num>=JUMP_TABLE_LENGTH||(!isreg(q1)&&ct->num>=JUMP_TABLE_LENGTH/2))){
2792 int r,defl,tabl=++label;
2793 long l;unsigned long ul;
2794 struct IC *np;
2795 for(np=p;np!=ct->next_ic;np=np->next){
2796 if(np->code==ALLOCREG) allocreg(np->q1.reg);
2797 if(np->code==FREEREG) freereg(np->q1.reg);
2798 }
2799 if(ct->next_ic->code==BRA)
2800 defl=ct->next_ic->typf;
2801 else
2802 defl=++label;
2803 if(!isreg(q1)){
2804 if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==DREFOBJ){
2805 p->q1.flags&=~DREFOBJ;
2806 load_reg(f,t1,&p->q1,POINTER,t1);
2807 p->q1.flags|=(REG|DREFOBJ);
2808 p->q1.flags&=~VAR;
2809 p->q1.reg=t1;
2810 }
2811 load_reg(f,t2,&p->q1,p->typf,t1);
2812 r=t2;
2813 }else
2814 r=p->q1.reg;
2815 if(t&UNSIGNED)
2816 l=-(long)zum2ul(ct->min.vumax);
2817 else
2818 l=-zm2l(ct->min.vmax);
2819 if(l>=-32767&&l<=32767){
2820 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[r],l);
2821 }else{
2822 emit(f,"\taddis\t%s,%s,%ld\n",mregnames[t2],mregnames[r],hi(l));
2823 if(lo(l))
2824 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[t2],lo(l));
2825 }
2826 ul=zum2ul(ct->diff);
2827 if(regs[cr0]) ierror(0);
2828 if(ul<=65535){
2829 emit(f,"\tcmplwi\t%s,%lu\n",mregnames[t2],ul);
2830 }else{
2831 emit(f,"\tlis\t%s,%ld\n",mregnames[t1],hi(ul));
2832 if(lo(ul))
2833 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t1],regnames[t1],lo(ul));
2834 }
2835 emit(f,"\tbgt\t%s,%s%d\n",mregnames[cr0],labprefix,defl);
2836 emit(f,"\tslwi\t%s,%s,2\n",mregnames[t2],mregnames[t2]);
2837 /*FIXME: small-data */
2838 if(POWEROPEN){
2839 emit(f,"\tlwz\t%s,%s%s%d(%s)\n",mregnames[t1],tocprefix,labprefix,tabl,mregnames[r2]);
2840 }else{
2841 emit(f,"\tlis\t%s,%s%d@ha\n",mregnames[t1],labprefix,tabl);
2842 emit(f,"\taddi\t%s,%s,%s%d@l\n",mregnames[t1],mregnames[t1],labprefix,tabl);
2843 }
2844 emit(f,"\tlwzx\t%s,%s,%s\n",mregnames[t2],mregnames[t1],mregnames[t2]);
2845 emit(f,"\tmtctr\t%s\n",mregnames[t2]);
2846 emit(f,"\tbctr\n");
2847 BSET(regs_modified,ctr);
2848 if(POWEROPEN){
2849 emit(f,tocname);
2850 emit(f,"%s%s%d:\n",tocprefix,labprefix,tabl);
2851 emit(f,"\t.long\t%s%d\n",labprefix,tabl);
2852 }
2853 emit(f,rodataname);
2854 emit(f,"\t.align\t2\n");
2855 emit(f,"%s%d:\n",labprefix,tabl);
2856 emit_jump_table(f,ct,"\t.long\t",labprefix,defl);
2857 if(!special_section(f,v)) emit(f,codename);
2858 if(ct->next_ic->code!=BRA){
2859 emit(f,"%s%d:\n",labprefix,defl);
2860 p=ct->next_ic->prev;
2861 }else
2862 p=ct->next_ic;
2863 continue;
2864 }
2865 }
2866 if(c==LABEL) {ccset=0;emit(f,"%s%d:\n",labprefix,t);continue;}
2867 if(c==BRA){
2868 ccset=0;
2869 if(t==exit_label&&framesize==0)
2870 emit(f,ret);
2871 else
2872 emit(f,"\tb\t%s%d\n",labprefix,t);
2873 continue;
2874 }
2875 if(c>=BEQ&&c<BRA){
2876 ccset=0;
2877 if(!(p->q1.flags&REG)) p->q1.reg=cr0;
2878 if(!(g_flags[9]&USEDFLAG)&&!BTST(twice,p->typf-lastlabel)){
2879 struct IC *p2,*p3,*p4;int exit_label;
2880 p2=p->next;
2881 while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
2882 if(p2&&p2->code==SETRETURN&&p2->z.reg){p2->code=ASSIGN;p2->z.flags=REG;}
2883 if(p2&&p2->code==ASSIGN&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg<=32){
2884 p3=p2->next;
2885 while(p3&&(p3->code==FREEREG||p3->code==ALLOCREG)) p3=p3->next;
2886 if(p3&&p3->code==BRA){
2887 exit_label=p3->typf;
2888 p3=p3->next;
2889 while(p3&&(p3->code==FREEREG||p3->code==ALLOCREG)) p3=p3->next;
2890 if(p3&&p3->code==LABEL&&p3->typf==p->typf){
2891 p3=p3->next;
2892 while(p3&&(p3->code==FREEREG||p3->code==ALLOCREG)) p3=p3->next;
2893 if(p3&&p3->code==SETRETURN&&p3->z.reg){p3->code=ASSIGN;p3->z.flags=REG;}
2894 if(p3&&p3->code==ASSIGN&&(p3->z.flags&(REG|DREFOBJ))==REG&&p3->z.reg==p2->z.reg){
2895 p4=p3->next;
2896 while(p4&&(p4->code==FREEREG||p4->code==ALLOCREG)) p4=p4->next;
2897 if(p4&&p4->code==LABEL&&p4->typf==exit_label){
2898 int bit=(p->q1.reg-cr0)*4;
2899 if((p2->q1.flags&KONST)&&(p3->q1.flags&KONST)){
2900 eval_const(&p2->q1.val,p2->typf);
2901 if(zmeqto(vmax,l2zm(0L))){
2902 eval_const(&p3->q1.val,p3->typf);
2903 if(zmeqto(vmax,l2zm(1L))||zmeqto(vmax,l2zm(-1L))){
2904 if(c==BLE){emit(f,"\tcror\t%d,%d,%d\n",bit,bit,bit+2);}
2905 if(c==BGE){bit++;emit(f,"\tcror\t%d,%d,%d\n",bit,bit,bit+1);}
2906 if(c==BNE){bit+=2;emit(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
2907 if(c==BGT) bit++;
2908 if(c==BEQ) bit+=2;
2909 emit(f,"\tmfcr\t%s\n",mregnames[t1]);
2910 emit(f,"\trlwinm\t%s,%s,%d,%d,%d\n",mregnames[p2->z.reg],mregnames[t1],bit+1,31,31);
2911 if(zmeqto(vmax,l2zm(-1L))) emit(f,"\tneg\t%s,%s\n",mregnames[p2->z.reg],mregnames[p2->z.reg]);
2912 if(BTST(twice,p4->typf-lastlabel)) emit(f,"%s%d:\n",labprefix,p4->typf);
2913 p=p4;continue;
2914 }
2915 }else{
2916 eval_const(&p3->q1.val,p3->typf);
2917 if(zmeqto(vmax,l2zm(0L))){
2918 eval_const(&p2->q1.val,p2->typf);
2919 if(zmeqto(vmax,l2zm(1L))||zmeqto(vmax,l2zm(-1L))){
2920 if(c==BLE){emit(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit+2);}
2921 if(c==BGE){bit++;emit(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit+1);}
2922 if(c==BNE){bit+=2;}
2923 if(c==BGT){bit++;emit(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
2924 if(c==BEQ){bit+=2;emit(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
2925 if(c==BLT){emit(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
2926 emit(f,"\tmfcr\t%s\n",mregnames[t1]);
2927 emit(f,"\trlwinm\t%s,%s,%d,%d,%d\n",mregnames[p2->z.reg],mregnames[t1],bit+1,31,31);
2928 if(zmeqto(vmax,l2zm(-1L))) emit(f,"\tneg\t%s,%s\n",mregnames[p2->z.reg],mregnames[p2->z.reg]);
2929 if(BTST(twice,p4->typf-lastlabel)) emit(f,"%s%d:\n",labprefix,p4->typf);
2930 p=p4;continue;
2931 }
2932 }
2933 }
2934 }
2935 }
2936 }
2937 }
2938 }
2939 }
2940 }
2941 if(t==exit_label&&framesize==0&&!strcmp(ret,"\tblr\n"))
2942 emit(f,"\tb%slr\t%s\n",ccs[c-BEQ],mregnames[p->q1.reg]);
2943 else
2944 emit(f,"\tb%s\t%s,%s%d\n",ccs[c-BEQ],mregnames[p->q1.reg],labprefix,t);
2945 continue;
2946 }
2947 if(c==MOVETOREG){
2948 if(p->z.reg<=32){
2949 load_reg(f,p->z.reg,&p->q1,INT,t1);
2950 }else if(p->z.reg>=33&&p->z.reg<=64){
2951 load_reg(f,p->z.reg,&p->q1,DOUBLE,t1);
2952 }else if(reg_pair(p->z.reg,&rp)){
2953 create_loadable(f,&p->q1,t1);
2954 load_hword(f,rp.r1,&p->q1,LLONG,t2);
2955 load_lword(f,rp.r2,&p->q1,LLONG,t2);
2956 }else
2957 ierror(0);
2958 p->z.flags=0;
2959 continue;
2960 }
2961 if(c==MOVEFROMREG){
2962 if(p->q1.reg<=32){
2963 store_reg(f,p->q1.reg,&p->z,INT);
2964 }else if(p->q1.reg>=33&&p->q1.reg<=64){
2965 store_reg(f,p->q1.reg,&p->z,DOUBLE);
2966 }else if(reg_pair(p->q1.reg,&rp)){
2967 create_loadable(f,&p->z,t1);
2968 store_hword(f,rp.r1,&p->z);
2969 store_lword(f,rp.r2,&p->z);
2970 }else
2971 ierror(0);
2972 p->z.flags=0;
2973 continue;
2974 }
2975 if((p->q1.flags&&(q1typ(p)&NQ)==LLONG)||(p->q2.flags&&(q2typ(p)&NQ)==LLONG)||(p->z.flags&&(ztyp(p)&NQ)==LLONG))
2976 if(handle_llong(f,p))
2977 continue;
2978 if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zm2l(p->q2.val.vmax)!=1))){
2979 unsigned long size,l;
2980 int a1,a2,b;char *ld,*st;
2981 size=zm2l(p->q2.val.vmax);
2982 a1=balign(&p->q1);
2983 if(c==ASSIGN) a2=balign(&p->z); else a2=0;
2984 b=1;ld=ldt(CHAR);st=sdt(CHAR);
2985 if(p->q1.flags&VAR){
2986 if(p->q1.flags&DREFOBJ){
2987 if(p->q1.v->vtyp->next&&zmeqto(p->q2.val.vmax,szof(p->q1.v->vtyp->next))&&(a1&1)){
2988 a1=zm2l(falign(p->q1.v->vtyp->next))&3;
2989 a2&=a1;
2990 }
2991 }else{
2992 if(zmeqto(p->q2.val.vmax,szof(p->q1.v->vtyp))&&(a1&1)){
2993 a1=zm2l(falign(p->q1.v->vtyp))&3;
2994 a2&=a1;
2995 }
2996 }
2997 }
2998 if(p->z.flags&VAR){
2999 if(p->z.flags&DREFOBJ){
3000 if(p->z.v->vtyp->next&&zmeqto(p->q2.val.vmax,szof(p->z.v->vtyp->next))&&(a2&1)){
3001 a2=zm2l(falign(p->z.v->vtyp->next))&3;
3002 a1&=a2;
3003 }
3004 }else{
3005 if(zmeqto(p->q2.val.vmax,szof(p->z.v->vtyp))&&(a2&1)){
3006 a2=zm2l(falign(p->z.v->vtyp))&3;
3007 a1&=a2;
3008 }
3009 }
3010 }
3011 if(a1>=0&&a2>=0){
3012 if(a1==0&&a2==0){
3013 b=4;ld=ldt(INT);st=sdt(INT);
3014 }else if((a1&1)==0&&(a2&1)==0){
3015 b=2;ld=ldt(SHORT);st=sdt(SHORT);
3016 }
3017 }
3018 if(p->q1.flags&DREFOBJ){
3019 if(p->q1.am){
3020 if(p->q1.am->flags&REG_IND){
3021 emit(f,"\tadd\t%s,%s,%s\n",mregnames[t1],mregnames[p->q1.am->offset],mregnames[p->q1.am->base]);
3022 emit(f,"\taddi\t%s,%s,%d\n",mregnames[t1],mregnames[t1],-b);
3023 }
3024 if(p->q1.am->flags&IMM_IND)
3025 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t1],mregnames[p->q1.am->base],p->q1.am->offset-b);
3026 }else{
3027 p->q1.flags&=~DREFOBJ;
3028 if(isreg(q1)){
3029 emit(f,"\taddi\t%s,%s,%d\n",mregnames[t1],mregnames[p->q1.reg],-b);
3030 }else{
3031 load_reg(f,t1,&p->q1,POINTER,t1);
3032 emit(f,"\taddi\t%s,%s,%d\n",mregnames[t1],mregnames[t1],-b);
3033 }
3034 p->q1.flags|=DREFOBJ;
3035 }
3036 }else{
3037 p->q1.val.vmax=zmsub(p->q1.val.vmax,l2zm((long)b));
3038 load_address(f,t1,&p->q1,POINTER);
3039 p->q1.val.vmax=zmadd(p->q1.val.vmax,l2zm((long)b));
3040 }
3041 if(p->z.flags&DREFOBJ){
3042 if(p->z.am){
3043 if(p->z.am->flags&REG_IND){
3044 emit(f,"\tadd\t%s,%s,%s\n",mregnames[t2],mregnames[p->z.am->offset],mregnames[p->z.am->base]);
3045 emit(f,"\taddi\t%s,%s,%d\n",mregnames[t2],mregnames[t2],-b);
3046 }
3047 if(p->z.am->flags&IMM_IND)
3048 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[p->z.am->base],p->z.am->offset-b);
3049 }else{
3050 p->z.flags&=~DREFOBJ;
3051 if(isreg(z)){
3052 emit(f,"\taddi\t%s,%s,%d\n",mregnames[t2],mregnames[p->z.reg],-b);
3053 }else{
3054 load_reg(f,t2,&p->z,POINTER,t2);
3055 emit(f,"\taddi\t%s,%s,%d\n",mregnames[t2],mregnames[t2],-b);
3056 }
3057 p->z.flags|=DREFOBJ;
3058 }
3059 }else{
3060 if(c==PUSH){
3061 pushed=(pushed+3)/4*4;
3062 if(align_arguments&&p->ityp){
3063 long al=falign(p->ityp);
3064 pushed=(pushed+al-1)/al*al;
3065 }
3066 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[sp],pushed+minframe-b);
3067 pushed+=size;
3068 size=zm2l(p->z.val.vmax);
3069 }else{
3070 p->z.val.vmax=zmsub(p->z.val.vmax,l2zm((long)b));
3071 load_address(f,t2,&p->z,POINTER);
3072 p->z.val.vmax=zmsub(p->z.val.vmax,l2zm((long)b));
3073 }
3074 }
3075 BSET(regs_modified,t1);
3076 BSET(regs_modified,t2);
3077 BSET(regs_modified,t3);
3078 if(optspeed)
3079 l=size/(8*b);
3080 else
3081 l=size/b;
3082 if(l>1){
3083 if(hi(l)){
3084 emit(f,"\tlis\t%s,%lu\n",mregnames[t3],(l>>16)&65535);
3085 emit(f,"\tori\t%s,%s,%lu\n",mregnames[t3],mregnames[t3],l&65535);
3086 }else{
3087 emit(f,"\tli\t%s,%ld\n",mregnames[t3],lo(l));
3088 }
3089 emit(f,"\tmtctr\t%s\n",mregnames[t3]);
3090 BSET(regs_modified,ctr);
3091 emit(f,"%s%d:\n",labprefix,++label);
3092 }
3093 if(l>0){
3094 for(i=b;optspeed&&i<=7*b;i+=b){
3095 emit(f,"\tl%s\t%s,%d(%s)\n",ld,mregnames[t3],i,mregnames[t1]);
3096 emit(f,"\tst%s\t%s,%d(%s)\n",st,mregnames[t3],i,mregnames[t2]);
3097 }
3098 emit(f,"\tl%su\t%s,%d(%s)\n",ld,mregnames[t3],i,mregnames[t1]);
3099 emit(f,"\tst%su\t%s,%d(%s)\n",st,mregnames[t3],i,mregnames[t2]);
3100
3101 }
3102 if(l>1){
3103 emit(f,"\tbdnz\t%s%d\n",labprefix,label);
3104 }
3105 if(optspeed)
3106 size=size%(8*b);
3107 else
3108 size=size%b;
3109 for(i=0;i<size/b;i++){
3110 emit(f,"\tl%su\t%s,%d(%s)\n",ld,mregnames[t3],b,mregnames[t1]);
3111 emit(f,"\tst%su\t%s,%d(%s)\n",st,mregnames[t3],b,mregnames[t2]);
3112 }
3113 size=size%b;i=b;
3114 if(size&2){
3115 emit(f,"\tl%su\t%s,%d(%s)\n",ldt(SHORT),mregnames[t3],b,mregnames[t1]);
3116 emit(f,"\tst%su\t%s,%d(%s)\n",sdt(SHORT),mregnames[t3],b,mregnames[t2]);
3117 i=2;
3118 }
3119 if(size&1){
3120 emit(f,"\tl%su\t%s,%d(%s)\n",ldt(CHAR),mregnames[t3],i,mregnames[t1]);
3121 emit(f,"\tst%su\t%s,%d(%s)\n",sdt(CHAR),mregnames[t3],i,mregnames[t2]);
3122 }
3123 p->z.flags=0;
3124 continue;
3125 }
3126 if(c==TEST&&ISFLOAT(t)){
3127 p->code=c=COMPARE;
3128 p->q2.flags=KONST;
3129 p->q2.val.vldouble=d2zld(0.0);
3130 if((t&NQ)==DOUBLE) p->q2.val.vdouble=zld2zd(p->q2.val.vldouble);
3131 if((t&NQ)==FLOAT) p->q2.val.vfloat=zld2zf(p->q2.val.vldouble);
3132 }
3133 p=do_refs(f,p);
3134 c=p->code;
3135 setcc=p->ext.setcc;
3136 if(c==SUBPFP) c=SUB;
3137 if(c==ADDI2P) c=ADD;
3138 if(c==SUBIFP) c=SUB;
3139 if(c==CONVERT){
3140 int to;
3141 static struct obj o;char *ip;
3142 long moff;int offreg;
3143 to=p->typf2;
3144 if(ISFLOAT(to)){
3145 if(ISFLOAT(t)){
3146 zreg=q1reg;
3147 continue;
3148 }
3149 if(tmpoff>32767){
3150 moff=0;offreg=t1;
3151 emit(f,"\taddis\t%s,%s,%ld\n",mregnames[offreg],mregnames[sp],hi(tmpoff));
3152 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[offreg],mregnames[offreg],lo(tmpoff));
3153 }else{
3154 moff=tmpoff;
3155 offreg=sp;
3156 }
3157 if((t&NU)==(UNSIGNED|INT)||(t&NU)==(UNSIGNED|LONG)){
3158 o.flags=KONST;
3159 ip=(char *)&o.val.vdouble;
3160 ip[0]=0x41;
3161 ip[1]=0xe0;
3162 ip[2]=0x00;
3163 ip[3]=0x00;
3164 ip[4]=0x00;
3165 ip[5]=0x00;
3166 ip[6]=0x00;
3167 ip[7]=0x00;
3168 load_reg(f,f2,&o,DOUBLE,t2);
3169 emit(f,"\tfcmpu\t%s,%s,%s\n",mregnames[cr0],mregnames[q1reg],mregnames[f2]);
3170 emit(f,"\tcror\t3,2,1\n");
3171 emit(f,"\tbso\t%s,%s%d\n",mregnames[cr0],labprefix,++label);
3172 emit(f,"\tfctiwz\t%s,%s\n",mregnames[f2],mregnames[q1reg]);
3173 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(DOUBLE),mregnames[f2],moff-8,mregnames[offreg]);
3174 emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(t&NQ),mregnames[zreg],moff-zm2l(sizetab[t&NQ]),mregnames[offreg]);
3175 emit(f,"\tb\t%s%d\n",labprefix,++label);
3176 emit(f,"%s%d:\n",labprefix,label-1);
3177 emit(f,"\tfsub\t%s,%s,%s\n",mregnames[f2],mregnames[q1reg],mregnames[f2]);
3178 emit(f,"\tfctiwz\t%s,%s\n",mregnames[f2],mregnames[f2]);
3179 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(DOUBLE),mregnames[f2],moff-8,mregnames[offreg]);
3180 emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(INT),mregnames[zreg],moff-zm2l(sizetab[t&NQ]),mregnames[offreg]);
3181 emit(f,"\txoris\t%s,%s,32768\n",mregnames[zreg],mregnames[zreg]);
3182 emit(f,"%s%d:\n",labprefix,label);
3183 BSET(regs_modified,f2);
3184 BSET(regs_modified,zreg);
3185 BSET(regs_modified,q1reg);
3186 }else{
3187 emit(f,"\tfctiwz\t%s,%s\n",mregnames[f3],mregnames[q1reg]);
3188 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(DOUBLE),mregnames[f3],moff-8,mregnames[offreg]);
3189 emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(t&NQ),mregnames[zreg],moff-zm2l(sizetab[t&NQ]),mregnames[offreg]);
3190 BSET(regs_modified,f3);
3191 BSET(regs_modified,zreg);
3192 BSET(regs_modified,q1reg);
3193 }
3194 if(t==CHAR) emit(f,"\textsb\t%s,%s\n",mregnames[zreg],mregnames[zreg]);
3195 continue;
3196 }
3197 if(ISFLOAT(t)){
3198 if(tmpoff>32767){
3199 moff=0;offreg=t1;
3200 if(q1reg==t1){
3201 emit(f,"\tmr\t%s,%s\n",mregnames[t3],mregnames[q1reg]);
3202 q1reg=t3;
3203 BSET(regs_modified,t3);
3204 }
3205 emit(f,"\taddis\t%s,%s,%ld\n",mregnames[offreg],mregnames[sp],hi(tmpoff));
3206 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[offreg],mregnames[offreg],lo(tmpoff));
3207 }else{
3208 moff=tmpoff;
3209 offreg=sp;
3210 }
3211 o.flags=KONST;
3212 ip=(char *)&o.val.vdouble;
3213 ip[0]=0x43;
3214 ip[1]=0x30;
3215 ip[2]=0x00;
3216 ip[3]=0x00;
3217 ip[4]=0x80;
3218 ip[5]=0x00;
3219 ip[6]=0x00;
3220 ip[7]=0x00;
3221 if((to&NU)==(UNSIGNED|INT)||(to&NU)==(UNSIGNED|LONG)){
3222 ip[4]=0x00;
3223 load_reg(f,f2,&o,DOUBLE,t2);
3224 emit(f,"\tlis\t%s,17200\n",mregnames[t2]);
3225 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(INT),mregnames[q1reg],moff-4,mregnames[offreg]);
3226 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(INT),mregnames[t2],moff-8,mregnames[offreg]);
3227 emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(DOUBLE),mregnames[zreg],moff-8,mregnames[offreg]);
3228 emit(f,"\tfsub\t%s,%s,%s\n",mregnames[zreg],mregnames[zreg],mregnames[f2]);
3229 }else{
3230 emit(f,"\tlis\t%s,17200\n",mregnames[t2]);
3231 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(INT),mregnames[t2],moff-8,mregnames[offreg]);
3232 emit(f,"\txoris\t%s,%s,32768\n",mregnames[t2],mregnames[q1reg]);
3233 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(INT),mregnames[t2],moff-4,mregnames[offreg]);
3234 emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(DOUBLE),mregnames[zreg],moff-8,mregnames[offreg]);
3235 load_reg(f,f2,&o,DOUBLE,t2);
3236 emit(f,"\tfsub\t%s,%s,%s\n",mregnames[zreg],mregnames[zreg],mregnames[f2]);
3237 }
3238 continue;
3239 }
3240 if((t&NQ)>=(to&NQ)){
3241 if((to&NU)==CHAR){
3242 emit(f,"\textsb%s\t%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
3243 ccset|=setcc;
3244 }else if((to&NU)==SHORT&&!q1loaded){
3245 emit(f,"\textsh%s\t%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
3246 ccset|=setcc;
3247 }else if((to&NU)==(UNSIGNED|CHAR)&&!q1loaded){
3248 emit(f,"\tclrlwi%s\t%s,%s,24\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
3249 ccset|=setcc;
3250 }else if((to&NU)==(UNSIGNED|SHORT)&&!q1loaded){
3251 emit(f,"\tclrlwi%s\t%s,%s,16\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
3252 ccset|=setcc;
3253 }else{
3254 if(setcc){
3255 emit(f,"\tmr.\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
3256 ccset=1;
3257 }else{
3258 zreg=q1reg;
3259 }
3260 }
3261 continue;
3262 }else{
3263 zreg=q1reg;
3264 continue;
3265 }
3266 }
3267 if(c==KOMPLEMENT){
3268 emit(f,"\tnor%s\t%s,%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg],mregnames[q1reg]);
3269 ccset|=setcc;
3270 continue;
3271 }
3272 if(ISFLOAT(t)) {fpp="f";fpf=1;} else {fpp="";fpf=0;}
3273 if(c==SETRETURN){
3274 if(p->z.reg){
3275 if((t&NU)==CHAR)
3276 emit(f,"\textsb\t%s,%s\n",mregnames[p->z.reg],mregnames[q1reg]);
3277 else if(!q1loaded&&(t&NU)==SHORT)
3278 emit(f,"\textsh\t%s,%s\n",mregnames[p->z.reg],mregnames[q1reg]);
3279 else if(!q1loaded&&(t&NU)==(UNSIGNED|CHAR))
3280 emit(f,"\tclrlwi\t%s,%s,24\n",mregnames[p->z.reg],mregnames[q1reg]);
3281 else if(!q1loaded&&(t&NU)==(UNSIGNED|SHORT))
3282 emit(f,"\tclrlwi\t%s,%s,16\n",mregnames[p->z.reg],mregnames[q1reg]);
3283 else if(p->z.reg!=q1reg)
3284 emit(f,"\t%smr\t%s,%s\n",fpp,mregnames[p->z.reg],mregnames[q1reg]);
3285 BSET(regs_modified,p->z.reg);
3286 }else
3287 ierror(0);
3288 continue;
3289 }
3290 if(c==GETRETURN){
3291 if(p->q1.reg)
3292 zreg=p->q1.reg;
3293 else
3294 p->z.flags=0;
3295 continue;
3296 }
3297 if(c==CALL){
3298 ccset=0;
3299 if(stack_valid){
3300 int i;
3301 if(p->call_cnt<=0){
3302 err_ic=p;error(320);
3303 stack_valid=0;
3304 v->fi->flags|=(WARNED_STACK|WARNED_REGS);
3305 }
3306 for(i=0;i<p->call_cnt;i++){
3307 if(p->call_list[i].v->fi&&(p->call_list[i].v->fi->flags&ALL_STACK)){
3308 if(framesize+zum2ul(p->call_list[i].v->fi->stack1)>stack)
3309 stack=framesize+zum2ul(p->call_list[i].v->fi->stack1);
3310 }else{
3311 err_ic=p;
3312 if(!p->call_list[i].v->fi) p->call_list[i].v->fi=new_fi();
3313 if(!(p->call_list[i].v->fi->flags&WARNED_STACK)){
3314 error(317,p->call_list[i].v->identifier);
3315 p->call_list[i].v->fi->flags|=WARNED_STACK;
3316 }
3317 v->fi->flags|=WARNED_STACK;
3318 stack_valid=0;
3319 }
3320#if HAVE_OSEK
3321/* removed */
3322/* removed */
3323/* removed */
3324/* removed */
3325/* removed */
3326/* removed */
3327#endif
3328 }
3329 }
3330 if(!calc_regs(p,f!=0)&&v->fi) all_regs=0;
3331#if HAVE_OSEK
3332/* removed */
3333/* removed */
3334#endif
3335 if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
3336 emit_inline_asm(f,p->q1.v->fi->inline_asm);
3337 }else{
3338 if((p->q1.flags&(VAR|DREFOBJ))==VAR){
3339 if(!strcmp("__va_start",p->q1.v->identifier)){
3340 emit(f,"\taddi\t%s,%s,%lu\n",mregnames[r3],mregnames[sp],framesize+minframe+zm2l(va_offset(v))/*+vparmos*/);
3341 BSET(regs_modified,r3);continue;
3342 }
3343 if(!strcmp("__va_regbase",p->q1.v->identifier)){
3344 emit(f,"\taddi\t%s,%s,%ld\n",mregnames[r3],mregnames[sp],regbase);
3345 BSET(regs_modified,r3);continue;continue;
3346 }
3347 if(!strcmp("__va_fixedgpr",p->q1.v->identifier)){
3348 emit(f,"\tli\t%s,%d\n",mregnames[r3],fixedgpr);
3349 BSET(regs_modified,r3);continue;continue;
3350 }
3351 if(!strcmp("__va_fixedfpr",p->q1.v->identifier)){
3352 emit(f,"\tli\t%s,%d\n",mregnames[r3],fixedfpr);
3353 BSET(regs_modified,r3);continue;continue;
3354 }
3355 }
3356 if(g_flags[10]&USEDFLAG) emit(f,"\tcreqv\t6,6,6\n");
3357 /* poweropen-hack! look if some fp-args have been passed on the stack */
3358 if(POWEROPEN&&!zmeqto(p->q2.val.vmax,l2zm(0L))){
3359 int r=45/*f12*/,off=24;
3360 for(i=0;r<47&&i<p->arg_cnt;i++){
3361 if(p->arg_list[i]->code==PUSH){
3362 int typ=p->arg_list[i]->typf;
3363 if(ISFLOAT(typ)){
3364 emit(f,"\tl%s\t%s,%d(%s)\n",ldt(typ&NQ),mregnames[r],off,mregnames[sp]);
3365 r++;
3366 }
3367 }
3368 off+=(zm2l(p->arg_list[i]->q2.val.vmax)+3)/4*4;
3369 }
3370 }
3371 if(q1reg){
3372 emit(f,"\tmtlr\t%s\n",mregnames[q1reg]);
3373 emit(f,"\tblrl\n");
3374 }else{
3375 emit(f,"\tbl\t");emit_obj(f,&p->q1,t);
3376 emit(f,"\n");
3377 }
3378 BSET(regs_modified,lr);
3379 }
3380 pushed-=zm2l(p->q2.val.vmax);
3381 continue;
3382 }
3383 if(c==ASSIGN||c==PUSH){
3384 if(t==0) ierror(0);
3385 if(q1reg||c==PUSH){
3386 if(c==PUSH){
3387 pushed=(pushed+3)/4*4;
3388 if(align_arguments&&malign[p->typf&NQ]==8)
3389 pushed=(pushed+7)/8*8;
3390 if(q1reg)
3391 emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(t&NQ),mregnames[q1reg],pushed+minframe,mregnames[sp]);
3392 pushed+=zm2l(p->q2.val.vmax);
3393 continue;
3394 }
3395 if(c==ASSIGN){
3396 if(setcc&&!fpf&&sizetab[t&NQ]==sizetab[INT]){
3397 emit(f,"\tmr.\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
3398 ccset=1;
3399 }else{
3400 zreg=q1reg;
3401 }
3402 }
3403 continue;
3404 }
3405 }
3406 if(c==ADDRESS){
3407 load_address(f,zreg,&p->q1,POINTER);
3408 continue;
3409 }
3410 if(c==MINUS){
3411 emit(f,"\t%sneg%s\t%s,%s\n",fpp,record[setcc&&!fpf],mregnames[zreg],mregnames[q1reg]);
3412 if(setcc&&!fpf) ccset=1;
3413 continue;
3414 }
3415 if(c==TEST){
3416 if(!(p->z.flags&REG))
3417 p->z.reg=cr0;
3418 if(!multiple_ccs&&(t&UNSIGNED)){
3419 struct IC *p2=p->next;
3420 while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
3421 if(!p2) continue;
3422 if(p2->code==BGT) p2->code=BNE;
3423 else if(p2->code==BGE) p2->code=BRA;
3424 else if(p2->code==BLT) p2->code=NOP;
3425 else if(p2->code==BLE) p2->code=BEQ;
3426 }
3427 if(ccset&&p->z.reg==cr0) continue;
3428 if(ISFLOAT(t)){
3429 ierror(0);
3430 }else{
3431 if((t&NU)==CHAR)
3432 emit(f,"\textsb.\t%s,%s\n",mregnames[p->z.reg],mregnames[q1reg]);
3433 else if((t&NU)==SHORT)
3434 emit(f,"\textsh.\t%s,%s\n",mregnames[p->z.reg],mregnames[q1reg]);
3435 else if((t&NU)==(UNSIGNED|CHAR))
3436 emit(f,"\tandi.\t%s,%s,255\n",mregnames[p->z.reg],mregnames[q1reg]);
3437 else if((t&NU)==(UNSIGNED|SHORT))
3438 emit(f,"\tandi.\t%s,%s,65535\n",mregnames[p->z.reg],mregnames[q1reg]);
3439 else
3440 emit(f,"\tcmp%swi\t%s,%s,0\n",(t&UNSIGNED)?"l":"",mregnames[p->z.reg],mregnames[q1reg]);
3441 }
3442 if(p->z.reg==cr0) ccset=0;
3443 continue;
3444 }
3445 if(c==COMPARE){
3446 if(!(p->z.flags&REG))
3447 p->z.reg=cr0;
3448 if(ISFLOAT(t))
3449 emit(f,"\tfcmpu\t%s,%s,",mregnames[p->z.reg],mregnames[q1reg]);
3450 else
3451 emit(f,"\tcmp%sw%s\t%s,%s,",((t&UNSIGNED)||((t&NQ)==POINTER))?"l":"",isimm[q2reg==0],mregnames[p->z.reg],mregnames[q1reg]);
3452 emit_obj(f,&p->q2,t);emit(f,"\n");
3453 if(p->z.reg==cr0) ccset=0;
3454 continue;
3455 }
3456 BSET(regs_modified,zreg);
3457 if(c==AND&&q2reg==0){
3458 ccset=setcc;
3459 emit(f,"\tandi.\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
3460 emit_obj(f,&p->q2,t|UNSIGNED);emit(f,"\n");
3461 continue;
3462 }
3463 if(c>=OR&&c<=AND){
3464 emit(f,"\t%s%s%s\t%s,%s,",logicals[c-OR],isimm[q2reg==0],record[setcc&&q2reg],mregnames[zreg],mregnames[q1reg]);
3465 emit_obj(f,&p->q2,t|UNSIGNED);emit(f,"\n");
3466 if(setcc&&q2reg) ccset=1;
3467 continue;
3468 }
3469 if(c==SUB&&(p->q1.flags&KONST)){
3470 emit(f,"\tsubfic\t%s,%s,",mregnames[zreg],mregnames[q2reg]);
3471 emit_obj(f,&p->q1,t&NQ);emit(f,"\n");
3472 continue;
3473 }
3474 if(c>=LSHIFT&&c<=MOD){
3475 if(c==RSHIFT&&((t&NQ)<=SHORT)){
3476 /* special treatment for short shifts used in bitfields with
3477 sub-int type; will not handle the general case (which, however,
3478 should never occur) */
3479 int width,shift;
3480 width=sizetab[t&NQ]*8;
3481 if(!(p->q2.flags&KONST)) ierror(0);
3482 eval_const(&p->q2.val,p->typf2&NU);
3483 shift=zm2l(vmax);
3484 if(shift<0||shift>=width) ierror(0);
3485 if(shift==0) continue;
3486 if(!(t&UNSIGNED)){
3487 emit(f,"\texts%c\t%s,%s\n",width==8?'b':'h',mregnames[zreg],mregnames[q1reg]);
3488 q1reg=zreg;
3489 }
3490 emit(f,"\trlwinm\t%s,%s,%d,%d,%d\n",mregnames[zreg],mregnames[q1reg],32-shift,32-width+((t&UNSIGNED)?shift:0),31);
3491 continue;
3492 }
3493 if(c==RSHIFT&&!(t&UNSIGNED)){
3494 emit(f,"\tsraw%s%s\t%s,%s,",isimm[q2reg==0],record[setcc],mregnames[zreg],mregnames[q1reg]);
3495 emit_obj(f,&p->q2,q2typ(p));
3496 /* fix for illegal shift values (undefined behaviour) */
3497 if(!isreg(q2))
3498 emit(f,"&31");
3499 emit(f,"\n");
3500 ccset|=setcc;
3501 continue;
3502 }
3503 if(c==MOD){
3504 i=0;
3505 if(zreg==q1reg||zreg==q2reg){
3506 if(t1!=q1reg&&t1!=q2reg) i=t1;
3507 if(t2!=q1reg&&t2!=q2reg) i=t2;
3508 }else i=zreg;
3509 if(i==0||i==q1reg||i==q2reg) ierror(0);
3510 emit(f,"\tdivw%s\t%s,%s,%s\n",(t&UNSIGNED)?"u":"",mregnames[i],mregnames[q1reg],mregnames[q2reg]);
3511 emit(f,"\tmullw\t%s,%s,%s\n",mregnames[i],mregnames[i],mregnames[q2reg]);
3512 emit(f,"\tsubf%s\t%s,%s,%s\n",record[setcc],mregnames[zreg],mregnames[i],mregnames[q1reg]);
3513 ccset|=setcc;
3514 continue;
3515 }
3516 if(c==DIV&&(t&UNSIGNED)){
3517 emit(f,"\tdivwu%s%s\t%s,%s,",isimm[q2reg==0],record[setcc&&q2reg],mregnames[zreg],mregnames[q1reg]);
3518 if(setcc&&q2reg) ccset=1;
3519 }else if(c==MULT&&ISFLOAT(t)){
3520 if(isreg(z)&&(g_flags[14]&USEDFLAG)){
3521 struct IC *np=p->next,*add;int madd;
3522 while(np&&(np->code==FREEREG||np->code==ALLOCREG)) np=np->next;
3523 if(np&&(np->code==ADD||np->code==SUB)&&(np->q1.flags&(REG|DREFOBJ))==REG&&(np->q1.reg==p->z.reg||(np->code==ADD&&np->q2.reg==p->z.reg))&&(np->q2.flags&(REG|DREFOBJ))==REG&&np->q1.reg!=np->q2.reg){
3524 add=np;
3525 madd=0;
3526 if((np->z.flags&(REG|DREFOBJ))==REG&&np->z.reg==p->z.reg) madd=1;
3527 np=np->next;
3528 while(np&&(np->code==FREEREG||np->code==ALLOCREG)){
3529 if(np->code==FREEREG&&np->q1.reg==p->z.reg) madd=1;
3530 np=np->next;
3531 }
3532 if(madd){
3533 if((add->z.flags&(REG|DREFOBJ))==REG) zreg=add->z.reg;
3534 if(add->code==ADD){
3535 if(add->q1.reg==p->z.reg) madd=add->q2.reg; else madd=add->q1.reg;
3536 emit(f,"\tfmadd%s\t%s,%s,%s,%s\n",(t&NQ)==FLOAT?"s":"",mregnames[zreg],mregnames[q1reg],mregnames[q2reg],mregnames[madd]);
3537 }else
3538 emit(f,"\tfmsub%s\t%s,%s,%s,%s\n",(t&NQ)==FLOAT?"s":"",mregnames[zreg],mregnames[q1reg],mregnames[q2reg],mregnames[add->q2.reg]);
3539 add->code=NOP;
3540 p->z=add->z;
3541 add->z.am=0;
3542 continue;
3543 }
3544 }
3545 }
3546 emit(f,"\tfmul%s\t%s,%s,",(t&NQ)==FLOAT?"s":"",mregnames[zreg],mregnames[q1reg]);
3547 }else if(c==DIV&&ISFLOAT(t)){
3548 emit(f,"\tfdiv%s\t%s,%s,",(t&NQ)==FLOAT?"s":"",mregnames[zreg],mregnames[q1reg]);
3549 }else if(c==MULT&&q2reg==0){
3550 emit(f,"\tmulli\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
3551 }else if(c==ADD&&setcc&&!q2reg){
3552 emit(f,"\taddic.\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
3553 ccset=1;
3554 }else{
3555 emit(f,"\t%s%s%s%s%s\t%s,%s,",fpp,arithmetics[c-LSHIFT],(t&NQ)==FLOAT?"s":"",isimm[q2reg==0],record[setcc&&q2reg&&!fpf],mregnames[zreg],mregnames[q1reg]);
3556 if(setcc&&q2reg&&!fpf) ccset=1;
3557 }
3558 emit_obj(f,&p->q2,q2typ(p)&NQ);
3559 /* fix for illegal shift values (undefined behaviour) */
3560 if((c==LSHIFT||c==RSHIFT)&&q2reg==0) emit(f,"&31");
3561 emit(f,"\n");
3562 continue;
3563 }
3564 pric2(stdout,p);
3565 ierror(0);
3566 }
3567 if(!cross_module) lastlabel=label; /*FIXME*/
3568 free(once);free(twice);
3569 function_bottom(f,v,of);
3570#if HAVE_OSEK
3571/* removed */
3572#endif
3573 if(stack_valid){
3574 if(!v->fi) v->fi=new_fi();
3575 if(v->fi->flags&ALL_STACK){
3576 if(v->fi->stack1!=stack&&!(v->tattr&SAVEALL))
3577 if(f) error(319,"",stack,v->fi->stack1);
3578#if HAVE_OSEK
3579/* removed */
3580/* removed */
3581/* removed */
3582#endif
3583 }else{
3584 v->fi->flags|=ALL_STACK;
3585 v->fi->stack1=stack;
3586 }
3587 }
3588 emit(f,"# stacksize=%lu%s\n",(unsigned long)stack,stack_valid?"":"+??");
3589 if(stack_valid) emit(f,"\t.set\t%s__stack_%s,%lu\n",idprefix,v->identifier,(unsigned long)stack);
3590 if(debug_info){
3591 emit(f,"%s%d:\n",labprefix,++label);
3592 dwarf2_function(f,v,label);
3593 if(f) section=-1;
3594 }
3595}
3596
3597int shortcut(int code,int typ)
3598{
3599 return 0;
3600}
3601
3602int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *ft)
3603{
3604#if HAVE_AOS4
3605 extern int aos4_attr(struct Typ *,char *);
3606#endif
3607 int f;
3608 if(!m) ierror(0);
3609 if(!t) ierror(0);
3610 if(vararg&&POWEROPEN) return 0;
3611#ifdef HAVE_AOS4
3612 if(vararg&&ft&&aos4_attr(ft,"linearvarargs")) return 0;
3613#endif
3614 f=t->flags&NQ;
3615 if(f<=LONG||f==POINTER){
3616 if(m->gregs>=8) return 0;
3617 if(POWEROPEN){
3618 if(!STORMC) m->fregs++;
3619 return -(r3+m->gregs++);
3620 }else{
3621 return r3+m->gregs++;
3622 }
3623 }
3624 if(f==LLONG){
3625 int r;
3626 if(m->gregs>=7) return 0;
3627 m->gregs=(m->gregs+3)/2*2;
3628 if(m->gregs==2) r=74;
3629 else if(m->gregs==4) r=75;
3630 else if(m->gregs==6) r=76;
3631 else if(m->gregs==8) r=77;
3632 else ierror(0);
3633 if(POWEROPEN)
3634 return -r;
3635 else
3636 return r;
3637 }
3638 if(ISFLOAT(f)){
3639 if(POWEROPEN){
3640 if(m->fregs>=11) return 0; /* hack! we pretend fp-arg 12/13 is passed on the stack */
3641 if(!STORMC){
3642 if(f!=FLOAT) m->gregs+=2; else m->gregs++;
3643 }
3644 return -(34+m->fregs++);
3645 }else{
3646 if(m->fregs>=8) return 0;
3647 return 34+m->fregs++;
3648 }
3649 }
3650 return 0;
3651}
3652
3653int handle_pragma(const char *s)
3654{
3655 if(!strncmp("amiga-align",s,11)){
3656 align[INT]=align[LONG]=align[LLONG]=align[POINTER]=align[FLOAT]=align[DOUBLE]=align[LDOUBLE]=l2zm(2L);
3657 return 1;
3658 }else if(!strncmp("natural-align",s,13)){
3659 align[INT]=align[LONG]=align[POINTER]=align[FLOAT]=l2zm(4L);
3660 align[LLONG]=align[DOUBLE]=align[LDOUBLE]=l2zm(8L);
3661 return 1;
3662 }else if(!strncmp("default-align",s,13)){
3663 if(g_flags[7]&USEDFLAG){
3664 align[INT]=align[LONG]=align[LLONG]=align[POINTER]=align[FLOAT]=align[DOUBLE]=align[LDOUBLE]=l2zm(2L);
3665 }else{
3666 align[INT]=align[LONG]=align[POINTER]=align[FLOAT]=l2zm(4L);
3667 align[LLONG]=align[DOUBLE]=align[LDOUBLE]=l2zm(8L);
3668 }
3669 return 1;
3670 }
3671 return 0;
3672}
3673
3674void cleanup_cg(FILE *f)
3675{
3676 struct fpconstlist *p;
3677 unsigned char *ip;
3678 struct StatFPtrList *tfp,*fp=firstfptr;
3679
3680 title(f);
3681
3682 if(fp){
3683 emit(f,tocname);
3684 if(f) section=TOC;
3685 }
3686 while(tfp=fp){
3687 emit(f,"%s%s%ld:\n\t.long\t%s%ld\n",
3688 tocprefix,labprefix,zm2l(tfp->vptr->offset),
3689 labprefix,zm2l(tfp->vptr->offset));
3690 fp=fp->next;
3691 free(tfp);
3692 }
3693 if(f&&stack_check)
3694 emit(f,"\t.global\t%s__stack_check\n",idprefix);
3695 while(p=firstfpc){
3696 if(f){
3697 if(POWEROPEN&&!use_sd(p->typ)){
3698 emit(f,tocname);
3699 emit(f,"%s%s%ld:\n",tocprefix,labprefix,zm2l(p->label));
3700 emit(f,"\t.long\t%s%ld\n",labprefix,zm2l(p->label));
3701 if(f) section=TOC;
3702 }
3703 if(use_sd(p->typ)){
3704 if(EABI){
3705 if(section!=SDATA2){emit(f,sdata2name);if(f) section=SDATA2;}
3706 }else{
3707 if(section!=TOC){emit(f,tocname);if(f) section=TOC;}
3708 }
3709 }else{
3710 if(section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
3711 }
3712 if((p->typ&NQ)==DOUBLE)
3713 emit(f,"\t.align\t3\n");
3714 else
3715 emit(f,"\t.align\t2\n");
3716 emit(f,"%s%d:\n\t.long\t",labprefix,p->label);
3717 ip=(unsigned char *)&p->val.vdouble;
3718 emit(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
3719 if((p->typ&NQ)==DOUBLE){
3720 emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
3721 }
3722 emit(f,"\n");
3723 }
3724 firstfpc=p->next;
3725 free(p);
3726 }
3727}
3728void cleanup_db(FILE *f)
3729{
3730 dwarf2_cleanup(f);
3731 if(f) section=-1;
3732}
3733/* mark instructions which can (probably) be implemented with faster
3734 machine-code than the IC migh suggest, e.g. an addition which can
3735 be merged with a load bz use of target addressing-modes;
3736 the optimizer should hesitate to modifz such instructions if it's not
3737 a definite win */
3738
3739static int is_single_eff_ic(struct IC *p)
3740{
3741 struct Var *v;
3742 if(p->code!=ADDI2P&&p->code!=SUBIFP)
3743 return 0;
3744 if(!(p->q2.flags&KONST)){
3745 if(CONSERVATIVE_SR){
3746 if((p->q2.flags&(VAR|DREFOBJ))!=VAR)
3747 return 0;
3748 if(p->q2.v->storage_class==STATIC||p->q2.v->storage_class==EXTERN)
3749 return 0;
3750 }else
3751 return 0;
3752 }
3753 if((p->q1.flags&(VAR|DREFOBJ))!=VAR)
3754 return 0;
3755 if(p->q1.v->storage_class==STATIC||p->q1.v->storage_class==EXTERN)
3756 return 0;
3757 if((p->z.flags&(VAR|DREFOBJ))!=VAR)
3758 return 0;
3759 if(p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN)
3760 return 0;
3761 v=p->z.v;
3762 for(p=p->next;p;p=p->next){
3763 int c=p->code;
3764 if(c==LABEL||(c>=BEQ&&c<=BRA))
3765 return 0;
3766 if((p->q1.flags&VAR)&&p->q1.v==v){
3767 if(p->q1.flags&DREFOBJ)
3768 return 1;
3769 else
3770 return 0;
3771 }
3772 if((p->q2.flags&VAR)&&p->q2.v==v){
3773 if(p->q2.flags&DREFOBJ)
3774 return 1;
3775 else
3776 return 0;
3777 }
3778 if((p->z.flags&VAR)&&p->z.v==v){
3779 if(p->z.flags&DREFOBJ)
3780 return 1;
3781 else
3782 return 0;
3783 }
3784 }
3785}
3786void mark_eff_ics(void)
3787{
3788 struct IC *p;
3789 for(p=first_ic;p;p=p->next){
3790 if(is_single_eff_ic(p))
3791 p->flags|=EFF_IC;
3792 else
3793 p->flags&=~EFF_IC;
3794 }
3795}
3796
3797char *use_libcall(int c,int t,int t2)
3798{
3799 static char fname[32];
3800 char *ret=0;
3801
3802 if(OLDLIBCALLS) return 0;
3803
3804 if((t&NQ)==LLONG){
3805 ret=fname;
3806 if(c==MULT)
3807 sprintf(fname,"__mulint64");
3808 else if(c==DIV)
3809 sprintf(fname,"__div%cint64",(t&UNSIGNED)?'u':'s');
3810 else if(c==MOD)
3811 sprintf(fname,"__mod%cint64",(t&UNSIGNED)?'u':'s');
3812 else if(c==RSHIFT)
3813 sprintf(fname,"__rsh%cint64",(t&UNSIGNED)?'u':'s');
3814 else if(c==LSHIFT)
3815 sprintf(fname,"__lshint64");
3816 else
3817 ret=0;
3818 }
3819 return ret;
3820}
3821
3822
3823
3824#if HAVE_OSEK
3825/* removed */
3826/* removed */
3827/* removed */
3828/* removed */
3829/* removed */
3830/* removed */
3831/* removed */
3832/* removed */
3833/* removed */
3834/* removed */
3835/* removed */
3836/* removed */
3837/* removed */
3838/* removed */
3839/* removed */
3840/* removed */
3841/* removed */
3842/* removed */
3843/* removed */
3844/* removed */
3845/* removed */
3846/* removed */
3847/* removed */
3848/* removed */
3849/* removed */
3850/* removed */
3851/* removed */
3852/* removed */
3853/* removed */
3854/* removed */
3855/* removed */
3856/* removed */
3857/* removed */
3858/* removed */
3859/* removed */
3860/* removed */
3861/* removed */
3862/* removed */
3863/* removed */
3864/* removed */
3865/* removed */
3866/* removed */
3867/* removed */
3868/* removed */
3869/* removed */
3870/* removed */
3871/* removed */
3872/* removed */
3873/* removed */
3874/* removed */
3875/* removed */
3876/* removed */
3877/* removed */
3878/* removed */
3879/* removed */
3880/* removed */
3881/* removed */
3882/* removed */
3883/* removed */
3884/* removed */
3885/* removed */
3886/* removed */
3887/* removed */
3888/* removed */
3889/* removed */
3890/* removed */
3891/* removed */
3892/* removed */
3893/* removed */
3894/* removed */
3895/* removed */
3896/* removed */
3897/* removed */
3898/* removed */
3899/* removed */
3900/* removed */
3901/* removed */
3902/* removed */
3903/* removed */
3904/* removed */
3905/* removed */
3906/* removed */
3907/* removed */
3908/* removed */
3909/* removed */
3910/* removed */
3911/* removed */
3912/* removed */
3913/* removed */
3914/* removed */
3915/* removed */
3916/* removed */
3917/* removed */
3918/* removed */
3919/* removed */
3920/* removed */
3921/* removed */
3922/* removed */
3923/* removed */
3924/* removed */
3925/* removed */
3926/* removed */
3927/* removed */
3928/* removed */
3929/* removed */
3930/* removed */
3931/* removed */
3932/* removed */
3933/* removed */
3934/* removed */
3935/* removed */
3936/* removed */
3937/* removed */
3938/* removed */
3939/* removed */
3940/* removed */
3941/* removed */
3942/* removed */
3943/* removed */
3944/* removed */
3945/* removed */
3946/* removed */
3947/* removed */
3948/* removed */
3949/* removed */
3950/* removed */
3951/* removed */
3952/* removed */
3953/* removed */
3954/* removed */
3955/* removed */
3956/* removed */
3957/* removed */
3958/* removed */
3959/* removed */
3960/* removed */
3961/* removed */
3962/* removed */
3963/* removed */
3964/* removed */
3965/* removed */
3966/* removed */
3967/* removed */
3968/* removed */
3969/* removed */
3970/* removed */
3971/* removed */
3972/* removed */
3973/* removed */
3974/* removed */
3975/* removed */
3976/* removed */
3977/* removed */
3978/* removed */
3979/* removed */
3980/* removed */
3981/* removed */
3982/* removed */
3983/* removed */
3984/* removed */
3985/* removed */
3986/* removed */
3987/* removed */
3988/* removed */
3989/* removed */
3990/* removed */
3991/* removed */
3992/* removed */
3993/* removed */
3994/* removed */
3995/* removed */
3996/* removed */
3997/* removed */
3998/* removed */
3999/* removed */
4000/* removed */
4001/* removed */
4002/* removed */
4003/* removed */
4004/* removed */
4005/* removed */
4006/* removed */
4007/* removed */
4008/* removed */
4009/* removed */
4010/* removed */
4011/* removed */
4012#endif