blob: 1462bef4b3515a3cadd10c5b1fc5bb8b4326d99e [file] [log] [blame]
PulkoMandy17fc7592022-07-28 18:27:54 +02001/*
2 * ARM code generator
3 * A 32-bit RISC with 16 general purpose registers.
4 * Written by Frank Wille <frank@phoenix.owl.de>
5 */
6
7#include "supp.h"
8#include "vbc.h"
9
10static char FILE_[] = __FILE__;
11
12
13/* Public data that MUST be there. */
14
15/* Name and copyright. */
16char cg_copyright[] = "vbcc code-generator for ARM V0.0 (c) in 2006 by Frank Wille";
17
18/* Commandline-flags the code-generator accepts:
19 0: just a flag
20 VALFLAG: a value must be specified
21 STRINGFLAG: a string can be specified
22 FUNCFLAG: a function will be called
23 apart from FUNCFLAG, all other versions can only be specified once */
24int g_flags[MAXGF] = {
25 STRINGFLAG,STRINGFLAG,0,0,0,0,
26 0,0,0,0
27};
28
29/* the flag-name, do not use names beginning with l, L, I, D or U, because
30 they collide with the frontend */
31char *g_flags_name[MAXGF] = {
32 "cpu","fpu","little-endian","big-endian","arm","thumb",
33 "const-in-data","merge-constants","elf","use-commons"
34};
35
36/* the results of parsing the command-line-flags will be stored here */
37union ppi g_flags_val[MAXGF];
38
39/* Alignment-requirements for all types in bytes. */
40zmax align[MAX_TYPE+1];
41
42/* Alignment that is sufficient for every object. */
43zmax maxalign;
44
45/* CHAR_BIT for the target machine. */
46zmax char_bit;
47
48/* sizes of the basic types (in bytes) */
49zmax sizetab[MAX_TYPE+1];
50
51/* Minimum and Maximum values each type can have. */
52/* Must be initialized in init_cg(). */
53zmax t_min[MAX_TYPE+1];
54zumax t_max[MAX_TYPE+1];
55zumax tu_max[MAX_TYPE+1];
56
57/* Names of all registers. */
58char *regnames[MAXR+1] = {
59 "noreg",
60 "r0","r1","r2","r3","r4","r5","r6","r7",
61 "r8","r9","r10","r11","r12","sp","lr","pc",
62 "s0","s1","s2","s3","s4","s5","s6","s7",
63 "s8","s9","s10","s11","s12","s13","s14","s15",
64 "cpsr",
65 "r0/r1","r2/r3","r4/r5","r6/r7","r10/r11",
66 "d0","d1","d2","d3","d4","d5","d6","d7"
67};
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 0,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0, /* r0-r3,r12 */
82 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, /* vfp s0-s3 */
83 1, /* cpsr */
84 1,1,0,0,0, /* r0/r1, r2/r3 */
85 1,1,0,0,0,0,0,0 /* vfp d0-d1 */
86};
87
88/* specifies the priority for the register-allocator, if the same
89 estimated cost-saving can be obtained by several registers, the
90 one with the highest priority will be used */
91int reg_prio[MAXR+1] = {
92 0,10,11,12,13,2,3,4,5,6,7,8,9,14,0,1,0,
93 1,2,3,4,0,0,0,0,0,0,0,0,0,0,0,0,
94 0,
95 10,12,2,4,8,
96 1,2,0,0,0,0,0,0
97};
98
99/* an empty reg-handle representing initial state */
100struct reg_handle empty_reg_handle = {0,0};
101
102/* Names of target-specific variable attributes. */
103char *g_attr_name[] = {
104 "__arm","__thumb","__interrupt","__syscall",0
105};
106#define ARM 1
107#define THUMB 2
108#define INTERRUPT 4
109#define SYSCALL 8
110
111
112/****************************************/
113/* Private data and functions. */
114/****************************************/
115
116#define LE_MODE (g_flags[2]&USEDFLAG)
117#define BE_MODE (g_flags[3]&USEDFLAG)
118#define ARM_DEFAULT (g_flags[4]&USEDFLAG)
119#define THUMB_DEFAULT (g_flags[5]&USEDFLAG)
120#define CONST_IN_DATA (g_flags[6]&USEDFLAG)
121#define ELF_LABELS (g_flags[8]&USEDFLAG)
122#define USE_COMMONS (g_flags[9]&USEDFLAG)
123
124int arm_le_mode = 1; /* defaults to little-endian */
125static int thumb_default = 0; /* we start in ARM mode */
126static int thumb = 0; /* current mode */
127
128enum {
129 AAANY=0,AA2,AA3,AA3M,AA4,AA4T,AA5,AA5T,AA5TE
130};
131static int aa = AAANY; /* ARM architecture version */
132
133/* alignment of basic data-types, used to initialize align[] */
134static long malign[MAX_TYPE+1] = {
135 1,1,2,4,4,8,4,8,8,1,4,1,1,1,4,1
136};
137/* sizes of basic data-types, used to initialize sizetab[] */
138static long msizetab[MAX_TYPE+1] = {
139 1,1,2,4,4,8,4,8,8,0,4,0,0,0,4,0
140};
141
142/* used to initialize regtyp[] */
143static struct Typ ltyp = {LONG};
144static struct Typ lltyp = {LLONG};
145static struct Typ ftyp = {FLOAT};
146static struct Typ dtyp = {DOUBLE};
147
148/* macros defined by the backend */
149static char *marray[]={"__section(x,y)=__vattr(\"section(\"#x\",\"#y\")\")",
150 "__ARM__",
151 0};
152
153/* special registers */
154static int ip = FIRST_GPR+12; /* inter-procedural scratch register */
155static int sp = FIRST_GPR+13; /* stack pointer */
156static int lr = FIRST_GPR+14; /* link register */
157static int pc = FIRST_GPR+15; /* program counter */
158static int r0 = FIRST_GPR;
159static int r1 = FIRST_GPR+1;
160
161/* load/store instructions */
162static char *ldts[MAX_TYPE+1] = {
163 "ldr","ldrsb","ldrsh","ldr","ldr","ldr","ldr","ldr","ldr","??","ldr"};
164static char *ldtu[MAX_TYPE+1] = {
165 "ldr","ldrb","ldrh","ldr","ldr","ldr","??","??","??","??","??"};
166static char *sdts[MAX_TYPE+1] = {
167 "str","strb","strh","str","str","str","str","str","str","??","str"};
168static char *sdtu[MAX_TYPE+1] = {
169 "str","strb","strh","str","str","str","??","??","??","??","??"};
170#define ldt(t) ((t&UNSIGNED) ? ldtu[(t)&NQ] : ldts[(t)&NQ])
171#define sdt(t) ((t&UNSIGNED) ? sdtu[(t)&NQ] : sdts[(t)&NQ])
172
173static char *ldstprefix[] = {
174 "ld","st"
175};
176
177static char *dct[] = {
178 "","byte","short","word","word","word","word","word","word"
179};
180
181static char *ccs[] = {
182 "eq","ne","lt","ge","le","gt",""
183};
184
185static char *logicals[] = {
186 "orr","eor","and"
187};
188
189static char *shifts[2][2] = {
190 "lsl","asr","lsl","lsr"
191};
192
193/* sections */
194#define DATA 0
195#define BSS 1
196#define CODE 2
197#define RODATA 3
198#define SPECIAL 4
199
200#if 0
201static long stack;
202static int stack_valid;
203#endif
204static int newobj;
205static int section = -1;
206
207static char *codename = "\t.text\n";
208static char *dataname = "\t.data\n";
209static char *bssname = "";
210static char *rodataname = "\t.rodata\n";
211
212/* list of floating point constants to output at end of file */
213struct fpconstlist {
214 struct fpconstlist *next;
215 int label;
216 int typ;
217 union atyps val;
218};
219static struct fpconstlist *firstfpc = NULL;
220
221/* data reference pointers at the end of each function */
222struct DataRefPtrList {
223 struct DataRefPtrList *next;
224 int label;
225 struct Var *vptr; /* valid, when label==0 */
226};
227static struct DataRefPtrList *dataptrs = NULL;
228static int drefptr_array_label; /* current array's label */
229
230#define isreg(x) (((x)&(REG|DREFOBJ))==REG)
231#define isconst(x) (((x)&(KONST|DREFOBJ))==KONST)
232
233static int q1reg,q2reg,zreg;
234static struct Var *current_function;
235static int icnt; /* counts number of lines in cur. function */
236
237#define MAXCODELINES 500 /* emit data-ref. ptr array after that */
238#define MAXCOPYINSTS 4 /* max. nb. of load/store copy-instructions */
239
240/* return-instruction */
241static char *ret;
242
243/* label at the end of the function (if any) */
244static int exit_label;
245
246/* assembly-prefixes for labels and external identifiers */
247static char *labprefix="l";
248static char *idprefix="_";
249
250/* variables to calculate the size and partitioning of the stack-frame */
251static long frameoffset,pushoffs,framesize;
252static int needframe;
253static long localsize,rsavesize,argsize,rsaveoffs,maxrsaveoffs;
254
255
256
257static long real_offset(struct obj *o)
258/* calculate the actual current offset of an object relative to the
259 stack-pointer; we use a layout like this:
260 ------------------------------------------------
261 | stack-arguments to this function |
262 ------------------------------------------------
263 | caller-save registers [size=rsavesize] |
264 ------------------------------------------------
265 | local variables [size=localsize] |
266 ------------------------------------------------
267 | arguments to called functions [size=argsize] |
268 ------------------------------------------------
269 All sizes will be aligned as necessary.
270 The stack-pointer will be adjusted at
271 function-entry to leave enough space for the arguments and have it
272 aligned to 16 bytes. Therefore, when calling a function, the
273 stack-pointer is always aligned to 16 bytes.
274*/
275{
276 long off = zm2l(o->v->offset);
277
278 if (off < 0) {
279 /* function parameter */
280 off = localsize + rsavesize - off - zm2l(maxalign);
281 }
282 else {
283 /* local variable */
284 off += argsize;
285 off += zm2l(o->val.vmax);
286 }
287
288 return off;
289}
290
291
292static struct obj *cam(int flags,int base,long offset)
293/* Initializes an addressing-mode structure and returns a pointer to
294 that object. Will not survive a second call! */
295{
296 static struct obj obj;
297 static struct AddressingMode am;
298
299#if 0
300 obj.am = &am;
301 am.flags = flags;
302 am.base = base;
303 am.offset = offset;
304#endif
305 return &obj;
306}
307
308
309static int objalign(struct obj *o)
310/* yields the object's lower two bits, 1 when unknown */
311{
312 if (o->flags & DREFOBJ)
313 return 1;
314 if (o->am)
315 ierror(0);
316 if (!(o->flags & VAR))
317 ierror(0);
318
319 if (isstatic(o->v->storage_class) || isextern(o->v->storage_class)) {
320 /* all static data should be 32-bits aligned */
321 return zm2l(zmand(o->val.vmax,l2zm(3L)));
322 }
323
324 if (isauto(o->v->storage_class)) {
325 zmax of = o->v->offset;
326
327 if (!zmleq(l2zm(0L),of))
328 of = zmsub(l2zm(0L),zmadd(of,maxalign));
329 return zm2l(zmand(zmadd(of,o->val.vmax),l2zm(3L)));
330 }
331
332 ierror(0);
333}
334
335
336static void title(FILE *f)
337/* set file symbol with input file name */
338{
339 extern char *inname;
340 static int done;
341
342 if (!done && f) {
343 done = 1;
344 emit(f,"\t.file\t\"%s\"\n",inname);
345 }
346}
347
348
349static void emitnl(FILE *f)
350/* emit a newline character */
351{
352 emit(f,"\n");
353}
354
355
356static void emit_obj(FILE *f,struct obj *p,int t)
357/* prints an object */
358{
359 if (p->flags & VAR) {
360 if (isauto(p->v->storage_class)) {
361 emit(f,"[%s,#%ld]",regnames[sp],real_offset(p));
362 }
363 else {
364 if (!zmeqto(l2zm(0L),p->val.vmax)) {
365 emitval(f,&p->val,LONG);
366 emit(f,"+");
367 }
368 if (isstatic(p->v->storage_class))
369 emit(f,"%s%ld",labprefix,zm2l(p->v->offset));
370 else
371 emit(f,"%s%s",idprefix,p->v->identifier);
372 }
373 }
374
375 if (p->flags & REG) {
376 emit(f,"%s",regnames[p->reg]);
377 }
378
379 if (p->flags & KONST) {
380 emit(f,"#");
381 emitval(f,&p->val,t&NU);
382 }
383}
384
385
386static int special_section(FILE *f,struct Var *v)
387/* changes to a special section, used for __section() */
388{
389 char *sec;
390
391 if (v->vattr) {
392 if (sec = strstr(v->vattr,"section(")) {
393 sec += strlen("section(");
394 emit(f,"\t.section\t");
395 while (*sec && *sec!=')')
396 emit_char(f,*sec++);
397 emitnl(f);
398 if (f)
399 section = SPECIAL;
400 return 1;
401 }
402 }
403 return 0;
404}
405
406
407static int addfpconst(struct obj *o,int t)
408/* return label for a float-constant, create if it didn't exist */
409{
410 struct fpconstlist *p=firstfpc;
411
412 t &= NQ;
413 if (t == LDOUBLE)
414 t = DOUBLE;
415
416 for (p=firstfpc; p; p=p->next) {
417 if (t == p->typ) {
418 eval_const(&p->val,t);
419 if (t==FLOAT && zldeqto(vldouble,zf2zld(o->val.vfloat)))
420 return p->label;
421 if (t==DOUBLE && zldeqto(vldouble,zd2zld(o->val.vdouble)))
422 return p->label;
423 }
424 }
425
426 p = mymalloc(sizeof(struct fpconstlist));
427 p->next = firstfpc;
428 p->label = ++label;
429 p->typ = t;
430 p->val = o->val;
431 firstfpc = p;
432
433 return p->label;
434}
435
436
437static void emit_dataptr_array(FILE *f)
438/* emit all data-reference pointers which were collected until now,
439 then reset the array */
440{
441 struct DataRefPtrList *drp,*next;
442
443 if (next = dataptrs) {
444 emit(f,"\t.align\t2\n");
445 emit(f,"%s%d:\n",labprefix,drefptr_array_label);
446
447 while (drp = next) {
448 next = drp->next;
449 emit(f,"\t.%s\t",dct[LONG]);
450 if (drp->label) {
451 emit(f,"%s%d\n",labprefix,drp->label);
452 }
453 else {
454 if (isstatic(drp->vptr->storage_class))
455 emit(f,"%s%ld\n",labprefix,zm2l(drp->vptr->offset));
456 else
457 emit(f,"%s%s\n",idprefix,drp->vptr->identifier);
458 }
459 free(drp);
460 }
461 dataptrs = NULL;
462 }
463 drefptr_array_label = 0;
464}
465
466
467static int cg_getreg(FILE *f,struct IC *ic)
468/* allocate a code generator internal general purpose register */
469{
470 /* alloc_code: 1:compiler, 2:backend, >=4:backend rsave-area offset - 4 */
471 int alloc_code = 2;
472 int i,p,r;
473
474 /* try to get a free scratch-register or a non-volatile
475 register which has to be saved anyway,
476 r12 (ip) is reserved to the backend and will be used as well,
477 r14 (lr) is available when the function builds a stack frame */
478 for (i=FIRST_GPR,p=0,r=0; i<FIRST_GPR+13; i++) {
479 if (((i==ip && regs[i]==1) ||
480 (i==lr && regs[i]==1 && needframe) ||
481 (regs[i]==0 && (regscratch[i] || regused[i]))) &&
482 reg_prio[i]+(regused[i]<<8) > p) {
483 p = reg_prio[i] + (regused[i] << 8);
484 r = i;
485 }
486 }
487 if (!r) {
488 /* seems we have to save a new non-volatile register */
489 for (i=FIRST_GPR,p=0; i<FIRST_GPR+13; i++) {
490 if (regs[i]==0 && reg_prio[i]>p) {
491 p = reg_prio[i];
492 r = i;
493 }
494 }
495 }
496 if (!r) {
497 /* no register available - save one to the stack-frame, but
498 make sure it is not used in this IC */
499 for (i=FIRST_GPR,p=0; i<FIRST_GPR+13; i++) {
500 if (regs[i]<2 && reg_prio[i]>p) {
501 if ((!isreg(ic->q1.flags) || ic->q1.reg!=i) &&
502 (!isreg(ic->q2.flags) || ic->q2.reg!=i) &&
503 (!isreg(ic->z.flags) || ic->z.reg!=i)) {
504 p = reg_prio[i];
505 r = i;
506 }
507 }
508 }
509 if (r) {
510 if (f)
511 emit(f,"\tstr\t%s,[%s,#%ld]\n",
512 regnames[r],regnames[sp],argsize+localsize+rsaveoffs);
513 rsaveoffs += 4;
514 if (rsaveoffs > maxrsaveoffs)
515 maxrsaveoffs = rsaveoffs;
516 alloc_code = rsaveoffs;
517 }
518 else
519 ierror(0);
520 }
521
522 regs[r] = alloc_code;
523 regused[r] = 1;
524 return r;
525}
526
527
528static int cg_getdpreg(FILE *f,struct IC *ic)
529/* allocate a code generator internal double precision FP register */
530{
531 int i,p,r;
532 struct rpair rp;
533
534 /* try to get a free scratch-register or a non-volatile
535 register which has to be saved anyway */
536 for (i=FIRST_DOUBLE,p=0,r=0; i<=LAST_PAIR; i++) {
537 if (regs[i]==0 && (regscratch[i] || regused[i]) &&
538 reg_prio[i]+(regused[i]<<8) > p && reg_pair(i,&rp)) {
539 if (regs[rp.r1]==0 && regs[rp.r2]==0) {
540 p = reg_prio[i] + (regused[i] << 8);
541 r = i;
542 }
543 }
544 }
545 if (!r) {
546 ierror(0); /* @@@ FIXME */
547 }
548
549 regs[r] = 2;
550 regused[r] = 1;
551 if (!reg_pair(i,&rp))
552 ierror(0);
553 regs[rp.r1] = regs[rp.r2] = 2;
554 regused[rp.r1] = regused[rp.r2] = 1;
555 return r;
556}
557
558
559static void cg_restorereg(FILE *f,int r)
560{
561 if (f) {
562 if (r <= LAST_GPR)
563 emit(f,"\tldr\t%s,[%s,#%ld]\n",
564 regnames[r],regnames[sp],argsize+localsize+regs[r]-4);
565 else
566 ierror(0); /* @@@ FIXME */
567 }
568}
569
570
571static void cg_freereg(FILE *f,int r)
572/* free a code generator internal general purpose register */
573{
574 struct rpair rp;
575
576 if (regs[r] > 1) {
577 if (regs[r] > 2)
578 cg_restorereg(f,r);
579 regs[r] = (r==ip||r==lr) ? 1 : 0; /* ip/lr need to stay reserved */
580 }
581 else
582 ierror(0);
583
584 if (reg_pair(r,&rp)) {
585 if (regs[rp.r1]>1 && regs[rp.r2]>1) {
586 if (regs[rp.r1] > 2)
587 cg_restorereg(f,rp.r1);
588 if (regs[rp.r2] > 2)
589 cg_restorereg(f,rp.r2);
590 regs[rp.r1] = regs[rp.r2] = 0;
591 }
592 else
593 ierror(0);
594 }
595}
596
597
598static void cg_freeall(FILE *f)
599/* reset internal register allocations */
600{
601 int i;
602
603 for (i=1; i<=MAXR; i++) {
604 if (regs[i] > 1) {
605 if (regs[i] > 2)
606 cg_restorereg(f,i);
607 regs[i] = (i==ip||i==lr) ? 1 : 0; /* ip/lr need to stay reserved */
608 }
609 }
610 rsaveoffs = 0;
611}
612
613
614static long dataptr_offset(int label,struct obj *o)
615/* return offset into data-reference-pointer array for label l
616 or for object o (mutually exclusive) */
617{
618 long off = 0;
619 struct DataRefPtrList **olddrp = &dataptrs;
620 struct DataRefPtrList *drp = dataptrs;
621
622 if (!label) {
623 if (!(o->flags & VAR))
624 ierror(0);
625 if (!isstatic(o->v->storage_class) && !isextern(o->v->storage_class))
626 ierror(0);
627 }
628
629 /* check if a pointer to this object already exists */
630 while (drp) {
631 if (label) {
632 if (drp->label == label)
633 break;
634 }
635 else {
636 if (drp->vptr == o->v)
637 break;
638 }
639 olddrp = &drp->next;
640 drp = drp->next;
641 off += 4;
642 }
643
644 /* create a new entry if it doesn't exist */
645 if (drp == NULL) {
646 *olddrp = drp = mymalloc(sizeof(struct DataRefPtrList));
647
648 drp->next = NULL;
649 if (drp->label = label)
650 drp->vptr = NULL;
651 else
652 drp->vptr = o->v;
653 }
654
655 return off;
656}
657
658
659static void load_dataptr(FILE *f,int r,int l,struct obj *o)
660/* load data-reference-pointer array entry for label l or object o into r */
661{
662 BSET(regs_modified,r);
663
664 if (!drefptr_array_label)
665 drefptr_array_label = ++label;
666
667 emit(f,"\tldr\t%s,%s%d+%ld\n",
668 regnames[r],labprefix,drefptr_array_label,dataptr_offset(l,o));
669}
670
671
672static void ldst64(FILE *f,int store,struct rpair *rp,int base)
673/* generate a ldmia or stmia (store=1) instruction to transfer a 64-bit
674 value in register pair rp pointed to by base-register base */
675{
676 emit(f,"%smia\t%s,{%s-%s}\n",
677 ldstprefix[store],regnames[base],regnames[rp->r1],regnames[rp->r2]);
678}
679
680
681static void load_address(FILE *f,int r,struct obj *o,int type)
682/* Generates code to load the address of a variable into register r. */
683{
684 BSET(regs_modified,r);
685
686 if (!(o->flags & VAR))
687 ierror(0);
688
689 if (isauto(o->v->storage_class))
690 emit(f,"\tadd\t%s,%s,#%ld\n",regnames[r],regnames[sp],real_offset(o));
691 else
692 load_dataptr(f,r,0,o);
693}
694
695
696static void load_regindir(FILE *f,struct IC *p,int type,
697 int dst,int base,long off)
698/* Load register dst of type type from [base,#off].
699 base and dst may be the same.
700 Perform size extensions as required by architecture. */
701{
702 BSET(regs_modified,dst);
703
704 if (aa >= AA4) {
705 emit(f,"\t%s\t%s,[%s,#%ld]\n",
706 ldt(type),regnames[dst],regnames[base],off);
707 }
708
709 else {
710 /* this requires more effort on older ARMs */
711 int tmp;
712
713 switch (sizetab[type&NQ]) {
714 case 1:
715 emit(f,"\tldrb\t%s,[%s,#%ld]\n",regnames[dst],regnames[base],off);
716 if (!(type & UNSIGNED)) {
717 emit(f,"\tmov\t%s,%s,lsl #24\n",regnames[dst],regnames[dst]);
718 emit(f,"\tmov\t%s,%s,asr #24\n",regnames[dst],regnames[dst]);
719 }
720 break;
721 case 2:
722 tmp = cg_getreg(f,p);
723 emit(f,"\tldrb\t%s,[%s,#%ld]\n",regnames[tmp],regnames[base],
724 off+1-arm_le_mode);
725 emit(f,"\tldrb\t%s,[%s,#%ld]\n",regnames[dst],regnames[base],
726 off+arm_le_mode);
727 if (!(type & UNSIGNED)) {
728 emit(f,"\tmov\t%s,%s,lsl #24\n",regnames[dst],regnames[dst]);
729 emit(f,"\torr\t%s,%s,%s asr #16\n",
730 regnames[dst],regnames[tmp],regnames[dst]);
731 }
732 else {
733 emit(f,"\torr\t%s,%s,%s lsl #8\n",
734 regnames[dst],regnames[tmp],regnames[dst]);
735 }
736 cg_freereg(f,tmp);
737 break;
738 case 4:
739 emit(f,"\tldr\t%s,[%s,#%ld]\n",regnames[dst],regnames[base],off);
740 break;
741 default:
742 ierror(0);
743 }
744 }
745}
746
747
748static void load_reg(FILE *f,struct IC *p,int r,struct obj *o,int type)
749/* Generates code to load a memory object into register r. */
750{
751 type &= NU;
752 BSET(regs_modified,r);
753
754 if (o->flags & KONST) {
755 /* evaluate and load a constant */
756
757 eval_const(&o->val,type);
758
759 if (ISFLOAT(type)) {
760 int lab = addfpconst(o,type);
761
762 load_dataptr(f,r,lab,NULL);
763 if (type == FLOAT)
764 load_regindir(f,p,type,r,r,0);
765 else
766 ierror(0); /* double can only be in a register-pair */
767 }
768
769 else {
770 /* integer constant */
771 emit(f,"\tmov\t%s,",regnames[r]);
772 emit_obj(f,o,type);
773 emitnl(f);
774 }
775 }
776
777 else if (isreg(o->flags)) {
778 if (r != o->reg)
779 emit(f,"\tmov\t%s,%s\n",regnames[r],regnames[o->reg]);
780 }
781
782 else if ((o->flags & (REG|DREFOBJ)) == (REG|DREFOBJ)) {
783 load_regindir(f,p,type,r,o->reg,0);
784 }
785
786 else if (o->flags & VAR) {
787 if (isstatic(o->v->storage_class) || isextern(o->v->storage_class)) {
788 /* load from a static variable */
789 if (o->flags & VARADR) {
790 load_address(f,r,o,POINTER);
791 }
792 else {
793 load_dataptr(f,r,0,o);
794 load_regindir(f,p,type,r,r,zm2l(o->val.vmax));
795 }
796 }
797 else {
798 /* dynamic variable on stack */
799 load_regindir(f,p,type,r,sp,real_offset(o));
800 }
801 }
802
803 else
804 ierror(0);
805}
806
807
808static void store_regindir(FILE *f,struct IC *p,int type,
809 int src,int base,long off)
810/* Store register src of type type to [base,#off]. */
811{
812 if (aa>=AA4 || sizetab[type&NQ]!=2) {
813 emit(f,"\t%s\t%s,[%s,#%ld]\n",
814 sdt(type),regnames[src],regnames[base],off);
815 }
816
817 else {
818 /* storing halfwords requires more effort on older ARMs */
819 int tmp = cg_getreg(f,p);
820
821 emit(f,"\tstrb\t%s,[%s,#%ld]\n",regnames[src],regnames[base],
822 off+1-arm_le_mode);
823 emit(f,"\tmov\t%s,%s,asr #8\n",regnames[tmp],regnames[src]);
824 emit(f,"\tstrb\t%s,[%s,#%ld]\n",regnames[src],regnames[base],
825 off+arm_le_mode);
826 cg_freereg(f,tmp);
827 }
828}
829
830
831static void store_reg(FILE *f,struct IC *p,int r,struct obj *o,int type)
832/* Generates code to store register r into memory object o. */
833{
834 if (isreg(o->flags)) {
835 if (r != o->reg)
836 emit(f,"\tmov\t%s,%s\n",regnames[o->reg],regnames[r]);
837 }
838
839 else if ((o->flags & (REG|DREFOBJ)) == (REG|DREFOBJ)) {
840 store_regindir(f,p,type,r,o->reg,0);
841 }
842
843 else if (o->flags & VAR) {
844 if (isstatic(o->v->storage_class) || isextern(o->v->storage_class)) {
845 /* store to a static variable */
846 int tmp = cg_getreg(f,p);
847
848 load_dataptr(f,tmp,0,o);
849 store_regindir(f,p,type,r,tmp,zm2l(o->val.vmax));
850 cg_freereg(f,tmp);
851 }
852 else {
853 /* dynamic variable on stack */
854 store_regindir(f,p,type,r,sp,real_offset(o));
855 }
856 }
857
858 else
859 ierror(0);
860}
861
862
863static int load_objptr(FILE *f,struct IC *p,struct obj *o)
864/* Make sure object o can be dereferenced by a single load.
865 Return new base register, or 0 if object was not modified. */
866{
867 if ((o->flags & (REG|DREFOBJ)) == DREFOBJ) {
868 int r = cg_getreg(f,p);
869
870 load_reg(f,p,r,o,POINTER);
871 o->flags |= REG;
872 o->reg = r;
873 return r;
874 }
875
876 if ((o->flags & (VAR|REG)) == VAR) {
877 if (isstatic(o->v->storage_class) || isextern(o->v->storage_class)) {
878 int r = cg_getreg(f,p);
879
880 load_dataptr(f,r,0,o);
881 o->reg = r;
882 o->flags = REG|DREFOBJ;
883 return r;
884 }
885 }
886
887 return 0;
888}
889
890
891static void load_regpair(FILE *f,struct IC *p,struct rpair *rp,
892 struct obj *o,int type)
893/* Generates code to load a memory object into the register pair rp.
894 tmp is a general purpose register which may be used. */
895{
896 BSET(regs_modified,rp->r1);
897 BSET(regs_modified,rp->r2);
898
899 if (o->flags & KONST) {
900 /* evaluate and load a constant */
901 eval_const(&o->val,type);
902
903 if (ISFLOAT(type)) {
904 int lab = addfpconst(o,type);
905 int tmp = cg_getreg(f,p);
906
907 load_dataptr(f,tmp,lab,NULL);
908 if (type != FLOAT)
909 ldst64(f,0,rp,tmp);
910 else
911 ierror(0); /* have to load float in a single register */
912 cg_freereg(f,tmp);
913 }
914 else {
915 struct obj cobj;
916
917 cobj.flags = KONST;
918 cobj.val.vulong = zum2zul(zumand(vumax,ul2zum(0xffffffff)));
919 load_reg(f,p,arm_le_mode?rp->r1:rp->r2,&cobj,UNSIGNED|LONG);
920 cobj.val.vulong = zum2zul(zumand(zumrshift(vumax,ul2zum(32UL)),
921 ul2zum(0xffffffff)));
922 load_reg(f,p,arm_le_mode?rp->r2:rp->r1,&cobj,UNSIGNED|LONG);
923 }
924 }
925
926 else {
927 /* make sure that object can be addressed through a register */
928 load_objptr(f,p,o);
929
930 if (isreg(o->flags)) {
931 struct rpair qrp;
932
933 if (!reg_pair(o->reg,&qrp))
934 ierror(0);
935 if (qrp.r1 != rp->r1) {
936 emit(f,"\tmov\t%s,%s\n\tmov\t%s,%s\n",regnames[rp->r1],
937 regnames[qrp.r1],regnames[rp->r2],regnames[qrp.r2]);
938 }
939 }
940 else if ((o->flags & (REG|DREFOBJ)) == (REG|DREFOBJ)) {
941 ldst64(f,0,rp,o->reg);
942 }
943 else
944 ierror(0);
945 }
946}
947
948
949static void store_regpair(FILE *f,struct IC *p,struct rpair *rp,
950 struct obj *o,int type)
951/* Generates code to store the register pair rp into memory object o.
952 tmp is a general purpose register which may be used. */
953{
954 /* make sure that object can be addressed through a register */
955 load_objptr(f,p,o);
956
957 if (isreg(o->flags)) {
958 struct rpair zrp;
959
960 if (!reg_pair(o->reg,&zrp))
961 ierror(0);
962 if (zrp.r1 != rp->r1) {
963 emit(f,"\tmov\t%s,%s\n\tmov\t%s,%s\n",regnames[zrp.r1],
964 regnames[rp->r1],regnames[zrp.r2],regnames[rp->r2]);
965 }
966 }
967 else if ((o->flags & (REG|DREFOBJ)) == (REG|DREFOBJ)) {
968 ldst64(f,1,rp,o->reg);
969 }
970 else
971 ierror(0);
972}
973
974
975static long pof2(zumax x)
976/* yields log2(x)+1 or 0 */
977{
978 zumax p;
979 int ln = 1;
980
981 p = ul2zum(1L);
982 while (ln<=32 && zumleq(p,x)) {
983 if (zumeqto(x,p))
984 return ln;
985 ln++;
986 p = zumadd(p,p);
987 }
988 return 0;
989}
990
991
992static struct IC *preload(FILE *f,struct IC *p)
993/* Does some pre-processing like fetching operands from memory to
994 registers etc. */
995/* @@@ FIXME - Is this function needed at all ??? */
996{
997#if 0
998 if (isreg(p->q1.flags))
999 q1reg = p->q1.reg;
1000 else
1001 q1reg = 0;
1002
1003 if (isreg(p->q2.flags))
1004 q2reg = p->q2.reg;
1005 else
1006 q2reg = 0;
1007#endif
1008
1009 if (isreg(p->z.flags)) {
1010 zreg = p->z.reg;
1011 }
1012 else {
1013 if (ISFLOAT(ztyp(p)))
1014 zreg = FIRST_PAIR; /* @@@ VFP? ->f1 */
1015 else
1016 zreg = cg_getreg(f,p);
1017 }
1018
1019#if 0 /* Better use load_objptr() when needed? */
1020 if ((p->q1.flags & (REG|DREFOBJ)) == DREFOBJ) {
1021 int tmp = cg_getreg(f,p);
1022
1023 p->q1.flags &= ~DREFOBJ;
1024 load_reg(f,p,tmp,&p->q1,q1typ(p));
1025 p->q1.reg = tmp;
1026 p->q1.flags |= REG|DREFOBJ;
1027 }
1028
1029 if ((p->q2.flags & (REG|DREFOBJ)) == DREFOBJ) {
1030 int tmp = cg_getreg(f,p);
1031
1032 p->q2.flags &= ~DREFOBJ;
1033 load_reg(f,p,tmp,&p->q2,q2typ(p));
1034 p->q2.reg = tmp;
1035 p->q2.flags |= REG|DREFOBJ;
1036 }
1037#endif
1038
1039 return p;
1040}
1041
1042
1043static void save_result(FILE *f,struct IC *p)
1044/* save the result (in zreg) into p->z */
1045{
1046 if ((p->z.flags&(REG|DREFOBJ)) == DREFOBJ) {
1047 int tmp = cg_getreg(f,p);
1048
1049 p->z.flags &= ~DREFOBJ;
1050 load_reg(f,p,tmp,&p->z,POINTER);
1051 p->z.reg = tmp;
1052 p->z.flags |= REG|DREFOBJ;
1053 }
1054 if (isreg(p->z.flags)) {
1055 if (p->z.reg != zreg)
1056 emit(f,"\tmov\t%s,%s\n",regnames[p->z.reg],regnames[zreg]);
1057 }
1058 else {
1059 store_reg(f,p,zreg,&p->z,ztyp(p));
1060 }
1061}
1062
1063
1064static void registerize(FILE *f,struct IC *p,struct obj *o,int t)
1065/* make sure object is loaded into a register */
1066{
1067 if (!(isreg(o->flags))) {
1068 int r;
1069
1070 r = load_objptr(f,p,o);
1071 if (!r)
1072 r = cg_getreg(f,p);
1073 if ((o->flags & (REG|DREFOBJ)) == DREFOBJ)
1074 ierror(0);
1075 load_reg(f,p,r,o,t);
1076 o->reg = r;
1077 }
1078 o->flags = REG;
1079}
1080
1081
1082static void cg_memcopy(FILE *f,struct IC *p)
1083/* generates code to copy an object of non-elementary type (ARRAY, STRUCT) */
1084{
1085 unsigned long size = opsize(p);
1086 int a1 = objalign(&p->q1);
1087 int a2 = (p->code==ASSIGN) ? objalign(&p->z) : 0;
1088 int b = 1;
1089 char *ld = ldt(CHAR);
1090 char *st = sdt(CHAR);
1091 unsigned long l;
1092 int srcreg,dstreg,tmpreg,cntreg,ncp;
1093
1094 if (p->q1.flags & VAR) {
1095 if (p->q1.flags & DREFOBJ) {
1096 if (p->q1.v->vtyp->next &&
1097 zmeqto(p->q2.val.vmax,szof(p->q1.v->vtyp->next)) && (a1&1)) {
1098 a1 = zm2l(falign(p->q1.v->vtyp->next)) & 3;
1099 a2 &= a1;
1100 }
1101 }
1102 else {
1103 if (zmeqto(p->q2.val.vmax,szof(p->q1.v->vtyp)) && (a1&1)) {
1104 a1 = zm2l(falign(p->q1.v->vtyp)) & 3;
1105 a2 &= a1;
1106 }
1107 }
1108 }
1109 if (p->z.flags & VAR) {
1110 if (p->z.flags & DREFOBJ) {
1111 if (p->z.v->vtyp->next &&
1112 zmeqto(p->q2.val.vmax,szof(p->z.v->vtyp->next)) && (a2&1)) {
1113 a2 = zm2l(falign(p->z.v->vtyp->next)) & 3;
1114 a1 &= a2;
1115 }
1116 }
1117 else {
1118 if (zmeqto(p->q2.val.vmax,szof(p->z.v->vtyp)) && (a2&1)) {
1119 a2 = zm2l(falign(p->z.v->vtyp)) & 3;
1120 a1 &= a2;
1121 }
1122 }
1123 }
1124
1125 /* @@@ implement with ldmia/stmia */
1126 if (a1>=0 && a2>=0) {
1127 if (a1==0 && a2==0) {
1128 /* 32-bit copy */
1129 b = 4;
1130 ld = ldt(LONG);
1131 st = sdt(LONG);
1132 }
1133 else if ((a1&1)==0 && (a2&1)==0 && aa>=AA4) {
1134 /* 16-bit copy for ARM-architecture 4 and better only */
1135 b = 2;
1136 ld = ldt(SHORT);
1137 st = sdt(SHORT);
1138 }
1139 }
1140
1141 srcreg = cg_getreg(f,p);
1142 BSET(regs_modified,srcreg);
1143
1144 if (p->q1.flags & DREFOBJ) {
1145 p->q1.flags &= ~DREFOBJ;
1146 if (isreg(p->q1.flags))
1147 emit(f,"\tmov\t%s,%s\n",regnames[srcreg],regnames[p->q1.reg]);
1148 else
1149 load_reg(f,p,srcreg,&p->q1,POINTER);
1150 p->q1.flags |= DREFOBJ;
1151 }
1152 else {
1153 load_address(f,srcreg,&p->q1,POINTER);
1154 }
1155
1156 dstreg = cg_getreg(f,p);
1157 BSET(regs_modified,dstreg);
1158
1159 if (p->z.flags & DREFOBJ) {
1160 p->z.flags &= ~DREFOBJ;
1161 if (isreg(p->z.flags))
1162 emit(f,"\tmov\t%s,%s\n",regnames[dstreg],regnames[p->z.reg]);
1163 else
1164 load_reg(f,p,dstreg,&p->z,POINTER);
1165 p->z.flags |= DREFOBJ;
1166 }
1167 else {
1168 if (p->code == PUSH) {
1169 emit(f,"\tadd\t%s,%s,#%ld\n",regnames[dstreg],regnames[sp],pushoffs);
1170 pushoffs += size;
1171 }
1172 else
1173 load_address(f,dstreg,&p->z,POINTER);
1174 }
1175
1176 tmpreg = cg_getreg(f,p);
1177 BSET(regs_modified,tmpreg);
1178 l = size/b;
1179
1180 if (l > MAXCOPYINSTS) { /* @@@ make MAXCOPYINSTS changeable by an option? */
1181 cntreg = cg_getreg(f,p);
1182 BSET(regs_modified,cntreg);
1183 emit(f,"\tmov\t%s,#%lu\n",regnames[cntreg],l);
1184 emit(f,"%s%d:\n",labprefix,++label);
1185 ncp = 1;
1186 }
1187 else
1188 ncp = l;
1189 while (ncp--) {
1190 emit(f,"\t%s\t%s,[%s],#%d\n",ld,regnames[tmpreg],regnames[srcreg],b);
1191 emit(f,"\t%s\t%s,[%s],#%d\n",st,regnames[tmpreg],regnames[dstreg],b);
1192 }
1193 if (l > MAXCOPYINSTS) {
1194 emit(f,"\tsubs\t%s,%s,#1\n",regnames[cntreg],regnames[cntreg]);
1195 emit(f,"\tbne\t%s%d\n",labprefix,label);
1196 cg_freereg(f,cntreg);
1197 }
1198
1199 size = size % b;
1200 ncp = 0;
1201 if (size & 2) {
1202 if (aa >= AA4) {
1203 emit(f,"\t%s\t%s,[%s],#%d\n",ldt(SHORT),regnames[tmpreg],regnames[srcreg],b);
1204 emit(f,"\t%s\t%s,[%s],#%d\n",sdt(SHORT),regnames[tmpreg],regnames[dstreg],b);
1205 }
1206 else
1207 ncp = 2;
1208 }
1209 ncp += (size & 1);
1210 while (ncp--) {
1211 emit(f,"\t%s\t%s,[%s],#%d\n",ldt(CHAR),regnames[tmpreg],regnames[srcreg],b);
1212 emit(f,"\t%s\t%s,[%s],#%d\n",sdt(CHAR),regnames[tmpreg],regnames[dstreg],b);
1213 }
1214}
1215
1216
1217static int exists_freereg(struct IC *p,int reg)
1218/* Test if there is a sequence of FREEREGs containing FREEREG reg.
1219 Used by peephole(). */
1220{
1221 while (p && (p->code==FREEREG || p->code==ALLOCREG)) {
1222 if (p->code==FREEREG && p->q1.reg==reg)
1223 return 1;
1224 p=p->next;
1225 }
1226 return 0;
1227}
1228
1229
1230#if 0
1231static void peephole(struct IC *p)
1232/* search for possible addressing-modes */
1233{
1234 int c,c2,r;struct IC *p2;struct AddressingMode *am;
1235
1236 for(;p;p=p->next){
1237 c=p->code;
1238 if(c!=FREEREG&&c!=ALLOCREG&&(c!=SETRETURN||!isreg(p->q1.flags)||p->q1.reg!=p->z.reg)) exit_label=0;
1239 if(c==LABEL) exit_label=p->typf;
1240
1241 /* Try const(reg) */
1242 if(IMM_IND&&(c==ADDI2P||c==SUBIFP)&&isreg(p->z.flags)&&isconst(p->q2.flags)){
1243 int base;zmax of;struct obj *o;
1244 eval_const(&p->q2.val,p->typf);
1245 if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
1246 if(1/*zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))*/){
1247 r=p->z.reg;
1248 if(isreg(p->q1.flags)) base=p->q1.reg; else base=r;
1249 o=0;
1250 for(p2=p->next;p2;p2=p2->next){
1251 c2=p2->code;
1252 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
1253 if(c2!=FREEREG&&isreg(p2->q1.flags)&&p2->q1.reg==r) break;
1254 if(c2!=FREEREG&&isreg(p2->q2.flags)&&p2->q2.reg==r) break;
1255 if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/){
1256 if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
1257 if(o) break;
1258 o=&p2->q1;
1259 }
1260 if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
1261 if(o) break;
1262 o=&p2->q2;
1263 }
1264 if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
1265 if(o) break;
1266 o=&p2->z;
1267 }
1268 }
1269 if(c2==FREEREG||isreg(p2->z.flags)){
1270 int m;
1271 if(c2==FREEREG)
1272 m=p2->q1.reg;
1273 else
1274 m=p2->z.reg;
1275 if(m==r){
1276 if(o){
1277 o->am=am=mymalloc(sizeof(*am));
1278 am->flags=IMM_IND;
1279 am->base=base;
1280 am->offset=zm2l(of);
1281 if(isreg(p->q1.flags)){
1282 p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
1283 }else{
1284 p->code=c=ASSIGN;p->q2.flags=0;
1285 p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ];
1286 }
1287 }
1288 break;
1289 }
1290 if(c2!=FREEREG&&m==base) break;
1291 continue;
1292 }
1293 }
1294 }
1295 }
1296 /* Try reg,reg */
1297 if(GPR_IND&&c==ADDI2P&&isreg(p->q2.flags)&&isreg(p->z.flags)&&(isreg(p->q1.flags)||p->q2.reg!=p->z.reg)){
1298 int base,idx;struct obj *o;
1299 r=p->z.reg;idx=p->q2.reg;
1300 if(isreg(p->q1.flags)) base=p->q1.reg; else base=r;
1301 o=0;
1302 for(p2=p->next;p2;p2=p2->next){
1303 c2=p2->code;
1304 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
1305 if(c2!=FREEREG&&isreg(p2->q1.flags)&&p2->q1.reg==r) break;
1306 if(c2!=FREEREG&&isreg(p2->q2.flags)&&p2->q2.reg==r) break;
1307 if(isreg(p2->z.flags)&&p2->z.reg==idx&&idx!=r) break;
1308
1309 if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/){
1310 if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
1311 if(o||(q1typ(p2)&NQ)==LLONG) break;
1312 o=&p2->q1;
1313 }
1314 if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
1315 if(o||(q2typ(p2)&NQ)==LLONG) break;
1316 o=&p2->q2;
1317 }
1318 if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
1319 if(o||(ztyp(p2)&NQ)==LLONG) break;
1320 o=&p2->z;
1321 }
1322 }
1323 if(c2==FREEREG||isreg(p2->z.flags)){
1324 int m;
1325 if(c2==FREEREG)
1326 m=p2->q1.reg;
1327 else
1328 m=p2->z.reg;
1329 if(m==r){
1330 if(o){
1331 o->am=am=mymalloc(sizeof(*am));
1332 am->flags=GPR_IND;
1333 am->base=base;
1334 am->offset=idx;
1335 if(isreg(p->q1.flags)){
1336 p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
1337 }else{
1338 p->code=c=ASSIGN;p->q2.flags=0;
1339 p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ];
1340 }
1341 }
1342 break;
1343 }
1344 if(c2!=FREEREG&&m==base) break;
1345 continue;
1346 }
1347 }
1348 }
1349 }
1350}
1351#endif
1352
1353
1354static void function_top(FILE *f,struct Var *v,long offset)
1355/* generates the function entry code */
1356{
1357 static char ret_instr[64];
1358 char gprsave[32];
1359 char *p;
1360 int i;
1361
1362 title(f);
1363
1364 /* determine rsavesize and registers to save */
1365 rsavesize = 0;
1366 gprsave[0] = '\0';
1367 for (i=FIRST_GPR,p=gprsave; i<=LAST_GPR; i++) {
1368 if (!regsa[i] && !regscratch[i] && regused[i]) {
1369 p += sprintf(p,"%s,",regnames[i]);
1370 rsavesize += 4;
1371 }
1372 }
1373
1374 if (!special_section(f,v) && section!=CODE) {
1375 emit(f,codename);
1376 section = CODE;
1377 }
1378
1379 if (isextern(v->storage_class)) {
1380 if ((v->flags & (INLINEFUNC|INLINEEXT)) != INLINEFUNC)
1381 emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
1382 emit(f,"%s%s:\n",idprefix,v->identifier);
1383 }
1384 else
1385 emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
1386
1387 if (rsavesize==0 && !needframe) {
1388 ret = "\tmov\tpc,lr\n";
1389 }
1390 else {
1391 rsavesize += 3*4; /* sp,lr,pc to be saved as well */
1392 emit(f,"\tstmfd\t%s!,{%s%s,%s,%s}\n",
1393 regnames[sp],gprsave,regnames[sp],regnames[lr],regnames[pc]);
1394 sprintf(ret_instr,"\tldmfd\t%s,{%s%s,%s}\n",
1395 regnames[sp],gprsave,regnames[sp],regnames[pc]);
1396 ret = ret_instr;
1397 if (localsize+argsize > 0) {
1398 emit(f,"\tsub\t%s,%s,#%ld\n",
1399 regnames[sp],regnames[sp],localsize+argsize);
1400 }
1401 }
1402}
1403
1404
1405static void function_bottom(FILE *f,struct Var *v,long offset)
1406/* generates the function exit code */
1407{
1408 if (localsize+argsize > 0) {
1409 emit(f,"\tadd\t%s,%s,#%ld\n",
1410 regnames[sp],regnames[sp],localsize+argsize);
1411 }
1412 emit(f,ret);
1413 emit_dataptr_array(f);
1414
1415 if (isextern(v->storage_class)) {
1416 emit(f,"\t.type\t%s%s,@function\n",idprefix,v->identifier);
1417 emit(f,"\t.size\t%s%s,.-%s%s\n\n",
1418 idprefix,v->identifier,idprefix,v->identifier);
1419 }
1420 else {
1421 emit(f,"\t.type\t%s%ld,@function\n",labprefix,zm2l(v->offset));
1422 emit(f,"\t.size\t%s%ld,.-%s%ld\n\n",
1423 labprefix,zm2l(v->offset),labprefix,zm2l(v->offset));
1424 }
1425
1426 /*if(all_regs&&v->fi) v->fi->flags|=ALL_REGS;*/
1427}
1428
1429
1430/****************************************/
1431/* End of private data and functions. */
1432/****************************************/
1433
1434
1435int init_cg(void)
1436/* Does necessary initializations for the code-generator. Gets called */
1437/* once at the beginning and should return 0 in case of problems. */
1438{
1439 int i;
1440
1441 /* Initialize some values which cannot be statically initialized */
1442 /* because they are stored in the target's arithmetic. */
1443 maxalign = l2zm(8L);
1444 stackalign = l2zm(4L);
1445 char_bit = l2zm(8L);
1446
1447 for (i=0; i<=MAX_TYPE; i++) {
1448 sizetab[i] = l2zm(msizetab[i]);
1449 align[i] = l2zm(malign[i]);
1450 }
1451
1452 for (i=FIRST_GPR; i<=LAST_GPR; i++) {
1453 regsize[i] = l2zm(4L);
1454 regtype[i] = &ltyp;
1455 }
1456
1457 for (i=FIRST_FPR; i<=LAST_FPR; i++) {
1458 regsize[i] = l2zm(8L);
1459 regtype[i] = &ftyp;
1460 }
1461
1462 for (i=FIRST_CCR; i<=LAST_CCR; i++) {
1463 regsize[i] = l2zm(4L);
1464 regtype[i] = &ltyp;
1465 }
1466
1467 for (i=FIRST_PAIR; i<FIRST_DOUBLE; i++) {
1468 regsize[i] = l2zm(8L);
1469 regtype[i] = &lltyp;
1470 }
1471
1472 for (i=FIRST_DOUBLE; i<=LAST_PAIR; i++) {
1473 regsize[i] = l2zm(8L);
1474 regtype[i] = &dtyp;
1475 }
1476
1477 /* Initialize the min/max-settings. Note that the types of the */
1478 /* host system may be different from the target system and you may */
1479 /* only use the smallest maximum values ANSI guarantees if you */
1480 /* want to be portable. */
1481 /* That's the reason for the subtraction in t_min[INT]. Long could */
1482 /* be unable to represent -2147483648 on the host system. */
1483 t_min[CHAR] = l2zm(-128L);
1484 t_min[SHORT] = l2zm(-32768L);
1485 t_min[INT] = zmsub(l2zm(-2147483647L),l2zm(1L));
1486 t_min[LONG] = t_min(INT);
1487 t_min[LLONG] = zmlshift(l2zm(1L),l2zm(63L));
1488 t_min[MAXINT] = t_min(LLONG);
1489 t_max[CHAR] = ul2zum(127L);
1490 t_max[SHORT] = ul2zum(32767UL);
1491 t_max[INT] = ul2zum(2147483647UL);
1492 t_max[LONG] = t_max(INT);
1493 t_max[LLONG] = zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL));
1494 t_max[MAXINT] = t_max(LLONG);
1495 tu_max[CHAR] = ul2zum(255UL);
1496 tu_max[SHORT] = ul2zum(65535UL);
1497 tu_max[INT] = ul2zum(4294967295UL);
1498 tu_max[LONG] = t_max(UNSIGNED|INT);
1499 tu_max[LLONG] = zumkompl(ul2zum(0UL));
1500 tu_max[MAXINT] = t_max(UNSIGNED|LLONG);
1501
1502 /* Reserve a few registers for use by the code-generator. */
1503 regsa[ip] = regsa[sp] = regsa[lr] = regsa[pc] = 1;
1504 regscratch[ip] = regscratch[sp] = regscratch[lr] = regscratch[pc] = 0;
1505
1506 if (LE_MODE)
1507 arm_le_mode = 1;
1508 if (BE_MODE)
1509 arm_le_mode = 0;
1510 if (ARM_DEFAULT)
1511 thumb_default = 0;
1512 if (THUMB_DEFAULT)
1513 thumb_default = 1;
1514 if (ELF_LABELS) {
1515 labprefix = ".l";
1516 idprefix = "";
1517 }
1518
1519 target_macros = marray;
1520
1521
1522 /* TODO: set argument registers */
1523 declare_builtin("__mulint64",LLONG,LLONG,0,LLONG,0,1,0);
1524 declare_builtin("__addint64",LLONG,LLONG,0,LLONG,0,1,0);
1525 declare_builtin("__subint64",LLONG,LLONG,0,LLONG,0,1,0);
1526 declare_builtin("__andint64",LLONG,LLONG,0,LLONG,0,1,0);
1527 declare_builtin("__orint64",LLONG,LLONG,0,LLONG,0,1,0);
1528 declare_builtin("__eorint64",LLONG,LLONG,0,LLONG,0,1,0);
1529 declare_builtin("__negint64",LLONG,LLONG,0,0,0,1,0);
1530 declare_builtin("__lslint64",LLONG,LLONG,0,INT,0,1,0);
1531
1532 declare_builtin("__divsint64",LLONG,LLONG,0,LLONG,0,1,0);
1533 declare_builtin("__divuint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
1534 declare_builtin("__modsint64",LLONG,LLONG,0,LLONG,0,1,0);
1535 declare_builtin("__moduint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
1536 declare_builtin("__lsrsint64",LLONG,LLONG,0,INT,0,1,0);
1537 declare_builtin("__lsruint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,INT,0,1,0);
1538 declare_builtin("__cmpsint64",INT,LLONG,0,LLONG,0,1,0);
1539 declare_builtin("__cmpuint64",INT,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
1540 declare_builtin("__sint64toflt32",FLOAT,LLONG,0,0,0,1,0);
1541 declare_builtin("__uint64toflt32",FLOAT,UNSIGNED|LLONG,0,0,0,1,0);
1542 declare_builtin("__sint64toflt64",DOUBLE,LLONG,0,0,0,1,0);
1543 declare_builtin("__uint64toflt64",DOUBLE,UNSIGNED|LLONG,0,0,0,1,0);
1544 declare_builtin("__flt32tosint64",LLONG,FLOAT,0,0,0,1,0);
1545 declare_builtin("__flt32touint64",UNSIGNED|LLONG,FLOAT,0,0,0,1,0);
1546 declare_builtin("__flt64tosint64",LLONG,DOUBLE,0,0,0,1,0);
1547 declare_builtin("__flt64touint64",UNSIGNED|LLONG,DOUBLE,0,0,0,1,0);
1548
1549 declare_builtin("__flt32toflt64",DOUBLE,FLOAT,0,0,0,1,0);
1550 declare_builtin("__flt64toflt32",FLOAT,DOUBLE,0,0,0,1,0);
1551
1552
1553 declare_builtin("__addflt32",FLOAT,FLOAT,0,FLOAT,0,1,0);
1554 declare_builtin("__subflt32",FLOAT,FLOAT,0,FLOAT,0,1,0);
1555 declare_builtin("__mulflt32",FLOAT,FLOAT,0,FLOAT,0,1,0);
1556 declare_builtin("__divflt32",FLOAT,FLOAT,0,FLOAT,0,1,0);
1557 declare_builtin("__negflt32",FLOAT,FLOAT,0,FLOAT,0,1,0);
1558 declare_builtin("__cmpflt32",INT,FLOAT,0,FLOAT,0,1,0);
1559
1560 declare_builtin("__addflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0);
1561 declare_builtin("__subflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0);
1562 declare_builtin("__mulflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0);
1563 declare_builtin("__divflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0);
1564 declare_builtin("__negflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0);
1565 declare_builtin("__cmpflt64",INT,DOUBLE,0,DOUBLE,0,1,0);
1566
1567
1568 return 1;
1569}
1570
1571
1572void init_db(FILE *f)
1573{
1574}
1575
1576
1577int freturn(struct Typ *t)
1578/* Returns the register in which variables of type t are returned. */
1579/* If the value cannot be returned in a register returns 0. */
1580/* A pointer MUST be returned in a register. The code-generator */
1581/* has to simulate a pseudo register if necessary. */
1582{
1583 int tu = t->flags&NQ;
1584
1585 /* @@@ handle VFP */
1586
1587 if (tu==LLONG || tu==DOUBLE)
1588 return FIRST_PAIR;
1589
1590 if (zmleq(szof(t),l2zm(4L)))
1591 return FIRST_GPR;
1592
1593 return 0;
1594}
1595
1596
1597int reg_pair(int r,struct rpair *p)
1598/* Returns 0 if the register is no register pair. If r */
1599/* is a register pair non-zero will be returned and the */
1600/* structure pointed to p will be filled with the two */
1601/* elements. */
1602{
1603 if (r<FIRST_PAIR || r>LAST_PAIR)
1604 return 0;
1605
1606 switch (r) {
1607 case FIRST_PAIR:
1608 p->r1 = FIRST_GPR;
1609 p->r2 = FIRST_GPR+1;
1610 return 1;
1611 case FIRST_PAIR+1:
1612 p->r1 = FIRST_GPR+2;
1613 p->r2 = FIRST_GPR+3;
1614 return 1;
1615 case FIRST_PAIR+2:
1616 p->r1 = FIRST_GPR+4;
1617 p->r2 = FIRST_GPR+5;
1618 return 1;
1619 case FIRST_PAIR+3:
1620 p->r1 = FIRST_GPR+6;
1621 p->r2 = FIRST_GPR+7;
1622 return 1;
1623 case FIRST_PAIR+4:
1624 p->r1 = FIRST_GPR+10;
1625 p->r2 = FIRST_GPR+11;
1626 return 1;
1627 case FIRST_DOUBLE:
1628 p->r1 = FIRST_FPR;
1629 p->r2 = FIRST_FPR+1;
1630 return 1;
1631 case FIRST_DOUBLE+1:
1632 p->r1 = FIRST_FPR+2;
1633 p->r2 = FIRST_FPR+3;
1634 return 1;
1635 case FIRST_DOUBLE+2:
1636 p->r1 = FIRST_FPR+4;
1637 p->r2 = FIRST_FPR+5;
1638 return 1;
1639 case FIRST_DOUBLE+3:
1640 p->r1 = FIRST_FPR+6;
1641 p->r2 = FIRST_FPR+7;
1642 return 1;
1643 case FIRST_DOUBLE+4:
1644 p->r1 = FIRST_FPR+8;
1645 p->r2 = FIRST_FPR+9;
1646 return 1;
1647 case FIRST_DOUBLE+5:
1648 p->r1 = FIRST_FPR+10;
1649 p->r2 = FIRST_FPR+11;
1650 return 1;
1651 case FIRST_DOUBLE+6:
1652 p->r1 = FIRST_FPR+12;
1653 p->r2 = FIRST_FPR+13;
1654 return 1;
1655 case FIRST_DOUBLE+7:
1656 p->r1 = FIRST_FPR+14;
1657 p->r2 = FIRST_FPR+15;
1658 return 1;
1659 default:
1660 ierror(0);
1661 }
1662
1663 return 0;
1664}
1665
1666
1667int cost_savings(struct IC *p,int r,struct obj *o)
1668/* estimate the cost-saving if object o from IC p is placed in */
1669/* register r */
1670{
1671 int c = p->code;
1672
1673 /* @@@ FIXME */
1674 if (o->flags & VKONST) {
1675 if (o==&p->q1 && p->code==ASSIGN && (p->z.flags&DREFOBJ))
1676 return 4;
1677 else
1678 return 2;
1679 }
1680 if (o->flags & DREFOBJ)
1681 return 4;
1682 if (c==SETRETURN && r==p->z.reg && !(o->flags&DREFOBJ))
1683 return 3;
1684 if (c==GETRETURN && r==p->q1.reg && !(o->flags&DREFOBJ))
1685 return 3;
1686 return 2;
1687}
1688
1689
1690int regok(int r,int t,int mode)
1691/* Returns 0 if register r cannot store variables of */
1692/* type t. If t==POINTER and mode!=0 then it returns */
1693/* non-zero only if the register can store a pointer */
1694/* and dereference a pointer to mode. */
1695{
1696 if (r==0)
1697 return 0;
1698
1699 if (t==0 && r>=FIRST_CCR && r<=LAST_CCR)
1700 return 1;
1701
1702 t &= NQ;
1703
1704 if (ISFLOAT(t)) {
1705 /* @@@ handle VFP */
1706 if (t==FLOAT && r>=FIRST_GPR && r<=LAST_GPR)
1707 return 1;
1708 else if (r>=FIRST_PAIR && r<=LAST_PAIR)
1709 return 1;
1710 }
1711 else if (t==POINTER && r>=FIRST_GPR && r<=LAST_GPR)
1712 return 1;
1713 else if (t>=CHAR && t<=LONG && r>=FIRST_GPR && r<=LAST_GPR)
1714 return 1;
1715 else if (t==LLONG && r>=FIRST_PAIR && r<=LAST_PAIR)
1716 return 1;
1717
1718 return 0;
1719}
1720
1721
1722int dangerous_IC(struct IC *p)
1723/* Returns zero if the IC p can be safely executed */
1724/* without danger of exceptions or similar things. */
1725/* vbcc may generate code in which non-dangerous ICs */
1726/* are sometimes executed although control-flow may */
1727/* never reach them (mainly when moving computations */
1728/* out of loops). */
1729/* Typical ICs that generate exceptions on some */
1730/* machines are: */
1731/* - accesses via pointers */
1732/* - division/modulo */
1733/* - overflow on signed integer/floats */
1734{
1735 if ((p->q1.flags&DREFOBJ) || (p->q2.flags&DREFOBJ) || (p->z.flags&DREFOBJ))
1736 return 1;
1737 /* ARM has no division/modulo instructions */
1738 return 0;
1739}
1740
1741
1742int must_convert(int o,int t,int const_expr)
1743/* Returns zero if code for converting np to type t */
1744/* can be omitted. */
1745/* On the PowerPC cpu pointers and 32bit */
1746/* integers have the same representation and can use */
1747/* the same registers. */
1748{
1749 int op = o & NQ;
1750 int tp = t & NQ;
1751
1752 if ((op==INT||op==LONG||op==POINTER) && (tp==INT||tp==LONG||tp==POINTER))
1753 return 0;
1754 if (op==DOUBLE && tp==LDOUBLE)
1755 return 0;
1756 if (op==LDOUBLE && tp==DOUBLE)
1757 return 0;
1758 if(op==tp)
1759 return 0;
1760 return 1;
1761}
1762
1763
1764char *use_libcall(int c,int t,int t2)
1765/* Return name of library function, if this node should be
1766 implemented via libcall. */
1767{
1768 static char fname[16];
1769 char *ret = NULL;
1770
1771 if (((c==MULT && aa<AA2) ||
1772 (c>MULT && c<=MOD)) && (t&NQ) <= LONG) {
1773 if ((t&UNSIGNED) && (c==DIV || c==MOD))
1774 sprintf(fname,"__%s",ename[c]);
1775 else
1776 sprintf(fname,"__%ss",ename[c]);
1777 ret = fname;
1778 }
1779
1780 if(c==COMPARE){
1781 if((t&NQ)==LLONG||ISFLOAT(t)){
1782 sprintf(fname,"__cmp%s%s%ld",(t&UNSIGNED)?"u":"s",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8);
1783 ret=fname;
1784 }
1785 }else{
1786 t&=NU;
1787 t2&=NU;
1788 if(t==LDOUBLE) t=DOUBLE;
1789 if(t2==LDOUBLE) t2=DOUBLE;
1790 if(c==CONVERT){
1791 if(t==t2) return 0;
1792 if(t==FLOAT&&t2==DOUBLE) return "__flt64toflt32";
1793 if(t==DOUBLE&&t2==FLOAT) return "__flt32toflt64";
1794
1795 if(ISFLOAT(t)){
1796 sprintf(fname,"__%cint%ldtoflt%d",(t2&UNSIGNED)?'u':'s',zm2l(sizetab[t2&NQ])*8,(t==FLOAT)?32:64);
1797 ret=fname;
1798 }
1799 if(ISFLOAT(t2)&&(t&NU)==LLONG){
1800 sprintf(fname,"__flt%dto%cint%ld",((t2&NU)==FLOAT)?32:64,(t&UNSIGNED)?'u':'s',zm2l(sizetab[t&NQ])*8);
1801 ret=fname;
1802 }
1803 }
1804 if((t&NQ)==LLONG||ISFLOAT(t)){
1805 if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==KOMPLEMENT||c==MINUS){
1806 if(t==(UNSIGNED|LLONG)&&(c==DIV||c==MOD||c==RSHIFT)){
1807 sprintf(fname,"__%suint64",ename[c]);
1808 ret=fname;
1809 }else if((t&NQ)==LLONG){
1810 sprintf(fname,"__%sint64",ename[c]);
1811 ret=fname;
1812 }else{
1813 sprintf(fname,"__%s%s%s%ld",ename[c],(t&UNSIGNED)?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8);
1814 ret=fname;
1815 }
1816 }
1817 }
1818 }
1819
1820 return ret;
1821}
1822
1823
1824void gen_ds(FILE *f,zmax size,struct Typ *t)
1825/* This function has to create <size> bytes of storage */
1826/* initialized with zero. */
1827{
1828 title(f);
1829
1830 if (newobj && section!=SPECIAL)
1831 emit(f,"%ld\n",zm2l(size));
1832 else
1833 emit(f,"\t.space\t%ld\n",zm2l(size));
1834
1835 newobj = 0;
1836}
1837
1838
1839void gen_align(FILE *f,zmax align)
1840/* This function has to make sure the next data is */
1841/* aligned to multiples of <align> bytes. */
1842{
1843 title(f);
1844
1845 if (zm2l(align) > 1)
1846 emit(f,"\t.align\t2\n");
1847}
1848
1849
1850void gen_var_head(FILE *f,struct Var *v)
1851/* This function has to create the head of a variable */
1852/* definition, i.e. the label and information for */
1853/* linkage etc. */
1854{
1855 int constflag;
1856 char *sec;
1857
1858 title(f);
1859
1860 if(v->clist)
1861 constflag = is_const(v->vtyp);
1862
1863 if (isstatic(v->storage_class)) {
1864 if (ISFUNC(v->vtyp->flags))
1865 return;
1866 if (!special_section(f,v)) {
1867 if (v->clist && (!constflag || CONST_IN_DATA) && section!=DATA) {
1868 emit(f,dataname);
1869 if (f)
1870 section = DATA;
1871 }
1872 if (v->clist && constflag && !CONST_IN_DATA && section!=RODATA) {
1873 emit(f,rodataname);
1874 if (f)
1875 section = RODATA;
1876 }
1877 if (!v->clist && section!=BSS) {
1878 emit(f,bssname);
1879 if (f)
1880 section = BSS;
1881 }
1882 }
1883 if (v->clist || section==SPECIAL) {
1884 gen_align(f,falign(v->vtyp));
1885 emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
1886 }
1887 else
1888 emit(f,"\t.lcomm\t%s%ld,",labprefix,zm2l(v->offset));
1889 newobj = 1;
1890 }
1891
1892 if (isextern(v->storage_class)) {
1893 emit(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
1894 if (v->flags & (DEFINED|TENTATIVE)) {
1895 if (!special_section(f,v)) {
1896 if (v->clist && (!constflag || CONST_IN_DATA) && section!=DATA) {
1897 emit(f,dataname);
1898 if(f)
1899 section = DATA;
1900 }
1901 if (v->clist && constflag && !CONST_IN_DATA && section!=RODATA) {
1902 emit(f,rodataname);
1903 if (f)
1904 section = RODATA;
1905 }
1906 if (!v->clist && section!=BSS) {
1907 emit(f,bssname);
1908 if (f)
1909 section = BSS;
1910 }
1911 }
1912 if (v->clist || section==SPECIAL) {
1913 gen_align(f,falign(v->vtyp));
1914 emit(f,"%s%s:\n",idprefix,v->identifier);
1915 }
1916 else {
1917 emit(f,"\t.global\t%s%s\n\t.%scomm\t%s%s,",idprefix,
1918 v->identifier,(USE_COMMONS?"":"l"),idprefix,v->identifier);
1919 }
1920 newobj = 1;
1921 }
1922 }
1923}
1924
1925
1926void gen_dc(FILE *f,int t,struct const_list *p)
1927/* This function has to create static storage */
1928/* initialized with const-list p. */
1929{
1930 title(f);
1931
1932 if ((t&NQ) == POINTER)
1933 t = UNSIGNED|LONG;
1934 emit(f,"\t.%s\t",dct[t&NQ]);
1935
1936 if (!p->tree) {
1937 if (ISFLOAT(t)) {
1938 unsigned char *ip = (unsigned char *)&p->val.vdouble;
1939
1940 emit(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
1941 if ((t&NQ) != FLOAT)
1942 emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
1943 }
1944 else {
1945 emitval(f,&p->val,t&NU);
1946 }
1947 }
1948 else {
1949 emit_obj(f,&p->tree->o,t&NU);
1950 }
1951
1952 emitnl(f);
1953 newobj = 0;
1954}
1955
1956
1957/* The main code-generation routine. */
1958/* f is the stream the code should be written to. */
1959/* p is a pointer to a doubly linked list of ICs */
1960/* containing the function body to generate code for. */
1961/* v is a pointer to the function. */
1962/* offset is the size of the stackframe the function */
1963/* needs for local variables. */
1964
1965void gen_code(FILE *f,struct IC *p,struct Var *v,zmax offset)
1966/* The main code-generation routine. */
1967{
1968 FILE *outfile = f;
1969 struct IC *p_start = p;
1970 int c,t,i,pass;
1971 struct rpair rp;
1972
1973 if (DEBUG & 1)
1974 printf("gen_code()\n");
1975
1976 current_function = v;
1977 icnt = 0;
1978 drefptr_array_label = 0;
1979 argsize = 0;
1980 rsavesize = 0;
1981 maxrsaveoffs = 0;
1982 needframe = 0;
1983
1984 for (c=1; c<=MAXR; c++)
1985 regs[c] = regsa[c];
1986
1987 for (p=p_start; p; p=p->next) {
1988 c = p->code;
1989 t = p->typf & NU;
1990
1991 if (c == ALLOCREG) {
1992 if (reg_pair(p->q1.reg,&rp)) {
1993 regs[rp.r1] = 1;
1994 regs[rp.r2] = 1;
1995 }
1996 regs[p->q1.reg] = 1;
1997 continue;
1998 }
1999
2000 if (c == FREEREG) {
2001 if (reg_pair(p->q1.reg,&rp)) {
2002 regs[rp.r1] = 0;
2003 regs[rp.r2] = 0;
2004 }
2005 regs[p->q1.reg] = 0;
2006 continue;
2007 }
2008
2009 /* try MULT/DIV/MOD with powers of two */
2010 if ((c==MULT || ((c==DIV || c==MOD) && (t&UNSIGNED))) &&
2011 (t&NQ)<=LONG && isconst(p->q2.flags)) {
2012 eval_const(&p->q2.val,t);
2013 if (i = pof2(vmax)) {
2014 if (c == MOD) {
2015 vmax = zmsub(vmax,l2zm(1L));
2016 p->code = AND;
2017 }
2018 else {
2019 vmax = l2zm(i-1);
2020 p->code = c==DIV ? RSHIFT : LSHIFT;
2021 }
2022 c = p->code;
2023 gval.vmax = vmax;
2024 eval_const(&gval,MAXINT);
2025 if (c == AND) {
2026 insert_const(&p->q2.val,t);
2027 }
2028 else {
2029 insert_const(&p->q2.val,INT);
2030 p->typf2 = INT;
2031 }
2032 }
2033 }
2034
2035 if (c == CALL) {
2036 needframe = 1;
2037 if (argsize < zm2l(pushedargsize(p)))
2038 argsize = zm2l(pushedargsize(p)); /* set max argsize */
2039 }
2040 }
2041
2042 /*peephole(p); @@@ FIXME */
2043
2044 for (c=i; i<=MAXR; i++) {
2045 if (regsa[i] || regused[i])
2046 BSET(regs_modified,i);
2047 if (!regsa[i] && !regscratch[i] && regused[i])
2048 needframe = 1;
2049 }
2050
2051 /* determine word-aligned space for local variables */
2052 localsize = ((zm2l(offset) + 3) / 4) * 4;
2053 if (localsize > 0)
2054 needframe = 1;
2055
2056 for (pass=0,f=NULL; pass<2; pass++,f=outfile) {
2057 struct IC my_ic;
2058 struct IC *p2;
2059
2060 if (pass) {
2061 emit_dataptr_array(NULL); /* reset ptr-array */
2062 icnt = 0;
2063 function_top(f,v,argsize+localsize);
2064 }
2065
2066 pushoffs = 0;
2067
2068 for (p2=p_start; p2; p2=p2->next) {
2069 if (pass) {
2070 p = p2;
2071 }
2072 else { /* work on a copy in first pass */
2073 p = &my_ic;
2074 *p = *p2;
2075 }
2076
2077 c = p->code;
2078 t = p->typf;
2079
2080 cg_freeall(f); /* reset internal register allocations */
2081
2082 if (icnt > MAXCODELINES) {
2083 /* function has grown too big, emit all data-reference pointers first */
2084 emit(f,"\tb\t%s%d\n",labprefix,++label);
2085 emit_dataptr_array(f);
2086 emit(f,"%s%d:\n",labprefix,label);
2087 icnt = 0;
2088 }
2089
2090 if (c == NOP) {
2091 p->z.flags = 0;
2092 continue;
2093 }
2094
2095 if (c == ALLOCREG) {
2096 if (reg_pair(p->q1.reg,&rp)) {
2097 regs[rp.r1] = 1;
2098 regs[rp.r2] = 1;
2099 }
2100 regs[p->q1.reg] = 1;
2101 continue;
2102 }
2103
2104 if (c == FREEREG) {
2105 if (reg_pair(p->q1.reg,&rp)) {
2106 regs[rp.r1] = 0;
2107 regs[rp.r2] = 0;
2108 }
2109 regs[p->q1.reg] = 0;
2110 continue;
2111 }
2112
2113 if (c == LABEL) {
2114 emit(f,"%s%d:\n",labprefix,t);
2115 continue;
2116 }
2117
2118 if (c == BRA) {
2119 if (t==exit_label && framesize==0)
2120 emit(f,ret);
2121 else
2122 emit(f,"\tb\t%s%d\n",labprefix,t);
2123 continue;
2124 }
2125
2126 if (c>=BEQ && c<BRA) {
2127 emit(f,"\tb%s\t",ccs[c-BEQ]);
2128 if (isreg(p->q1.flags)) {
2129 ierror(0); /* @@@ was ist das? */
2130 emit_obj(f,&p->q1,0);
2131 emit(f,",");
2132 }
2133 emit(f,"%s%d\n",labprefix,t);
2134 continue;
2135 }
2136
2137 if (c == MOVETOREG) {
2138 if (p->z.reg>=FIRST_GPR && p->z.reg<=LAST_GPR) {
2139 load_reg(f,p,p->z.reg,&p->q1,t);
2140 }
2141 else if (reg_pair(p->z.reg,&rp)) {
2142 BSET(regs_modified,p->z.reg);
2143 load_regpair(f,p,&rp,&p->q1,t);
2144 }
2145 else
2146 ierror(0); /* @@@ VFP registers */
2147 p->z.flags = 0;
2148 continue;
2149 }
2150
2151 if (c == MOVEFROMREG) {
2152 if (p->q1.reg>=FIRST_GPR && p->q1.reg<=LAST_GPR) {
2153 store_reg(f,p,p->q1.reg,&p->z,t);
2154 }
2155 else if (reg_pair(p->q1.reg,&rp)) {
2156 store_regpair(f,p,&rp,&p->z,t);
2157 }
2158 else
2159 ierror(0); /* @@@ VFP registers */
2160 p->z.flags = 0;
2161 continue;
2162 }
2163
2164 if ((c==ASSIGN || c==PUSH) &&
2165 ((t&NQ)>POINTER || ((t&NQ)==CHAR && zm2l(opsize(p))!=1))) {
2166 cg_memcopy(f,p);
2167 p->z.flags = 0;
2168 continue;
2169 }
2170
2171 p = preload(f,p);
2172 c = p->code;
2173
2174 if (c == SUBPFP)
2175 c = SUB;
2176 else if (c == ADDI2P)
2177 c = ADD;
2178 else if (c == SUBIFP)
2179 c = SUB;
2180
2181 if (c == CONVERT) {
2182 if (ISFLOAT(q1typ(p)) || ISFLOAT(ztyp(p))) /* @@@ */
2183 ierror(0);
2184
2185 if (sizetab[q1typ(p)&NQ] < sizetab[ztyp(p)&NQ]) {
2186 int sh = 0;
2187
2188 if ((q1typ(p)&NQ) == CHAR)
2189 sh = 24;
2190 else if ((q1typ(p)&NQ) == SHORT)
2191 sh = 16;
2192 else if (sizetab[ztyp(p)&NQ] > 4)
2193 ierror(0); /* @@@ */
2194
2195 if (sh) {
2196 registerize(f,p,&p->q1,q1typ(p));
2197 emit(f,"\tmov\t%s,%s,lsl #%d\n",regnames[zreg],regnames[p->q1.reg],sh);
2198 emit(f,"\tmov\t%s,%s,%csr #%d\n",regnames[zreg],regnames[zreg],
2199 (q1typ(p)&UNSIGNED)?'l':'a',sh);
2200 }
2201 }
2202 save_result(f,p);
2203 continue;
2204 }
2205
2206 if (c == KOMPLEMENT) {
2207 registerize(f,p,&p->q1,t);
2208 emit(f,"\tmvn\t%s,%s\n",regnames[zreg],regnames[p->q1.reg]);
2209 save_result(f,p);
2210 continue;
2211 }
2212
2213 if (c == SETRETURN) {
2214 load_reg(f,p,p->z.reg,&p->q1,t);
2215 BSET(regs_modified,p->z.reg);
2216 continue;
2217 }
2218
2219 if (c == GETRETURN) {
2220 if (p->q1.reg) { /* REG-flag is not set!? */
2221 zreg = p->q1.reg;
2222 save_result(f,p);
2223 }
2224 else
2225 p->z.flags = 0;
2226 continue;
2227 }
2228
2229 if (c == CALL) {
2230 if ((p->q1.flags & (VAR|DREFOBJ))==VAR &&
2231 p->q1.v->fi && p->q1.v->fi->inline_asm) {
2232 emit_inline_asm(f,p->q1.v->fi->inline_asm);
2233 }
2234 else if (p->q1.flags & DREFOBJ) {
2235 int reg;
2236
2237 if (p->q1.flags & REG) {
2238 reg = p->q1.reg;
2239 }
2240 else {
2241 reg = cg_getreg(f,p);
2242 load_reg(f,p,reg,&p->q1,POINTER);
2243 }
2244 emit(f,"\tmov\t%s,%s\n",regnames[lr],regnames[pc]);
2245 if (aa < AA4T)
2246 emit(f,"\tmov\t%s,%s\n",regnames[pc],regnames[reg]);
2247 else
2248 emit(f,"\tbx\t%s\n",regnames[reg]);
2249 }
2250 else {
2251 emit(f,"\tbl\t");
2252 emit_obj(f,&p->q1,t);
2253 emitnl(f);
2254 }
2255
2256 pushoffs -= zm2l(pushedargsize(p));
2257
2258 if ((p->q1.flags & (VAR|DREFOBJ))==VAR &&
2259 p->q1.v->fi && (p->q1.v->fi->flags & ALL_REGS)) {
2260 bvunite(regs_modified,p->q1.v->fi->regs_modified,RSIZE);
2261 }
2262 else{
2263 int i;
2264
2265 for (i=1; i<=MAXR; i++) {
2266 if (regscratch[i])
2267 BSET(regs_modified,i);
2268 }
2269 }
2270 continue;
2271 }
2272
2273 if (c == PUSH) {
2274 if (t == 0)
2275 ierror(0);
2276 registerize(f,p,&p->q1,t);
2277 emit(f,"\tstr\t%s,[%s,#%ld]\n",
2278 regnames[p->q1.reg],regnames[sp],pushoffs);
2279 pushoffs += zm2l(opsize(p));
2280 continue;
2281 }
2282
2283 if (c == ASSIGN) {
2284 if (t == 0)
2285 ierror(0);
2286 if (isreg(p->q1.flags))
2287 zreg = p->q1.reg;
2288 else
2289 load_reg(f,p,zreg,&p->q1,t);
2290 save_result(f,p);
2291 continue;
2292 }
2293
2294 if (c == ADDRESS) {
2295 load_address(f,zreg,&p->q1,POINTER);
2296 save_result(f,p);
2297 continue;
2298 }
2299
2300 if (c == MINUS) {
2301 registerize(f,p,&p->q1,t);
2302 emit(f,"\trsb\t%s,%s,#0\n",regnames[zreg],regnames[p->q1.reg]);
2303 save_result(f,p);
2304 continue;
2305 }
2306
2307 if (c == TEST) {
2308 registerize(f,p,&p->q1,t);
2309 emit(f,"\tteq\t%s,#0\n",regnames[p->q1.reg]);
2310 continue;
2311 }
2312
2313 if (c == COMPARE) {
2314 if (!isconst(p->q1.flags))
2315 registerize(f,p,&p->q1,t);
2316 emit(f,"\tcmp\t%s,",regnames[p->q1.reg]);
2317 emit_obj(f,&p->q2,t);
2318 emitnl(f);
2319 continue;
2320 }
2321
2322 if ((c>=OR && c<=AND)) {
2323 registerize(f,p,&p->q1,t);
2324 if (!isconst(p->q2.flags))
2325 registerize(f,p,&p->q2,t);
2326 emit(f,"\t%s\t%s,%s,",logicals[c-OR],regnames[zreg],
2327 regnames[p->q1.reg]);
2328 emit_obj(f,&p->q2,t);
2329 emitnl(f);
2330 save_result(f,p);
2331 continue;
2332 }
2333
2334 if (c>=LSHIFT && c<=RSHIFT) {
2335 registerize(f,p,&p->q1,t);
2336 if (!isconst(p->q2.flags))
2337 registerize(f,p,&p->q2,t);
2338 emit(f,"\tmov\t%s,%s,%s ",regnames[zreg],regnames[p->q1.reg],
2339 shifts[(t&UNSIGNED)!=0][c-LSHIFT]);
2340 emit_obj(f,&p->q2,t);
2341 emitnl(f);
2342 save_result(f,p);
2343 continue;
2344 }
2345
2346 if (c>=ADD && c<=SUB) {
2347 registerize(f,p,&p->q1,t);
2348 if (!isconst(p->q2.flags))
2349 registerize(f,p,&p->q2,t);
2350 emit(f,"\t%s\t%s,%s,",c==ADD?"add":"sub",
2351 regnames[zreg],regnames[p->q1.reg]);
2352 emit_obj(f,&p->q2,t);
2353 emitnl(f);
2354 save_result(f,p);
2355 continue;
2356 }
2357
2358 if (c==MULT && aa>=AA2 && sizetab[t&NQ]<=4) {
2359 registerize(f,p,&p->q1,t);
2360 registerize(f,p,&p->q2,t);
2361 emit(f,"\tmul\t%s,%s,%s\n",
2362 regnames[zreg],regnames[p->q1.reg],regnames[p->q2.reg]);
2363 save_result(f,p);
2364 continue;
2365 }
2366
2367 if (pass) {
2368 pric2(stdout,p);
2369 ierror(0);
2370 }
2371 }
2372 }
2373
2374 cg_freeall(f);
2375 function_bottom(f,v,argsize+localsize+rsavesize);
2376
2377#if 0 /* @@@ wozu? */
2378 if (stack_valid) {
2379 if (!v->fi)
2380 v->fi = new_fi();
2381 v->fi->flags |= ALL_STACK;
2382 v->fi->stack1 = stack;
2383 }
2384 emit(f,"; stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");
2385#endif
2386}
2387
2388
2389int shortcut(int code,int typ)
2390{
2391 return 0;
2392}
2393
2394
2395int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
2396{
2397 int f;
2398
2399 if (!m || !t)
2400 ierror(0);
2401
2402 f = t->flags & NQ;
2403
2404 if (f<=LONG || f==POINTER) {
2405 if (m->gregs >= GPR_ARGS)
2406 return 0;
2407 else
2408 return FIRST_GPR + m->gregs++;
2409 }
2410
2411 if (f == LLONG) {
2412 if (m->gregs >= GPR_ARGS-1)
2413 return 0;
2414 else
2415 ierror(0); /* @@@ check ABI if odd registers are skipped!? */
2416 }
2417
2418 if (ISFLOAT(f)) {
2419#if 0 /* @@@ VFP only! */
2420 if (m->fregs >= FPR_ARGS)
2421 return 0;
2422 else
2423 return FIRST_DOUBLE + m->fregs++;
2424#endif
2425 }
2426
2427 return 0;
2428}
2429
2430
2431int emit_peephole(void)
2432/* This function will not optimize anything, but just update the
2433 number of lines counter, icnt, for the current function.
2434 It is required to estimate if a data-reference-pointer array
2435 is still reachable with a 12-bit offset. */
2436{
2437 int entries;
2438
2439 entries = emit_f ? EMIT_BUF_DEPTH : emit_l - emit_f + 1;
2440 icnt += entries;
2441 return 0;
2442}
2443
2444
2445int handle_pragma(const char *s)
2446{
2447 return 0;
2448}
2449
2450
2451void cleanup_cg(FILE *f)
2452{
2453}
2454
2455
2456void cleanup_db(FILE *f)
2457{
2458 if (f)
2459 section = -1;
2460}