blob: 675df3ff5f5f84aacd0cd8dc261e17d22850fda7 [file] [log] [blame]
PulkoMandy17fc7592022-07-28 18:27:54 +02001/* Example backend for vbcc, it models a generic 32bit RISC or CISC
2CPU.
3
4Configurable at build-time are:
5- number of (32bit) general-purpose-registers
6- number of (64bit) floating-point-registers
7- number of (8bit) condition-code-registers
8- mechanism for stack-arguments (moving ot fixed sp)
9
10It allows to select as run-time-options:
11- two- or three-address code
12- memory operands or load-store-architecture
13- number of register-arguments
14- number of caller-save-registers
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 Messiahtron code-generator "__DATE__" (c) in 2008 by Andrew Price";
25
26/* Commandline-flags the code-generator accepts:
270: just a flag
28VALFLAG: a value must be specified
29STRINGFLAG: a string can be specified
30FUNCFLAG: a function will be called
31apart from FUNCFLAG, all other versions can only be specified once */
32int g_flags[MAXGF]={0,0,
33VALFLAG,VALFLAG,VALFLAG,
340,0,
35VALFLAG,VALFLAG,0};
36
37/* the flag-name, do not use names beginning with l, L, I, D or U, because
38they collide with the frontend */
39char *g_flags_name[MAXGF]={"three-addr","load-store",
40"volatile-gprs","volatile-fprs","volatile-ccrs",
41"imm-ind","gpr-ind",
42"gpr-args","fpr-args","use-commons"};
43
44/* the results of parsing the command-line-flags will be stored here */
45union ppi g_flags_val[MAXGF];
46
47/* Alignment-requirements for all types in bytes. */
48zmax align[MAX_TYPE+1];
49
50/* Alignment that is sufficient for every object. */
51zmax maxalign;
52
53/* CHAR_BIT for the target machine. */
54zmax char_bit;
55
56/* sizes of the basic types (in bytes) */
57zmax sizetab[MAX_TYPE+1];
58
59/* Minimum and Maximum values each type can have. */
60/* Must be initialized in init_cg(). */
61zmax t_min[MAX_TYPE+1];
62zumax t_max[MAX_TYPE+1];
63zumax tu_max[MAX_TYPE+1];
64
65/* Names of all registers. will be initialized in init_cg(),
66register number 0 is invalid, valid registers start at 1 */
67char *regnames[MAXR+1];
68
69/* The Size of each register in bytes. */
70zmax regsize[MAXR+1];
71
72/* a type which can store each register. */
73struct Typ *regtype[MAXR+1];
74
75/* regsa[reg]!=0 if a certain register is allocated and should */
76/* not be used by the compiler pass. */
77int regsa[MAXR+1];
78
79/* Specifies which registers may be scratched by functions. */
80int regscratch[MAXR+1];
81
82/* specifies the priority for the register-allocator, if the same
83estimated cost-saving can be obtained by several registers, the
84one with the highest priority will be used */
85int reg_prio[MAXR+1];
86
87/* an empty reg-handle representing initial state */
88struct reg_handle empty_reg_handle={0,0};
89
90/* Names of target-specific variable attributes. */
91char *g_attr_name[]={"__interrupt",0};
92
93
94/****************************************/
95/* Private data and functions. */
96/****************************************/
97
98#define THREE_ADDR (g_flags[0]&USEDFLAG)
99#define LOAD_STORE (g_flags[1]&USEDFLAG)
100//#define VOL_FIXED NUM_FIXED
101#define VOL_16BIT ((g_flags[3]&USEDFLAG)?g_flags_val[3].l:NUM_16BIT/2)
102#define VOL_32BIT ((g_flags[4]&USEDFLAG)?g_flags_val[4].l:NUM_32BIT/2)
103#define VOL_64BIT ((g_flags[4]&USEDFLAG)?g_flags_val[5].l:NUM_64BIT/2)
104#define VOL_8BIT ((g_flags[4]&USEDFLAG)?g_flags_val[6].l:NUM_8BIT/2)
105#define IMM_IND ((g_flags[5]&USEDFLAG)?1:0)
106#define GPR_IND ((g_flags[6]&USEDFLAG)?2:0)
107//#define ARGS8 ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:1)
108//#define ARGS16 ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:0)
109//#define ARGS32 ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:0)
110//#define ARGS64 ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:0)
111// #define FPR_ARGS ((g_flags[8]&USEDFLAG)?g_flags_val[8].l:0)
112//#define USE_COMMONS (g_flags[9]&USEDFLAG)
113
114
115/* alignment of basic data-types, used to initialize align[] */
116static long malign[MAX_TYPE+1]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
117/* sizes of basic data-types, used to initialize sizetab[] */
118static long msizetab[MAX_TYPE+1]={0,1,2,4,4,8,4,8,8,0,4,0,0,0,4,0};
119
120/* used to initialize regtyp[] */
121static struct Typ llong={LLONG},ltyp={LONG},lshort={SHORT},lchar={CHAR};
122
123/* macros defined by the backend */
124static char *marray[]={"__section(x)=__vattr(\"section(\"#x\")\")",
125"__GENERIC__",
1260};
127
128/* special registers */
129static int sp; /* Stackpointer */
130static int t8bit1,t8bit2; /* temporary gprs */
131static int t16bit1,t16bit2;
132static int t32bit1,t32bit2;
133static int t64bit1,t64bit2;
134
135#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])
136static char *sdt[MAX_TYPE+1]={"??","c","s","i","l","ll","f","d","ld","v","p"};
137static char *udt[MAX_TYPE+1]={"??","uc","us","ui","ul","ull","f","d","ld","v","p"};
138
139/* sections */
140#define DATA 0
141#define BSS 1
142#define CODE 2
143#define RODATA 3
144#define SPECIAL 4
145
146static long stack;
147static int stack_valid;
148static int section=-1,newobj;
149static char *codename=".resetlocals\n;code\n",
150*dataname=";data\n",
151*bssname=";bss\n",
152*rodataname=";read only data\n";
153
154/* return-instruction */
155static char *ret;
156
157/* label at the end of the function (if any) */
158static int exit_label;
159
160/* assembly-prefixes for labels and external identifiers */
161static char *labprefix="l",*idprefix="_";
162
163/* variables to keep track of the current stack-offset in the case of
164a moving stack-pointer */
165static long loff,stackoffset,notpopped,dontpop,maxpushed,stack;
166static pushorder=2;
167
168static long localsize,rsavesize,argsize;
169
170/* pushed on the stack by a callee, no pop needed */
171static void callee_push(long l)
172{
173}
174
175static void push(long l)
176{
177 stackoffset-=l;
178 if(stackoffset<maxpushed)
179 maxpushed=stackoffset;
180}
181static void pop(long l)
182{
183 stackoffset+=l;
184}
185
186static void emit_obj(FILE *f,struct obj *p,int t);
187
188/* calculate the actual current offset of an object relativ to the
189stack-pointer; we use a layout like this:
190------------------------------------------------
191| arguments to this function |
192------------------------------------------------
193| return-address [size=4] |
194------------------------------------------------
195| caller-save registers [size=rsavesize] |
196------------------------------------------------
197| local variables [size=localsize] |
198------------------------------------------------
199| arguments to called functions [size=argsize] |
200------------------------------------------------
201All sizes will be aligned as necessary.
202In the case of FIXED_SP, the stack-pointer will be adjusted at
203function-entry to leave enough space for the arguments and have it
204aligned to 16 bytes. Therefore, when calling a function, the
205stack-pointer is always aligned to 16 bytes.
206For a moving stack-pointer, the stack-pointer will usually point
207to the bottom of the area for local variables, but will move while
208arguments are put on the stack.
209
210This is just an example layout. Other layouts are also possible.
211*/
212
213static long real_offset(struct obj *o)
214{
215 long off=zm2l(o->v->offset);
216 if(off<0){
217 /* function parameter */
218 off=localsize+rsavesize+4-off-zm2l(maxalign);
219 }
220
221 off+=4;
222
223 off+=stackoffset;
224 off+=zm2l(o->val.vmax);
225 return off;
226}
227
228/* Initializes an addressing-mode structure and returns a pointer to
229that object. Will not survive a second call! */
230static struct obj *cam(int flags,int base,long offset)
231{
232 static struct obj obj;
233 static struct AddressingMode am;
234 obj.am=&am;
235 am.flags=flags;
236 am.base=base;
237 am.offset=offset;
238 return &obj;
239}
240
241/* changes to a special section, used for __section() */
242static int special_section(FILE *f,struct Var *v)
243{
244 char *sec;
245 if(!v->vattr) return 0;
246 sec=strstr(v->vattr,"section(");
247 if(!sec) return 0;
248 sec+=strlen("section(");
249 emit(f,"; section");
250 while(*sec&&*sec!=')') emit_char(f,*sec++);
251 emit(f,"\n");
252 if(f) section=SPECIAL;
253 return 1;
254}
255
256/* generate code to load the address of a variable into register r */
257static void load_address(FILE *f,int r,struct obj *o,int type)
258/* Generates code to load the address of a variable into register r. */
259{
260 if(!(o->flags&VAR))
261 ierror(0);
262 if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)
263 {
264 long off=real_offset(o);
265 emit(f,"\tmov\t%s %s ; load_address %s\n",regnames[r],regnames[sp],dt(POINTER));
266 if(off)
267 {
268 emit(f,"\tmov\tb30 %ld ; %s\n",off,dt(POINTER));
269 emit(f,"\tsub\t%s b30 ; %s\n",regnames[r],dt(POINTER));
270 }
271 }
272 else
273 {
274 emit(f,"\tmov\t%s ",regnames[r]);
275 emit_obj(f,o,type);
276 emit(f," ;%s\n", dt(POINTER));
277 }
278}
279/* Generates code to load a memory object into register r. tmp is a
280general purpose register which may be used. tmp can be r. */
281static void load_reg(FILE *f,int r,struct obj *o,int type)
282{
283 type&=NU;
284 if(o->flags&VARADR)
285 {
286 load_address(f,r,o,POINTER);
287 }
288 else
289 {
290 if((o->flags&(REG|DREFOBJ))==REG&&o->reg==r)
291 return;
292 if((o->flags&VAR)&&!(o->flags&REG))
293 {
294 if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)
295 {
296 unsigned long offset = real_offset(o);
297 if(offset == 0)
298 {
299 emit(f,"\tmov\t%s\t[z2] ;%s\n",regnames[r],dt(type));
300 }
301 else
302 {
303 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
304 emit(f,"\tmov\tb29\tz2\n");
305 emit(f,"\tsub\tb29\tb28\n");
306 if(ISFLOAT(type))
307 emit(f,"\tmovf\t%s\t[b29] ;%s\n",regnames[r],dt(type));
308 else if((type & UNSIGNED) || type == POINTER || type == STRUCT)
309 emit(f,"\tmov\t%s\t[b29] ;%s\n",regnames[r],dt(type));
310 else
311 emit(f,"\tmovs\t%s\t[b29] ;%s\n",regnames[r],dt(type));
312 }
313
314 return;
315 }
316 }
317
318 if(ISFLOAT(type))
319 emit(f,"\tmovf \t%s ",regnames[r]);
320 else if((type & UNSIGNED) || type == POINTER || type == STRUCT)
321 emit(f,"\tmov \t%s ",regnames[r]);
322 else
323 emit(f,"\tmovs \t%s ",regnames[r]);
324 emit_obj(f,o,type);
325 emit(f," ;%s\n",dt(type));
326 }
327}
328
329/* Generates code to store register r into memory object o. */
330static void store_reg(FILE *f,int r,struct obj *o,int type)
331{
332 type&=NQ;
333
334 if((o->flags&VAR)&&!(o->flags&REG))
335 {
336
337 if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)
338 {
339 unsigned long offset = real_offset(o);
340
341 if(offset == 0)
342 {
343 if(ISFLOAT(type))
344 emit(f,"\tmovf\t[z2]\t%s ;%s\n",regnames[r],dt(type));
345 else if((type & UNSIGNED) || type == POINTER || type == STRUCT)
346 emit(f,"\tmov\t[z2]\t%s ;%s\n",regnames[r],dt(type));
347 else
348 emit(f,"\tmovs\t[z2]\t%s ;%s\n",regnames[r],dt(type));
349 }
350 else
351 {
352 emit(f,"\tmov\tb28\t%ld ; mov to stack\n", offset);
353 emit(f,"\tmov\tb29\tz2\n");
354 emit(f,"\tsub\tb29\tb28\n");
355 if(ISFLOAT(type))
356 emit(f,"\tmovf\t[b29]\t%s ;%s\n",regnames[r],dt(type));
357 else if((type & UNSIGNED) || type == POINTER || type == STRUCT)
358 emit(f,"\tmov\t[b29]\t%s ;%s\n",regnames[r],dt(type));
359 else
360 emit(f,"\tmovs\t[b29]\t%s ;%s\n",regnames[r],dt(type));
361 }
362 return;
363 }
364 }
365 if(r == 0)
366 emit(f, ";");
367
368 if(ISFLOAT(type))
369 emit(f,"\tmovf\t");
370 else if(type & UNSIGNED)
371 emit(f,"\tmov\t");
372 else
373 emit(f,"\tmovs\t");
374
375 emit_obj(f,o,type);
376 emit(f,"\t%s ;%s\n",regnames[r],dt(type));
377}
378
379/* Yields log2(x)+1 or 0. */
380static long pof2(zumax x)
381{
382 zumax p;int ln=1;
383 p=ul2zum(1L);
384 while(ln<=32&&zumleq(p,x)){
385 if(zumeqto(x,p)) return ln;
386 ln++;p=zumadd(p,p);
387 }
388 return 0;
389}
390
391static struct IC *preload(FILE *,struct IC *);
392
393static void function_top(FILE *,struct Var *,long);
394static void function_bottom(FILE *f,struct Var *,long);
395
396#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
397#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
398
399static int q1reg,q2reg,zreg;
400
401/* Does some pre-processing like fetching operands from memory to
402registers etc. */
403static struct IC *preload(FILE *f,struct IC *p)
404{
405 int r;
406
407 if(isreg(q1))
408 q1reg=p->q1.reg;
409 else
410 q1reg=0;
411
412 if(isreg(q2))
413 q2reg=p->q2.reg;
414 else
415 q2reg=0;
416
417// emit(f," ; Preload register type %d\t%d z:%d\t%d\t ", q1typ(p), q1typ(p) & NQ, ztyp(p), ztyp(p) & NQ);
418
419 if(isreg(z))
420 {
421 zreg=p->z.reg;
422// emit(f," is a reg ");
423 }
424 else
425 {
426 if((ztyp(p) & NQ) == CHAR)
427 {
428// emit(f," is a 8 bit reg (1) ");
429 zreg=t8bit1;
430 }
431 else if((ztyp(p) & NQ) == SHORT)
432 {
433// emit(f," is a 16 bit reg (1) ");
434 zreg=t16bit1;
435 }
436 else if((ztyp(p) & NQ) == LDOUBLE || (ztyp(p) & NQ) == LLONG || (ztyp(p) & NQ) == DOUBLE)
437 {
438// emit(f," is a 64 bit reg (1) ");
439 zreg=t64bit1;
440 }
441 else
442 {
443// emit(f," is a 32 bit reg (1) ");
444 zreg=t32bit1;
445 }
446 }
447
448 if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q1.am){
449 p->q1.flags&=~DREFOBJ;
450 if((q1typ(p) & NQ) == CHAR)
451 {
452 load_reg(f,t8bit1,&p->q1,q1typ(p));
453 p->q1.reg=t8bit1;
454// emit(f," is a 8 bit reg (2) ");
455 }
456 else if((q1typ(p) & NQ) == SHORT)
457 {
458 load_reg(f,t16bit1,&p->q1,q1typ(p));
459 p->q1.reg=t16bit1;
460// emit(f," is a 16 bit reg (2) ");
461 }
462 else if((q1typ(p) & NQ) == LDOUBLE || (q1typ(p) & NQ) == LLONG || (q1typ(p) & NQ) == DOUBLE)
463 {
464 load_reg(f,t64bit1,&p->q1,q1typ(p));
465 p->q1.reg=t64bit1;
466// emit(f," is a 64 bit reg (2) ");
467 }
468 else
469 {
470 load_reg(f,t32bit1,&p->q1,q1typ(p));
471 p->q1.reg=t32bit1;
472// emit(f," is a 32 bit reg (2) ");
473 }
474 p->q1.flags|=(REG|DREFOBJ);
475 }
476 if(p->q1.flags&&LOAD_STORE&&!isreg(q1)){
477 if((q1typ(p) & NQ) == CHAR)
478 {
479 q1reg=t8bit1;
480// emit(f," is a 8 bit reg (3) ");
481 }
482 else if((q1typ(p) & NQ) == SHORT)
483 {
484 q1reg=t16bit1;
485// emit(f," is a 16 bit reg (3) ");
486 }
487 else if((q1typ(p) & NQ) == LDOUBLE || (q1typ(p) & NQ) == LLONG || (q1typ(p) & NQ) == DOUBLE)
488 {
489 q1reg=t64bit1;
490// emit(f," is a 64 bit reg (3) ");
491 }
492 else
493 {
494 q1reg=t32bit1;
495// emit(f," is a 32 bit reg (3) ");
496 }
497 load_reg(f,q1reg,&p->q1,q1typ(p));
498 p->q1.reg=q1reg;
499 p->q1.flags=REG;
500 }
501
502 if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q2.am){
503 p->q2.flags&=~DREFOBJ;
504 if((q1typ(p) & NQ) == CHAR)
505 {
506 load_reg(f,t8bit1,&p->q2,q2typ(p));
507 p->q2.reg=t8bit1;
508// emit(f," is a 8 bit reg (4) ");
509 }
510 else if((q1typ(p) & NQ) == SHORT)
511 {
512 load_reg(f,t16bit1,&p->q2,q2typ(p));
513 p->q2.reg=t16bit1;
514// emit(f," is a 16 bit reg (4) ");
515 }
516 else if((q1typ(p) & NQ) == LDOUBLE || (q1typ(p) & NQ) == LLONG || (q1typ(p) & NQ) == DOUBLE)
517 {
518 load_reg(f,t64bit1,&p->q2,q2typ(p));
519 p->q2.reg=t64bit1;
520// emit(f," is a 64 bit reg (4) ");
521 }
522 else
523 {
524 load_reg(f,t32bit1,&p->q2,q2typ(p));
525 p->q2.reg=t32bit1;
526// emit(f," is a 32 bit reg (4) ");
527 }
528
529 p->q2.flags|=(REG|DREFOBJ);
530 }
531 if(p->q2.flags&&LOAD_STORE&&!isreg(q2)){
532 if((q1typ(p) & NQ) == CHAR)
533 {
534 q2reg=t8bit1;
535// emit(f," is a 8 bit reg (5) ");
536 }
537 else if((q1typ(p) & NQ) == SHORT)
538 {
539 q2reg=t16bit1;
540// emit(f," is a 16 bit reg (5) ");
541 }
542 else if((q1typ(p) & NQ) == LDOUBLE || (q1typ(p) & NQ) == LLONG || (q1typ(p) & NQ) == DOUBLE)
543 {
544 q2reg=t64bit1;
545// emit(f," is a 64 bit reg (5) ");
546 }
547 else
548 {
549 q2reg=t32bit1;
550// emit(f," is a 32 bit reg (5) ");
551 }
552
553 load_reg(f,q2reg,&p->q2,q2typ(p));
554 p->q2.reg=q2reg;
555 p->q2.flags=REG;
556 }
557
558// emit(f,"\n");
559 return p;
560}
561
562/* save the result (in zreg) into p->z */
563void save_result(FILE *f,struct IC *p)
564{
565 if((p->z.flags&(REG|DREFOBJ))==DREFOBJ&&!p->z.am){
566 p->z.flags&=~DREFOBJ;
567 if((p->typf & NQ) == CHAR)
568 {
569 load_reg(f,t8bit2,&p->z,POINTER);
570 p->z.reg=t8bit2;
571 }
572 else if((p->typf & NQ) == SHORT)
573 {
574 load_reg(f,t16bit2,&p->z,POINTER);
575 p->z.reg=t16bit2;
576 }
577 else if((p->typf & NQ) == LDOUBLE || (p->typf & NQ) == LLONG || (p->typf & NQ) == DOUBLE)
578 {
579 load_reg(f,t64bit2,&p->z,POINTER);
580 p->z.reg=t64bit2;
581 }
582 else
583 {
584 load_reg(f,t32bit2,&p->z,POINTER);
585 p->z.reg=t32bit2;
586 }
587 p->z.flags|=(REG|DREFOBJ);
588 //printf("setting reg to %s\n", regnames[p->z.reg]);
589 }
590
591 if(isreg(z)){
592 if(p->z.reg!=zreg)
593 emit(f,"\tmov\t%s %s ;%s\n",regnames[p->z.reg],regnames[zreg],dt(ztyp(p)));
594 }else{
595 store_reg(f,zreg,&p->z,ztyp(p));
596 }
597}
598
599/* prints an object */
600static void emit_obj(FILE *f,struct obj *p,int t)
601{
602 //printf("type = %i\n", t);
603 if((p->flags&(DREFOBJ|KONST))==(DREFOBJ|KONST))
604 {
605 emitval(f,&p->val,p->dtyp&NU);
606 return;
607 }
608 if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG))
609 emit(f,"[");
610
611 if((p->flags&VAR)&&!(p->flags&REG))
612 {
613 if(!zmeqto(l2zm(0L),p->val.vmax))
614 {
615 emitval(f,&p->val,LONG);
616 emit(f,"+");
617 }
618 if(p->v->storage_class==STATIC)
619 {
620 emit(f,"%s%ld", labprefix, zm2l(p->v->offset));
621 }
622 else
623 {
624 if(t == FUNKT)
625 emit(f,"%s%s", idprefix, p->v->identifier);
626 else if(p->flags&VARADR)
627 emit(f,"%s%s", idprefix, p->v->identifier);
628 else
629 emit(f,"[%s%s]", idprefix, p->v->identifier);
630 }
631 }
632 if(p->flags&REG)
633 {
634 emit(f, "%s", regnames[p->reg]);
635 }
636 if(p->flags&KONST)
637 {
638 if(ISFLOAT(t))
639 {
640 // case FLOAT:
641 char *values = (char *)&p->val.vfloat;
642 // swap the order
643 char tmp = values[0];
644 values[0] = values[3];
645 values[3] = tmp;
646 tmp = values[1];
647 values[1] = values[2];
648 values[2] = tmp;
649
650 emit(f, "0x%1X", *(unsigned int *)values);
651 // break;
652
653 // case DOUBLE:
654 // fprintf(fp, "[double #%08X]", obj->val.vdouble);
655 // emit(f,"0f%e",/*labprefix,*/p->val.vfloat);
656 // emit(f,"0f");
657 // emitval(f,&p->val,t&NU);
658 }
659 else if(t & UNSIGNED)
660 {
661 // emit(f, "0u");
662 emitval(f,&p->val,t&NU);
663 }
664 else
665 {
666 emit(f,"0s");
667 emitval(f,&p->val,t&NU);
668 }
669 }
670 if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG))
671 emit(f,"]");
672}
673
674/* Test if there is a sequence of FREEREGs containing FREEREG reg.
675Used by peephole. */
676static int exists_freereg(struct IC *p,int reg)
677{
678 while(p&&(p->code==FREEREG||p->code==ALLOCREG))
679 {
680 if(p->code==FREEREG&&p->q1.reg==reg)
681 return 1;
682 p=p->next;
683 }
684 return 0;
685}
686
687/* search for possible addressing-modes */
688static void peephole(struct IC *p)
689{
690 int c,c2,r;
691 struct IC *p2;
692 struct AddressingMode *am;
693
694 for(;p;p=p->next)
695 {
696 c=p->code;
697 if(c != FREEREG && c != ALLOCREG && (c != SETRETURN || !isreg(q1) || p->q1.reg != p->z.reg))
698 exit_label=0;
699 if(c==LABEL)
700 exit_label=p->typf;
701
702 /* Try const(reg) */
703 if(IMM_IND&&(c==ADDI2P||c==SUBIFP)&&isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST)
704 {
705 int base;zmax of;struct obj *o;
706 eval_const(&p->q2.val,p->typf);
707 if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
708 if(1/*zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))*/)
709 {
710 r=p->z.reg;
711 if(isreg(q1))
712 base=p->q1.reg;
713 else
714 base=r;
715 o=0;
716 for(p2=p->next;p2;p2=p2->next)
717 {
718 c2=p2->code;
719 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA))
720 break;
721 if(c2!=FREEREG&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r)
722 break;
723 if(c2!=FREEREG&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==r)
724 break;
725 if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/)
726 {
727 if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r)
728 {
729 if(o) break;
730 o=&p2->q1;
731 }
732 if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r)
733 {
734 if(o) break;
735 o=&p2->q2;
736 }
737 if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r)
738 {
739 if(o) break;
740 o=&p2->z;
741 }
742 }
743 if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG)
744 {
745 int m;
746 if(c2==FREEREG)
747 m=p2->q1.reg;
748 else
749 m=p2->z.reg;
750 if(m==r)
751 {
752 if(o)
753 {
754 o->am=am=mymalloc(sizeof(*am));
755 am->flags=IMM_IND;
756 am->base=base;
757 am->offset=zm2l(of);
758 if(isreg(q1))
759 {
760 p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
761 }
762 else
763 {
764 p->code=c=ASSIGN;p->q2.flags=0;
765 p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ];
766 }
767 }
768 break;
769 }
770 if(c2!=FREEREG&&m==base)
771 break;
772 continue;
773 }
774 }
775 }
776 }
777 /* Try reg,reg */
778 if(GPR_IND&&c==ADDI2P&&isreg(q2)&&isreg(z)&&(isreg(q1)||p->q2.reg!=p->z.reg))
779 {
780 int base,idx;struct obj *o;
781 r=p->z.reg;idx=p->q2.reg;
782 if(isreg(q1)) base=p->q1.reg; else base=r;
783 o=0;
784 for(p2=p->next;p2;p2=p2->next)
785 {
786 c2=p2->code;
787 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA))
788 break;
789 if(c2!=FREEREG&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r)
790 break;
791 if(c2!=FREEREG&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==r)
792 break;
793 if((p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==idx&&idx!=r)
794 break;
795
796 if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/)
797 {
798 if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r)
799 {
800 if(o||(q1typ(p2)&NQ)==LLONG) break;
801 o=&p2->q1;
802 }
803 if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r)
804 {
805 if(o||(q2typ(p2)&NQ)==LLONG) break;
806 o=&p2->q2;
807 }
808 if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r)
809 {
810 if(o||(ztyp(p2)&NQ)==LLONG) break;
811 o=&p2->z;
812 }
813 }
814 if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG)
815 {
816 int m;
817 if(c2==FREEREG)
818 m=p2->q1.reg;
819 else
820 m=p2->z.reg;
821 if(m==r)
822 {
823 if(o)
824 {
825 o->am=am=mymalloc(sizeof(*am));
826 am->flags=GPR_IND;
827 am->base=base;
828 am->offset=idx;
829 if(isreg(q1))
830 {
831 p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
832 }
833 else
834 {
835 p->code=c=ASSIGN;p->q2.flags=0;
836 p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ];
837 }
838 }
839 break;
840 }
841 if(c2!=FREEREG&&m==base) break;
842 continue;
843 }
844 }
845 }
846 }
847}
848
849static void pr(FILE *f,struct IC *p)
850{
851 int i;
852 for(;pushorder>2;pushorder>>=1)
853 {
854 for(i=1;i<=8;i++)
855 {
856 if(regs[i]&pushorder)
857 {
858 if(p->code==PUSH||p->code==CALL)
859 {
860 //emit(f,"\tmovl\t%ld(%s),%s\n",loff-4-stackoffset,regnames[sp],regnames[i]);
861 }
862 else
863 {
864 emit(f,"\tpop\t%s\n",regnames[i]);
865 pop(4);
866 }
867 regs[i]&=~pushorder;
868 }
869 }
870 }
871 for(i=1;i<=8;i++)
872 if(regs[i]&2) regs[i]&=~2;
873}
874
875/* generates the function entry code */
876static void function_top(FILE *f,struct Var *v,long offset)
877{
878 rsavesize=0;
879 if(!special_section(f,v)&&section!=CODE){emit(f,codename);if(f) section=CODE;}
880 if(v->storage_class==EXTERN)
881 {
882 if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC)
883 emit(f,".global ");
884 // emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
885 emit(f,"%s%s:\n",idprefix,v->identifier);
886 }
887 else
888 emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
889
890 // reserve enough in stack for local functions
891 if(offset > 0)
892 {
893 emit(f,"\tmov\tb28\t%d\n", offset);
894 emit(f,"\tadd\tz2\tb28 ;reserve %d on stack\n", offset);
895 }
896}
897/* generates the function exit code */
898static void function_bottom(FILE *f,struct Var *v,long offset)
899{
900 // reserve enough in stack for local functions
901 if(offset > 0)
902 {
903 emit(f,"\tmov\tb28\t%d\n", offset);
904 emit(f,"\tsub\tz2\tb28 ;reserve %d on stack\n", offset);
905 }
906
907 emit(f,ret);
908}
909
910/****************************************/
911/* End of private data and functions. */
912/****************************************/
913
914/* Does necessary initializations for the code-generator. Gets called */
915/* once at the beginning and should return 0 in case of problems. */
916int init_cg(void)
917{
918 int i;
919 /* Initialize some values which cannot be statically initialized */
920 /* because they are stored in the target's arithmetic. */
921 maxalign=l2zm(1L);
922 char_bit=l2zm(8L);
923
924 for(i=0;i<=MAX_TYPE;i++)
925 {
926 sizetab[i]=l2zm(msizetab[i]);
927 align[i]=l2zm(malign[i]);
928 }
929
930 regnames[0]="noreg";
931 regtype[0]=mymalloc(sizeof(struct Typ));
932 // for(i=FIRST_FIXED;i<=LAST_FIXED;i++)
933 // {
934 // regnames[i]=mymalloc(10);
935 // sprintf(regnames[i],"b%d",(i-FIRST_FIXED) + 27);
936 // regsize[i]=4;
937 // regtype[i]=&ltyp;
938 // }
939
940 // static struct Typ lltype={LLONG},ltyp={LONG},lshort={SHORT},lchar={CHAR};
941
942 for(i=FIRST_16BIT;i<=LAST_16BIT;i++)
943 {
944 regnames[i]=mymalloc(10);
945 sprintf(regnames[i],"a%d",i-FIRST_16BIT);
946 regsize[i]=2;
947 regtype[i]=mymalloc(sizeof(struct Typ));
948 }
949
950 for(i=FIRST_32BIT;i<=LAST_32BIT;i++)
951 {
952 regnames[i]=mymalloc(10);
953 sprintf(regnames[i],"b%d",(i-FIRST_32BIT) + 5);
954 regsize[i]=4;
955 regtype[i]=mymalloc(sizeof(struct Typ));
956 }
957
958 for(i=FIRST_64BIT;i<=LAST_64BIT;i++)
959 {
960 regnames[i]=mymalloc(10);
961 sprintf(regnames[i],"c%d",(i-FIRST_64BIT) + 9);
962 regsize[i]=8;
963 regtype[i]=mymalloc(sizeof(struct Typ));
964 }
965
966 for(i=FIRST_8BIT;i<=LAST_8BIT;i++)
967 {
968 regnames[i]=mymalloc(10);
969 sprintf(regnames[i],"h%d",(i-FIRST_8BIT));
970 regsize[i]=1;
971 //regtype[i]=&lchar;
972 regtype[i]=mymalloc(sizeof(struct Typ));
973 }
974
975 regnames[STACK_POINTER]=mymalloc(10);
976 sprintf(regnames[STACK_POINTER],"z2");
977 regsize[STACK_POINTER]=4;
978 regtype[STACK_POINTER]=&ltyp;
979 regtype[STACK_POINTER]=mymalloc(sizeof(struct Typ));
980
981 /* Use multiple ccs. */
982 multiple_ccs=0;
983
984 /* Initialize the min/max-settings. Note that the types of the */
985 /* host system may be different from the target system and you may */
986 /* only use the smallest maximum values ANSI guarantees if you */
987 /* want to be portable. */
988 /* That's the reason for the subtraction in t_min[INT]. Long could */
989 /* be unable to represent -2147483648 on the host system. */
990 t_min[CHAR]=l2zm(-128L);
991 t_min[SHORT]=l2zm(-32768L);
992 t_min[INT]=zmsub(l2zm(-2147483647L),l2zm(1L));
993 t_min[LONG]=t_min(INT);
994 t_min[LLONG]=zmlshift(l2zm(1L),l2zm(63L));
995 t_min[MAXINT]=t_min(LLONG);
996 t_max[CHAR]=ul2zum(127L);
997 t_max[SHORT]=ul2zum(32767UL);
998 t_max[INT]=ul2zum(2147483647UL);
999 t_max[LONG]=t_max(INT);
1000 t_max[LLONG]=zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL));
1001 t_max[MAXINT]=t_max(LLONG);
1002 tu_max[CHAR]=ul2zum(255UL);
1003 tu_max[SHORT]=ul2zum(65535UL);
1004 tu_max[INT]=ul2zum(4294967295UL);
1005 tu_max[LONG]=t_max(UNSIGNED|INT);
1006 tu_max[LLONG]=zumkompl(ul2zum(0UL));
1007 tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
1008
1009 for(i=FIRST_16BIT;i<=LAST_16BIT-VOL_16BIT;i++)
1010 regscratch[i]=1;
1011 for(i=FIRST_32BIT;i<=LAST_32BIT-VOL_32BIT;i++)
1012 regscratch[i]=1;
1013 for(i=FIRST_64BIT;i<=LAST_64BIT-VOL_64BIT;i++)
1014 regscratch[i]=1;
1015 for(i=FIRST_8BIT;i<=LAST_8BIT-VOL_8BIT;i++)
1016 regscratch[i]=1;
1017
1018 /* Reserve a few registers for use by the code-generator. */
1019 /* This is not optimal but simple. */
1020 sp=STACK_POINTER;
1021 t8bit1=FIRST_8BIT;
1022 t8bit2=FIRST_8BIT+1;
1023 t16bit1=FIRST_16BIT;
1024 t16bit2=FIRST_16BIT+1;
1025 t32bit1=FIRST_32BIT;
1026 t32bit2=FIRST_32BIT+1;
1027 t64bit1=FIRST_64BIT;
1028 t64bit2=FIRST_64BIT+1;
1029 regsa[t8bit1]=regsa[t8bit2]=1;
1030 regsa[t16bit1]=regsa[t16bit2]=1;
1031 regsa[t32bit1]=regsa[t32bit2]=1;
1032 regsa[t64bit1]=regsa[t64bit2]=1;
1033 regsa[sp]=1;
1034 regscratch[t8bit1]=regscratch[t8bit2]=0;
1035 regscratch[t16bit1]=regscratch[t16bit2]=0;
1036 regscratch[t32bit1]=regscratch[t32bit2]=0;
1037 regscratch[t64bit1]=regscratch[t64bit2]=0;
1038 regscratch[sp]=0;
1039
1040 // for(i=FIRST_FIXED;i<=LAST_FIXED-VOL_FIXED;i++)
1041 // regscratch[i]=1;
1042 target_macros=marray;
1043
1044 return 1;
1045}
1046
1047void init_db(FILE *f)
1048{
1049}
1050
1051int freturn(struct Typ *t)
1052/* Returns the register in which variables of type t are returned. */
1053/* If the value cannot be returned in a register returns 0. */
1054/* A pointer MUST be returned in a register. The code-generator */
1055/* has to simulate a pseudo register if necessary. */
1056{
1057 if(ISSTRUCT(t->flags)||ISUNION(t->flags))
1058 return 0;
1059 if(t->size == 1)
1060 return FIRST_8BIT+3;
1061 if(t->size == 2)
1062 return FIRST_16BIT+3;
1063 if(t->size == 4)
1064 return FIRST_32BIT+3;
1065 if(t->size == 8)
1066 return FIRST_64BIT+3;
1067
1068 return 0;
1069}
1070
1071int reg_pair(int r,struct rpair *p)
1072/* Returns 0 if the register is no register pair. If r */
1073/* is a register pair non-zero will be returned and the */
1074/* structure pointed to p will be filled with the two */
1075/* elements. */
1076{
1077 return 0;
1078}
1079
1080/* estimate the cost-saving if object o from IC p is placed in
1081register r */
1082int cost_savings(struct IC *p,int r,struct obj *o)
1083{
1084 int c=p->code;
1085 if(o->flags&VKONST)
1086 {
1087 if(!LOAD_STORE)
1088 return 0;
1089 if(o==&p->q1&&p->code==ASSIGN&&(p->z.flags&DREFOBJ))
1090 return 4;
1091 else
1092 return 2;
1093 }
1094 if(o->flags&DREFOBJ)
1095 return 4;
1096 if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ))
1097 return 3;
1098 if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ))
1099 return 3;
1100 return 2;
1101}
1102
1103int regok(int r,int t,int mode)
1104/* Returns 0 if register r cannot store variables of */
1105/* type t. If t==POINTER and mode!=0 then it returns */
1106/* non-zero only if the register can store a pointer */
1107/* and dereference a pointer to mode. */
1108{
1109 if(r==0)
1110 return 0;
1111 t&=NQ;
1112
1113 if(r>=FIRST_8BIT&&r<=LAST_8BIT)
1114 {
1115// printf("8 bit register: ");
1116 if(t == CHAR)
1117 {
1118// printf(" can fit\n");
1119 return 1;
1120 }
1121// else
1122// printf(" can't fit\n");
1123 }
1124 else if(r>=FIRST_16BIT&&r<=LAST_16BIT)
1125 {
1126// printf("16 bit register: ");
1127 if(t == SHORT)
1128 {
1129// printf(" can fit\n");
1130 return 1;
1131 }
1132// else
1133// printf(" can't fit\n");
1134 }
1135 else if(r>=FIRST_32BIT&&r<=LAST_32BIT)
1136 {
1137// printf("32 bit register: ");
1138 if(t == INT || t == LONG || t == FLOAT
1139 ||t == POINTER)
1140 {
1141// printf(" can fit\n");
1142 return 1;
1143 }
1144// etse
1145// printf(" can't fit\n");
1146 }
1147 else if(r>=FIRST_64BIT&&r<=LAST_64BIT)
1148 {
1149// printf("64 bit register: ");
1150 if(t == LDOUBLE || t == DOUBLE || t == LLONG)
1151 {
1152// printf(" can fit\n");
1153 return 1;
1154 }
1155// else
1156// printf(" can't fit\n");;
1157 }
1158
1159 return 0;
1160
1161
1162 /*#define CHAR 1
1163 #define SHORT 2
1164 #define INT 3
1165 #define LONG 4
1166 #define LLONG 5
1167 #define FLOAT 6
1168 #define DOUBLE 7
1169 #define LDOUBLE 8
1170 #define VOID 9
1171 #define POINTER 10
1172 #define ARRAY 11
1173 #define STRUCT 12
1174 #define UNION 13
1175 #define ENUM 14*/
1176}
1177
1178int dangerous_IC(struct IC *p)
1179/* Returns zero if the IC p can be safely executed */
1180/* without danger of exceptions or similar things. */
1181/* vbcc may generate code in which non-dangerous ICs */
1182/* are sometimes executed although control-flow may */
1183/* never reach them (mainly when moving computations */
1184/* out of loops). */
1185/* Typical ICs that generate exceptions on some */
1186/* machines are: */
1187/* - accesses via pointers */
1188/* - division/modulo */
1189/* - overflow on signed integer/floats */
1190{
1191 int c=p->code;
1192 if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
1193 return 1;
1194 if((c==DIV||c==MOD)&&!isconst(q2))
1195 return 1;
1196 return 0;
1197}
1198
1199int must_convert(int o,int t,int const_expr)
1200/* Returns zero if code for converting np to type t */
1201/* can be omitted. */
1202/* On the PowerPC cpu pointers and 32bit */
1203/* integers have the same representation and can use */
1204/* the same registers. */
1205{
1206 int op=o&NQ,tp=t&NQ;
1207
1208 if(op == LONG || op == POINTER)
1209 op = INT;
1210
1211 if(tp==LONG || tp ==POINTER)
1212 tp = INT;
1213
1214 if(op == tp) // same type
1215 if((o & NQ)== (t & NQ)) // same signess
1216 return 0; // no code needed
1217
1218 return 1;
1219}
1220
1221void gen_ds(FILE *f,zmax size,struct Typ *t)
1222/* This function has to create <size> bytes of storage */
1223/* initialized with zero. */
1224{
1225 if(newobj&&section!=SPECIAL)
1226 emit(f," data %ld\n",zm2l(size));
1227 else
1228 emit(f," data %ld\n",zm2l(size));
1229 newobj=0;
1230}
1231
1232void gen_align(FILE *f,zmax align)
1233/* This function has to make sure the next data is */
1234/* aligned to multiples of <align> bytes. */
1235{
1236 if(zm2l(align)>1)
1237 emit(f,"; NOT IMPLEMENTED - \t.align\t%d\n", align);
1238}
1239
1240void gen_var_head(FILE *f,struct Var *v)
1241/* This function has to create the head of a variable */
1242/* definition, i.e. the label and information for */
1243/* linkage etc. */
1244{
1245 int constflag;
1246 char *sec;
1247 if(v->clist) constflag=is_const(v->vtyp);
1248 if(v->storage_class==STATIC)
1249 {
1250 if(ISFUNC(v->vtyp->flags))
1251 return;
1252 if(!special_section(f,v))
1253 {
1254 if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
1255 if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
1256 if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
1257 }
1258 if(v->clist||section==SPECIAL)
1259 {
1260 gen_align(f,falign(v->vtyp));
1261 emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
1262 }
1263 else
1264 emit(f,"\t.lcomm\t%s%ld,",labprefix,zm2l(v->offset));
1265 newobj=1;
1266 }
1267 if(v->storage_class==EXTERN)
1268 {
1269 // emit(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
1270 if(v->flags&(DEFINED|TENTATIVE))
1271 {
1272 if(!special_section(f,v))
1273 {
1274 if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA)
1275 {
1276 emit(f,dataname);
1277 if(f)
1278 section=DATA;
1279 }
1280 if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA)
1281 {
1282 emit(f,rodataname);
1283 if(f)
1284 section=RODATA;
1285 }
1286 if(!v->clist&&section!=BSS)
1287 {
1288 emit(f,bssname);
1289 if(f)
1290 section=BSS;
1291 }
1292 }
1293 if(v->clist||section==SPECIAL)
1294 {
1295 gen_align(f,falign(v->vtyp));
1296 // emit(f,"%s%s:\n",idprefix,v->identifier);
1297 }
1298 else
1299 emit(f,".global %s%s:",/*(USE_COMMONS?"":"l"),*/idprefix,v->identifier);
1300 newobj=1;
1301 }
1302 }
1303}
1304
1305void gen_dc(FILE *f,int t,struct const_list *p)
1306/* This function has to create static storage */
1307/* initialized with const-list p. */
1308{
1309 //emit(f,"\tdc.%s\t",dt(t&NQ));
1310 int o = t&NQ;
1311 int size = 4;
1312 if(o == CHAR)
1313 size = 1;
1314 if(o == SHORT)
1315 size = 2;
1316 if(o == LLONG || t == DOUBLE)
1317 size = 8;
1318
1319 emit(f,"\tdata\t%i\t",size);
1320 if(!p->tree)
1321 {
1322 if(ISFLOAT(t))
1323 {
1324 /* auch wieder nicht sehr schoen und IEEE noetig */
1325 unsigned char *ip;
1326 ip=(unsigned char *)&p->val.vdouble;
1327 emit(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
1328 if((t&NQ)!=FLOAT){
1329 emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
1330 }
1331 }
1332 else if(o & UNSIGNED)
1333 {
1334 emitval(f,&p->val,t);
1335 }
1336 else
1337 {
1338 emit(f, "0s");
1339 emitval(f,&p->val,t);
1340 }
1341 }
1342 else
1343 {
1344 emit_obj(f,&p->tree->o,t);
1345 }
1346 emit(f,"\n");
1347 newobj=0;
1348}
1349
1350
1351/* The main code-generation routine. */
1352/* f is the stream the code should be written to. */
1353/* p is a pointer to a doubly linked list of ICs */
1354/* containing the function body to generate code for. */
1355/* v is a pointer to the function. */
1356/* offset is the size of the stackframe the function */
1357/* needs for local variables. */
1358
1359void gen_code(FILE *f,struct IC *p,struct Var *v,zmax offset)
1360/* The main code-generation. */
1361{
1362 int c,t,i,lastcomp=0;
1363 struct IC *m;
1364 argsize=0;
1365 if(DEBUG&1)
1366 printf("gen_code()\n");
1367 for(c=1;c<=MAXR;c++)
1368 regs[c]=regsa[c];
1369 maxpushed=0;
1370
1371 /*FIXME*/
1372 ret="\tret\n";
1373
1374 struct IC *p_test = 0;
1375 char test_handled = 0;
1376 int test_reg = 0;
1377 int test_reg2 = 0;
1378
1379 for(m=p;m;m=m->next)
1380 {
1381 c=m->code;t=m->typf;
1382 if(c==ALLOCREG)
1383 {
1384 regs[m->q1.reg]=1;
1385 continue;
1386 }
1387 if(c==FREEREG)
1388 {
1389 regs[m->q1.reg]=0;
1390 continue;
1391 }
1392
1393 /* convert MULT/DIV/MOD with powers of two */
1394 if((t&NQ)<=LONG&&(m->q2.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)<=LONG&&(c==MULT||((c==DIV||c==MOD)&&(t&UNSIGNED))))
1395 {
1396 eval_const(&m->q2.val,t);
1397 i=pof2(vmax);
1398 if(i)
1399 {
1400 if(c==MOD)
1401 {
1402 vmax=zmsub(vmax,l2zm(1L));
1403 m->code=AND;
1404 }
1405 else
1406 {
1407 vmax=l2zm(i-1);
1408 if(c==DIV)
1409 m->code=RSHIFT;
1410 else
1411 m->code=LSHIFT;
1412 }
1413 c=m->code;
1414 gval.vmax=vmax;
1415 eval_const(&gval,MAXINT);
1416 if(c==AND)
1417 {
1418 insert_const(&m->q2.val,t);
1419 }
1420 else
1421 {
1422 insert_const(&m->q2.val,INT);
1423 p->typf2=INT;
1424 }
1425 }
1426 }
1427#if FIXED_SP
1428 if(c==CALL&&argsize<zm2l(m->q2.val.vmax))
1429 argsize=zm2l(m->q2.val.vmax);
1430#endif
1431 }
1432 peephole(p);
1433
1434 for(c=1;c<=MAXR;c++)
1435 {
1436 if(regsa[c]||regused[c])
1437 {
1438 BSET(regs_modified,c);
1439 }
1440 }
1441
1442 localsize=(zm2l(offset)+3)/4*4;
1443#if FIXED_SP
1444 /*FIXME: adjust localsize to get an aligned stack-frame */
1445#endif
1446
1447 function_top(f,v,localsize);
1448
1449 stackoffset=notpopped=dontpop=0;
1450
1451 for(;p;p=p->next)
1452 {
1453 c=p->code;t=p->typf;
1454 if(c==NOP)
1455 {
1456 p->z.flags=0;
1457 continue;
1458 }
1459
1460 if(c==ALLOCREG)
1461 {
1462 regs[p->q1.reg]=1;
1463 continue;
1464 }
1465
1466 if(c==FREEREG)
1467 {
1468 regs[p->q1.reg]=0;
1469 continue;
1470 }
1471 if(c==LABEL)
1472 {
1473 emit(f,"%s%d:\n",labprefix,t);
1474 continue;
1475 }
1476
1477 if(notpopped&&!dontpop)
1478 {
1479 if(c==LABEL||c==COMPARE||c==TEST||c==BRA)
1480 {
1481 emit(f,"\taddl\t$%ld,%%esp\n",notpopped);
1482 pop(notpopped);
1483 notpopped=0;
1484 }
1485 }
1486 if(c==BRA)
1487 {
1488 emit(f,"\tmov b29 %s%d\n", labprefix, t);
1489 emit(f,"\tjmp\tb29\n");
1490
1491 //emit(f,"\tmov b29\t");
1492 //if(isreg(q1)){
1493 //emit_obj(f,&p->q1,0);
1494 //emit(f,",");
1495 //}
1496 //emit(f,"%s%d;\n",labprefix,t);
1497 continue;
1498 }
1499
1500 if(c==MOVETOREG)
1501 {
1502 //printf("reg: %s\n", regnames[p->z.reg]);
1503 if(p->z.reg <= MAXR)
1504 load_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
1505 else
1506 emit(f," ; move non existant reg in to %s\n",regnames[p->q1.reg]);
1507 continue;
1508 }
1509 if(c==MOVEFROMREG)
1510 {
1511 // printf("reg: %s\n", regnames[p->z.reg]);
1512 if(p->z.reg <= MAXR)
1513 store_reg(f, p->z.reg, &p->q1, regtype[p->z.reg]->flags);
1514 continue;
1515 }
1516 if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zm2l(p->q2.val.vmax)!=1)))
1517 {
1518 ierror(0);
1519 }
1520 p=preload(f,p);
1521 c=p->code;
1522 if(c==SUBPFP)
1523 c=SUB;
1524 if(c==ADDI2P)
1525 c=ADD;
1526 if(c==SUBIFP)
1527 c=SUB;
1528 if(c==CONVERT)
1529 {
1530 load_reg(f,zreg,&p->q1,p->typf2);
1531 if(ISFLOAT(p->typf)) // convert to float
1532 {
1533 if(ISFLOAT(p->typf2)) // from float
1534 {
1535 // emit(f,"\tmovf\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);
1536 }
1537 else if(!(p->typf2 & UNSIGNED)) // from signed
1538 {
1539 // emit(f,"\tmovs\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);
1540 emit(f,"\tstf\t%s ;%s\n",regnames[zreg],dt(q1typ(p)));
1541 }
1542 else if(p->typf2 & UNSIGNED) // from unsigned
1543 {
1544 // emit(f,"\tmov\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);
1545 emit(f,"\tutf\t%s ;%s\n",regnames[zreg],dt(q1typ(p)));
1546 }
1547 }
1548 else if(!(p->typf & UNSIGNED)) // convert to signed
1549 {
1550 if(ISFLOAT(p->typf2)) // from float
1551 {
1552 // emit(f,"\tmovf\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);
1553 emit(f,"\tfts\t%s ;%s\n",regnames[zreg],dt(q1typ(p)));
1554 }
1555 else if(!(p->typf2 & UNSIGNED)) // from signed
1556 {
1557 // emit(f,"\tmovs\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);
1558 }
1559 else if(p->typf2 & UNSIGNED) // from unsigned
1560 {
1561 // emit(f,"\tmov\t%s\t", regnames[zreg]);
1562 // emit_obj(f,&p->q1,p->typf2);
1563// emit(f,"\n\tuts\t%s ;%s\n",regnames[zreg],dt(q1typ(p)));
1564 }
1565 }
1566 else if(p->typf & UNSIGNED) // convert to unsigned
1567 {
1568 if(ISFLOAT(p->typf2)) // from float
1569 {
1570 // emit(f,"\tmovf\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);
1571 emit(f,"\tftu\t%s ;%s\n",regnames[zreg],dt(q1typ(p)));
1572 }
1573 else if(!(p->typf2 & UNSIGNED)) // from signed
1574 {
1575 // emit(f,"\tmovs\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);
1576// emit(f,"\tstu\t%s ;%s\n",regnames[zreg],dt(q1typ(p)));
1577 }
1578 else if(p->typf2 & UNSIGNED) // from unsigned
1579 {
1580 // emit(f,"\tmov\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);
1581 }
1582 }
1583 save_result(f,p);
1584 continue;
1585 }
1586 if(c==KOMPLEMENT)
1587 {
1588 load_reg(f,zreg,&p->q1,t);
1589 emit(f,"\tcpl.%s\t%s\n",dt(t),regnames[zreg]);
1590 save_result(f,p);
1591 continue;
1592 }
1593 if(c==SETRETURN)
1594 {
1595 load_reg(f,p->z.reg,&p->q1,t);
1596 BSET(regs_modified,p->z.reg);
1597 continue;
1598 }
1599 if(c==GETRETURN)
1600 {
1601 if(p->q1.reg)
1602 {
1603 zreg=p->q1.reg;
1604 save_result(f,p);
1605 }
1606 else
1607 p->z.flags=0;
1608 continue;
1609 }
1610 if(c==CALL)
1611 {
1612 int reg;
1613 /*FIXME*/
1614#if 0
1615 if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK))
1616 {
1617 if(framesize+zum2ul(p->q1.v->fi->stack1)>stack)
1618 stack=framesize+zum2ul(p->q1.v->fi->stack1);
1619 }else
1620 stack_valid=0;
1621#endif
1622 if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm)
1623 {
1624 emit_inline_asm(f,p->q1.v->fi->inline_asm);
1625 }
1626 else
1627 {
1628 emit(f, "\tmov\tb29\t");
1629 emit_obj(f,&p->q1,t);
1630 emit(f,"\n");
1631 emit(f,"\tcall\tb29\n");
1632 }
1633 /*FIXME*/
1634#if FIXED_SP
1635 pushed-=zm2l(p->q2.val.vmax);
1636#endif
1637 if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_REGS))
1638 {
1639 bvunite(regs_modified,p->q1.v->fi->regs_modified,RSIZE);
1640 }
1641 else
1642 {
1643 int i;
1644 for(i=1;i<=MAXR;i++)
1645 {
1646 if(regscratch[i]) BSET(regs_modified,i);
1647 }
1648 }
1649 continue;
1650 }
1651 if(c==ASSIGN||c==PUSH)
1652 {
1653 if(t==0)
1654 ierror(0);
1655 if(c==PUSH)
1656 {
1657 emit(f,"\tpush\t"/*,dt(t)*/);
1658 emit_obj(f,&p->q1,t);
1659 emit(f,"\n");
1660 push(zm2l(p->q2.val.vmax));
1661 continue;
1662 }
1663 if(c==ASSIGN)
1664 {
1665 load_reg(f,zreg,&p->q1,t);
1666 if(q2reg != 0)
1667 load_reg(f,q2reg,&p->q2,t);
1668 save_result(f,p);
1669 }
1670 continue;
1671 }
1672 if(c==ADDRESS)
1673 {
1674 load_address(f,zreg,&p->q1,POINTER);
1675 save_result(f,p);
1676 continue;
1677 }
1678 if(c==MINUS)
1679 {
1680 load_reg(f,zreg,&p->q1,t);
1681 emit(f,"\tneg\t%s ; %s\n",dt(t),regnames[zreg]);
1682 save_result(f,p);
1683 continue;
1684 }
1685 if(c >= BEQ && c < BRA)
1686 {
1687
1688 char *ccu[]={"cmp","nequ","gt","!gte","gte","!gt"};
1689 char *ccs[]={"cmps","nequs","gts","!gtes","gtes","!gts"};
1690 char *ccf[]={"cmpf","nequf","gtf","!gtef","gtef","!gtf"};
1691 if(p_test == 0)
1692 {
1693 printf("Calling %s without a test!\n",ccs[c-BEQ]);
1694 emit(f,"Calling %s without a test!\n",ccs[c-BEQ]);
1695 continue;
1696 }
1697
1698 struct IC *p_old = p;
1699 p = p_test;
1700 t=p->typf;
1701
1702 if(test_handled == 0)
1703 {
1704 if(ISFLOAT(t))
1705 {
1706 if(isreg(q2))
1707 {
1708 char instruction[10];
1709 sprintf(instruction, "%s", ccf[c-BEQ]);
1710 if(instruction[0] == '!')
1711 {
1712 instruction[0] = ' ';
1713 emit(f,"\n\t%s\t%s\t%s\n",instruction,regnames[test_reg],regnames[test_reg2]);
1714 }
1715 else
1716 emit(f,"\n\t%s\t%s\t%s\n",instruction,regnames[test_reg2],regnames[test_reg]);
1717
1718 save_result(f,p);
1719 }
1720 else
1721 {
1722 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
1723 {
1724 unsigned long offset = real_offset(&p->q2);
1725 if(offset == 0)
1726 {
1727 emit(f,"\tmovf\tb28\t[z2]\n");
1728 }
1729 else
1730 {
1731 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
1732 emit(f,"\tmov\tb29\tz2\n");
1733 emit(f,"\tsub\tb29\tb28\n");
1734 emit(f,"\tmovf\tb28\t[b29]\n");
1735 }
1736 }
1737 else
1738 {
1739 emit(f,"\tmovf\tb28\t");
1740 emit_obj(f,&p->q2,t);
1741 emit(f,"\n");
1742 }
1743
1744 char instruction[10];
1745 sprintf(instruction, "%s", ccf[c-BEQ]);
1746 if(instruction[0] == '!')
1747 {
1748 instruction[0] = ' ';
1749 emit(f,"\n\t%s\t%s\tb28\n",instruction,regnames[test_reg]);
1750 }
1751 else
1752 emit(f,"\n\t%s\tb28\t%s\n",instruction,regnames[test_reg]);
1753 }
1754 }
1755 else if(t & UNSIGNED)
1756 {
1757 if(isreg(q2))
1758 {
1759 char instruction[10];
1760 sprintf(instruction, "%s", ccu[c-BEQ]);
1761 if(instruction[0] == '!')
1762 {
1763 instruction[0] = ' ';
1764 emit(f,"\n\t%s\t%s\t%s\n",instruction,regnames[test_reg2],regnames[test_reg]);
1765 }
1766 else
1767 emit(f,"\n\t%s\t%s\t%s\n",instruction,regnames[test_reg],regnames[test_reg2]);
1768 save_result(f,p);
1769 continue;
1770 }
1771 else
1772 {
1773 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
1774 {
1775 unsigned long offset = real_offset(&p->q2);
1776 if(offset == 0)
1777 {
1778 emit(f,"\tmov\tb28\t[z2]\n");
1779 }
1780 else
1781 {
1782 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
1783 emit(f,"\tmov\tb29\tz2\n");
1784 emit(f,"\tsub\tb29\tb28\n");
1785 emit(f,"\tmov\tb28\t[b29]\n");
1786 }
1787 }
1788 else
1789 {
1790 emit(f,"\tmov\tb28\t");
1791 emit_obj(f,&p->q2,t);
1792 emit(f,"\n");
1793 }
1794
1795 char instruction[10];
1796 sprintf(instruction, "%s", ccu[c-BEQ]);
1797 if(instruction[0] == '!')
1798 {
1799 instruction[0] = ' ';
1800 emit(f,"\n\t%s\t%s\tb28\n",instruction,regnames[test_reg]);
1801 }
1802 else
1803 emit(f,"\n\t%s\tb28\t%s\n",instruction,regnames[test_reg]);
1804 }
1805 }
1806 else
1807 {
1808 if(isreg(q2))
1809 {
1810 char instruction[10];
1811 sprintf(instruction, "%s", ccs[c-BEQ]);
1812 if(instruction[0] == '!')
1813 {
1814 instruction[0] = ' ';
1815 emit(f,"\n\t%s\t%s\t%s\n",instruction,regnames[test_reg],regnames[test_reg2]);
1816 }
1817 else
1818 emit(f,"\n\t%s\t%s\t%s\n",instruction,regnames[p->q2.reg],regnames[test_reg]);
1819
1820 save_result(f,p);
1821 continue;
1822 }
1823 else
1824 {
1825 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
1826 {
1827 unsigned long offset = real_offset(&p->q2);
1828 if(offset == 0)
1829 {
1830 emit(f,"\tmovs\tb28\t[z2]\n");
1831 }
1832 else
1833 {
1834 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
1835 emit(f,"\tmov\tb29\tz2\n");
1836 emit(f,"\tsub\tb29\tb28\n");
1837 emit(f,"\tmovs\tb28\t[b29]\n");
1838 }
1839 }
1840 else
1841 {
1842 emit(f,"\tmovs\tb28\t");
1843 emit_obj(f,&p->q2,t);
1844 emit(f,"\n");
1845 }
1846
1847 char instruction[10];
1848 sprintf(instruction, "%s", ccs[c-BEQ]);
1849 if(instruction[0] == '!')
1850 {
1851 instruction[0] = ' ';
1852 emit(f,"\n\t%s\t%s\tb28\n",instruction,regnames[test_reg]);
1853 }
1854 else
1855 emit(f,"\n\t%s\tb28\t%s\n",instruction,regnames[test_reg]);
1856 }
1857 }
1858
1859 //emit(f,"\tj%s\t",ccs[c-BEQ]);
1860 //if(isreg(q1))
1861 //{
1862 //emit_obj(f,&p->q1,0);
1863 //emit(f,",");
1864 //}
1865 //emit(f,"%s%d ;\n",labprefix,t);
1866
1867 // next
1868
1869 }
1870 else
1871 {
1872 if(p_old->code == BEQ)
1873 {
1874 emit(f,"\n\trz\t%s\n",regnames[test_reg]);
1875 }
1876 else if(p_old->code == BNE)
1877 {
1878 emit(f,"\n\trnz\t%s\n",regnames[test_reg]);
1879 }
1880 else
1881 emit(f,"not sure what to do with %d\n", p_old->code);
1882 }
1883
1884 p = p_old;
1885 t=p->typf;
1886
1887 test_handled = 0;
1888
1889 emit(f,"\tmov\tb28\t%s%d\n",labprefix,t);
1890 emit(f,"\tjnz\tz0\tb28\n");
1891 continue;
1892 }
1893 if(c==TEST)
1894 {
1895 // printf("found test");
1896/* emit(f,"\ttst\t");
1897 if(multiple_ccs)
1898 emit(f,"%s,",regnames[zreg]);
1899 emit_obj(f,&p->q1,t);
1900 emit(f," ; %s\n",dt(t));
1901 if(multiple_ccs)
1902 save_result(f,p); */
1903
1904 test_reg = zreg;
1905 test_reg2 = q2reg;
1906
1907 if(!isreg(q1))
1908 load_reg(f,test_reg,&p->q1,t);
1909
1910 p_test = p;
1911 test_handled = 1;
1912
1913 continue;
1914 }
1915 if(c==COMPARE)
1916 {
1917 test_reg = zreg;
1918 test_reg2 = q2reg;
1919
1920 if(!isreg(q1))
1921 load_reg(f,zreg,&p->q1,t);
1922
1923 p_test = p;
1924 test_handled = 0;
1925// emit(f, "; compare %s\n", regnames[zreg]);
1926 continue;
1927 }
1928 if(c==OR)
1929 {
1930 emit(f,"\tmov\tb28\t");
1931 emit_obj(f,&p->q2,t);
1932
1933 emit(f,"\n\tor\t%s b28\n",/*dt(t),*/regnames[zreg]);
1934 save_result(f,p);
1935 continue;
1936 }
1937 if(c==XOR)
1938 {
1939 emit(f,"\tmov\tb28\t");
1940 emit_obj(f,&p->q2,t);
1941
1942 emit(f,"\n\txor\t%s b28\n",/*dt(t),*/regnames[zreg]);
1943 save_result(f,p);
1944 continue;
1945 }
1946 if(c==AND)
1947 {
1948 emit(f,"\tmov\tb28\t");
1949 emit_obj(f,&p->q2,t);
1950
1951 emit(f,"\n\tand\t%s b28\n",/*dt(t),*/regnames[zreg]);
1952 save_result(f,p);
1953 continue;
1954 }
1955
1956 if(c==LSHIFT)
1957 {
1958 emit(f,"\tmov\tb28\t");
1959 emit_obj(f,&p->q2,t);
1960
1961 emit(f,"\n\tsal\t%s b28\n",/*dt(t),*/regnames[zreg]);
1962 save_result(f,p);
1963 continue;
1964 }
1965
1966 if(c==RSHIFT)
1967 {
1968 emit(f,"\tmov\tb28\t");
1969 emit_obj(f,&p->q2,t);
1970
1971 emit(f,"\n\tsar\t%s b28\n",/*dt(t),*/regnames[zreg]);
1972 save_result(f,p);
1973 continue;
1974 }
1975
1976 if(c==ADD) ///////////////////////////////////////// ADDITION
1977 {
1978 if(!isreg(q1))
1979 load_reg(f,zreg,&p->q1,t);
1980
1981 if(p->q2.flags&KONST)
1982 {
1983 if(ISFLOAT(t))
1984 {
1985 char *ds = (char *)&p->q2.val.vfloat;
1986 char tmp = ds[0];
1987 ds[0] = ds[3];
1988 ds[3] = tmp;
1989 tmp = ds[1];
1990 ds[1] = ds[2];
1991 ds[2] = tmp;
1992
1993 if((*(float *)ds) == 1.0f)
1994 {
1995 emit(f,"\tincf\t%s\n", regnames[zreg]);
1996 save_result(f,p);
1997 continue;
1998 }
1999 }
2000 else if(t & UNSIGNED)
2001 {
2002 if(*(unsigned int *)&p->q2.val == 1)
2003 {
2004 emit(f,"\tinc\t%s\n", regnames[zreg]);
2005 save_result(f,p);
2006 continue;
2007 }
2008 }
2009 else
2010 {
2011 if(*(unsigned int *)&p->q2.val == 1)
2012 {
2013 emit(f,"\tincs\t%s\n", regnames[zreg]);
2014 save_result(f,p);
2015 continue;
2016 }
2017 }
2018 }
2019
2020 if(ISFLOAT(t))
2021 {
2022 if(isreg(q2))
2023 {
2024 emit(f,"\n\taddf\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2025 save_result(f,p);
2026 continue;
2027 }
2028
2029 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2030 {
2031 unsigned long offset = real_offset(&p->q2);
2032 if(offset == 0)
2033 {
2034 emit(f,"\tmovf\tb28\t[z2]\n");
2035 }
2036 else
2037 {
2038 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2039 emit(f,"\tmov\tb29\tz2\n");
2040 emit(f,"\tsub\tb29\tb28\n");
2041 emit(f,"\tmovf\tb28\t[b29]\n");
2042 }
2043 }
2044 else
2045 {
2046 emit(f,"\tmovf\tb28\t");
2047 emit_obj(f,&p->q2,t);
2048 emit(f,"\n");
2049 }
2050
2051 emit(f,"\n\taddf\t%s b28\n",/*dt(t),*/regnames[zreg]);
2052 save_result(f,p);
2053 continue;
2054 }
2055 else if(t & UNSIGNED)
2056 {
2057 if(isreg(q2))
2058 {
2059 emit(f,"\n\tadd\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2060 save_result(f,p);
2061 continue;
2062 }
2063
2064 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2065 {
2066 unsigned long offset = real_offset(&p->q2);
2067 if(offset == 0)
2068 {
2069 emit(f,"\tmov\tb28\t[z2]\n");
2070 }
2071 else
2072 {
2073 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2074 emit(f,"\tmov\tb29\tz2\n");
2075 emit(f,"\tsub\tb29\tb28\n");
2076 emit(f,"\tmov\tb28\t[b29]\n");
2077 }
2078 }
2079 else
2080 {
2081 emit(f,"\tmov\tb28\t");
2082 emit_obj(f,&p->q2,t);
2083 emit(f,"\n");
2084 }
2085
2086 emit(f,"\n\tadd\t%s b28\n",/*dt(t),*/regnames[zreg]);
2087 save_result(f,p);
2088 continue;
2089 }
2090 else
2091 {
2092 if(isreg(q2))
2093 {
2094 emit(f,"\n\tadds\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2095 save_result(f,p);
2096 continue;
2097 }
2098
2099 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2100 {
2101 unsigned long offset = real_offset(&p->q2);
2102 if(offset == 0)
2103 {
2104 emit(f,"\tmovs\tb28\t[z2]\n");
2105 }
2106 else
2107 {
2108 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2109 emit(f,"\tmov\tb29\tz2\n");
2110 emit(f,"\tsub\tb29\tb28\n");
2111 emit(f,"\tmovs\tb28\t[b29]\n");
2112 }
2113 }
2114 else
2115 {
2116 emit(f,"\tmovs\tb28\t");
2117 emit_obj(f,&p->q2,t);
2118 emit(f,"\n");
2119 }
2120
2121 emit(f,"\n\tadds\t%s b28\n",/*dt(t),*/regnames[zreg]);
2122 save_result(f,p);
2123 continue;
2124 }
2125 }
2126
2127 if(c==SUB)
2128 {
2129 if(!isreg(q1))
2130 load_reg(f,zreg,&p->q1,t);
2131
2132 if(p->q2.flags&KONST)
2133 {
2134 if(ISFLOAT(t))
2135 {
2136 char *ds = (char *)&p->q2.val.vfloat;
2137 char tmp = ds[0];
2138 ds[0] = ds[3];
2139 ds[3] = tmp;
2140 tmp = ds[1];
2141 ds[1] = ds[2];
2142 ds[2] = tmp;
2143
2144 if((*(float *)ds) == 1.0f)
2145 {
2146 emit(f,"\tdecf\t%s\n", regnames[zreg]);
2147 save_result(f,p);
2148 continue;
2149 }
2150 }
2151 else if(t & UNSIGNED)
2152 {
2153 if(*(unsigned int *)&p->q2.val == 1)
2154 {
2155 emit(f,"\tdec\t%s\n", regnames[zreg]);
2156 save_result(f,p);
2157 continue;
2158 }
2159 }
2160 else
2161 {
2162 if(*(unsigned int *)&p->q2.val == 1)
2163 {
2164 emit(f,"\tdecs\t%s\n", regnames[zreg]);
2165 save_result(f,p);
2166 continue;
2167 }
2168 }
2169 }
2170 if(ISFLOAT(t))
2171 {
2172 if(isreg(q2))
2173 {
2174 emit(f,"\n\tsubf\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2175 save_result(f,p);
2176 continue;
2177 }
2178
2179 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2180 {
2181 unsigned long offset = real_offset(&p->q2);
2182 if(offset == 0)
2183 {
2184 emit(f,"\tmovf\tb28\t[z2]\n");
2185 }
2186 else
2187 {
2188 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2189 emit(f,"\tmov\tb29\tz2\n");
2190 emit(f,"\tsub\tb29\tb28\n");
2191 emit(f,"\tmovf\tb28\t[b29]\n");
2192 }
2193 }
2194 else
2195 {
2196 emit(f,"\tmovf\tb28\t");
2197 emit_obj(f,&p->q2,t);
2198 emit(f,"\n");
2199 }
2200
2201 emit(f,"\n\tsubf\t%s\tb28\n",/*dt(t),*/regnames[zreg]);
2202 save_result(f,p);
2203 continue;
2204 }
2205 else if(t & UNSIGNED)
2206 {
2207 if(isreg(q2))
2208 {
2209 emit(f,"\n\tsub\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2210 save_result(f,p);
2211 continue;
2212 }
2213
2214 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2215 {
2216 unsigned long offset = real_offset(&p->q2);
2217 if(offset == 0)
2218 {
2219 emit(f,"\tmov\tb28\t[z2]\n");
2220 }
2221 else
2222 {
2223 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2224 emit(f,"\tmov\tb29\tz2\n");
2225 emit(f,"\tsub\tb29\tb28\n");
2226 emit(f,"\tmov\tb28\t[b29]\n");
2227 }
2228 }
2229 else
2230 {
2231 emit(f,"\tmov\tb28\t");
2232 emit_obj(f,&p->q2,t);
2233 emit(f,"\n");
2234 }
2235
2236 emit(f,"\n\tsub\t%s\tb28\n",/*dt(t),*/regnames[zreg]);
2237 save_result(f,p);
2238 continue;
2239 }
2240 else
2241 {
2242 if(isreg(q2))
2243 {
2244 emit(f,"\n\tsubs\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2245 save_result(f,p);
2246 continue;
2247 }
2248
2249 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2250 {
2251 unsigned long offset = real_offset(&p->q2);
2252 if(offset == 0)
2253 {
2254 emit(f,"\tmovs\tb28\t[z2]\n");
2255 }
2256 else
2257 {
2258 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2259 emit(f,"\tmov\tb29\tz2\n");
2260 emit(f,"\tsub\tb29\tb28\n");
2261 emit(f,"\tmovs\tb28\t[b29]\n");
2262 }
2263 }
2264 else
2265 {
2266 emit(f,"\tmovs\tb28\t");
2267 emit_obj(f,&p->q2,t);
2268 emit(f,"\n");
2269 }
2270
2271 emit(f,"\n\tsubs\t%s\tb28\n",/*dt(t),*/regnames[zreg]);
2272 save_result(f,p);
2273 continue;
2274 }
2275 }
2276
2277 if(c==MULT)
2278 {
2279 if(ISFLOAT(t))
2280 {
2281 if(isreg(q2))
2282 {
2283 emit(f,"\n\tmulf\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2284 save_result(f,p);
2285 continue;
2286 }
2287
2288 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2289 {
2290 unsigned long offset = real_offset(&p->q2);
2291 if(offset == 0)
2292 {
2293 emit(f,"\tmovf\tb28\t[z2]\n");
2294 }
2295 else
2296 {
2297 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2298 emit(f,"\tmov\tb29\tz2\n");
2299 emit(f,"\tsub\tb29\tb28\n");
2300 emit(f,"\tmovf\tb28\t[b29]\n");
2301 }
2302 }
2303 else
2304 {
2305 emit(f,"\tmovf\tb28\t");
2306 emit_obj(f,&p->q2,t);
2307 emit(f,"\n");
2308 }
2309
2310 emit(f,"\n\tmulf\t%s\tb28\n",/*dt(t),*/regnames[zreg]);
2311 save_result(f,p);
2312 continue;
2313 }
2314 else if(t & UNSIGNED)
2315 {
2316 if(isreg(q2))
2317 {
2318 emit(f,"\n\tmul\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2319 save_result(f,p);
2320 continue;
2321 }
2322
2323 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2324 {
2325 unsigned long offset = real_offset(&p->q2);
2326 if(offset == 0)
2327 {
2328 emit(f,"\tmov\tb28\t[z2]\n");
2329 }
2330 else
2331 {
2332 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2333 emit(f,"\tmov\tb29\tz2\n");
2334 emit(f,"\tsub\tb29\tb28\n");
2335 emit(f,"\tmov\tb28\t[b29]\n");
2336 }
2337 }
2338 else
2339 {
2340 emit(f,"\tmov\tb28\t");
2341 emit_obj(f,&p->q2,t);
2342 emit(f,"\n");
2343 }
2344
2345 emit(f,"\n\tmul\t%s\tb28\n",/*dt(t),*/regnames[zreg]);
2346 save_result(f,p);
2347 continue;
2348 }
2349 else
2350 {
2351 if(isreg(q2))
2352 {
2353 emit(f,"\n\tmuls\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2354 save_result(f,p);
2355 continue;
2356 }
2357
2358 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2359 {
2360 unsigned long offset = real_offset(&p->q2);
2361 if(offset == 0)
2362 {
2363 emit(f,"\tmovs\tb28\t[z2]\n");
2364 }
2365 else
2366 {
2367 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2368 emit(f,"\tmov\tb29\tz2\n");
2369 emit(f,"\tsub\tb29\tb28\n");
2370 emit(f,"\tmovs\tb28\t[b29]\n");
2371 }
2372 }
2373 else
2374 {
2375 emit(f,"\tmovs\tb28\t");
2376 emit_obj(f,&p->q2,t);
2377 emit(f,"\n");
2378 }
2379
2380 emit(f,"\n\tmuls\t%s\tb28\n",/*dt(t),*/regnames[zreg]);
2381 save_result(f,p);
2382 continue;
2383 }
2384
2385 continue;
2386 }
2387
2388 if(c==DIV)
2389 {
2390 if(ISFLOAT(t))
2391 {
2392 if(isreg(q2))
2393 {
2394 emit(f,"\n\tdivf\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2395 save_result(f,p);
2396 continue;
2397 }
2398
2399 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2400 {
2401 unsigned long offset = real_offset(&p->q2);
2402 if(offset == 0)
2403 {
2404 emit(f,"\tmovf\tb28\t[z2]\n");
2405 }
2406 else
2407 {
2408 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2409 emit(f,"\tmov\tb29\tz2\n");
2410 emit(f,"\tsub\tb29\tb28\n");
2411 emit(f,"\tmovf\tb28\t[b29]\n");
2412 }
2413 }
2414 else
2415 {
2416 emit(f,"\tmovf\tb28\t");
2417 emit_obj(f,&p->q2,t);
2418 emit(f,"\n");
2419 }
2420
2421 emit(f,"\n\tdivf\t%s\tb28\n",/*dt(t),*/regnames[zreg]);
2422 save_result(f,p);
2423 continue;
2424 }
2425 else if(t & UNSIGNED)
2426 {
2427 if(isreg(q2))
2428 {
2429 emit(f,"\n\tdiv\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2430 save_result(f,p);
2431 continue;
2432 }
2433
2434 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2435 {
2436 unsigned long offset = real_offset(&p->q2);
2437 if(offset == 0)
2438 {
2439 emit(f,"\tmov\tb28\t[z2]\n");
2440 }
2441 else
2442 {
2443 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2444 emit(f,"\tmov\tb29\tz2\n");
2445 emit(f,"\tsub\tb29\tb28\n");
2446 emit(f,"\tmov\tb28\t[b29]\n");
2447 }
2448 }
2449 else
2450 {
2451 emit(f,"\tmov\tb28\t");
2452 emit_obj(f,&p->q2,t);
2453 emit(f,"\n");
2454 }
2455
2456 emit(f,"\n\tdiv\t%s\tb28\n",/*dt(t),*/regnames[zreg]);
2457 save_result(f,p);
2458 continue;
2459 }
2460 else
2461 {
2462 if(isreg(q2))
2463 {
2464 emit(f,"\n\tdivs\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2465 save_result(f,p);
2466 continue;
2467 }
2468
2469 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2470 {
2471 unsigned long offset = real_offset(&p->q2);
2472 if(offset == 0)
2473 {
2474 emit(f,"\tmovs\tb28\t[z2]\n");
2475 }
2476 else
2477 {
2478 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2479 emit(f,"\tmov\tb29\tz2\n");
2480 emit(f,"\tsub\tb29\tb28\n");
2481 emit(f,"\tmovs\tb28\t[b29]\n");
2482 }
2483 }
2484 else
2485 {
2486 emit(f,"\tmovs\tb28\t");
2487 emit_obj(f,&p->q2,t);
2488 emit(f,"\n");
2489 }
2490
2491 emit(f,"\n\tdivs\t%s\tb28\n",/*dt(t),*/regnames[zreg]);
2492 save_result(f,p);
2493 continue;
2494 }
2495 }
2496
2497 if(c==MOD)
2498 {
2499 if(ISFLOAT(t))
2500 {
2501 if(isreg(q2))
2502 {
2503 emit(f,"\n\tmodf\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2504 save_result(f,p);
2505 continue;
2506 }
2507
2508 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2509 {
2510 unsigned long offset = real_offset(&p->q2);
2511 if(offset == 0)
2512 {
2513 emit(f,"\tmovf\tb28\t[z2]\n");
2514 }
2515 else
2516 {
2517 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2518 emit(f,"\tmov\tb29\tz2\n");
2519 emit(f,"\tsub\tb29\tb28\n");
2520 emit(f,"\tmovf\tb28\t[b29]\n");
2521 }
2522 }
2523 else
2524 {
2525 emit(f,"\tmovf\tb28\t");
2526 emit_obj(f,&p->q2,t);
2527 emit(f,"\n");
2528 }
2529
2530 emit(f,"\n\tmodf\t%s\tb28\n",/*dt(t),*/regnames[zreg]);
2531 save_result(f,p);
2532 continue;
2533 }
2534 else if(t & UNSIGNED)
2535 {
2536 if(isreg(q2))
2537 {
2538 emit(f,"\n\tmod\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2539 save_result(f,p);
2540 continue;
2541 }
2542
2543 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2544 {
2545 unsigned long offset = real_offset(&p->q2);
2546 if(offset == 0)
2547 {
2548 emit(f,"\tmov\tb28\t[z2]\n");
2549 }
2550 else
2551 {
2552 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2553 emit(f,"\tmov\tb29\tz2\n");
2554 emit(f,"\tsub\tb29\tb28\n");
2555 emit(f,"\tmov\tb28\t[b29]\n");
2556 }
2557 }
2558 else
2559 {
2560 emit(f,"\tmov\tb28\t");
2561 emit_obj(f,&p->q2,t);
2562 emit(f,"\n");
2563 }
2564
2565 emit(f,"\n\tmod\t%s\tb28\n",/*dt(t),*/regnames[zreg]);
2566 save_result(f,p);
2567 continue;
2568 }
2569 else
2570 {
2571 if(isreg(q2))
2572 {
2573 emit(f,"\n\tmods\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);
2574 save_result(f,p);
2575 continue;
2576 }
2577
2578 if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))
2579 {
2580 unsigned long offset = real_offset(&p->q2);
2581 if(offset == 0)
2582 {
2583 emit(f,"\tmovs\tb28\t[z2]\n");
2584 }
2585 else
2586 {
2587 emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);
2588 emit(f,"\tmov\tb29\tz2\n");
2589 emit(f,"\tsub\tb29\tb28\n");
2590 emit(f,"\tmovs\tb28\t[b29]\n");
2591 }
2592 }
2593 else
2594 {
2595 emit(f,"\tmovs\tb28\t");
2596 emit_obj(f,&p->q2,t);
2597 emit(f,"\n");
2598 }
2599
2600 emit(f,"\n\tmods\t%s\tb28\n",/*dt(t),*/regnames[zreg]);
2601 save_result(f,p);
2602 continue;
2603 }
2604 }
2605
2606 pric2(stdout,p);
2607 ierror(0);
2608 }
2609 function_bottom(f,v,localsize);
2610 if(stack_valid)
2611 {
2612 if(!v->fi)
2613 v->fi=new_fi();
2614 v->fi->flags|=ALL_STACK;
2615 v->fi->stack1=stack;
2616 }
2617 emit(f," ; stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");
2618}
2619
2620int shortcut(int code,int typ)
2621{
2622 return 1;
2623}
2624
2625int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
2626{
2627 int f;
2628 f=t->flags&NQ;
2629 if(f==CHAR)
2630 {
2631 if(m->regs8>=NUM_8BIT)
2632 return 0;
2633 else
2634 return FIRST_8BIT+m->regs8++;
2635 }
2636 if(f==SHORT)
2637 {
2638 if(m->regs16>=NUM_16BIT)
2639 return 0;
2640 else
2641 return FIRST_16BIT+m->regs16++;
2642 }
2643 if(f==INT || f==LONG || f==POINTER || f==FLOAT)
2644 {
2645 if(m->regs32>=NUM_32BIT)
2646 return 0;
2647 else
2648 return FIRST_32BIT+m->regs32++;
2649 }
2650 if(f==DOUBLE || f==LDOUBLE || f==LLONG){
2651 if(m->regs64>=NUM_64BIT)
2652 return 0;
2653 else
2654 return FIRST_64BIT+m->regs64++;
2655 }
2656 return 0;
2657}
2658
2659int handle_pragma(const char *s)
2660{
2661 return 0;
2662}
2663
2664void cleanup_cg(FILE *f)
2665{
2666 if(!f)
2667 return;
2668
2669}
2670
2671void cleanup_db(FILE *f)
2672{
2673 if(f)
2674 section=-1;
2675}
2676
2677/*
2678C registers:
2679b28 - temp - store var during calculation/comparison
2680b29 - temp - store address during jump
2681b30 - temp store address of parameters
2682b31 - temp store addresses to jump to
2683
2684a0 - 16 bit 4
2685a1 - 16 bit 5
2686a2 - 16 bit 6
2687a3 - 16 bit 7
2688a4 - 16 bit 8
2689a5 - 16 bit 9
2690a6 - 16 bit 10
2691a7 - 16 bit 11
2692a8 - 16 bit 12
2693a9 - 16 bit 13
2694b5 - 32 bit 14
2695b6 - 32 bit 15
2696b7 - 32 bit 16
2697b8 - 32 bit 17
2698b9 - 32 bit 18
2699b10 - 32 bit 19
2700b11 - 32 bit 20
2701b12 - 32 bit 21
2702b13 - 32 bit 22
2703b14 - 32 bit 23
2704b15 - 32 bit 24
2705b16 - 32 bit 25
2706b17 - 32 bit 26
2707c9 - 64 bit 27
2708c10 - 64 bit 28
2709c11 - 64 bit 29
2710c12 - 64 bit 30
2711c13 - 64 bit 31
2712
2713h0 - 8bit 32
2714h1 - 8bit 33
2715h2 - 8bit 34
2716h3 - 8bit 35
2717*/