blob: 420a4d0c1b7f76e9034378f22e90f8c47744577a [file] [log] [blame]
PulkoMandy17fc7592022-07-28 18:27:54 +02001/* Backend for VideoCore IV
2 (c) in 2013 by Volker Barthelmann
3*/
4
5/* TODO:
6 - extended registers
7 - floating point
8 - long long
9 - memcpy
10 - addcmp
11 - bcc reg
12 - cond. ins
13 - vector
14 - non-pc addressing
15*/
16
17#include "supp.h"
18
19static char FILE_[]=__FILE__;
20
21/* Public data that MUST be there. */
22
23/* Name and copyright. */
24char cg_copyright[]="vbcc VideoCore IV code-generator V0.1 (c) in 2013 by Volker Barthelmann";
25
26/* the flag-name, do not use names beginning with l, L, I, D or U, because
27 they collide with the frontend */
28char *g_flags_name[MAXGF]={"use-commons","use-framepointer",
29 "short-double","one-section",
30 "no-delayed-popping"};
31
32int g_flags[MAXGF]={0,0,
33 0};
34
35/* the results of parsing the command-line-flags will be stored here */
36union ppi g_flags_val[MAXGF];
37
38/* Alignment-requirements for all types in bytes. */
39zmax align[MAX_TYPE+1];
40
41/* Alignment that is sufficient for every object. */
42zmax maxalign;
43
44/* CHAR_BIT for the target machine. */
45zmax char_bit;
46
47/* sizes of the basic types (in bytes) */
48zmax sizetab[MAX_TYPE+1];
49
50/* Minimum and Maximum values each type can have. */
51/* Must be initialized in init_cg(). */
52zmax t_min[MAX_TYPE+1];
53zumax t_max[MAX_TYPE+1];
54zumax tu_max[MAX_TYPE+1];
55
56/* Names of all registers. will be initialized in init_cg(),
57 register number 0 is invalid, valid registers start at 1 */
58char *regnames[MAXR+1];
59
60/* The Size of each register in bytes. */
61zmax regsize[MAXR+1];
62
63/* a type which can store each register. */
64struct Typ *regtype[MAXR+1];
65
66/* regsa[reg]!=0 if a certain register is allocated and should */
67/* not be used by the compiler pass. */
68int regsa[MAXR+1];
69
70/* Specifies which registers may be scratched by functions. */
71int regscratch[MAXR+1];
72
73/* specifies the priority for the register-allocator, if the same
74 estimated cost-saving can be obtained by several registers, the
75 one with the highest priority will be used */
76int reg_prio[MAXR+1];
77
78/* an empty reg-handle representing initial state */
79struct reg_handle empty_reg_handle={0};
80
81/* Names of target-specific variable attributes. */
82char *g_attr_name[]={"__interrupt",0};
83
84
85/****************************************/
86/* Private data and functions. */
87/****************************************/
88
89/* addressing modes */
90#define AM_IMM_IND 1
91#define AM_GPR_IND 2
92#define AM_POSTINC 3
93#define AM_PREDEC 4
94
95#define USE_COMMONS (g_flags[0]&USEDFLAG)
96#define USE_FP (g_flags[1]&USEDFLAG)
97#define SHORT_DOUBLE (g_flags[2]&USEDFLAG)
98#define ONESEC (g_flags[3]&USEDFLAG)
99#define NODELAYEDPOP (g_flags[4]&USEDFLAG)
100
101
102/* alignment of basic data-types, used to initialize align[] */
103static long malign[MAX_TYPE+1]= {1,1,2,4,4,4,4,8,8,1,4,1,1,1,4,1};
104/* sizes of basic data-types, used to initialize sizetab[] */
105static long msizetab[MAX_TYPE+1]={1,1,2,4,4,8,4,8,8,0,4,0,0,0,4,0};
106
107/* used to initialize regtyp[] */
108static struct Typ ltyp={LONG},ldbl={DOUBLE},lchar={CHAR};
109
110/* macros defined by the backend */
111static char *marray[]={"__section(x)=__vattr(\"section(\"#x\")\")",
112 "__VIDEOCORE__",
113 0, /* __SHORT_DOUBLE__ */
114 0};
115
116/* special registers */
117enum{
118 r0=1,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,
119 r16,r17,r18,r19,r20,r21,r22,r23,r24,r25,r26,r27,r28,r29,r30,r31,
120 r0r1,r2r3,r4r5,r6r7,r8r9,r10r11,r12r13,r14r15,
121 r16r17,r18r19,r20r21,r22r23,r24r25,r26r27,r28r29,r30r31
122};
123
124static int sd=r24;
125static int sp=r25;
126static int lr=r26;
127static int sr=r30;
128static int pc=r31;
129static int t1=r15;
130static int t2=r14;
131
132static int last_saved;
133
134#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])
135#define sdt(t) (udt[(t)&NQ])
136static char *sdt[MAX_TYPE+1]={"??","b","hs","","","ll","","d","ld","v",""};
137static char *udt[MAX_TYPE+1]={"??","b","h","","","ull","","d","ld","v",""};
138
139static char *dct[]={"","byte","2byte","4byte","4byte","4byte","4byte","4byte","4byte"};
140
141static int no_suffix;
142
143/* sections */
144#define DATA 0
145#define BSS 1
146#define CODE 2
147#define RODATA 3
148#define SPECIAL 4
149
150static long stack;
151static int stack_valid;
152static int section=-1,newobj;
153static char *codename="\t.text\n",
154 *dataname="\t.data\n",
155 *bssname="",
156 *rodataname="\t.section\t.rodata\n";
157
158/* conditional execution */
159static char *cc;
160
161/* return-instruction */
162static char *ret;
163
164/* label at the end of the function (if any) */
165static int exit_label;
166
167/* assembly-prefixes for labels and external identifiers */
168static char *labprefix="l",*idprefix="_";
169
170#if 0
171/* variables to calculate the size and partitioning of the stack-frame
172 in the case of FIXED_SP */
173static long frameoffset,pushed,maxpushed,framesize;
174#else
175/* variables to keep track of the current stack-offset in the case of
176 a moving stack-pointer */
177static long notpopped,dontpop,stackoffset,maxpushed;
178#endif
179
180static long localsize,rsavesize,argsize;
181
182static void emit_obj(FILE *f,struct obj *p,int t);
183
184/* calculate the actual current offset of an object relativ to the
185 stack-pointer; we use a layout like this:
186 ------------------------------------------------
187 | arguments to this function |
188 ------------------------------------------------
189 | return-address [size=4] |
190 ------------------------------------------------
191 | caller-save registers [size=rsavesize] |
192 ------------------------------------------------
193 | local variables [size=localsize] |
194 ------------------------------------------------
195 | arguments to called functions [size=argsize] |
196 ------------------------------------------------
197 All sizes will be aligned as necessary.
198 In the case of FIXED_SP, the stack-pointer will be adjusted at
199 function-entry to leave enough space for the arguments and have it
200 aligned to 16 bytes. Therefore, when calling a function, the
201 stack-pointer is always aligned to 16 bytes.
202 For a moving stack-pointer, the stack-pointer will usually point
203 to the bottom of the area for local variables, but will move while
204 arguments are put on the stack.
205
206 This is just an example layout. Other layouts are also possible.
207*/
208
209static void push(long l)
210{
211 stackoffset-=l;
212 if(stackoffset<maxpushed)
213 maxpushed=stackoffset;
214 if(-maxpushed>stack)
215 stack=-maxpushed;
216}
217
218static void pop(long l)
219{
220 stackoffset+=l;
221}
222
223static long real_offset(struct obj *o)
224{
225 long off=zm2l(o->v->offset);
226 if(off<0){
227 /* function parameter */
228 off=localsize+rsavesize-off-zm2l(maxalign);
229 }
230
231 off-=stackoffset;
232
233 off+=zm2l(o->val.vmax);
234 return off;
235}
236
237/* Initializes an addressing-mode structure and returns a pointer to
238 that object. Will not survive a second call! */
239static struct obj *cam(int flags,int base,long offset)
240{
241 static struct obj obj;
242 static struct AddressingMode am;
243 obj.am=&am;
244 am.flags=flags;
245 am.base=base;
246 am.offset=offset;
247 return &obj;
248}
249
250/* changes to a special section, used for __section() */
251static int special_section(FILE *f,struct Var *v)
252{
253 char *sec;
254 if(!v->vattr) return 0;
255 sec=strstr(v->vattr,"section(");
256 if(!sec) return 0;
257 sec+=strlen("section(");
258 emit(f,"\t.section\t");
259 while(*sec&&*sec!=')') emit_char(f,*sec++);
260 emit(f,"\n");
261 if(f) section=SPECIAL;
262 return 1;
263}
264
265static unsigned long pushmask;
266
267static int ic_uses_reg(struct IC *p,int r,int onlyuses)
268{
269 if(reg_pair(r,&rp)){
270 return ic_uses_reg(p,rp.r1,onlyuses)||ic_uses_reg(p,rp.r2,onlyuses);
271 }
272 /*FIXME: handle regpairs */
273 if((p->q1.flags&REG)&&p->q1.reg==r) return 1;
274 if((p->q2.flags&REG)&&p->q2.reg==r) return 1;
275 if(onlyuses){
276 if((p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->z.reg==r) return 1;
277 }else{
278 if((p->z.flags&REG)&&p->z.reg==r) return 1;
279 }
280 if(p->q1.am){
281 if(p->q1.am->base==r) return 1;
282 if(p->q1.am->flags==AM_GPR_IND&&p->q1.am->offset==r) return 1;
283 }
284 if(p->q2.am){
285 if(p->q2.am->base==r) return 1;
286 if(p->q2.am->flags==AM_GPR_IND&&p->q2.am->offset==r) return 1;
287 }
288 if(p->z.am){
289 if(p->z.am->base==r) return 1;
290 if(p->z.am->flags==AM_GPR_IND&&p->z.am->offset==r) return 1;
291 }
292 return 0;
293}
294
295static int reg_is_scratched(struct IC *p,int r)
296{
297 for(p=p->next;p;p=p->next){
298 int c=p->code;
299 if(c>=LABEL&&c<=BRA)
300 return 0;
301 if(c==FREEREG&&p->q1.reg==r)
302 return 1;
303 if(ic_uses_reg(p,r,1))
304 return 0;
305 if((p->q1.flags&(REG|DREFOBJ))==REG&&p->z.reg==r)
306 return 1;
307 }
308 return 0;
309}
310
311static int get_reg(FILE *f,struct IC *p)
312{
313 int r;
314 for(r=r0;r<=r31;r++){
315 if(!regs[r]&&regused[r]&&!ic_uses_reg(p,r,0)){
316 regs[r]=1;
317 return r;
318 }
319 }
320 for(r=r0;r<=r31;r++){
321 if(!regs[r]&&!ic_uses_reg(p,r,0)){
322 regs[r]=1;
323 return r;
324 }
325 }
326 for(r=r0;r<=r31;r++){
327 if(!ic_uses_reg(p,r,0))
328 break;
329 }
330 argsize+=4;
331 emit(f,"\tst\t%s,--(%s)\n",regnames[r],regnames[sp]);
332 push(4);
333 pushmask|=(1<<(r-1));
334 regs[r]=1;
335 return r;
336}
337
338static void free_reg(FILE *f,int r)
339{
340 if(pushmask&(1<<(r-1))){
341 emit(f,"\tld\t%s,(%s)++\n",regnames[r],regnames[sp]);
342 pop(4);
343 argsize-=4;
344 }else
345 regs[r]=0;
346 pushmask&=~(1<<(r-1));
347}
348
349/* generate code to load the address of a variable into register r */
350static void load_address(FILE *f,int r,struct obj *o,int type)
351/* Generates code to load the address of a variable into register r. */
352{
353 if(!(o->flags&VAR)) ierror(0);
354 if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
355 long off=real_offset(o);
356 emit(f,"\tadd%s\t%s,%s,%ld\n",cc,regnames[r],regnames[sp],off);
357 }else{
358 emit(f,"\tlea%s\t%s,",cc,regnames[r]);
359 emit_obj(f,o,type);
360 emit(f,"\n");
361 }
362}
363/* Generates code to load a memory object into register r. tmp is a
364 general purpose register which may be used. tmp can be r. */
365static void load_reg(FILE *f,int r,struct obj *o,int type)
366{
367 type&=NU;
368 if(reg_pair(r,&rp)) ierror(0);
369 if(o->flags&VARADR){
370 load_address(f,r,o,POINTER);
371 }else if(o->flags&KONST){
372 emit(f,"\tmov%s\t%s,",cc,regnames[r]);
373 emit_obj(f,o,type);
374 emit(f,"\n");
375 }else{
376 if((o->flags&(REG|DREFOBJ))==REG){
377 if(o->reg!=r)
378 emit(f,"\tmov%s\t%s,%s\n",cc,regnames[r],regnames[o->reg]);
379 }else{
380 if(SHORT_DOUBLE&&ISFLOAT(type)) type=FLOAT;
381 emit(f,"\tld%s%s\t%s,",dt(type),cc,regnames[r]);
382 emit_obj(f,o,type);
383 emit(f,"\n");
384 }
385 }
386}
387
388/* Generates code to store register r into memory object o. */
389static void store_reg(FILE *f,int r,struct obj *o,int type)
390{
391 if(reg_pair(r,&rp)) ierror(0);
392 type&=NQ;
393 if(SHORT_DOUBLE&&ISFLOAT(type)) type=FLOAT;
394 emit(f,"\tst%s%s\t%s,",sdt(type),cc,regnames[r]);
395 emit_obj(f,o,type);
396 emit(f,"\n");
397}
398
399/* Yields log2(x)+1 or 0. */
400static long pof2(zumax x)
401{
402 zumax p;int ln=1;
403 p=ul2zum(1L);
404 while(ln<=32&&zumleq(p,x)){
405 if(zumeqto(x,p)) return ln;
406 ln++;p=zumadd(p,p);
407 }
408 return 0;
409}
410
411static struct IC *preload(FILE *,struct IC *);
412
413static void function_top(FILE *,struct Var *,long);
414static void function_bottom(FILE *f,struct Var *,long);
415
416#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
417#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
418
419static int q1reg,q2reg,zreg;
420
421static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
422static char *ccu[]={"eq","ne","cs","cc","ls","hi",""};
423static char *logicals[]={"or","eor","and"};
424static char *arithmetics[]={"lsl","asr","add","sub","mul","divs","mod"};
425static char *uarithmetics[]={"lsl","lsr","add","sub","mul","divu","mod"};
426static char *farithmetics[]={"--","--","fadd","fsub","fmul","fdiv","--"};
427
428
429/* Does some pre-processing like fetching operands from memory to
430 registers etc. */
431static struct IC *preload(FILE *f,struct IC *p)
432{
433 int r,load;
434
435 if(isreg(q1))
436 q1reg=p->q1.reg;
437 else
438 q1reg=0;
439
440 if(isreg(q2))
441 q2reg=p->q2.reg;
442 else
443 q2reg=0;
444
445 if(isreg(z)){
446 zreg=p->z.reg;
447 }else{
448 zreg=t1;
449 }
450
451 if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q1.am){
452 p->q1.flags&=~DREFOBJ;
453 load_reg(f,t1,&p->q1,POINTER);
454 p->q1.reg=t1;
455 p->q1.flags|=(REG|DREFOBJ);
456 }
457 if(p->q1.flags&&!isreg(q1)&&p->code!=ASSIGN&&p->code!=PUSH&&p->code!=SETRETURN/*&&!(p->q1.flags&KONST)*/){
458 q1reg=zreg;
459 load_reg(f,q1reg,&p->q1,q1typ(p));
460 p->q1.reg=q1reg;
461 p->q1.flags=REG;
462 }
463
464 if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q2.am){
465 p->q2.flags&=~DREFOBJ;
466 load_reg(f,t2,&p->q2,POINTER);
467 p->q2.reg=t2;
468 p->q2.flags|=(REG|DREFOBJ);
469 }
470
471 if(p->q2.flags){
472 load=1;
473 if(isreg(q2)) load=0;
474 if((p->q2.flags&KONST)&&!ISFLOAT(p->typf)&&(p->code==ADD||p->code==SUB||p->code==ADDI2P||p->code==COMPARE||p->code==SUBIFP||p->code==SUBPFP))
475 load=0;
476 if(p->code>=OR&&p->code<=MOD&&(p->q2.flags&KONST)&&!ISFLOAT(p->typf)){
477 unsigned long v;
478 eval_const(&p->q2.val,q2typ(p));
479 v=zum2ul(vumax);
480 if(v<=31) load=0;
481 }
482 if(load){
483 q2reg=t2;
484 load_reg(f,q2reg,&p->q2,q2typ(p));
485 p->q2.reg=q2reg;
486 p->q2.flags=REG;
487 }
488 }
489 return p;
490}
491
492/* save the result (in zreg) into p->z */
493void save_result(FILE *f,struct IC *p)
494{
495 if((p->z.flags&(REG|DREFOBJ))==DREFOBJ&&!p->z.am){
496 p->z.flags&=~DREFOBJ;
497 load_reg(f,t2,&p->z,POINTER);
498 p->z.reg=t2;
499 p->z.flags|=(REG|DREFOBJ);
500 }
501 if(isreg(z)){
502 if(p->z.reg!=zreg)
503 emit(f,"\tmov%s\t%s,%s\n",cc,regnames[p->z.reg],regnames[zreg]);
504 }else{
505 store_reg(f,zreg,&p->z,ztyp(p));
506 }
507}
508
509/* prints an object */
510static void emit_obj(FILE *f,struct obj *p,int t)
511{
512 if((p->flags&DREFOBJ)&&p->am){
513 if(p->am->flags==AM_GPR_IND) emit(f,"(%s,%s)",regnames[p->am->base],regnames[p->am->offset]);
514 if(p->am->flags==AM_IMM_IND) emit(f,"%ld(%s)",p->am->offset,regnames[p->am->base]);
515 if(p->am->flags==AM_POSTINC) emit(f,"(%s)++",regnames[p->am->base]);
516 if(p->am->flags==AM_PREDEC) emit(f,"--(%s)",regnames[p->am->base]);
517 return;
518 }
519 if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
520 emitval(f,&p->val,p->dtyp&NU);
521 return;
522 }
523 if(p->flags&DREFOBJ) emit(f,"(");
524 if(p->flags&REG){
525 emit(f,"%s",regnames[p->reg]);
526 }else if(p->flags&VAR) {
527 if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER)
528 emit(f,"%ld(%s)",real_offset(p),regnames[sp]);
529 else{
530 if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,LONG);emit(f,"+");}
531 if(p->v->storage_class==STATIC){
532 emit(f,"%s%ld",labprefix,zm2l(p->v->offset));
533 }else{
534 emit(f,"%s%s",idprefix,p->v->identifier);
535 }
536 if(!no_suffix)
537 emit(f,"(%s)",regnames[pc]);
538 }
539 }
540 if(p->flags&KONST){
541 if(ISFLOAT(t)){
542 unsigned char *ip;
543 eval_const(&p->val,t);
544 ip=(unsigned char *)&vfloat;
545 emit(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
546 }else
547 emitval(f,&p->val,t&NU);
548 }
549 if(p->flags&DREFOBJ) emit(f,")");
550}
551
552/* Test if there is a sequence of FREEREGs containing FREEREG reg.
553 Used by peephole. */
554static int exists_freereg(struct IC *p,int reg)
555{
556 while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
557 if(p->code==FREEREG&&p->q1.reg==reg) return 1;
558 p=p->next;
559 }
560 return 0;
561}
562
563/* search for possible addressing-modes */
564static void peephole(struct IC *p)
565{
566 int c,c2,r;struct IC *p2;struct AddressingMode *am;
567
568 for(;p;p=p->next){
569 c=p->code;
570 if(c!=FREEREG&&c!=ALLOCREG&&(c!=SETRETURN||!isreg(q1)||p->q1.reg!=p->z.reg)) exit_label=0;
571 if(c==LABEL) exit_label=p->typf;
572
573 /* -(ax) */
574 if(c==SUBIFP&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg&&p->q1.reg<=8&&isconst(q2)){
575 zmax sz;
576 int t;
577 r=p->q1.reg;
578 eval_const(&p->q2.val,q2typ(p));
579 sz=zm2l(vmax);
580 if(sz==1||sz==2||sz==4){
581 for(p2=p->next;p2;p2=p2->next){
582 c2=p2->code;
583 if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r&&(!(p2->q2.flags&REG)||p2->q2.reg!=r)&&(!(p2->z.flags&REG)||p2->z.reg!=r)&&(
584c2!=CONVERT||(q1typ(p2)&NQ)<=(ztyp(p2)&NQ))){
585 t=(q1typ(p2)&NQ);
586 if((ISINT(t)||ISPOINTER(t))&&t!=LLONG&&zmeqto(sizetab[q1typ(p2)&NQ],l2zm(sz))){
587 p2->q1.am=am=mymalloc(sizeof(*am));
588 p2->q1.val.vmax=l2zm(0L);
589 am->base=r;
590 am->flags=AM_PREDEC;
591 p->code=NOP;
592 p->q1.flags=p->q2.flags=p->z.flags=0;
593 break;
594 }
595 }
596 if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r&&(!(p2->q1.flags&REG)||p2->q1.reg!=r)&&(!(p2->z.flags&REG)||p2->z.reg!=r)){
597 t=(q2typ(p2)&NQ);
598 if((ISINT(t)||ISPOINTER(t))&&t!=LLONG&&zmeqto(sizetab[q2typ(p2)&NQ],l2zm(sz))){
599 p2->q2.am=am=mymalloc(sizeof(*am));
600 p2->q2.val.vmax=l2zm(0L);
601 am->base=r;
602 am->flags=AM_PREDEC;
603 p->code=NOP;
604 p->q1.flags=p->q2.flags=p->z.flags=0;
605 break;
606 }
607 }
608 if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r&&(!(p2->q2.flags&REG)||p2->q2.reg!=r)&&(!(p2->q1.flags&REG)||p2->q1.reg!=r)){
609 t=(ztyp(p2)&NQ);
610 if((ISINT(t)||ISPOINTER(t))&&t!=LLONG&&zmeqto(sizetab[ztyp(p2)&NQ],l2zm(sz))){
611 p2->z.am=am=mymalloc(sizeof(*am));
612 p2->z.val.vmax=l2zm(0L);
613 am->base=r;
614 am->flags=AM_PREDEC;
615 p->code=NOP;
616 p->q1.flags=p->q2.flags=p->z.flags=0;
617 break;
618 }
619 }
620 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
621 if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
622 if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
623 if((p2->z.flags&REG)&&p2->z.reg==r) break;
624 }
625 }
626 }
627
628 /* (ax)+ in q1 */
629 if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&(c!=CONVERT||(q1typ(p)&NQ)<=(ztyp(p)&NQ))){
630 int t=(q1typ(p)&NQ);
631 long sz=zm2l(sizetab[t]);
632 r=p->q1.reg;
633 if((sz==1||sz==2||sz==4)&&(ISINT(t)||ISPOINTER(t)||ISFLOAT(t))&&(!(p->q2.flags&REG)||p->q2.reg!=r)&&(!(p->z.flags&REG)||p->z.reg!=r)){
634 for(p2=p->next;p2;p2=p2->next){
635 c2=p2->code;
636 if(c2==ADDI2P&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){
637 eval_const(&p2->q2.val,q2typ(p2));
638 if(zmeqto(vmax,l2zm(sz))){
639 p->q1.am=am=mymalloc(sizeof(*am));
640 p->q1.val.vmax=l2zm(0L);
641 am->flags=AM_POSTINC;
642 am->base=r;
643 am->offset=0;
644 p2->code=NOP;
645 p2->q1.flags=p2->q2.flags=p2->z.flags=0;
646 break;
647 }
648 }
649 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
650 if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
651 if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
652 if((p2->z.flags&REG)&&p2->z.reg==r) break;
653 }
654 }
655 }
656 /* (ax)+ in q2 */
657 if(!p->q2.am&&(p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&(c!=CONVERT||(q2typ(p)&NQ)<=(ztyp(p)&NQ))){
658 int t=(q2typ(p)&NQ);
659 long sz=zm2l(sizetab[t]);
660 r=p->q2.reg;
661 if((sz==1||sz==2||sz==4)&&(ISINT(t)||ISPOINTER(t)||ISFLOAT(t))&&(!(p->q1.flags&REG)||p->q1.reg!=r)&&(!(p->z.flags&REG)||p->z.reg!=r)){
662 for(p2=p->next;p2;p2=p2->next){
663 c2=p2->code;
664 if(c2==ADDI2P&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){
665 eval_const(&p2->q2.val,q2typ(p2));
666 if(zmeqto(vmax,l2zm(sz))){
667 p->q2.am=am=mymalloc(sizeof(*am));
668 p->q2.val.vmax=l2zm(0L);
669 am->flags=AM_POSTINC;
670 am->base=r;
671 am->offset=0;
672 p2->code=NOP;
673 p2->q1.flags=p2->q2.flags=p2->z.flags=0;
674 break;
675 }
676 }
677 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
678 if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
679 if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
680 if((p2->z.flags&REG)&&p2->z.reg==r) break;
681 }
682 }
683 }
684 /* (ax)+ in z */
685 if(!p->z.am&&(p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->z.reg<=8&&(c!=CONVERT||(q2typ(p)&NQ)<=(ztyp(p)&NQ))){
686 int t=(ztyp(p)&NQ);
687 long sz=zm2l(sizetab[t]);
688 r=p->z.reg;
689 if((sz==1||sz==2||sz==4)&&(ISINT(t)||ISPOINTER(t)||ISFLOAT(t))&&(!(p->q1.flags&REG)||p->q1.reg!=r)&&(!(p->q2.flags&REG)||p->q2.reg!=r)){
690 for(p2=p->next;p2;p2=p2->next){
691 c2=p2->code;
692 if(c2==ADDI2P&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){
693 eval_const(&p2->q2.val,q2typ(p2));
694 if(zmeqto(vmax,l2zm(sz))){
695 p->z.am=am=mymalloc(sizeof(*am));
696 p->z.val.vmax=l2zm(0L);
697 am->flags=AM_POSTINC;
698 am->base=r;
699 am->offset=0;
700 p2->code=NOP;
701 p2->q1.flags=p2->q2.flags=p2->z.flags=0;
702 break;
703 }
704 }
705 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
706 if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
707 if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
708 if((p2->z.flags&REG)&&p2->z.reg==r) break;
709 }
710 }
711 }
712 /* Try const(reg) */
713 if((c==ADDI2P/*||c==SUBIFP*/)&&isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
714 int base;zmax of;struct obj *o;
715 eval_const(&p->q2.val,p->typf);
716 if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
717 if(1/*zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))*/){
718 r=p->z.reg;
719 if(isreg(q1)) base=p->q1.reg; else base=r;
720 o=0;
721 for(p2=p->next;p2;p2=p2->next){
722 c2=p2->code;
723 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
724 if(c2!=FREEREG&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r) break;
725 if(c2!=FREEREG&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==r) break;
726 if((c2==ASSIGN||c2==PUSH)&&(!ISSCALAR(p2->typf)||!zmeqto(p2->q2.val.vmax,sizetab[p2->typf&NQ]))){
727 if((p->q1.flags&REG)&&p->q1.reg==base)
728 break;
729 if((p->z.flags&REG)&&p->z.reg==base)
730 break;
731 }
732 if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/){
733 if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
734 if(o) break;
735 o=&p2->q1;
736 }
737 if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
738 if(o) break;
739 o=&p2->q2;
740 }
741 if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
742 if(o) break;
743 o=&p2->z;
744 }
745 }
746 if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG){
747 int m;
748 if(c2==FREEREG)
749 m=p2->q1.reg;
750 else
751 m=p2->z.reg;
752 if(m==r){
753 if(o){
754 o->am=am=mymalloc(sizeof(*am));
755 am->flags=AM_IMM_IND;
756 am->base=base;
757 am->offset=zm2l(of);
758 if(isreg(q1)){
759 p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
760 }else{
761 p->code=c=ASSIGN;p->q2.flags=0;
762 p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ];
763 }
764 }
765 break;
766 }
767 if(c2!=FREEREG&&m==base) break;
768 continue;
769 }
770 }
771 }
772 }
773 /* Try reg,reg */
774 if(c==ADDI2P&&isreg(q2)&&isreg(z)&&(isreg(q1)||p->q2.reg!=p->z.reg)){
775 int base,idx;struct obj *o;
776 r=p->z.reg;idx=p->q2.reg;
777 if(isreg(q1)) base=p->q1.reg; else base=r;
778 o=0;
779 for(p2=p->next;p2;p2=p2->next){
780 c2=p2->code;
781 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
782 if(c2!=FREEREG&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r) break;
783 if(c2!=FREEREG&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==r) break;
784 if((p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==idx&&idx!=r) break;
785
786 if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/){
787 if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
788 if(o||(q1typ(p2)&NQ)!=CHAR) break;
789 o=&p2->q1;
790 }
791 if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
792 if(o||(q2typ(p2)&NQ)!=CHAR) break;
793 o=&p2->q2;
794 }
795 if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
796 if(o||(ztyp(p2)&NQ)!=CHAR) break;
797 o=&p2->z;
798 }
799 }
800 if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG){
801 int m;
802 if(c2==FREEREG)
803 m=p2->q1.reg;
804 else
805 m=p2->z.reg;
806 if(m==r){
807 if(o){
808 o->am=am=mymalloc(sizeof(*am));
809 am->flags=AM_GPR_IND;
810 am->base=base;
811 am->offset=idx;
812 if(isreg(q1)){
813 p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
814 }else{
815 p->code=c=ASSIGN;p->q2.flags=0;
816 p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ];
817 }
818 }
819 break;
820 }
821 if(c2!=FREEREG&&m==base) break;
822 continue;
823 }
824 }
825 }
826 }
827}
828
829/* generates the function entry code */
830static void function_top(FILE *f,struct Var *v,long offset)
831{
832 int i;
833 rsavesize=0;
834 if(!special_section(f,v)&&section!=CODE){emit(f,codename);if(f) section=CODE;}
835 emit(f,"\t.align\t1\n");
836 if(v->storage_class==EXTERN){
837 if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC)
838 emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
839 emit(f,"%s%s:\n",idprefix,v->identifier);
840 }else
841 emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
842 last_saved=0;
843 for(i=r6;i<t2;i++){
844 if(regused[i])
845 last_saved=i;
846 }
847 if(last_saved){
848 emit(f,"\tpush\t%s-%s",regnames[r6],regnames[last_saved]);
849 rsavesize=(last_saved-r6+1)*4;
850 if(function_calls){
851 emit(f,",lr");
852 rsavesize+=4;
853 }
854 emit(f,"\n");
855 }else if(function_calls){
856 emit(f,"\tpush\t%s-%s,lr\n",regnames[r6],regnames[r6]);
857 rsavesize+=8;
858 }
859 if(offset){
860 emit(f,"\tsub\t%s,%ld\n",regnames[sp],offset);
861 }
862}
863/* generates the function exit code */
864static void function_bottom(FILE *f,struct Var *v,long offset)
865{
866 if(offset){
867 emit(f,"\tadd\t%s,%ld\n",regnames[sp],offset);
868 }
869 if(last_saved){
870 emit(f,"\tpop\t%s-%s",regnames[r6],regnames[last_saved]);
871 if(function_calls){
872 emit(f,",pc");
873 }
874 emit(f,"\n");
875 }else if(function_calls){
876 emit(f,"\tpop\t%s-%s,pc\n",regnames[r6],regnames[r6]);
877 }
878 if(!function_calls)
879 emit(f,ret);
880}
881
882/****************************************/
883/* End of private data and functions. */
884/****************************************/
885
886/* Does necessary initializations for the code-generator. Gets called */
887/* once at the beginning and should return 0 in case of problems. */
888int init_cg(void)
889{
890 int i;
891 /* Initialize some values which cannot be statically initialized */
892 /* because they are stored in the target's arithmetic. */
893 maxalign=l2zm(4L);
894 char_bit=l2zm(8L);
895 stackalign=l2zm(4);
896
897 for(i=0;i<=MAX_TYPE;i++){
898 sizetab[i]=l2zm(msizetab[i]);
899 align[i]=l2zm(malign[i]);
900 }
901
902 if(SHORT_DOUBLE){
903 sizetab[DOUBLE]=sizetab[FLOAT];
904 align[DOUBLE]=align[FLOAT];
905 sizetab[LDOUBLE]=sizetab[FLOAT];
906 align[LDOUBLE]=align[FLOAT];
907 }
908
909 regnames[0]="noreg";
910 for(i=1;i<=32;i++){
911 regnames[i]=mymalloc(10);
912 sprintf(regnames[i],"r%d",i-1);
913 regsize[i]=l2zm(4L);
914 regtype[i]=&ltyp;
915 }
916 for(i=33;i<=48;i++){
917 regnames[i]=mymalloc(10);
918 sprintf(regnames[i],"r%d/r%d",i-33,i-32);
919 regsize[i]=l2zm(8L);
920 regtype[i]=&ldbl;
921 }
922
923 /* Initialize the min/max-settings. Note that the types of the */
924 /* host system may be different from the target system and you may */
925 /* only use the smallest maximum values ANSI guarantees if you */
926 /* want to be portable. */
927 /* That's the reason for the subtraction in t_min[INT]. Long could */
928 /* be unable to represent -2147483648 on the host system. */
929 t_min[CHAR]=l2zm(-128L);
930 t_min[SHORT]=l2zm(-32768L);
931 t_min[INT]=zmsub(l2zm(-2147483647L),l2zm(1L));
932 t_min[LONG]=t_min(INT);
933 t_min[LLONG]=zmlshift(l2zm(1L),l2zm(63L));
934 t_min[MAXINT]=t_min(LLONG);
935 t_max[CHAR]=ul2zum(127L);
936 t_max[SHORT]=ul2zum(32767UL);
937 t_max[INT]=ul2zum(2147483647UL);
938 t_max[LONG]=t_max(INT);
939 t_max[LLONG]=zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL));
940 t_max[MAXINT]=t_max(LLONG);
941 tu_max[CHAR]=ul2zum(255UL);
942 tu_max[SHORT]=ul2zum(65535UL);
943 tu_max[INT]=ul2zum(4294967295UL);
944 tu_max[LONG]=t_max(UNSIGNED|INT);
945 tu_max[LLONG]=zumkompl(ul2zum(0UL));
946 tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
947
948 /* Reserve a few registers for use by the code-generator. */
949 /* This is not optimal but simple. */
950 regsa[t1]=regsa[t2]=1;
951 regsa[pc]=regsa[lr]=regsa[sp]=regsa[sr]=1;
952 regscratch[t1]=regscratch[t2]=0;
953 regscratch[pc]=regscratch[lr]=regscratch[sp]=regscratch[sr]=1;
954
955 for(i=r16;i<=r31;i++)
956 regscratch[i]=regsa[i]=1;
957
958 for(i=1;i<=6;i++)
959 regscratch[i]=1;
960
961 if(ONESEC){
962 bssname=codename;
963 dataname=codename;
964 rodataname=codename;
965 }
966
967 if(SHORT_DOUBLE) marray[2]="__SHORT_DOUBLE__=1";
968 target_macros=marray;
969
970
971 declare_builtin("__mulint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
972 declare_builtin("__addint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
973 declare_builtin("__subint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
974 declare_builtin("__andint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
975 declare_builtin("__orint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
976 declare_builtin("__eorint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
977 declare_builtin("__negint64",LLONG,LLONG,r0r1,0,0,1,0);
978 declare_builtin("__lslint64",LLONG,LLONG,r0r1,INT,r2,1,0);
979
980 declare_builtin("__divsint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
981 declare_builtin("__divuint64",UNSIGNED|LLONG,UNSIGNED|LLONG,r0r1,UNSIGNED|LLONG,r2r3,1,0);
982 declare_builtin("__modsint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
983 declare_builtin("__moduint64",UNSIGNED|LLONG,UNSIGNED|LLONG,r0r1,UNSIGNED|LLONG,r2r3,1,0);
984 declare_builtin("__lsrsint64",LLONG,LLONG,r0r1,INT,r2,1,0);
985 declare_builtin("__lsruint64",UNSIGNED|LLONG,UNSIGNED|LLONG,r0r1,INT,r2,1,0);
986 declare_builtin("__cmpsint64",INT,LLONG,r0r1,LLONG,r2r3,1,0);
987 declare_builtin("__cmpuint64",INT,UNSIGNED|LLONG,r0r1,UNSIGNED|LLONG,r2r3,1,0);
988 declare_builtin("__sint64toflt32",FLOAT,LLONG,r0r1,0,0,1,0);
989 declare_builtin("__uint64toflt32",FLOAT,UNSIGNED|LLONG,r0r1,0,0,1,0);
990 declare_builtin("__sint64toflt64",LDOUBLE,LLONG,r0r1,0,0,1,0);
991 declare_builtin("__uint64toflt64",LDOUBLE,UNSIGNED|LLONG,r0r1,0,0,1,0);
992 declare_builtin("__flt32tosint64",LLONG,FLOAT,r0,0,0,1,0);
993 declare_builtin("__flt32touint64",UNSIGNED|LLONG,FLOAT,r0,0,0,1,0);
994 declare_builtin("__flt64tosint64",LLONG,LDOUBLE,r0r1,0,0,1,0);
995 declare_builtin("__flt64touint64",UNSIGNED|LLONG,LDOUBLE,r0r1,0,0,1,0);
996
997 declare_builtin("__flt32toflt64",LDOUBLE,FLOAT,r0,0,0,1,0);
998 declare_builtin("__flt64toflt32",FLOAT,LDOUBLE,r0r1,0,0,1,0);
999
1000 declare_builtin("__addflt64",LDOUBLE,LDOUBLE,r0r1,LDOUBLE,r2r3,1,0);
1001 declare_builtin("__subflt64",LDOUBLE,LDOUBLE,r0r1,LDOUBLE,r2r3,1,0);
1002 declare_builtin("__mulflt64",LDOUBLE,LDOUBLE,r0r1,LDOUBLE,r2r3,1,0);
1003 declare_builtin("__divflt64",LDOUBLE,LDOUBLE,r0r1,LDOUBLE,r2r3,1,0);
1004 declare_builtin("__negflt64",LDOUBLE,LDOUBLE,r0r1,LDOUBLE,r2r3,1,0);
1005 declare_builtin("__cmpflt64",INT,LDOUBLE,r0r1,LDOUBLE,r2r3,1,0);
1006
1007
1008 return 1;
1009}
1010
1011void init_db(FILE *f)
1012{
1013}
1014
1015int freturn(struct Typ *t)
1016/* Returns the register in which variables of type t are returned. */
1017/* If the value cannot be returned in a register returns 0. */
1018/* A pointer MUST be returned in a register. The code-generator */
1019/* has to simulate a pseudo register if necessary. */
1020{
1021 if(SHORT_DOUBLE&&ISFLOAT(t->flags)) return r0;
1022 if(ISSTRUCT(t->flags)||ISUNION(t->flags))
1023 return 0;
1024 if(zmleq(szof(t),l2zm(4L)))
1025 return r0;
1026 if(zmeqto(szof(t),l2zm(8L)))
1027 return r0r1;
1028 return 0;
1029}
1030
1031int reg_pair(int r,struct rpair *p)
1032/* Returns 0 if the register is no register pair. If r */
1033/* is a register pair non-zero will be returned and the */
1034/* structure pointed to p will be filled with the two */
1035/* elements. */
1036{
1037 if(r>=r0r1&&r<=r30r31){
1038 p->r1=(r-r0r1)*2+r0;
1039 p->r2=(r-r0r1)*2+r1;
1040 return 1;
1041 }
1042 return 0;
1043}
1044
1045/* estimate the cost-saving if object o from IC p is placed in
1046 register r */
1047int cost_savings(struct IC *p,int r,struct obj *o)
1048{
1049 int c=p->code;
1050 if(o->flags&VKONST){
1051 return 0;
1052 }
1053 if(o->flags&DREFOBJ)
1054 return 4;
1055 if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 3;
1056 if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 3;
1057 return 2;
1058}
1059
1060int regok(int r,int t,int mode)
1061/* Returns 0 if register r cannot store variables of */
1062/* type t. If t==POINTER and mode!=0 then it returns */
1063/* non-zero only if the register can store a pointer */
1064/* and dereference a pointer to mode. */
1065{
1066 if(r==0)
1067 return 0;
1068 t&=NQ;
1069 if(ISINT(t)||ISFLOAT(t)||ISPOINTER(t)){
1070 if(zmeqto(sizetab[t],l2zm(8L))){
1071 if(r>=r0r1&&r<=r30r31)
1072 return 1;
1073 else
1074 return 0;
1075 }
1076 if(r>=r0&&r<=r31)
1077 return 1;
1078 else
1079 return 0;
1080 }
1081 return 0;
1082}
1083
1084int dangerous_IC(struct IC *p)
1085/* Returns zero if the IC p can be safely executed */
1086/* without danger of exceptions or similar things. */
1087/* vbcc may generate code in which non-dangerous ICs */
1088/* are sometimes executed although control-flow may */
1089/* never reach them (mainly when moving computations */
1090/* out of loops). */
1091/* Typical ICs that generate exceptions on some */
1092/* machines are: */
1093/* - accesses via pointers */
1094/* - division/modulo */
1095/* - overflow on signed integer/floats */
1096{
1097 int c=p->code;
1098 if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
1099 return 1;
1100 if((c==DIV||c==MOD)&&!isconst(q2))
1101 return 1;
1102 return 0;
1103}
1104
1105int must_convert(int o,int t,int const_expr)
1106/* Returns zero if code for converting np to type t */
1107/* can be omitted. */
1108/* On the VideCore IV pointers and 32bit */
1109/* integers have the same representation and can use */
1110/* the same registers. */
1111{
1112 int op=o&NQ,tp=t&NQ;
1113 if(SHORT_DOUBLE){
1114 if(op==DOUBLE||op==LDOUBLE) op=FLOAT;
1115 if(tp==DOUBLE||tp==LDOUBLE) tp=FLOAT;
1116 }
1117 if((op==INT||op==LONG||op==POINTER)&&(tp==INT||tp==LONG||tp==POINTER))
1118 return 0;
1119 if(op==FLOAT&&tp==FLOAT) return 0;
1120 if(op==DOUBLE&&tp==LDOUBLE) return 0;
1121 if(op==LDOUBLE&&tp==DOUBLE) return 0;
1122 return 1;
1123}
1124
1125void gen_ds(FILE *f,zmax size,struct Typ *t)
1126/* This function has to create <size> bytes of storage */
1127/* initialized with zero. */
1128{
1129 if(newobj&&!ONESEC&&section!=SPECIAL)
1130 emit(f,"%ld\n",zm2l(size));
1131 else
1132 emit(f,"\t.space\t%ld\n",zm2l(size));
1133 newobj=0;
1134}
1135
1136void gen_align(FILE *f,zmax align)
1137/* This function has to make sure the next data is */
1138/* aligned to multiples of <align> bytes. */
1139{
1140 if(zm2l(align)>1) emit(f,"\t.align\t2\n");
1141}
1142
1143void gen_var_head(FILE *f,struct Var *v)
1144/* This function has to create the head of a variable */
1145/* definition, i.e. the label and information for */
1146/* linkage etc. */
1147{
1148 int constflag;char *sec;
1149 if(v->clist) constflag=is_const(v->vtyp);
1150 if(v->storage_class==STATIC){
1151 if(ISFUNC(v->vtyp->flags)) return;
1152 if(!special_section(f,v)){
1153 if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
1154 if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
1155 if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
1156 }
1157 if(v->clist||ONESEC||section==SPECIAL){
1158 gen_align(f,falign(v->vtyp));
1159 emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
1160 }else
1161 emit(f,"\t.lcomm\t%s%ld,",labprefix,zm2l(v->offset));
1162 newobj=1;
1163 }
1164 if(v->storage_class==EXTERN){
1165 emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
1166 if(v->flags&(DEFINED|TENTATIVE)){
1167 if(!special_section(f,v)){
1168 if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
1169 if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
1170 if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
1171 }
1172 if(v->clist||ONESEC||section==SPECIAL){
1173 gen_align(f,falign(v->vtyp));
1174 emit(f,"%s%s:\n",idprefix,v->identifier);
1175 }else
1176 emit(f,"\t.%scomm\t%s%s,",(USE_COMMONS?"":"l"),idprefix,v->identifier);
1177 newobj=1;
1178 }
1179 }
1180}
1181
1182void gen_dc(FILE *f,int t,struct const_list *p)
1183/* This function has to create static storage */
1184/* initialized with const-list p. */
1185{
1186 if((t&NQ)==POINTER) t=UNSIGNED|LONG;
1187 emit(f,"\t.%s\t",dct[t&NQ]);
1188 if(!p->tree){
1189 if(ISFLOAT(t)){
1190 /* auch wieder nicht sehr schoen und IEEE noetig */
1191 unsigned char *ip;
1192 if(SHORT_DOUBLE){
1193 eval_const(&p->val,t);
1194 ip=(unsigned char *)&vfloat;
1195 t=FLOAT;
1196 }else
1197 ip=(unsigned char *)&p->val.vdouble;
1198 emit(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
1199 if((t&NQ)!=FLOAT){
1200 emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
1201 }
1202 }else if((t&NQ)==LLONG){
1203 zumax tmp;
1204 eval_const(&p->val,t);
1205 tmp=vumax;
1206 vumax=zumand(zumrshift(vumax,ul2zum(32UL)),ul2zum(0xffffffff));
1207 gval.vulong=zum2zul(vumax);
1208 emitval(f,&gval,UNSIGNED|LONG);
1209 emit(f,",");
1210 vumax=zumand(tmp,ul2zum(0xffffffff));
1211 gval.vulong=zum2zul(vumax);
1212 emitval(f,&gval,UNSIGNED|LONG);
1213 }else{
1214 emitval(f,&p->val,t&NU);
1215 }
1216 }else{
1217 no_suffix=1;
1218 emit_obj(f,&p->tree->o,t&NU);
1219 no_suffix=0;
1220 }
1221 emit(f,"\n");newobj=0;
1222}
1223
1224
1225/* The main code-generation routine. */
1226/* f is the stream the code should be written to. */
1227/* p is a pointer to a doubly linked list of ICs */
1228/* containing the function body to generate code for. */
1229/* v is a pointer to the function. */
1230/* offset is the size of the stackframe the function */
1231/* needs for local variables. */
1232
1233void gen_code(FILE *f,struct IC *p,struct Var *v,zmax offset)
1234/* The main code-generation. */
1235{
1236 int c,t,i,lastcomp;
1237 int q1wasreg,q2wasreg,zwasreg;
1238 struct IC *m;
1239 argsize=0;
1240 if(DEBUG&1) printf("gen_code()\n");
1241 for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
1242 stackoffset=notpopped=dontpop=maxpushed=0;
1243
1244
1245 /*FIXME*/
1246 ret="\trts\n";
1247
1248 cc="";
1249
1250 for(m=p;m;m=m->next){
1251 c=m->code;t=m->typf&NU;
1252 if(c==ALLOCREG) {regs[m->q1.reg]=1;continue;}
1253 if(c==FREEREG) {regs[m->q1.reg]=0;continue;}
1254
1255 if(notpopped&&!dontpop){
1256 int flag=0;
1257 if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
1258 emit(f,"\tadd\t%s,%ld\n",regnames[sp],notpopped);
1259 pop(notpopped);notpopped=0;
1260 }
1261 }
1262
1263
1264 /* convert MULT/DIV/MOD with powers of two */
1265 if((t&NQ)<=LONG&&(m->q2.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)<=LONG&&(c==MULT||((c==DIV||c==MOD)&&(t&UNSIGNED)))){
1266 eval_const(&m->q2.val,t);
1267 i=pof2(vmax);
1268 if(i){
1269 if(c==MOD){
1270 vmax=zmsub(vmax,l2zm(1L));
1271 m->code=AND;
1272 }else{
1273 vmax=l2zm(i-1);
1274 if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
1275 }
1276 c=m->code;
1277 gval.vmax=vmax;
1278 eval_const(&gval,MAXINT);
1279 if(c==AND){
1280 insert_const(&m->q2.val,t);
1281 }else{
1282 insert_const(&m->q2.val,INT);
1283 p->typf2=INT;
1284 }
1285 }
1286 }
1287 if(c==CALL&&argsize<zm2l(m->q2.val.vmax)) argsize=zm2l(m->q2.val.vmax);
1288 }
1289 peephole(p);
1290
1291 for(c=1;c<=MAXR;c++){
1292 if(regsa[c]||regused[c]){
1293 BSET(regs_modified,c);
1294 }
1295 }
1296
1297 localsize=(zm2l(offset)+3)/4*4;
1298#if FIXED_SP
1299 /*FIXME: adjust localsize to get an aligned stack-frame */
1300#endif
1301
1302 function_top(f,v,localsize);
1303
1304 for(;p;p=p->next){
1305 c=p->code;t=p->typf;
1306 if(c==NOP) {p->z.flags=0;continue;}
1307 if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
1308 if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
1309
1310 if(DEBUG&256){emit(f,"# "); pric2(f,p);}
1311 if(DEBUG&512) emit(f,"# stackoffset=%ld, notpopped=%ld, dontpop=%ld\n",stackoffset,notpopped,dontpop);
1312 if(notpopped&&!dontpop){
1313 int flag=0;
1314 if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
1315 emit(f,"\tadd\t%s,%ld\n",regnames[sp],notpopped);
1316 pop(notpopped);notpopped=0;
1317 }
1318 }
1319
1320 if(c==LABEL) {emit(f,"%s%d:\n",labprefix,t);continue;}
1321 if(c==BRA){
1322 if(0/*t==exit_label&&framesize==0*/)
1323 emit(f,ret);
1324 else
1325 emit(f,"\tb\t%s%d\n",labprefix,t);
1326 continue;
1327 }
1328 if(c>=BEQ&&c<BRA){
1329 if(lastcomp&UNSIGNED)
1330 emit(f,"\tb%s\t",ccu[c-BEQ]);
1331 else
1332 emit(f,"\tb%s\t",ccs[c-BEQ]);
1333 if(isreg(q1)){
1334 emit_obj(f,&p->q1,0);
1335 emit(f,",");
1336 }
1337 emit(f,"%s%d\n",labprefix,t);
1338 continue;
1339 }
1340 if(c==MOVETOREG){
1341 load_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
1342 continue;
1343 }
1344 if(c==MOVEFROMREG){
1345 store_reg(f,p->q1.reg,&p->z,regtype[p->q1.reg]->flags);
1346 continue;
1347 }
1348 if(c==PUSH)
1349 dontpop+=zm2l(p->q2.val.vmax);
1350 if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zm2l(p->q2.val.vmax)!=1))){
1351 int i,cnt,unit,lab,treg,acnt=0,atreg=0;
1352 long size;
1353 char *ut;
1354 if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&reg_is_scratched(p,p->q1.reg)){
1355 q1reg=p->q1.reg;
1356 if(p->q1.am) ierror(0);
1357 }else{
1358 q1reg=t1;
1359 if(p->q1.flags&(REG|DREFOBJ)){
1360 p->q1.flags&=~DREFOBJ;
1361 load_reg(f,q1reg,&p->q1,POINTER);
1362 }else
1363 load_address(f,q1reg,&p->q1,POINTER);
1364 }
1365 if((p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&reg_is_scratched(p,p->z.reg)){
1366 zreg=p->z.reg;
1367 if(p->z.am) ierror(0);
1368 }else if(c==PUSH){
1369 zreg=sp;
1370 }else{
1371 if(q1reg==t1)
1372 zreg=t2;
1373 else
1374 zreg=t1;
1375 if(p->z.flags&(REG|DREFOBJ)){
1376 p->z.flags&=~DREFOBJ;
1377 load_reg(f,zreg,&p->z,POINTER);
1378 }else
1379 load_address(f,zreg,&p->z,POINTER);
1380 }
1381 if(zreg==t2){
1382 treg=get_reg(f,p);
1383 atreg=1;
1384 }else if(zreg==t1||q1reg==t1)
1385 treg=t2;
1386 else
1387 treg=t1;
1388
1389 unit=1;ut="b";
1390 size=zm2l(p->q2.val.vmax);
1391
1392 if(c==PUSH)
1393 emit(f,"\tadd\t%s,%ld\n",regnames[q1reg],size);
1394
1395 if(size/unit>=8){
1396 if(treg!=t2&&zreg!=t2)
1397 cnt=t2;
1398 else{
1399 cnt=get_reg(f,p);
1400 acnt=1;
1401 }
1402 emit(f,"\tmov\t%s,%ld\n",regnames[cnt],(size/unit)>>2);
1403 emit(f,"%s%d:\n",labprefix,++label);
1404 }
1405
1406 for(i=0;i<((size/unit>4)?4:size/unit);i++){
1407 if(c!=PUSH){
1408 emit(f,"\tld%s\t%s,(%s)++\n",ut,regnames[treg],regnames[q1reg]);
1409 emit(f,"\tst%s\t%s,(%s)++\n",ut,regnames[treg],regnames[zreg]);
1410 }else{
1411 emit(f,"\tld%s\t%s,--(%s)\n",ut,regnames[treg],regnames[q1reg]);
1412 emit(f,"\tst%s\t%s,--(%s)\n",ut,regnames[treg],regnames[zreg]);
1413 }
1414 }
1415 if(size/unit>=8){
1416 emit(f,"\taddcmpbne\t%s,-1,0,%s%d\n",regnames[cnt],labprefix,label);
1417 }
1418 for(i=0;i<((size/unit)&3);i++){
1419 if(c!=PUSH){
1420 emit(f,"\tld%s\t%s,(%s)++\n",ut,regnames[treg],regnames[q1reg]);
1421 emit(f,"\tst%s\t%s,(%s)++\n",ut,regnames[treg],regnames[zreg]);
1422 }else{
1423 emit(f,"\tld%s\t%s,--(%s)\n",ut,regnames[treg],regnames[q1reg]);
1424 emit(f,"\tst%s\t%s,--(%s)\n",ut,regnames[treg],regnames[zreg]);
1425 }
1426 }
1427 if(c==PUSH)
1428 push(size);
1429 if(acnt) free_reg(f,cnt);
1430 if(atreg) free_reg(f,treg);
1431 continue;
1432 }
1433
1434 if(c==CALL){
1435 int reg;
1436 /*FIXME*/
1437#if 0
1438 if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK)){
1439 if(framesize+zum2ul(p->q1.v->fi->stack1)>stack)
1440 stack=framesize+zum2ul(p->q1.v->fi->stack1);
1441 }else
1442 stack_valid=0;
1443#endif
1444 /*FIXME: does not work with fixed parameters on stack */
1445 if((p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp("__va_start",p->q1.v->identifier)){
1446 emit(f,"\tadd\t%s,%s,%ld\n",regnames[r0],regnames[sp],localsize+rsavesize-stackoffset);
1447 continue;
1448 }
1449
1450 if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
1451 emit_inline_asm(f,p->q1.v->fi->inline_asm);
1452 }else{
1453 if((p->q1.flags&(REG|DREFOBJ))==DREFOBJ){
1454 p->q1.flags&=~DREFOBJ;
1455 load_reg(f,t1,&p->q1,POINTER);
1456 p->q1.flags|=(DREFOBJ|REG);
1457 p->q1.reg=t1;
1458 }
1459 emit(f,"\tbl\t");
1460 if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
1461 emit(f,"%s",regnames[p->q1.reg]);
1462 }else{
1463 no_suffix=1;
1464 emit_obj(f,&p->q1,t);
1465 no_suffix=0;
1466 }
1467 emit(f,"\n");
1468 }
1469
1470 if(!zmeqto(p->q2.val.vmax,l2zm(0L))){
1471 notpopped+=zm2l(p->q2.val.vmax);
1472 dontpop-=zm2l(p->q2.val.vmax);
1473 if(!NODELAYEDPOP&&!vlas&&stackoffset==-notpopped){
1474 /* Entfernen der Parameter verzoegern */
1475 }else{
1476 emit(f,"\tadd\t%s,%ld\n",regnames[sp],zm2l(p->q2.val.vmax));
1477 pop(zm2l(p->q2.val.vmax));
1478 notpopped-=zm2l(p->q2.val.vmax);
1479 }
1480 }
1481
1482 if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_REGS)){
1483 bvunite(regs_modified,p->q1.v->fi->regs_modified,RSIZE);
1484 }else{
1485 int i;
1486 for(i=1;i<=MAXR;i++){
1487 if(regscratch[i]) BSET(regs_modified,i);
1488 }
1489 }
1490 continue;
1491 }
1492
1493 if(c==ADDRESS){
1494 if(isreg(z))
1495 zreg=p->z.reg;
1496 else
1497 zreg=t1;
1498 load_address(f,zreg,&p->q1,POINTER);
1499 save_result(f,p);
1500 continue;
1501 }
1502
1503 if(isreg(q1)) q1wasreg=1; else q1wasreg=0;
1504 if(isreg(q2)) q2wasreg=1; else q2wasreg=0;
1505 if(isreg(z)) zwasreg=1; else zwasreg=0;
1506
1507 p=preload(f,p);
1508 c=p->code;
1509 if(c==SUBPFP) c=SUB;
1510 if(c==ADDI2P) c=ADD;
1511 if(c==SUBIFP) c=SUB;
1512 if(c==CONVERT){
1513 if(ISFLOAT(q1typ(p))){
1514 if(ztyp(p)&UNSIGNED) ierror(0);
1515 if(ISFLOAT(ztyp(p)))
1516 emit(f,"\tmov%s\t%s,%s\n",cc,regnames[zreg],regnames[q1reg]);
1517 else
1518 emit(f,"\tftrunc%s\t%s,%s\n",cc,regnames[zreg],regnames[q1reg]);
1519 save_result(f,p);
1520 continue;
1521 }
1522 if(ISFLOAT(ztyp(p))){
1523 emit(f,"\tflt%c%s\t%s,%s\n",(q1typ(p)&UNSIGNED)?'u':'s',cc,regnames[zreg],regnames[q1reg]);
1524 save_result(f,p);
1525 continue;
1526 }
1527 if(sizetab[q1typ(p)&NQ]<sizetab[ztyp(p)&NQ]){
1528 int mask;
1529 if((q1typ(p)&NQ)==CHAR)
1530 mask=7;
1531 else
1532 mask=15;
1533 if(q1typ(p)&UNSIGNED)
1534 mask++;
1535 if(q1wasreg||(q1typ(p)&NU)==CHAR)
1536 emit(f,"\text%c%s\t%s,%s,%d\n",(q1typ(p)&UNSIGNED)?'u':'s',cc,regnames[zreg],regnames[q1reg],mask);
1537 }else{
1538 zreg=q1reg;
1539 }
1540 save_result(f,p);
1541 continue;
1542 }
1543 if(c==KOMPLEMENT){
1544 emit(f,"\tmvn%s\t%s,%s\n",cc,regnames[zreg],regnames[q1reg]);
1545 save_result(f,p);
1546 continue;
1547 }
1548 if(c==SETRETURN){
1549 if(isreg(q1)){
1550 if(p->q1.reg!=p->z.reg)
1551 emit(f,"\tmov%s\t%s,%s\n",cc,regnames[p->z.reg],regnames[p->q1.reg]);
1552 }else
1553 load_reg(f,p->z.reg,&p->q1,t);
1554 BSET(regs_modified,p->z.reg);
1555 continue;
1556 }
1557 if(c==GETRETURN){
1558 if(p->q1.reg){
1559 zreg=p->q1.reg;
1560 save_result(f,p);
1561 }else
1562 p->z.flags=0;
1563 continue;
1564 }
1565
1566 if(c==ASSIGN||c==PUSH){
1567 if(t==0) ierror(0);
1568 if(c==PUSH){
1569 if(!q1reg){
1570 q1reg=t1;
1571 load_reg(f,q1reg,&p->q1,t);
1572 }
1573 if(SHORT_DOUBLE&&ISFLOAT(t)) t=FLOAT;
1574 emit(f,"\tst%s%s\t%s,--(%s)\n",sdt(t),cc,regnames[q1reg],regnames[sp]);
1575 push(zm2l(p->q2.val.vmax));
1576 continue;
1577 }
1578 if(c==ASSIGN){
1579 if(isreg(q1)){
1580 if(isreg(z))
1581 emit(f,"\tmov%s\t%s,%s\n",cc,regnames[zreg],regnames[p->q1.reg]);
1582 else
1583 zreg=p->q1.reg;
1584 }else
1585 load_reg(f,zreg,&p->q1,t);
1586 save_result(f,p);
1587 }
1588 continue;
1589 }
1590 if(c==MINUS){
1591 load_reg(f,zreg,&p->q1,t);
1592 emit(f,"\tneg%s\t%s,%s\n",cc,regnames[zreg],regnames[zreg]);
1593 save_result(f,p);
1594 continue;
1595 }
1596 if(c==TEST){
1597 emit(f,"\tcmp%s\t",cc);
1598 emit_obj(f,&p->q1,t);
1599 emit(f,",0\n");
1600 lastcomp=t;
1601 continue;
1602 }
1603 if(c==COMPARE){
1604 if(ISFLOAT(t))
1605 emit(f,"\tfcmp%s\t%s,",cc,regnames[t1]);
1606 else
1607 emit(f,"\tcmp%s\t",cc);
1608 emit_obj(f,&p->q1,t);
1609 emit(f,",");
1610 emit_obj(f,&p->q2,t);
1611 emit(f,"\n");
1612 lastcomp=t;
1613 continue;
1614 }
1615 if(c==MOD){
1616 /* TODO: is there a faster way? */
1617 int m;
1618 if(q2reg!=t2)
1619 m=t2;
1620 else
1621 m=get_reg(f,p);
1622 if(!isreg(q1)||p->q1.reg!=zreg)
1623 load_reg(f,zreg,&p->q1,t);
1624 emit(f,"\tdiv%c%s\t%s,%s,",(t&UNSIGNED)?'u':'s',cc,regnames[m],regnames[zreg]);
1625 emit_obj(f,&p->q2,t);
1626 emit(f,"\n");
1627 emit(f,"\tmul%s\t%s,",cc,regnames[m]);
1628 emit_obj(f,&p->q2,t);
1629 emit(f,"\n");
1630 emit(f,"\tsub%s\t%s,%s,%s\n",cc,regnames[zreg],regnames[zreg],regnames[m]);
1631 free_reg(f,m);
1632 save_result(f,p);
1633 continue;
1634 }
1635 if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<MOD)){
1636 if(c>=OR&&c<=AND)
1637 emit(f,"\t%s%s\t%s,",logicals[c-OR],cc,regnames[zreg]);
1638 else{
1639 if(ISFLOAT(t))
1640 emit(f,"\t%s%s\t%s,",farithmetics[c-LSHIFT],cc,regnames[zreg]);
1641 else
1642 emit(f,"\t%s%s\t%s,",(t&UNSIGNED)?uarithmetics[c-LSHIFT]:arithmetics[c-LSHIFT],cc,regnames[zreg]);
1643 }
1644 if(!isreg(q1)||p->q1.reg!=zreg||*cc||c==DIV||ISFLOAT(t)){
1645 emit_obj(f,&p->q1,t);
1646 emit(f,",");
1647 }
1648 emit_obj(f,&p->q2,t);
1649 emit(f,"\n");
1650 save_result(f,p);
1651 continue;
1652 }
1653 pric2(stdout,p);
1654 ierror(0);
1655 }
1656
1657 if(notpopped){
1658 emit(f,"\tadd\t%s,%ld\n",regnames[sp],notpopped);
1659 pop(notpopped);notpopped=0;
1660 }
1661
1662 function_bottom(f,v,localsize);
1663 if(stack_valid){
1664 if(!v->fi) v->fi=new_fi();
1665 v->fi->flags|=ALL_STACK;
1666 v->fi->stack1=stack;
1667 }
1668 /*emit(f,"# stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");*/
1669}
1670
1671int shortcut(int code,int typ)
1672{
1673 return 0;
1674}
1675
1676int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
1677{
1678 int f;
1679
1680 if(vararg)
1681 return 0;
1682
1683 f=t->flags&NQ;
1684 if(ISINT(f)||ISFLOAT(f)||f==POINTER){
1685 if(zmeqto(sizetab[f],l2zm(8L))){
1686 if(m->gregs<=r4){
1687 m->gregs=(m->gregs+1)&0xfe;
1688 m->gregs+=2;
1689 if(m->gregs==r1)
1690 return r0r1;
1691 else if(m->gregs==r3)
1692 return r2r3;
1693 else if(m->gregs==r5)
1694 return r4r5;
1695 else
1696 ierror(0);
1697 }else
1698 return 0;
1699 }else{
1700 if(m->gregs<=r4)
1701 return ++m->gregs;
1702 else
1703 return 0;
1704 }
1705 }
1706 return 0;
1707}
1708
1709int handle_pragma(const char *s)
1710{
1711}
1712void cleanup_cg(FILE *f)
1713{
1714}
1715void cleanup_db(FILE *f)
1716{
1717 if(f) section=-1;
1718}
1719
1720char *use_libcall(int c,int t,int t2)
1721/* Return name of library function, if this node should be
1722 implemented via libcall. */
1723{
1724 static char fname[16];
1725 char *ret = NULL;
1726
1727 if(c==COMPARE){
1728 if((t&NQ)==DOUBLE) t=(SHORT_DOUBLE)?FLOAT:LDOUBLE;
1729 if((t&NQ)==LLONG||t==LDOUBLE){
1730 sprintf(fname,"__cmp%s%s%ld",(t&UNSIGNED)?"u":"s",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8);
1731 ret=fname;
1732 }
1733 }else{
1734 t&=NU;
1735 t2&=NU;
1736 if(SHORT_DOUBLE){
1737 if(ISFLOAT(t)) t=FLOAT;
1738 if(ISFLOAT(t2)) t2=FLOAT;
1739 }else{
1740 if(t==DOUBLE) t=LDOUBLE;
1741 if(t2==DOUBLE) t2=LDOUBLE;
1742 }
1743 if(c==CONVERT){
1744 if(t==t2) return 0;
1745 if(t==FLOAT&&t2==LDOUBLE) return "__flt64toflt32";
1746 if(t==LDOUBLE&&t2==FLOAT) return "__flt32toflt64";
1747 if(t!=LDOUBLE&&t2!=LDOUBLE&&(t&NQ)!=LLONG&&(t2&NQ)!=LLONG) return 0;
1748 if(ISFLOAT(t)){
1749 sprintf(fname,"__%cint%ldtoflt%d",(t2&UNSIGNED)?'u':'s',zm2l(sizetab[t2&NQ])*8,(t==FLOAT)?32:64);
1750 ret=fname;
1751 }
1752 if(ISFLOAT(t2)&&(t&NU)==LLONG){
1753 sprintf(fname,"__flt%dto%cint%ld",((t2&NU)==FLOAT)?32:64,(t&UNSIGNED)?'u':'s',zm2l(sizetab[t&NQ])*8);
1754 ret=fname;
1755 }
1756 }
1757 if((t&NQ)==LLONG||t==DOUBLE){
1758 if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==KOMPLEMENT||c==MINUS){
1759 if(t==(UNSIGNED|LLONG)&&(c==DIV||c==MOD||c==RSHIFT)){
1760 sprintf(fname,"__%suint64",ename[c]);
1761 ret=fname;
1762 }else if((t&NQ)==LLONG){
1763 sprintf(fname,"__%sint64",ename[c]);
1764 ret=fname;
1765 }else{
1766 sprintf(fname,"__%s%s%s%ld",ename[c],(t&UNSIGNED)?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8);
1767 ret=fname;
1768 }
1769 }
1770 }
1771 }
1772
1773 return ret;
1774}