blob: b919925064b623c2051d17d98ecf5d7b18f46520 [file] [log] [blame]
PulkoMandy17fc7592022-07-28 18:27:54 +02001/* Code generator for qnice cpu. */
2
3#include "supp.h"
4
5static char FILE_[]=__FILE__;
6/* Public data that MUST be there. */
7
8/* Name and copyright. */
9char cg_copyright[]="vbcc code-generator for qnice V0.1 (c) in 2016 by Volker Barthelmann";
10
11/* Commandline-flags the code-generator accepts */
12int g_flags[MAXGF]={VALFLAG,0,0,0,
13 0,0,0,0,
14 0,VALFLAG};
15char *g_flags_name[MAXGF]={"cpu","int32","no-delayed-popping","const-in-data",
16 "merge-constants","no-peephole","mtiny","mlarge",
17 "mhuge","rw-threshold","soft-mul"};
18union ppi g_flags_val[MAXGF];
19
20/* Typenames (needed because of HAVE_EXT_TYPES). */
21char *typname[]={"strange","bit","char","short","int","long","long long",
22 "float","double","long double","void",
23 "near-pointer","far-pointer","huge-pointer",
24 "array","struct","union","enum","function"};
25
26/* Alignment-requirements for all types in bytes. */
27zmax align[MAX_TYPE+1];
28
29/* Alignment that is sufficient for every object. */
30zmax maxalign;
31
32/* CHAR_BIT of the target machine. */
33zmax char_bit;
34
35/* Sizes of all elementary types in bytes. */
36zmax sizetab[MAX_TYPE+1];
37
38/* Minimum and Maximum values each type can have. */
39/* Must be initialized in init_cg(). */
40zmax t_min[MAX_TYPE+1];
41zumax t_max[MAX_TYPE+1];
42zumax tu_max[MAX_TYPE+1];
43
44/* Names of all registers. */
45char *regnames[]={"noreg","R0","R1","R2","R3","R4","R5","R6","R7",
46 "R8","R9","R10","R11","R12","R13","R14","R15",
47 "R0/R1","R2/R3","R4/R5","R6/R7",
48 "R8/R9","R11/R12"};
49
50/* The Size of each register in bytes. */
51zmax regsize[MAXR+1];
52
53/* Type which can store each register. */
54struct Typ *regtype[MAXR+1];
55
56/* regsa[reg]!=0 if a certain register is allocated and should */
57/* not be used by the compiler pass. */
58int regsa[MAXR+1];
59
60/* Specifies which registers may be scratched by functions. */
61int regscratch[MAXR+1]={0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1};
62
63int reg_prio[MAXR+1]={0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1};
64
65struct reg_handle empty_reg_handle={0};
66
67/* Names of target-specific variable attributes. */
68char *g_attr_name[]={"__interrupt","__rbank","__norbank",0};
69#define INTERRUPT 1
70#define RBANK 2
71#define NORBANK 4
72
73
74/****************************************/
75/* Some private data and functions. */
76/****************************************/
77
78static long malign[MAX_TYPE+1]= {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
79static long msizetab[MAX_TYPE+1]={0,1,1,1,1,2,4,2,4,4,0,1,2,2,0,0,0,1,0,1,1};
80
81struct Typ ityp={SHORT},ltyp={LONG};
82
83#define INT32 (g_flags[1]&USEDFLAG)
84#define NOPEEP (g_flags[5]&USEDFLAG)
85#define TINY 1 /*(g_flags[6]&USEDFLAG)*/
86#define LARGE 0 /*(g_flags[7]&USEDFLAG)*/
87#define HUGE 0 /*(g_flags[8]&USEDFLAG)*/
88#define SOFTMUL (g_flags[10]&USEDFLAG)
89
90
91#define NDATA 0
92#define NBSS 1
93#define NCDATA 2
94#define FDATA 3
95#define FBSS 4
96#define FCDATA 5
97#define HDATA 6
98#define HBSS 7
99#define HCDATA 8
100#define CODE 9
101#define SPECIAL 10
102#define BITS 11
103
104static int section=-1,newobj,scnt;
105static char *codename="\t.text\n",
106 *ndataname="\t.data\n",
107 *fdataname="\t.data\n",
108 *hdataname="\t.data\n",
109 *nbssname="\t.bss\n",
110 *fbssname="\t.bss\n",
111 *hbssname="\t.bss\n",
112 *ncdataname="\t.text\n",
113 *fcdataname="\t.text\n",
114 *hcdataname="\t.text\n";
115
116#define POST_INC 1
117#define PRE_DEC 2
118
119extern int static_cse, dref_cse;
120
121/* (user)stack-pointer, pointer-tmp, int-tmp; reserved for compiler */
122static const int sp=14,sr=15,pc=16,t1=12,t2=13,MTMP1=22;
123static const int r8=9,r9=10,r8r9=21;
124static int tmp1,tmp2,tmp3,tmp4,t2_used;
125static void pr(FILE *,struct IC *);
126static void function_top(FILE *,struct Var *,long);
127static void function_bottom(FILE *f,struct Var *,long);
128static int scratchreg(int,struct IC *);
129static struct Var nvar,fvar;
130static int load_const;
131static struct IC *icp;
132
133static char *marray[]={0,
134 "__far=__attr(\"far\")",
135 "__near=__attr(\"near\")",
136 "__huge=__attr(\"huge\")",
137 "__section(x,y)=__vattr(\"section(\"#x\",\"#y\")\")",
138 "__interrupt(x)=__interrupt __vattr(\"ivec(\"__str(x)\")\")",
139 "__QNICE__",
140 "__SIZE_T_INT=1",
141 "__str(x)=#x",
142 0};
143
144#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
145#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
146
147static long loff,stack,stackoffset,notpopped,dontpop,maxpushed;
148
149static char *ccs[]={"z","!z","v","!v","??","??"};
150static char *ccu[]={"z","!z","n","!n","??","??"};
151
152static char *logicals[]={"or","xor","and"};
153static char *arithmetics[]={"shl","shr","add","sub"};
154
155static char *dct[]={"",".bit",".short",".short",".short",".short",".short",".short",".short",".short",
156 "(void)",".short",".long",".long"};
157static int pushedsize,pushorder=2;
158static char *idprefix="_",*labprefix="l";
159static int exit_label,have_frame,stackchecklabel,stack_valid;
160static char *ret,*call,*jump;
161static int frame_used;
162static int rwthreshold;
163
164#define STR_NEAR "near"
165#define STR_FAR "far"
166#define STR_HUGE "huge"
167
168#define ISNULL() (zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&zldeqto(vldouble,d2zld(0.0)))
169#define ISLWORD(t) ((t&NQ)==LONG||(t&NQ)==FPOINTER||(t&NQ)==HPOINTER||(t&NQ)==FLOAT)
170#define ISHWORD(t) ((t&NQ)==INT||(t&NQ)==SHORT||(t&NQ)==CHAR||(t&NQ)==NPOINTER)
171#define ISSTATIC(v) ((v)->storage_class==EXTERN||(v)->storage_class==STATIC)
172
173static int ISFAR(struct Var *v)
174{
175 struct Typ *vt;
176 if(v==&nvar) return 0;
177 if(v==&fvar) return 1;
178 vt=v->vtyp;
179 while(ISARRAY(vt->flags)) vt=vt->next;
180 if(vt->attr&&strstr(STR_NEAR,vt->attr))
181 return 0;
182 if(HUGE||LARGE)
183 return 1;
184 if(vt->attr&&(strstr(STR_FAR,vt->attr)||strstr(STR_HUGE,vt->attr)))
185 return 1;
186 return 0;
187}
188
189static int special_section(FILE *f,struct Var *v)
190{
191 char *sec,*e;
192 if(!v->vattr) return 0;
193 sec=strstr(v->vattr,"section(");
194 if(!sec) return 0;
195 sec+=strlen("section(");
196 emit(f,"\t.section\t");
197 while(*sec&&*sec!=')') emit_char(f,*sec++);
198 emit(f,"\n");
199 if(f) section=SPECIAL;
200 return 1;
201}
202
203static struct fpconstlist {
204 struct fpconstlist *next;
205 int label,typ;
206 union atyps val;
207} *firstfpc;
208
209static int addfpconst(struct obj *o,int t)
210{
211 struct fpconstlist *p=firstfpc;
212 t&=NQ;
213 if(g_flags[4]&USEDFLAG){
214 for(p=firstfpc;p;p=p->next){
215 if(t==p->typ){
216 eval_const(&p->val,t);
217 if(t==FLOAT&&zldeqto(vldouble,zf2zld(o->val.vfloat))) return p->label;
218 if(t==DOUBLE&&zldeqto(vldouble,zd2zld(o->val.vdouble))) return p->label;
219 if(t==LDOUBLE&&zldeqto(vldouble,o->val.vldouble)) return p->label;
220 }
221 }
222 }
223 p=mymalloc(sizeof(struct fpconstlist));
224 p->next=firstfpc;
225 p->label=++label;
226 p->typ=t;
227 p->val=o->val;
228 firstfpc=p;
229 return p->label;
230}
231static void callee_push(long push)
232{
233 if(push-stackoffset>stack)
234 stack=push-stackoffset;
235}
236static void push(long push)
237{
238 stackoffset-=push;
239 if(stackoffset<maxpushed)
240 maxpushed=stackoffset;
241 if(-maxpushed>stack) stack=-maxpushed;
242}
243static void pop(long pop)
244{
245 stackoffset+=pop;
246}
247int pointer_type(struct Typ *p)
248{
249 struct Typ *merk=p;
250 if(!p) ierror(0);
251 while(ISARRAY(p->flags)||ISFUNC(p->flags)) p=p->next;
252 if(p->attr){
253 if(strstr(p->attr,STR_HUGE)) return HPOINTER;
254 if(strstr(p->attr,STR_FAR)) return FPOINTER;
255 if(strstr(p->attr,STR_NEAR)) return NPOINTER;
256 }
257 if((merk->flags&NQ)==FUNKT){
258 if(TINY)
259 return NPOINTER;
260 else
261 return HPOINTER;
262 }
263 if(LARGE)
264 return FPOINTER;
265 else if(HUGE)
266 return HPOINTER;
267 else
268 return NPOINTER;
269}
270
271/* return non-zero if IC is implemented by a function call */
272static int islibcall(struct IC *p)
273{
274 /* TODO: check if necessary */
275 return 0;
276}
277
278static long voff(struct obj *p)
279{
280 if(p->v->offset<0)
281 return loff-zm2l(p->v->offset)+zm2l(p->val.vmax)-stackoffset+pushedsize;
282 return zm2l(p->v->offset)+zm2l(p->val.vmax)-stackoffset;
283}
284static int alignment(struct obj *o)
285{
286 if(o->flags&DREFOBJ) return 1;
287 if(!(o->flags&VAR)) ierror(0);
288 if(ISSTATIC(o->v)) return zm2l(o->val.vmax)&1;
289 return voff(o)&1;
290}
291
292static void emit_obj(FILE *f,struct obj *p,int t)
293/* output an operand */
294{
295 if(p->am){
296 if(p->am->flags==POST_INC){
297 emit(f,"@%s++",regnames[p->am->base]);
298 return;
299 }else if(p->am->flags==PRE_DEC){
300 emit(f,"@--%s",regnames[p->am->base]);
301 return;
302 }else{
303 ierror(0);
304 }
305 }
306 if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
307 emitval(f,&p->val,p->dtyp&NU);
308 return;
309 }
310 if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) emit(f,"@");
311 /*if(p->flags&VARADR) ierror(0);*/
312 if((p->flags&(VAR|REG))==VAR){
313 if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
314 if(voff(p))
315 emit(f,"@%s+#%ld",regnames[sp],voff(p));
316 else emit(f,"@%s",regnames[sp]);
317 }else{
318 if(p->v->storage_class==STATIC){
319 emit(f,"#%s%ld",labprefix,zm2l(p->v->offset));
320 }else{
321 emit(f,"#%s%s",idprefix,p->v->identifier);
322 }
323 if(!zmeqto(l2zm(0L),p->val.vmax))
324 emit(f,"+%ld",(long)zm2l(p->val.vmax)*2);
325 }
326 }
327 if(p->flags&REG){
328 emit(f,"%s",regnames[p->reg]);
329 }
330 /* sometimes we just or a REG into a KONST */
331 if((p->flags&(KONST|REG))==KONST){
332 if(ISFLOAT(t)){
333 ierror(0);
334 emit(f,"#%s%d",labprefix,addfpconst(p,t));
335 }else{
336 emitval(f,&p->val,t&NU);
337 }
338 }
339}
340
341static void emit_lword(FILE *f,struct obj *p,int t,char *def)
342/* output low-word of an operand */
343{
344 if((p->flags&(KONST|DREFOBJ))==KONST){
345 eval_const(&p->val,t);
346 if(ISFLOAT(t)){
347 unsigned char *ip=(unsigned char *)&vfloat;
348 emit(f,"0x%02x%02x",ip[1],ip[0]);
349 }else{
350 long v;
351 v=zm2l(vmax);
352 emit(f,"%ld",v&0xffff);
353 }
354 return;
355 }
356 if((p->flags&(REG|DREFOBJ))==REG){
357 if(!reg_pair(p->reg,&rp))
358 ierror(0);
359 emit(f,"%s",regnames[rp.r1]);
360 return;
361 }
362 if((p->flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
363 emit(f,def,regnames[p->reg]);
364 return;
365 }
366 ierror(0);
367}
368
369static void emit_hword(FILE *f,struct obj *p,int t,char *def)
370/* output high-word of an operand */
371{
372 if((p->flags&(KONST|DREFOBJ))==KONST){
373 eval_const(&p->val,t);
374 if(ISFLOAT(t)){
375 unsigned char *ip=(unsigned char *)&vfloat;
376 emit(f,"0x%02x%02x",ip[3],ip[2]);
377 }else{
378 long v;
379 v=zm2l(vmax);
380 emit(f,"%ld",(v>>16)&0xffff);
381 }
382 return;
383 }
384 if((p->flags&(REG|DREFOBJ))==REG){
385 if(!reg_pair(p->reg,&rp))
386 ierror(0);
387 emit(f,"%s",regnames[rp.r2]);
388 return;
389 }
390 if((p->flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
391 emit(f,def,regnames[p->reg]);
392 return;
393 }
394 ierror(0);
395}
396
397static void cleanup_lword(FILE *f,struct obj *p)
398/* cleanup increased address pointers of emit_hlword */
399{
400 if((p->flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&!scratchreg(p->reg,icp))
401 emit(f,"\tsub\t2,%s\n",regnames[p->reg]);
402}
403
404static void pr(FILE *f,struct IC *p)
405{
406}
407
408static void function_top(FILE *f,struct Var *v,long offset)
409/* erzeugt Funktionskopf */
410{
411 int i,rcnt;char *tmp;
412
413 have_frame=0;stack_valid=1;
414 pushedsize=0;
415
416 if(!special_section(f,v)&&section!=CODE){
417 emit(f,codename);
418 }
419 if(v->storage_class==EXTERN){
420 if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC)
421 emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
422 emit(f,"%s%s:\n",idprefix,v->identifier);
423 }else{
424 emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
425 }
426 if(stack_check){
427 stackchecklabel=++label;
428 BSET(regs_modified,t1);
429 emit(f,"\tmov\t%s,#%s%d\n",regnames[t1],labprefix,stackchecklabel);
430 emit(f,"\t%s\t%s__stack_check\n",call,idprefix);/*FIXME:usrstack*/
431 }
432 for(rcnt=0,i=1;i<=16;i++){
433 if(regused[i]&&!regscratch[i]&&!regsa[i])
434 rcnt++;
435 }
436 if(v->tattr&NORBANK) rcnt=0;
437 if(rcnt>((v->tattr&RBANK)?0:rwthreshold)){
438 /*emit(f,"\tadd\t256,%s\n",regnames[sr]);*/
439 emit(f,"\tincrb\n");
440 have_frame=3;
441 }else{
442 for(i=1;i<=16;i++){
443 if(regused[i]&&!regscratch[i]&&!regsa[i]){
444 emit(f,"\tmove\t%s,@--%s\n",regnames[i],regnames[sp]);
445 push(1);
446 have_frame=1;pushedsize+=1;
447 }
448 }
449 }
450 if(offset){
451 emit(f,"\tsub\t%ld,%s\n",offset,regnames[sp]);
452 if(!have_frame)
453 have_frame|=1;
454 }
455}
456static void function_bottom(FILE *f,struct Var *v,long offset)
457/* erzeugt Funktionsende */
458{
459 int i;
460 if(offset) emit(f,"\tadd\t%ld,%s\n",offset,regnames[sp]);
461 if(have_frame==3){
462 /*emit(f,"\tsub\t256,%s\n",regnames[sr]);*/
463 emit(f,"\tdecrb\n");
464 }else{
465 for(i=16;i>0;i--){
466 if(regused[i]&&!regscratch[i]&&!regsa[i]){
467 emit(f,"\tmove\t@%s++,%s\n",regnames[sp],regnames[i]);
468 pop(1);
469 }
470 }
471 }
472 if(v->tattr&INTERRUPT){
473 emit(f,"\trti\n");
474 }else{
475 if(ret) emit(f,"\t%s\n",ret);
476 }
477 if(v->storage_class==EXTERN){
478 emit(f,"\t.type\t%s%s,@function\n",idprefix,v->identifier);
479 emit(f,"\t.size\t%s%s,$-%s%s\n",idprefix,v->identifier,idprefix,v->identifier);
480 }else{
481 emit(f,"\t.type\t%s%ld,@function\n",labprefix,zm2l(v->offset));
482 emit(f,"\t.size\t%s%ld,$-%s%ld\n",labprefix,zm2l(v->offset),labprefix,zm2l(v->offset));
483 }
484 if(stack_check)
485 emit(f,"%s%d\tequ\t%ld\n",labprefix,stackchecklabel,offset+pushedsize-maxpushed);
486 if(stack_valid){
487 long ustack=stack+offset+pushedsize;
488 if(!v->fi) v->fi=new_fi();
489 if(v->fi->flags&ALL_STACK){
490 if(v->fi->stack1!=stack)
491 if(f) error(319,"stack",ustack,v->fi->stack1);
492 }else{
493 v->fi->flags|=ALL_STACK;
494 v->fi->stack1=stack;
495 }
496 emit(f,"\t.equ\t%s__ustack_%s,%ld\n",idprefix,v->identifier,zm2l(v->fi->stack1));
497 }
498}
499static int compare_objects(struct obj *o1,struct obj *o2)
500{
501 if((o1->flags&(REG|DREFOBJ))==REG&&(o2->flags&(REG|DREFOBJ))==REG&&o1->reg==o2->reg)
502 return 1;
503 if((o1->flags&(KONST|VAR|DREFOBJ|REG|VARADR))==(o2->flags&(KONST|VAR|DREFOBJ|REG|VARADR))&&o1->am==o2->am){
504 if(!(o1->flags&VAR)||(o1->v==o2->v&&zmeqto(o1->val.vmax,o2->val.vmax))){
505 if(!(o1->flags&REG)||o1->reg==o2->reg){
506 return 1;
507 }
508 }
509 }
510 return 0;
511}
512static void clear_ext_ic(struct ext_ic *p)
513{
514 p->flags=0;
515 p->r=0;
516 p->offset=0;
517}
518
519static void peephole(struct IC *p)
520{
521 int c,c2,r,t;struct IC *p2;
522 struct AddressingMode *am;
523 frame_used=0;
524 for(;p;p=p->next){
525 c=p->code;
526 if(!frame_used){
527 if((p->q1.flags&(REG|VAR))==VAR&&!ISSTATIC(p->q1.v)) frame_used=1;
528 if((p->q2.flags&(REG|VAR))==VAR&&!ISSTATIC(p->q2.v)) frame_used=1;
529 if((p->z.flags&(REG|VAR))==VAR&&!ISSTATIC(p->z.v)) frame_used=1;
530 }
531 /* letztes Label merken */
532 if(c!=FREEREG&&c!=ALLOCREG&&(c!=SETRETURN||!isreg(q1)||p->q1.reg!=p->z.reg)) exit_label=0;
533 if(c==LABEL) exit_label=p->typf;
534
535 /* [Rx+] in q1 */
536 if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
537 r=p->q1.reg; t=q1typ(p);
538 if((!(p->q2.flags&REG)||p->q2.reg!=r)&&(!(p->z.flags&REG)||p->z.reg!=r)){
539 for(p2=p->next;p2;p2=p2->next){
540 c2=p2->code;
541 if((c2==ADD||(c2==ADDI2P&&(p2->typf2&NQ)!=HPOINTER))&&(p2->q1.flags&(REG|DREFOBJ))==REG&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){
542 eval_const(&p2->q2.val,p2->typf2);
543 if(zmeqto(vmax,l2zm(1L))&&ISHWORD(t)){
544 p2->code=NOP;
545 p2->q1.flags=p2->q2.flags=p2->z.flags=0;
546 p->q1.am=mymalloc(sizeof(*am));
547 p->q1.am->flags=POST_INC;
548 p->q1.am->base=r;
549 }else break;
550 }
551 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
552 if(((p2->q1.flags&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&p2->z.reg==r)) break;
553 }
554 }
555 }
556 /* [Rx+] in q2 */
557 if(!p->q2.am&&(p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
558 r=p->q2.reg; t=q2typ(p);
559 if((!(p->q1.flags&REG)||p->q1.reg!=r)&&(!(p->z.flags&REG)||p->z.reg!=r)){
560 for(p2=p->next;p2;p2=p2->next){
561 c2=p2->code;
562 if((c2==ADD||(c2==ADDI2P&&(p2->typf2&NQ)!=HPOINTER))&&(p2->q1.flags&(REG|DREFOBJ))==REG&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){
563 eval_const(&p2->q2.val,p2->typf2);
564 if(zmeqto(vmax,l2zm(1L))&&ISHWORD(t)){
565 p2->code=NOP;
566 p2->q1.flags=p2->q2.flags=p2->z.flags=0;
567 p->q2.am=mymalloc(sizeof(*am));
568 p->q2.am->flags=POST_INC;
569 p->q2.am->base=r;
570 }else break;
571 }
572 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
573 if(((p2->q1.flags&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&p2->z.reg==r)) break;
574 }
575 }
576 }
577 /* [Rx+] in z */
578 /* currently we do it only if q2 is empty; could be more clever */
579 if(!p->z.am&&!p->q2.flags&&(p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
580 r=p->z.reg; t=ztyp(p);
581 if((!(p->q1.flags&REG)||p->q1.reg!=r)&&(!(p->q2.flags&REG)||p->q2.reg!=r)){
582 for(p2=p->next;p2;p2=p2->next){
583 c2=p2->code;
584 if((c2==ADD||(c2==ADDI2P&&(p2->typf2&NQ)!=HPOINTER))&&(p2->q1.flags&(REG|DREFOBJ))==REG&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){
585 eval_const(&p2->q2.val,p2->typf2);
586 if(zmeqto(vmax,l2zm(1L))&&ISHWORD(t)){
587 p2->code=NOP;
588 p2->q1.flags=p2->q2.flags=p2->z.flags=0;
589 p->z.am=mymalloc(sizeof(*am));
590 p->z.am->flags=POST_INC;
591 p->z.am->base=r;
592 }else break;
593 }
594 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
595 if(((p2->q1.flags&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&p2->z.reg==r)) break;
596 }
597 }
598 }
599 /* --@Rx */
600 if(c==SUBIFP&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg&&p->q1.reg<=16&&isconst(q2)){
601 long sz;
602 r=p->q1.reg;
603 eval_const(&p->q2.val,q2typ(p));
604 sz=zm2l(vmax);
605 if(sz==1){
606 for(p2=p->next;p2;p2=p2->next){
607 c2=p2->code;
608 if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r&&(!(p2->q2.flags&REG)||p2->q2.reg!=r)&&(!(p2->z.flags&REG)||p2->z.reg!=r)&&(c2!=CONVERT||(q1typ(p2)&NQ)<=(ztyp(p2)&NQ))){
609 t=(q1typ(p2)&NQ);
610 if((ISINT(t)||ISPOINTER(t))&&ISHWORD(t)&&zmeqto(sizetab[q1typ(p2)&NQ],l2zm(sz))&&!islibcall(p2)){
611 p2->q1.am=am=mymalloc(sizeof(*am));
612 p2->q1.val.vmax=l2zm(0L);
613 am->base=r;
614 am->flags=PRE_DEC;
615 p->code=NOP;
616 p->q1.flags=p->q2.flags=p->z.flags=0;
617 break;
618 }
619 }
620 if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r&&(!(p2->q1.flags&REG)||p2->q1.reg!=r)&&(!(p2->z.flags&REG)||p2->z.reg!=r)){
621 t=(q2typ(p2)&NQ);
622 if((ISINT(t)||ISPOINTER(t))&&ISHWORD(t)&&zmeqto(sizetab[q2typ(p2)&NQ],l2zm(sz))&&!islibcall(p2)){
623 p2->q2.am=am=mymalloc(sizeof(*am));
624 p2->q2.val.vmax=l2zm(0L);
625 am->base=r;
626 am->flags=PRE_DEC;
627 p->code=NOP;
628 p->q1.flags=p->q2.flags=p->z.flags=0;
629 break;
630 }
631 }
632 /* currently we do it only if q2 is empty; perhaps be more clever in the future */
633 if(!p2->z.am&&!p2->q2.flags&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r&&(!(p2->q2.flags&REG)||p2->q2.reg!=r)&&(!(p2->q1.flags&REG)||p2->q1.reg!=r)){
634 t=(ztyp(p2)&NQ);
635 if((ISINT(t)||ISPOINTER(t))&&ISHWORD(t)&&zmeqto(sizetab[ztyp(p2)&NQ],l2zm(sz))&&!islibcall(p2)){
636 p2->z.am=am=mymalloc(sizeof(*am));
637 p2->z.val.vmax=l2zm(0L);
638 am->base=r;
639 am->flags=PRE_DEC;
640 p->code=NOP;
641 p->q1.flags=p->q2.flags=p->z.flags=0;
642 break;
643 }
644 }
645 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
646 if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
647 if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
648 if((p2->z.flags&REG)&&p2->z.reg==r) break;
649 }
650 }
651 }
652 }
653}
654
655static struct obj *cam(int flags,int base,long offset,struct Var *v)
656/* Initializes an addressing-mode structure and returns a pointer to */
657/* that object. Will not survive a second call! */
658{
659 static struct obj obj;
660 static struct AddressingMode am;
661 obj.am=&am;
662 am.flags=flags;
663 am.base=base;
664 return &obj;
665}
666
667
668/* load an operand if necessary, use register r if needed */
669static void load_op(FILE *f,struct obj *o,int t,int r)
670{
671 if(o->am)
672 return;
673
674 if(o->flags&(REG|VARADR))
675 return;
676
677 if(o->flags&KONST){
678 if((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE){
679 int l=addfpconst(o,t);
680 emit(f,"\tmove\t%s%d,%s\n",labprefix,l,regnames[r]);
681 o->reg=r;
682 o->flags=REG|DREFOBJ;
683 }else if(load_const||(o->flags&DREFOBJ)){
684 emit(f,"\tmove\t");
685 emit_obj(f,o,t);
686 emit(f,",%s\n",regnames[r]);
687 o->flags|=REG;
688 o->flags&=~KONST;
689 }else
690 return;
691 }else{
692 if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
693 if(ISHWORD(t)&&voff(o)==0){
694 if(o->flags&DREFOBJ){
695 emit(f,"\tmove\t@%s,%s\n",regnames[sp],regnames[r]);
696 o->reg=r;
697 o->flags|=REG|DREFOBJ;
698 BSET(regs_modified,r);
699 return;
700 }else
701 r=sp;
702 }else{
703 emit(f,"\tmove\t%s,%s\n",regnames[sp],regnames[r]);
704 if(voff(o))
705 emit(f,"\tadd\t%ld,%s\n",voff(o),regnames[r]);
706 }
707
708 }else{
709 emit(f,"\tmove\t");
710 emit_obj(f,o,t);
711 emit(f,",%s\n",regnames[r]);
712 }
713
714
715 if(o->flags&DREFOBJ){
716 emit(f,"\tmove\t@%s,%s\n",regnames[r],regnames[r]);
717 }
718
719 o->flags|=REG|DREFOBJ;
720 }
721
722 BSET(regs_modified,r);
723 o->reg=r;
724}
725
726static void move(FILE *f,struct obj *q,int qr,struct obj *z,int zr,int t)
727/* Generates code to move object q (or register qr) into object z (or */
728/* register zr). One must be a register and DREFOBJ only allowed with */
729/* registers. */
730{
731 if(q&&z&&compare_objects(q,z))
732 return;
733
734 if(q&&(q->flags&(REG|DREFOBJ))==REG) qr=q->reg;
735 if(z&&(z->flags&(REG|DREFOBJ))==REG) zr=z->reg;
736
737 if(qr&&qr==zr)
738 return;
739
740
741 if(ISLWORD(t)){
742 if(!qr) load_op(f,q,t,t1);
743 if(!zr) load_op(f,z,t,t2);
744
745 emit(f,"\tmove\t");
746 if(qr&&reg_pair(qr,&rp))
747 emit(f,"%s",regnames[rp.r1]);
748 else
749 emit_lword(f,q,t,"@%s++");
750 emit(f,",");
751 if(zr&&reg_pair(zr,&rp))
752 emit(f,"%s",regnames[rp.r1]);
753 else
754 emit_lword(f,z,t,"@%s++");
755 emit(f,"\n");
756 emit(f,"\tmove\t");
757 if(qr&&reg_pair(qr,&rp))
758 emit(f,"%s",regnames[rp.r2]);
759 else
760 emit_hword(f,q,t,"@%s++");
761 emit(f,",");
762 if(zr&&reg_pair(zr,&rp))
763 emit(f,"%s",regnames[rp.r2]);
764 else
765 emit_hword(f,z,t,"@%s++");
766 emit(f,"\n");
767 if(!qr) cleanup_lword(f,q);
768 if(!zr) cleanup_lword(f,z);
769 return;
770 }
771
772
773 emit(f,"\tmove\t");
774 if(qr) emit(f,"%s",regnames[qr]); else emit_obj(f,q,t);
775 emit(f,",");
776 if(zr) emit(f,"%s",regnames[zr]); else emit_obj(f,z,t);
777 emit(f,"\n");
778}
779
780static int get_reg(FILE *f,struct IC *p)
781{
782 int i;
783 for(i=1;i<=16;i++){
784 if(!regs[i]&&(regscratch[i]||regused[i])&&!regsa[i]){
785 BSET(regs_modified,i);
786 return i;
787 }
788 }
789 return 0;
790}
791
792
793
794static void save_result(FILE *f,int r,struct IC *p,int t)
795/* Saves result in register r to object o. May use tp or ti. */
796{
797 ierror(0);
798}
799
800static int scratchreg(int r,struct IC *p)
801{
802 int c;
803 if(r==t1||r==t2)
804 return 1;
805 while(1){
806 p=p->next;
807 if(!p||((c=p->code)==FREEREG&&p->q1.reg==r)) return 1;
808 if(c==CALL||(c>=BEQ&&c<=BRA)) return 0;
809 if((p->q1.flags&REG)&&p->q1.reg==r) return 0;
810 if((p->q2.flags&REG)&&p->q2.reg==r) return 0;
811 if((p->z.flags&REG)&&p->z.reg==r) return 0;
812 }
813}
814
815/****************************************/
816/* End of private fata and functions. */
817/****************************************/
818
819int emit_peephole(void)
820{
821 int entries,i,r1,r2,r3,r4;long x,y,z;
822 char *asmline[EMIT_BUF_DEPTH];
823 char s1[16],s2[16];
824
825 if(NOPEEP)
826 return 0;
827
828 i=emit_l;
829 if(emit_f==0)
830 entries=i-emit_f+1;
831 else
832 entries=EMIT_BUF_DEPTH;
833 asmline[0]=emit_buffer[i];
834
835 if(entries>=1){
836 if(sscanf(asmline[0],"\tmove\t0,R%d",&r1)==1){
837 sprintf(asmline[0],"\txor\tR%d,R%d\n",r1,r1);
838 return 1;
839 }
840 }
841
842 if(entries>=2){
843 i--;
844 if(i<0) i=EMIT_BUF_DEPTH-1;
845 asmline[1]=emit_buffer[i];
846 if(sscanf(asmline[0],"\t%15s\t%ld,R%d",s1,&x,&r1)==3&&sscanf(asmline[1],"\t%15s\t%ld,R%d",s2,&y,&r2)==3&&r1==r2&&!strcmp(s1,s2)&&(!strcmp(s1,"add")||!strcmp(s1,"sub")||!strcmp(s1,"shl")||!strcmp(s1,"shr"))){
847 sprintf(asmline[1],"\t%s\t%ld,R%d\n",s1,x+y,r1);
848 remove_asm();
849 return 1;
850 }
851 if(sscanf(asmline[0],"\t%15s\t%ld,@R%d",s1,&x,&r1)==3&&sscanf(asmline[1],"\t%15s\t%ld,@R%d",s2,&y,&r2)==3&&r1==r2&&!strcmp(s1,s2)&&(!strcmp(s1,"add")||!strcmp(s1,"sub")||!strcmp(s1,"shl")||!strcmp(s1,"shr"))){
852 sprintf(asmline[1],"\t%s\t%ld,@R%d\n",s1,x+y,r1);
853 remove_asm();
854 return 1;
855 }
856 if(sscanf(asmline[0],"\tmove\tR%d,R%d",&r1,&r2)==2&&sscanf(asmline[1],"\tmove\tR%d,R%d",&r3,&r4)==2&&r1==r4&&r2==r3){
857 remove_asm();
858 return 1;
859 }
860 if(sscanf(asmline[0],"\tshl\t1,R%d",&r1)==1&&!strstr(asmline[0],"shr")){
861 sprintf(asmline[0],"\tadd\tR%d,R%d\n",r1,r1);
862 return 1;
863 }
864 }
865
866 return 0;
867}
868
869int init_cg(void)
870/* Does necessary initializations for the code-generator. Gets called */
871/* once at the beginning and should return 0 in case of problems. */
872{
873 int i;
874 /* Initialize some values which cannot be statically initialized */
875 /* because they are stored in the target's arithmetic. */
876 maxalign=l2zm(1L);
877 stackalign=l2zm(1L);
878 char_bit=l2zm(16L);
879 for(i=0;i<=MAX_TYPE;i++){
880 sizetab[i]=l2zm(msizetab[i]);
881 align[i]=l2zm(malign[i]);
882 }
883 for(i=1;i<=MAXR;i++){
884 if(i<=16){
885 regsize[i]=l2zm(1L);regtype[i]=&ityp;
886 }else{
887 regsize[i]=l2zm(2L);regtype[i]=&ltyp;
888 }
889 }
890
891 /* Initialize the min/max-settings. Note that the types of the */
892 /* host system may be different from the target system and you may */
893 /* only use the smallest maximum values ANSI guarantees if you */
894 /* want to be portable. */
895 /* That's the reason for the subtraction in t_min[INT]. Long could */
896 /* be unable to represent -2147483648 on the host system. */
897 t_min[CHAR]=l2zm(-32768L);
898 t_min[SHORT]=l2zm(-32768L);
899 t_min[INT]=t_min[SHORT];
900 t_min[LONG]=zmsub(l2zm(-2147483647L),l2zm(1L));
901 t_min[LLONG]=zmlshift(l2zm(1L),l2zm(63L));
902 t_min[MAXINT]=t_min(LLONG);
903 t_max[CHAR]=ul2zum(32767UL);
904 t_max[SHORT]=ul2zum(32767UL);
905 t_max[INT]=t_max[SHORT];
906 t_max[LONG]=ul2zum(2147483647UL);
907 t_max[LLONG]=zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL));
908 t_max[MAXINT]=t_max(LLONG);
909 tu_max[CHAR]=ul2zum(65535UL);
910 tu_max[SHORT]=ul2zum(65535UL);
911 tu_max[INT]=tu_max[SHORT];
912 tu_max[LONG]=ul2zum(4294967295UL);
913 tu_max[LLONG]=zumkompl(ul2zum(0UL));
914 tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
915
916 /* Reserve a few registers for use by the code-generator. */
917 regsa[sp]=regsa[sr]=regsa[pc]=regsa[t1]=regsa[t2]=regsa[MTMP1]=1;
918 regscratch[sp]=regscratch[sr]=regscratch[pc]=regscratch[t1]=regscratch[t2]=0;
919 target_macros=marray;
920 if(TINY) marray[0]="__TINY__";
921 else if(LARGE) marray[0]="__LARGE__";
922 else if(HUGE) marray[0]="__HUGE__";
923 else marray[0]="__MEDIUM__";
924
925 /*static_cse=0;*/
926 dref_cse=0;
927
928 if(g_flags[9]&USEDFLAG)
929 rwthreshold=g_flags_val[9].l;
930 else{
931 if(optspeed)
932 rwthreshold=1;
933 else
934 rwthreshold=2;
935 }
936
937 /* TODO: set argument registers */
938 declare_builtin("__mulint32",LONG,LONG,r8r9,LONG,0,1,0);
939 declare_builtin("__divint32",LONG,LONG,r8r9,LONG,0,1,0);
940 declare_builtin("__divuint32",LONG,LONG,r8r9,LONG,0,1,0);
941 declare_builtin("__modint32",LONG,LONG,r8r9,LONG,0,1,0);
942 declare_builtin("__moduint32",LONG,LONG,r8r9,LONG,0,1,0);
943 declare_builtin("__lslint32",LONG,LONG,r8r9,INT,11,1,0);
944 declare_builtin("__lsrint32",LONG,LONG,r8r9,INT,11,1,0);
945 declare_builtin("__lsruint32",LONG,LONG,r8r9,INT,11,1,0);
946
947 declare_builtin("__mulint64",LLONG,LLONG,0,LLONG,0,1,0);
948 declare_builtin("__addint64",LLONG,LLONG,0,LLONG,0,1,0);
949 declare_builtin("__subint64",LLONG,LLONG,0,LLONG,0,1,0);
950 declare_builtin("__andint64",LLONG,LLONG,0,LLONG,0,1,0);
951 declare_builtin("__orint64",LLONG,LLONG,0,LLONG,0,1,0);
952 declare_builtin("__eorint64",LLONG,LLONG,0,LLONG,0,1,0);
953 declare_builtin("__negint64",LLONG,LLONG,0,0,0,1,0);
954 declare_builtin("__lslint64",LLONG,LLONG,0,INT,0,1,0);
955
956 declare_builtin("__divint64",LLONG,LLONG,0,LLONG,0,1,0);
957 declare_builtin("__divuint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
958 declare_builtin("__modint64",LLONG,LLONG,0,LLONG,0,1,0);
959 declare_builtin("__moduint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
960 declare_builtin("__lsrint64",LLONG,LLONG,0,INT,0,1,0);
961 declare_builtin("__lsruint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,INT,0,1,0);
962 declare_builtin("__cmpint64",INT,LLONG,0,LLONG,0,1,0);
963 declare_builtin("__cmpuint64",INT,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
964
965 declare_builtin("__sint64toflt32",FLOAT,LLONG,0,0,0,1,0);
966 declare_builtin("__uint64toflt32",FLOAT,UNSIGNED|LLONG,0,0,0,1,0);
967 declare_builtin("__sint64toflt64",DOUBLE,LLONG,0,0,0,1,0);
968 declare_builtin("__uint64toflt64",DOUBLE,UNSIGNED|LLONG,0,0,0,1,0);
969 declare_builtin("__flt32tosint64",LLONG,FLOAT,0,0,0,1,0);
970 declare_builtin("__flt32touint64",UNSIGNED|LLONG,FLOAT,0,0,0,1,0);
971 declare_builtin("__flt64tosint64",LLONG,DOUBLE,0,0,0,1,0);
972 declare_builtin("__flt64touint64",UNSIGNED|LLONG,DOUBLE,0,0,0,1,0);
973
974 declare_builtin("__sint32toflt32",FLOAT,LONG,r8r9,0,0,1,0);
975 declare_builtin("__uint32toflt32",FLOAT,UNSIGNED|LONG,r8r9,0,0,1,0);
976 declare_builtin("__sint32toflt64",DOUBLE,LONG,0,0,0,1,0);
977 declare_builtin("__uint32toflt64",DOUBLE,UNSIGNED|LONG,0,0,0,1,0);
978 declare_builtin("__flt32tosint32",LONG,FLOAT,r8r9,0,0,1,0);
979 declare_builtin("__flt32touint32",UNSIGNED|LONG,FLOAT,r8r9,0,0,1,0);
980 declare_builtin("__flt64tosint32",LONG,DOUBLE,0,0,0,1,0);
981 declare_builtin("__flt64touint32",UNSIGNED|LONG,DOUBLE,0,0,0,1,0);
982
983 declare_builtin("__sint16toflt32",FLOAT,INT,r8,0,0,1,0);
984 declare_builtin("__uint16toflt32",FLOAT,UNSIGNED|INT,r8,0,0,1,0);
985 declare_builtin("__sint16toflt64",DOUBLE,INT,r9,0,0,1,0);
986 declare_builtin("__uint16toflt64",DOUBLE,UNSIGNED|INT,r9,0,0,1,0);
987 declare_builtin("__flt32tosint16",INT,FLOAT,r8r9,0,0,1,0);
988 declare_builtin("__flt32touint16",UNSIGNED|INT,FLOAT,r8r9,0,0,1,0);
989 declare_builtin("__flt64tosint16",INT,DOUBLE,0,0,0,1,0);
990 declare_builtin("__flt64touint16",UNSIGNED|INT,DOUBLE,0,0,0,1,0);
991
992
993
994
995 declare_builtin("__flt32toflt64",DOUBLE,FLOAT,0,0,0,1,0);
996 declare_builtin("__flt64toflt32",FLOAT,DOUBLE,0,0,0,1,0);
997
998
999 declare_builtin("__addflt32",FLOAT,FLOAT,r8r9,FLOAT,0,1,0);
1000 declare_builtin("__subflt32",FLOAT,FLOAT,r8r9,FLOAT,0,1,0);
1001 declare_builtin("__mulflt32",FLOAT,FLOAT,r8r9,FLOAT,0,1,0);
1002 declare_builtin("__divflt32",FLOAT,FLOAT,r8r9,FLOAT,0,1,0);
1003 declare_builtin("__negflt32",FLOAT,FLOAT,r8r9,0,0,1,0);
1004 declare_builtin("__cmpsflt32",INT,FLOAT,r8r9,FLOAT,0,1,0);
1005
1006 declare_builtin("__addflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0);
1007 declare_builtin("__subflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0);
1008 declare_builtin("__mulflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0);
1009 declare_builtin("__divflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0);
1010 declare_builtin("__negflt64",DOUBLE,DOUBLE,0,0,0,1,0);
1011 declare_builtin("__cmpsflt64",INT,DOUBLE,0,DOUBLE,0,1,0);
1012
1013 return 1;
1014}
1015
1016int freturn(struct Typ *t)
1017/* Returns the register in which variables of type t are returned. */
1018/* If the value cannot be returned in a register returns 0. */
1019{
1020 int f=t->flags&NQ;
1021 if(f==LLONG||f==DOUBLE||f==LDOUBLE)
1022 return 0;
1023 if(ISSCALAR(f)){
1024 if(f==LONG||f==FPOINTER||f==HPOINTER||f==FLOAT)
1025 return r8r9;
1026 else
1027 return r8;
1028 }
1029 return 0;
1030}
1031
1032int regok(int r,int t,int mode)
1033/* Returns 0 if register r cannot store variables of */
1034/* type t. If t==POINTER and mode!=0 then it returns */
1035/* non-zero only if the register can store a pointer */
1036/* and dereference a pointer to mode. */
1037{
1038 t&=NQ;
1039 if(r==0) return(0);
1040 if((t<LONG||t==NPOINTER)&&r<=16) return 1;
1041 if(t==LONG||t==FLOAT||t==FPOINTER||t==HPOINTER){
1042 if(r>16) return 1;
1043 }
1044 return 0;
1045}
1046
1047int reg_pair(int r,struct rpair *p)
1048/* Returns 0 if the register is no register pair. If r */
1049/* is a register pair non-zero will be returned and the */
1050/* structure pointed to p will be filled with the two */
1051/* elements. */
1052{
1053 if(r<=16) return 0;
1054 if(p){
1055 switch(r){
1056 case 17: p->r1=1;p->r2=2;break;
1057 case 18: p->r1=3;p->r2=4;break;
1058 case 19: p->r1=5;p->r2=6;break;
1059 case 20: p->r1=7;p->r2=8;break;
1060 case 21: p->r1=9;p->r2=10;break;
1061 case 22: p->r1=t1;p->r2=t2;break;
1062
1063 default: ierror(0);
1064 }
1065 }
1066 return 1;
1067}
1068
1069int cost_savings(struct IC *p,int r,struct obj *o)
1070{
1071 int c=p->code;
1072 if((o->flags&DREFOBJ)){
1073 if(o->flags&VKONST) return 1;
1074 if(r<=4&&p->q2.flags&&o!=&p->z)
1075 return 6;
1076 else
1077 return 4;
1078 }else if(o->flags&VKONST){
1079 struct obj *co=&o->v->cobj;
1080 if((p->code==ASSIGN&&(p->z.flags&DREFOBJ))||p->code==PUSH)
1081 return 4;
1082 if(co->flags&VARADR)
1083 return 4;
1084 if(o==&p->q1)
1085 eval_const(&co->val,q1typ(p));
1086 else
1087 eval_const(&co->val,q2typ(p));
1088 /*FIXME*/
1089 return 0;
1090 }else if(c==GETRETURN&&p->q1.reg==r){
1091 return 4;
1092 }else if(c==SETRETURN&&p->z.reg==r){
1093 return 4;
1094 }else if(c==CONVERT&&((p->typf&NQ)==CHAR||(p->typf2&NQ)==CHAR)&&regok(r,CHAR,0)){
1095 return 3;
1096 }
1097 return 2;
1098}
1099
1100int dangerous_IC(struct IC *p)
1101/* Returns zero if the IC p can be safely executed */
1102/* without danger of exceptions or similar things. */
1103/* vbcc may generate code in which non-dangerous ICs */
1104/* are sometimes executed although control-flow may */
1105/* never reach them (mainly when moving computations */
1106/* out of loops). */
1107/* Typical ICs that generate exceptions on some */
1108/* machines are: */
1109/* - accesses via pointers */
1110/* - division/modulo */
1111/* - overflow on signed integer/floats */
1112{
1113 int c=p->code;
1114 if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
1115 return 1;
1116 return 0;
1117}
1118
1119int must_convert(int o,int t,int const_expr)
1120/* Returns zero if code for converting np to type t */
1121/* can be omitted. */
1122/* In this generic 32bit RISC cpu pointers and 32bit */
1123/* integers have the same representation and can use */
1124/* the same registers. */
1125{
1126 int op=o&NQ,tp=t&NQ;
1127 if(op==tp) return 0;
1128 if(ISHWORD(op)&&ISHWORD(tp)) return 0;
1129 if(ISFLOAT(op)||ISFLOAT(tp)) return 1;
1130 if(ISLWORD(op)&&ISLWORD(tp)) return 0;
1131 return 1;
1132}
1133
1134void gen_ds(FILE *f,zmax size,struct Typ *t)
1135/* This function has to create <size> bytes of storage */
1136/* initialized with zero. */
1137{
1138 long l=zm2l(size)*2;
1139 if(newobj&&section!=SPECIAL)
1140 emit(f,"%ld\n",l);
1141 else
1142 emit(f,"\t.space\t%ld\n",l);
1143 newobj=0;
1144}
1145
1146void gen_align(FILE *f,zmax align)
1147/* This function has to make sure the next data is */
1148/* aligned to multiples of <align> bytes. */
1149{
1150}
1151static void new_section(FILE *f,int nsec)
1152{
1153 if(!f||section==nsec) return;
1154 section=nsec;
1155 if(nsec==HDATA){
1156 emit(f,hdataname);
1157 }else if(nsec==FDATA){
1158 emit(f,fdataname);
1159 }else if(nsec==NDATA){
1160 emit(f,ndataname);
1161 }else if(nsec==HCDATA){
1162 emit(f,hcdataname);
1163 }else if(nsec==FCDATA){
1164 emit(f,fcdataname);
1165 }else if(nsec==NCDATA){
1166 emit(f,ncdataname);
1167 }else if(nsec==HBSS){
1168 emit(f,hbssname);
1169 }else if(nsec==FBSS){
1170 emit(f,fbssname);
1171 }else if(nsec==NBSS){
1172 emit(f,nbssname);
1173 }
1174}
1175void gen_var_head(FILE *f,struct Var *v)
1176/* This function has to create the head of a variable */
1177/* definition, i.e. the label and information for */
1178/* linkage etc. */
1179{
1180 int constflag;
1181 char *attr;struct Typ *tv;
1182 tv=v->vtyp;
1183 while(tv->flags==ARRAY) tv=tv->next;
1184 attr=tv->attr;
1185 if(v->clist) constflag=is_const(v->vtyp);
1186 if(v->storage_class==STATIC){
1187 if(ISFUNC(v->vtyp->flags)) return;
1188 emit(f,"\t.type\t%s%ld,@object\n",labprefix,zm2l(v->offset));
1189 emit(f,"\t.size\t%s%ld,%ld\n",labprefix,zm2l(v->offset),zm2l(szof(v->vtyp))*2);
1190 if(!special_section(f,v)){
1191 if((v->vtyp->flags&NQ)==BIT){
1192 new_section(f,BITS);
1193 }else{
1194 if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))){
1195 if(attr&&strstr(attr,STR_HUGE))
1196 new_section(f,HDATA);
1197 else if(attr&&strstr(attr,STR_FAR))
1198 new_section(f,FDATA);
1199 else if(attr&&strstr(attr,STR_NEAR))
1200 new_section(f,NDATA);
1201 else{
1202 if(HUGE)
1203 new_section(f,HDATA);
1204 else if(LARGE)
1205 new_section(f,FDATA);
1206 else
1207 new_section(f,NDATA);
1208 }
1209 }
1210 if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)){
1211 if(attr&&strstr(attr,STR_HUGE))
1212 new_section(f,HCDATA);
1213 else if(attr&&strstr(attr,STR_FAR))
1214 new_section(f,FCDATA);
1215 else if(attr&&strstr(attr,STR_NEAR))
1216 new_section(f,NCDATA);
1217 else{
1218 if(HUGE)
1219 new_section(f,HCDATA);
1220 else if(LARGE)
1221 new_section(f,FCDATA);
1222 else
1223 new_section(f,NCDATA);
1224 }
1225 }
1226 if(!v->clist){
1227 if(attr&&strstr(attr,STR_HUGE))
1228 new_section(f,HBSS);
1229 else if(attr&&strstr(attr,STR_FAR))
1230 new_section(f,FBSS);
1231 else if(attr&&strstr(attr,STR_NEAR))
1232 new_section(f,NBSS);
1233 else{
1234 if(HUGE)
1235 new_section(f,HBSS);
1236 else if(LARGE)
1237 new_section(f,FBSS);
1238 else
1239 new_section(f,NBSS);
1240 }
1241 }
1242 }
1243 }
1244 gen_align(f,falign(v->vtyp));
1245 emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
1246 }
1247
1248 if(v->storage_class==EXTERN){
1249 if(v->flags&(DEFINED|TENTATIVE)){
1250 emit(f,"\t.type\t%s%s,@object\n",idprefix,v->identifier);
1251 emit(f,"\t.size\t%s%s,%ld\n",idprefix,v->identifier,zm2l(szof(v->vtyp))*2);
1252 emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
1253 if(!special_section(f,v)){
1254 if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))){
1255 if(attr&&strstr(attr,STR_HUGE))
1256 new_section(f,HDATA);
1257 else if(attr&&strstr(attr,STR_FAR))
1258 new_section(f,FDATA);
1259 else if(attr&&strstr(attr,STR_NEAR))
1260 new_section(f,NDATA);
1261 else{
1262 if(HUGE)
1263 new_section(f,HDATA);
1264 else if(LARGE)
1265 new_section(f,FDATA);
1266 else
1267 new_section(f,NDATA);
1268 }
1269 }
1270 if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)){
1271 if(attr&&strstr(attr,STR_HUGE))
1272 new_section(f,HCDATA);
1273 else if(attr&&strstr(attr,STR_FAR))
1274 new_section(f,FCDATA);
1275 else if(attr&&strstr(attr,STR_NEAR))
1276 new_section(f,NCDATA);
1277 else{
1278 if(HUGE)
1279 new_section(f,HCDATA);
1280 else if(LARGE)
1281 new_section(f,FCDATA);
1282 else
1283 new_section(f,NCDATA);
1284 }
1285 }
1286 if(!v->clist){
1287 if(attr&&strstr(attr,STR_HUGE))
1288 new_section(f,HBSS);
1289 else if(attr&&strstr(attr,STR_FAR))
1290 new_section(f,FBSS);
1291 else if(attr&&strstr(attr,STR_NEAR))
1292 new_section(f,NBSS);
1293 else{
1294 if(HUGE)
1295 new_section(f,HBSS);
1296 else if(LARGE)
1297 new_section(f,FBSS);
1298 else
1299 new_section(f,NBSS);
1300 }
1301 }
1302 }
1303 gen_align(f,falign(v->vtyp));
1304 emit(f,"%s%s:\n",idprefix,v->identifier);
1305 }else if(strcmp(v->identifier,"__va_start")){
1306 emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
1307 }
1308 }
1309}
1310
1311void gen_dc(FILE *f,int t,struct const_list *p)
1312/* This function has to create static storage */
1313/* initialized with const-list p. */
1314{
1315 if(ISPOINTER(t)){
1316 if(p->tree)
1317 emit(f,"\t%s\t",dct[t&NQ]);
1318 if(ISLWORD(t))
1319 t=UNSIGNED|LONG;
1320 else
1321 t=UNSIGNED|SHORT;
1322 if(!p->tree)
1323 emit(f,"\t%s\t",dct[t&NQ]);
1324 }else{
1325 emit(f,"\t%s\t",dct[t&NQ]);
1326 }
1327 if(!p->tree){
1328 if(ISFLOAT(t)){
1329 /* auch wieder nicht sehr schoen und IEEE noetig */
1330 unsigned char *ip;
1331
1332 ip=(unsigned char *)&p->val.vdouble;
1333 emit(f,"0x%02x%02x,0x%02x%02x",ip[1],ip[0],ip[3],ip[2]);
1334 if((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE){
1335 emit(f,",0x%02x%02x,0x%02x%02x",ip[5],ip[4],ip[7],ip[6]);
1336 }
1337 }else{
1338 if(ISLWORD(t)){
1339 long l;
1340 eval_const(&p->val,t);
1341 l=zm2l(zmand(p->val.vmax,l2zm(65535L)));
1342 emit(f,"%ld",l);
1343 l=zm2l(zmand(zmrshift(p->val.vmax,l2zm(16L)),l2zm(65535L)));
1344 emit(f,",%ld",l);
1345 }else
1346 emitval(f,&p->val,(t&NU)|UNSIGNED);
1347 }
1348 }else{
1349 int m=p->tree->o.flags;
1350 p->tree->o.flags&=~VARADR;
1351 emit_obj(f,&p->tree->o,t&NU);
1352 p->tree->o.flags=m;
1353 }
1354 emit(f,"\n");
1355}
1356
1357/* The main code-generation routine. */
1358/* f is the stream the code should be written to. */
1359/* p is a pointer to a doubly linked list of ICs */
1360/* containing the function body to generate code for. */
1361/* v is a pointer to the function. */
1362/* offset is the size of the stackframe the function */
1363/* needs for local variables. */
1364void gen_code(FILE *f,struct IC *p,struct Var *v,zmax offset)
1365{
1366 int c,t,lastcomp=0,cmpzero=0,elab=0,reg,short_add,bit_reverse,need_return=0;
1367 struct obj *bit_obj;char *bit_reg;
1368 static int idone;
1369 struct obj o,*cc=0;int cc_t;
1370 struct IC *p2;
1371 if(TINY){
1372 call="asub";
1373 jump="abra";
1374 }else{
1375 call="asub";
1376 jump="abra";
1377 }
1378 if(v->tattr&INTERRUPT){
1379 ret="rti";
1380 need_return=1;
1381 }else
1382 ret="move\t@R13++,R15";
1383
1384 if(DEBUG&1) printf("gen_code()\n");
1385 if(!v->fi) v->fi=new_fi();
1386 v->fi->flags|=ALL_REGS;
1387
1388 for(p2=p;p2;p2=p2->next) clear_ext_ic(&p2->ext);
1389 if(!(g_flags[5]&USEDFLAG)){
1390 peephole(p);
1391 if(!frame_used) offset=l2zm(0L);
1392 }
1393 for(c=1;c<=15;c++) regs[c]=regsa[c];
1394 regs[16]=0;
1395 for(c=1;c<=MAXR;c++){
1396 if(regscratch[c]&&(regsa[c]||regused[c])){
1397 BSET(regs_modified,c);
1398 }
1399 }
1400 loff=zm2l(offset);
1401 function_top(f,v,loff);
1402 stackoffset=notpopped=dontpop=maxpushed=0;
1403 stack=0;
1404 for(;p;pr(f,p),p=p->next){
1405 c=p->code;t=p->typf;
1406 t2_used=0; short_add=0;
1407 icp=p;
1408 if(c==NOP) continue;
1409 if(c==ALLOCREG){
1410 regs[p->q1.reg]=1;
1411 if(reg_pair(p->q1.reg,&rp)) regs[rp.r1]=regs[rp.r2]=1;
1412 BSET(regs_modified,p->q1.reg);
1413 continue;
1414 }
1415 if(c==FREEREG){
1416 regs[p->q1.reg]=0;
1417 if(reg_pair(p->q1.reg,&rp)) regs[rp.r1]=regs[rp.r2]=0;
1418 continue;
1419 }
1420 if(notpopped&&!dontpop){
1421 int flag=0;
1422 if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
1423 emit(f,"\tadd\t%ld,%s\n",notpopped,regnames[sp]);
1424 pop(notpopped);notpopped=0;cc=0;
1425 }
1426 }
1427 if(c==LABEL) {cc=0;emit(f,"%s%d:\n",labprefix,t);continue;}
1428 if(c==BRA){
1429 if(p->typf==exit_label&&!have_frame){
1430 emit(f,"\t%s\n",ret);
1431 }else{
1432 if(t==exit_label) need_return=1;
1433 emit(f,"\trbra\t%s%d,1\n",labprefix,t);
1434 }
1435 cc=0;continue;
1436 }
1437 if(c>=BEQ&&c<BRA){
1438 char *s=0;
1439 cc=0;
1440 if(cmpzero){
1441 cmpzero=0;
1442 if(lastcomp&UNSIGNED){
1443 if(c==BLT) continue;
1444 if(c==BGE) s="1";
1445 if(c==BLE) s="z";
1446 if(c==BGT) s="!z";
1447 }else{
1448 if(c==BLT) s="n";
1449 if(c==BGE) s="!n";
1450 if(c==BLE) ierror(0);
1451 if(c==BGT) ierror(0);
1452 }
1453 }
1454 if(!s){
1455 if(lastcomp&UNSIGNED) s=ccu[c-BEQ]; else s=ccs[c-BEQ];
1456 }
1457 if(t==exit_label&&!have_frame){
1458 emit(f,"\tabra\t@%s++,%s\n",regnames[sp],s);
1459 }else{
1460 emit(f,"\trbra\t%s%d,%s\n",labprefix,t,s);
1461 if(t==exit_label) need_return=1;
1462 }
1463 continue;
1464 }
1465 if(c==MOVETOREG){
1466 load_op(f,&p->q1,SHORT,t1);
1467 if(p->z.reg<=16){
1468 move(f,&p->q1,0,0,p->z.reg,SHORT);
1469 cc=&p->q1;cc_t=SHORT;
1470 }else{
1471 move(f,&p->q1,0,0,p->z.reg,LONG);
1472 cc=0;
1473 }
1474 continue;
1475 }
1476 if(c==MOVEFROMREG){
1477 load_op(f,&p->z,SHORT,t2);
1478 if(p->q1.reg<=16){
1479 move(f,0,p->q1.reg,&p->z,0,SHORT);
1480 cc=&p->z;cc_t=SHORT;
1481 }else{
1482 move(f,0,p->q1.reg,&p->z,0,LONG);
1483 cc=0;
1484 }
1485 continue;
1486 }
1487
1488 if(c==TEST){
1489 /* TODO: optimize in COMPARE? */
1490 lastcomp=t;
1491 if(cc&&(cc_t&NU)==(t&NU)&&compare_objects(cc,&p->q1)){
1492 continue;
1493 }
1494
1495 p->code=c=COMPARE;
1496 gval.vmax=l2zm(0L);
1497 p->q2.flags=KONST;
1498 eval_const(&gval,MAXINT);
1499 insert_const(&p->q2.val,t);
1500 }
1501 /* switch operands so that we have matching branch */
1502 if(c==COMPARE){
1503 p2=p->next;
1504 while(p2&&p2->code==FREEREG) p2=p2->next;
1505 if(!p2||p2->code<BEQ||p2->code>BGT) ierror(0);
1506 if(p2->code==BGT){
1507 o=p->q1;p->q1=p->q2;p->q2=o;
1508 p2->code=BLT;
1509 }else if(p2->code==BLE){
1510 o=p->q1;p->q1=p->q2;p->q2=o;
1511 p2->code=BGE;
1512 }
1513 }
1514
1515 if(c==COMPARE&&isconst(q2)){
1516 eval_const(&p->q2.val,t);
1517 if(ISNULL()){
1518 if(cc&&(cc_t&NU)==(t&NU)&&compare_objects(cc,&p->q1)){
1519 p2=p->next;
1520 while(p2&&p2->code==FREEREG) p2=p2->next;
1521 if(!p2||p2->code<BEQ||p2->code>BGT) ierror(0);
1522 if((t&UNSIGNED)||p2->code==BNE||p2->code==BEQ||p2->code==BLT||p2->code==BGE){
1523 lastcomp=t;
1524 cmpzero=1;
1525 continue;
1526 }
1527 }
1528 }
1529 }
1530
1531 if(c==SUBPFP){
1532 p->code=c=SUB;
1533 if((p->typf2&NQ)==NPOINTER) p->typf=t=INT;
1534 else if((p->typf2&NQ)==HPOINTER) p->typf=t=LONG;
1535 else ierror(0);
1536 if((p->typf2&NQ)==NPOINTER){
1537 cc=&p->z;cc_t=NPOINTER;
1538 }else{
1539 cc=0;
1540 }
1541 }
1542
1543 if(c==ADDI2P||c==SUBIFP){
1544 /*if(c==ADDI2P) p->code=c=ADD; else p->code=c=SUB;*/
1545 if((p->typf2&NQ)!=HPOINTER){
1546 p->typf=t=(UNSIGNED|SHORT);
1547 short_add=2;
1548 if(isreg(q2)&&reg_pair(p->q2.reg,&rp)){
1549 /*FIXME:warning*/
1550 p->q2.reg=rp.r1;
1551 }
1552 }else if(ISHWORD(t)){
1553 p->typf=t=(UNSIGNED|LONG);
1554 short_add=1;
1555 }
1556 if((p->typf2&NQ)==NPOINTER){
1557 cc=&p->z;cc_t=NPOINTER;
1558 }else{
1559 cc=0;
1560 }
1561 }
1562
1563 if(c==CONVERT&&!must_convert(p->typf,p->typf2,0)){
1564 p->code=c=ASSIGN;
1565 p->q2.val.vmax=sizetab[p->typf&NQ];
1566 }
1567
1568 if(c==CONVERT){
1569 int to=p->typf2&NU;
1570 if(to==INT||to==CHAR) to=SHORT;
1571 if(to==(UNSIGNED|INT)||to==(UNSIGNED|CHAR)||to==NPOINTER) to=(UNSIGNED|SHORT);
1572 if(to==FPOINTER||to==HPOINTER) to=(UNSIGNED|LONG);
1573 if((t&NU)==INT||(t&NU)==CHAR) t=SHORT;
1574 if((t&NU)==(UNSIGNED|INT)||(t&NU)==(UNSIGNED|CHAR)||(t&NU)==NPOINTER) t=(UNSIGNED|SHORT);
1575 if((t&NQ)==FPOINTER||(t&NQ)==HPOINTER) t=(UNSIGNED|LONG);
1576 if((to&NQ)==LONG){
1577 if((t&NQ)!=SHORT) ierror(0);
1578 load_op(f,&p->q1,to,t1);
1579 load_op(f,&p->z,t,t2);
1580 if(isreg(q1)){
1581 if(!reg_pair(p->q1.reg,&rp))
1582 ierror(0);
1583 move(f,0,rp.r1,&p->z,0,t);
1584 }else
1585 move(f,&p->q1,0,&p->z,0,t);
1586 cc=&p->z;cc_t=t;
1587 continue;
1588 }else if((t&NQ)==LONG){
1589 if((to&NQ)!=SHORT) ierror(0);
1590 load_op(f,&p->q1,to,t1);
1591 load_op(f,&p->z,t,t2);
1592 if(isreg(z)){
1593 if(!reg_pair(p->z.reg,&rp))
1594 ierror(0);
1595 emit(f,"\txor\t%s,%s\n",regnames[rp.r2],regnames[rp.r2]);
1596 move(f,&p->q1,0,0,rp.r1,to);
1597 if(!(to&UNSIGNED)){
1598 emit(f,"\trbra\t%s%d,!n\n",labprefix,++label);
1599 emit(f,"\tsub\t1,%s\n",regnames[rp.r2]);
1600 emit(f,"%s%d:\n",labprefix,label);
1601 }
1602 }else{
1603 if(to&UNSIGNED){
1604 emit(f,"\tmove\t");
1605 emit_obj(f,&p->q1,to);
1606 emit(f,",@%s++\n",regnames[p->z.reg]);
1607 emit(f,"\tmove\t0,@%s\n",regnames[p->z.reg]);
1608 }else{
1609 if(isreg(q1)){
1610 reg=p->q1.reg;
1611 }else{
1612 reg=t1;
1613 move(f,&p->q1,0,0,t1,to);
1614 }
1615 emit(f,"\tmove\t%s,@%s++\n",regnames[reg],regnames[p->z.reg]);
1616 emit(f,"\tmove\t0,@%s\n",regnames[p->z.reg]);
1617 emit(f,"\tmove\t%s,%s\n",regnames[reg],regnames[reg]);
1618 emit(f,"\trbra\t%s%d,!n\n",labprefix,++label);
1619 emit(f,"\tsub\t1,@%s\n",regnames[p->z.reg]);
1620 emit(f,"%s%d:\n",labprefix,label);
1621 }
1622 if(!scratchreg(p->z.reg,p))
1623 emit(f,"\tsub\t1,%s\n",regnames[p->z.reg]);
1624 }
1625 cc=0;
1626 continue;
1627 }else
1628 ierror(0);
1629 }
1630 if(c==MINUS){
1631 p->code=c=SUB;
1632 p->q2=p->q1;
1633 gval.vmax=l2zm(0L);
1634 eval_const(&gval,t);
1635 insert_const(&p->q1.val,t);
1636 p->q1.flags=KONST;
1637 }
1638 if(c==KOMPLEMENT){
1639 load_op(f,&p->q1,t,t1);
1640 load_op(f,&p->z,t,t2);
1641 if(ISLWORD(t)){
1642 emit(f,"\tnot\t");
1643 emit_lword(f,&p->q1,t,"@%s++");
1644 emit(f,",");
1645 emit_lword(f,&p->z,t,"@%s++");
1646 emit(f,"\n");
1647 emit(f,"\tnot\t");
1648 emit_hword(f,&p->q1,t,"@%s++");
1649 emit(f,",");
1650 emit_hword(f,&p->z,t,"@%s++");
1651 emit(f,"\n");
1652 cleanup_lword(f,&p->q1);
1653 cleanup_lword(f,&p->z);
1654 cc=0;
1655 }else{
1656 emit(f,"\tnot\t");
1657 emit_obj(f,&p->q1,t);
1658 emit(f,",");
1659 emit_obj(f,&p->z,t);
1660 emit(f,"\n");
1661 cc=&p->z;cc_t=t;
1662 }
1663 continue;
1664 }
1665 if(c==SETRETURN){
1666 if(p->z.reg){
1667 if(reg_pair(p->z.reg,&rp))
1668 load_op(f,&p->q1,t,t1);
1669 else
1670 load_op(f,&p->q1,t,p->z.reg);
1671 move(f,&p->q1,0,0,p->z.reg,t);
1672 BSET(regs_modified,p->z.reg);
1673 }
1674 cc=0; /* probably not needed */
1675 continue;
1676 }
1677 if(c==GETRETURN){
1678 if(p->q1.reg){
1679 if((!isreg(z)||p->z.reg!=p->q1.reg)&&!ISLWORD(t)){ cc=&p->z;cc_t=t;}
1680 load_op(f,&p->z,t,t2);
1681 move(f,0,p->q1.reg,&p->z,0,t);
1682 }
1683 continue;
1684 }
1685 if(c==CALL){
1686 int reg,jmp=0;long cstack=0;
1687 cc=0;
1688 if((p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp("__va_start",p->q1.v->identifier)){
1689 long va_off=loff-stackoffset+pushedsize+zm2l(va_offset(v))+1;
1690 emit(f,"\tmove\t%s,%s\n",regnames[sp],regnames[r8]);
1691 if(va_off)
1692 emit(f,"\tadd\t%ld,%s\n",va_off,regnames[r8]);
1693 BSET(regs_modified,r8);
1694 if(LARGE||HUGE){
1695 emit(f,"\tmove\t0,%s\n",regnames[r9]);
1696 BSET(regs_modified,r9);
1697 }
1698 continue;
1699 }
1700 if(stack_valid){
1701 int i;
1702 if(p->call_cnt<=0){
1703 err_ic=p;if(f) error(320);
1704 stack_valid=0;
1705 }
1706 for(i=0;stack_valid&&i<p->call_cnt;i++){
1707 if(p->call_list[i].v->fi&&(p->call_list[i].v->fi->flags&ALL_STACK)){
1708 if(p->call_list[i].v->fi->stack1>cstack) cstack=p->call_list[i].v->fi->stack1;
1709 }else{
1710 err_ic=p;if(f) error(317,p->call_list[i].v->identifier);
1711 stack_valid=0;
1712 }
1713 }
1714 }
1715 if(!calc_regs(p,f!=0)&&v->fi) v->fi->flags&=~ALL_REGS;
1716 if((p->q1.flags&VAR)&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
1717 emit_inline_asm(f,p->q1.v->fi->inline_asm);
1718 callee_push(cstack);
1719 }else{
1720 if(stackoffset==0&&!have_frame&&!(v->tattr&INTERRUPT)){
1721 struct IC *p2;
1722 jmp=1;
1723 for(p2=p->next;p2;p2=p2->next){
1724 if(p2->code!=FREEREG&&p2->code!=ALLOCREG&&p2->code!=LABEL&&p2->code!=NOP&&
1725 (p2->code!=GETRETURN||(p2->z.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=p2->z.reg)&&
1726 (p2->code!=SETRETURN||(p2->q1.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=p2->z.reg)){
1727 jmp=0;break;
1728 }
1729 }
1730 }
1731 if(p->q1.flags&DREFOBJ){
1732 int clabel=++label;
1733 if(ISLWORD(p->q1.dtyp)){
1734 ierror(0);
1735 }
1736 p->q1.flags&=~DREFOBJ;
1737 load_op(f,&p->q1,t,t1);
1738 if(!ISLWORD(p->q1.dtyp)){
1739 emit(f,"\t%s\t",jmp?jump:"asub");
1740 emit_obj(f,&p->q1,p->q1.dtyp);
1741 emit(f,",1\n");
1742 push(1);
1743 callee_push(cstack);
1744 pop(1);
1745 }else{
1746 ierror(0);
1747 }
1748 }else{
1749 if(jmp){
1750 emit(f,"\t%s\t",jump);
1751 callee_push(cstack);
1752 }else{
1753 emit(f,"\t%s\t",call);
1754 if(TINY)
1755 push(1);
1756 else
1757 push(2);
1758 callee_push(cstack);
1759 if(TINY)
1760 pop(1);
1761 else
1762 pop(2);
1763 }
1764 emit_obj(f,&p->q1,t);
1765 emit(f,",1\n");
1766 }
1767 }
1768 if(jmp&&!need_return) ret="";
1769 if(!zmeqto(l2zm(0L),p->q2.val.vmax)){
1770 notpopped+=zm2l(p->q2.val.vmax);
1771 dontpop-=zm2l(p->q2.val.vmax);
1772 if(!(g_flags[2]&USEDFLAG)&&stackoffset==-notpopped){
1773 /* Entfernen der Parameter verzoegern */
1774 }else{
1775 emit(f,"\tadd\t%ld,%s\n",zm2l(p->q2.val.vmax),regnames[sp]);
1776 pop(zm2l(p->q2.val.vmax));
1777 notpopped-=zm2l(p->q2.val.vmax);cc=0;
1778 }
1779 }
1780 continue;
1781 }
1782 if(c==ASSIGN||c==PUSH){
1783 if(c==PUSH) dontpop+=zm2l(p->q2.val.vmax);
1784
1785 if(c==ASSIGN||c==PUSH){
1786 long sz=zm2l(p->q2.val.vmax);
1787 int qreg,zreg,creg,i;
1788 if(sz==1){
1789 load_op(f,&p->q1,t,t1);
1790 if(c==ASSIGN){
1791 load_op(f,&p->z,t,t2);
1792 move(f,&p->q1,0,&p->z,0,t);
1793 cc=&p->z;cc_t=t;
1794 }else{
1795 emit(f,"\tmove\t");
1796 emit_obj(f,&p->q1,t);
1797 emit(f,",@--%s\n",regnames[sp]);
1798 push(zm2l(p->z.val.vmax));
1799 cc=&p->q1;cc_t=t;
1800 }
1801 continue;
1802 }else if(ISLWORD(t)&&(isreg(q1)||isreg(z)||(p->q1.flags&(KONST|DREFOBJ))==KONST)){
1803 if(c==ASSIGN){
1804 move(f,&p->q1,0,&p->z,0,t);
1805 }else{
1806 load_op(f,&p->q1,t,t1);
1807
1808 if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ))
1809 emit(f,"\tadd\t2,%s\n",regnames[p->q1.reg]);
1810
1811 emit(f,"\tmove\t");
1812 emit_hword(f,&p->q1,t,"@--%s");
1813 emit(f,",@--%s\n",regnames[sp]);
1814 emit(f,"\tmove\t");
1815 emit_lword(f,&p->q1,t,"@--%s");
1816 emit(f,",@--%s\n",regnames[sp]);
1817 push(2);
1818 }
1819 cc=0;
1820 continue;
1821 }else{
1822 static char cpstr[64];
1823 cc=0;
1824 load_op(f,&p->q1,t,t1);
1825 if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&scratchreg(p->q1.reg,p)){
1826 qreg=p->q1.reg;
1827 }else{
1828 if(!(p->q1.flags&REG))
1829 ierror(0);
1830 qreg=t1;
1831 move(f,0,p->q1.reg,0,qreg,INT);
1832 }
1833 if(c==ASSIGN){
1834 load_op(f,&p->z,t,t2);
1835 if((p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&scratchreg(p->z.reg,p)){
1836 zreg=p->z.reg;
1837 }else{
1838 if(!(p->z.flags&REG))
1839 ierror(0);
1840 if(qreg==t1) zreg=t2; else zreg=t1;
1841 move(f,0,p->z.reg,0,zreg,INT);
1842 }
1843 sprintf(cpstr,"\tmove\t@%s++,@%s++\n",regnames[qreg],regnames[zreg]);
1844 }else{
1845 zreg=sp;
1846 emit(f,"\tadd\t%ld,%s\n",sz,regnames[qreg]);
1847 sprintf(cpstr,"\tmove\t@--%s,@--%s\n",regnames[qreg],regnames[zreg]);
1848 push(zm2l(p->q2.val.vmax));
1849 }
1850 if(sz<=9){
1851 for(i=0;i<sz;i++)
1852 emit(f,cpstr);
1853 }else{
1854 int cntpushed=0;
1855 if(zreg!=t2)
1856 creg=t2;
1857 else{
1858 creg=get_reg(f,p);
1859 if(c==PUSH) ierror(0);
1860 creg=r8;
1861 emit(f,"\tmove\t%s,@--%s\n",regnames[creg],regnames[sp]);
1862 cntpushed=1;
1863 }
1864 emit(f,"\tmove\t%ld,%s\n",sz/4,regnames[creg]);
1865 emit(f,"%s%d:\n",labprefix,++label);
1866 emit(f,cpstr);
1867 emit(f,cpstr);
1868 emit(f,cpstr);
1869 emit(f,cpstr);
1870 emit(f,"\tsub\t1,%s\n",regnames[creg]);
1871 emit(f,"\trbra\t%s%d,!z\n",labprefix,label);
1872 for(i=0;i<sz%4;i++)
1873 emit(f,cpstr);
1874 if(cntpushed)
1875 emit(f,"\tmove\t@%s++,%s\n",regnames[sp],regnames[creg]);
1876 }
1877 continue;
1878 }
1879
1880 }
1881 ierror(0);
1882 }
1883 if(c==ADDRESS){
1884 reg=0;
1885 if(0/*reg_pair(reg,&rp)*/){
1886 ierror(0);
1887 emit(f,"\tmov\t%s,%s\n",regnames[rp.r1],regnames[sp]);
1888 emit(f,"\tmov\t%s,#0\n",regnames[rp.r2]);
1889 if(voff(&p->q1))
1890 emit(f,"\tadd\t%s,#%ld\n",regnames[rp.r1],voff(&p->q1)&0xffff);
1891 }else{
1892 if(isreg(z))
1893 reg=p->z.reg;
1894 else{
1895 load_op(f,&p->z,t,t2);
1896 }
1897 if(voff(&p->q1)){
1898 if(!reg) reg=t1;
1899 emit(f,"\tmove\t%s,%s\n",regnames[sp],regnames[reg]);
1900 emit(f,"\tadd\t%ld,%s\n",voff(&p->q1),regnames[reg]);
1901 }else
1902 reg=sp;
1903 move(f,0,reg,&p->z,0,ztyp(p));
1904 }
1905 cc=&p->z;cc_t=ztyp(p);
1906 continue;
1907 }
1908
1909 if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==COMPARE||c==ADDI2P||c==SUBIFP){
1910 char *s;
1911
1912 if(c==MULT||c==DIV||c==MOD){
1913 int code;
1914 load_op(f,&p->q1,t,t1);
1915 emit(f,"\tmove\t%ld,%s\n",(long)0xff1b,regnames[t2]);
1916 emit(f,"\tmove\t");
1917 emit_obj(f,&p->q1,t);
1918 emit(f,",@%s++\n",regnames[t2]);
1919 load_op(f,&p->q2,t,t1);
1920 emit(f,"\tmove\t");
1921 emit_obj(f,&p->q2,t);
1922 emit(f,",@%s++\n",regnames[t2]);
1923 emit(f,"\tmove\t%ld,%s\n",(long)0xff1f,regnames[t1]);
1924 if(c==MULT) code=0; else code=2;
1925 if(!(t&UNSIGNED)) code++;
1926 emit(f,"\tmove\t%d,@%s\n",code,regnames[t1]);
1927 if(c==MOD)
1928 emit(f,"\tmove\t%ld,%s\n",(long)0xff1e,regnames[t2]);
1929 load_op(f,&p->z,t,t1);
1930 emit(f,"\tmove\t@%s,",regnames[t2]);
1931 emit_obj(f,&p->z,t);
1932 emit(f,"\n");
1933 cc=&p->z;cc_t=t;
1934 continue;
1935 }
1936
1937 if(c==LSHIFT&&isconst(q2)&&isreg(q1)){
1938 eval_const(&p->q2.val,INT);
1939 if(zmeqto(vmax,l2zm(1L))){
1940 p->code=c=ADD;
1941 p->q2=p->q1;
1942 }
1943 }
1944
1945 if(compare_objects(&p->q2,&p->z)){
1946 if(!compare_objects(&p->q1,&p->z)){
1947 if(c==LSHIFT||c==RSHIFT){
1948 reg=get_reg(f,p);
1949 if(reg){
1950 move(f,&p->q2,0,0,reg,q2typ(p));
1951 p->q2.flags=REG;
1952 p->q2.reg=reg;
1953 }else{
1954 emit(f,"\tmove\t");
1955 emit_obj(f,&p->q2,q2typ(p));
1956 emit(f,",@--%s\n",regnames[sp]);
1957 p->q2.flags=REG|DREFOBJ;
1958 p->q2.reg=sp;
1959 p->q2.am=mymalloc(sizeof(*p->q2.am));
1960 p->q2.am->flags=POST_INC;
1961 p->q2.am->base=sp;
1962 }
1963 }else if(c==SUB||c==SUBPFP||c==SUBIFP){
1964 /* TODO: check pointer sizes subifp/subpfp */
1965 if(ISLWORD(t)){
1966 if(isreg(z)){
1967 if(!reg_pair(p->z.reg,&rp)) ierror(0);
1968 emit(f,"\tnot\t%s,%s\n",regnames[rp.r1],regnames[rp.r1]);
1969 emit(f,"\tnot\t%s,%s\n",regnames[rp.r2],regnames[rp.r2]);
1970 emit(f,"\tadd\t1,%s\n",regnames[rp.r1]);
1971 emit(f,"\taddc\t0,%s\n",regnames[rp.r2]);
1972 p->q2=p->q1;
1973 p->q1=p->z;
1974 p->code=c=ADD;
1975 }else
1976 ierror(0);
1977 }else{
1978 load_op(f,&p->z,t,t1);
1979 emit(f,"\tnot\t");
1980 emit_obj(f,&p->z,t);
1981 emit(f,",");
1982 emit_obj(f,&p->z,t);
1983 emit(f,"\n");
1984 emit(f,"\tadd\t1,");
1985 emit_obj(f,&p->z,t);
1986 emit(f,"\n");
1987 load_op(f,&p->q1,t,t2);
1988 emit(f,"\tadd\t");
1989 emit_obj(f,&p->q1,t);
1990 emit(f,",");
1991 emit_obj(f,&p->z,t);
1992 emit(f,"\n");
1993 cc=&p->z;cc_t=t;
1994 continue;
1995 }
1996 }else{
1997 struct obj m;
1998 m=p->q1;p->q1=p->q2;p->q2=m;
1999 }
2000 }
2001 }
2002
2003 if(c>=OR&&c<=AND){
2004 s=logicals[c-OR];
2005 }else{
2006 if(c==ADDI2P)
2007 s=arithmetics[ADD-LSHIFT];
2008 else if(c==SUBIFP)
2009 s=arithmetics[SUB-LSHIFT];
2010 else
2011 s=arithmetics[c-LSHIFT];
2012 }
2013
2014 if(c==COMPARE){
2015 lastcomp=t;
2016 load_op(f,&p->q1,t,t1);
2017 load_op(f,&p->q2,t,t2);
2018
2019 if(ISLWORD(t)){
2020 if((p->q1.flags&DREFOBJ)&&p->q1.reg!=t1){
2021 emit(f,"\tmove\t%s,%s\n",regnames[p->q1.reg],regnames[t1]);
2022 p->q1.reg=t1;
2023 }
2024 if((p->q2.flags&DREFOBJ)&&p->q2.reg!=t2){
2025 emit(f,"\tmove\t%s,%s\n",regnames[p->q2.reg],regnames[t2]);
2026 p->q2.reg=t2;
2027 }
2028 p2=p->next;
2029 while(p2&&p2->code==FREEREG) p2=p2->next;
2030 if(!p2||p2->code<BEQ||p2->code>BGT) ierror(0);
2031 c=p2->code;
2032 if(c==BEQ||c==BNE){
2033 emit(f,"\tcmp\t",s);
2034 emit_lword(f,&p->q1,t,"@%s++");
2035 emit(f,",");
2036 emit_lword(f,&p->q2,t,"@%s++");
2037 emit(f,"\n");
2038 if(c==BEQ)
2039 emit(f,"\trbra\t%s%d,!z\n",labprefix,elab=++label);
2040 else
2041 emit(f,"\trbra\t%s%d,!z\n",labprefix,p2->typf);
2042 emit(f,"\tcmp\t",s);
2043 emit_hword(f,&p->q1,t,"@%s++");
2044 emit(f,",");
2045 emit_hword(f,&p->q2,t,"@%s++");
2046 emit(f,"\n");
2047 emit(f,"\trbra\t%s%d,%s\n",labprefix,p2->typf,ccs[c-BEQ]);
2048 }else{
2049 elab=++label;
2050 if(p->q1.flags&DREFOBJ) emit(f,"\tadd\t1,%s\n",regnames[p->q1.reg]);
2051 if(p->q2.flags&DREFOBJ) emit(f,"\tadd\t1,%s\n",regnames[p->q2.reg]);
2052 emit(f,"\tcmp\t",s);
2053 emit_hword(f,&p->q2,t,"@%s");
2054 emit(f,",");
2055 emit_hword(f,&p->q1,t,"@%s");
2056 emit(f,"\n");
2057 emit(f,"\trbra\t%s%d,%s\n",labprefix,c==BLT?p2->typf:elab,(t&UNSIGNED)?ccu[BLT-BEQ]:ccs[BLT-BEQ]);
2058 /* unfortunately flags are overwritten... */
2059 emit(f,"\tcmp\t",s);
2060 emit_hword(f,&p->q2,t,"@%s");
2061 emit(f,",");
2062 emit_hword(f,&p->q1,t,"@%s");
2063 emit(f,"\n");
2064 emit(f,"\trbra\t%s%d,!z\n",labprefix,c==BLT?elab:p2->typf);
2065 if(p->q1.flags&DREFOBJ) emit(f,"\tsub\t1,%s\n",regnames[p->q1.reg]);
2066 if(p->q2.flags&DREFOBJ) emit(f,"\tsub\t1,%s\n",regnames[p->q2.reg]);
2067 emit(f,"\tcmp\t",s);
2068 emit_lword(f,&p->q2,t,"@%s");
2069 emit(f,",");
2070 emit_lword(f,&p->q1,t,"@%s");
2071 emit(f,"\n");
2072 emit(f,"\trbra\t%s%d,%s\n",labprefix,p2->typf,ccu[c-BEQ]);
2073 }
2074 cc=0;
2075#if 0
2076 /* last branch done in branch IC */
2077 lastcomp=UNSIGNED|INT;
2078#else
2079 if(c!=BNE)
2080 emit(f,"%s%d:\n",labprefix,elab);
2081 p2->code=NOP;
2082#endif
2083 continue;
2084 }else{
2085 emit(f,"\tcmp\t",s);
2086 emit_obj(f,&p->q2,t);
2087 emit(f,",");
2088 emit_obj(f,&p->q1,t);
2089 emit(f,"\n");
2090 }
2091 cc=0;
2092 continue;
2093 }
2094
2095
2096 if(!compare_objects(&p->q1,&p->z)){
2097 load_op(f,&p->q1,t,t1);
2098 load_op(f,&p->z,t,t2);
2099 if((p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&isreg(z)&&p->q2.reg==p->z.reg){
2100 move(f,0,p->q2.reg,0,t2,NPOINTER);
2101 p->q2.reg=t2;
2102 }
2103 move(f,&p->q1,0,&p->z,0,t);
2104 /* cleanup postinc if necessary (not done by cleanup_lword */
2105 if(p->z.reg==t2&&(p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&ISLWORD(t))
2106 emit(f,"\tsub\t2,%s\n",regnames[t2]);
2107 }else
2108 load_op(f,&p->z,t,t2);
2109 load_op(f,&p->q2,t,t1);
2110
2111 if(ISLWORD(t)){
2112
2113 emit(f,"\t%s\t",s);
2114 emit_lword(f,&p->q2,t,"@%s++");
2115 emit(f,",");
2116 emit_lword(f,&p->z,t,"@%s++");
2117 emit(f,"\n");
2118 emit(f,"\t%s%s\t",s,!strcmp(s,"add")||!strcmp(s,"sub")?"c":"");
2119 emit_hword(f,&p->q2,t,"@%s++");
2120 emit(f,",");
2121 emit_hword(f,&p->z,t,"@%s++");
2122 emit(f,"\n");
2123 cleanup_lword(f,&p->q2);
2124 cleanup_lword(f,&p->z);
2125 cc=0;
2126
2127 }else{
2128
2129 /* TODO: try to eliminate */
2130 if(c==LSHIFT){
2131 emit(f,"\tcmp\t%s,%s\n",regnames[sp],regnames[sp]);
2132 }else if(c==RSHIFT){
2133 if(t&UNSIGNED){
2134 emit(f,"\tor\t%s,%s\n",regnames[sp],regnames[sp]);
2135 }else{
2136 emit(f,"\tshl\t1,");
2137 emit_obj(f,&p->z,t);
2138 emit(f,"\n");
2139 emit(f,"\tshr\t1,");
2140 emit_obj(f,&p->z,t);
2141 emit(f,"\n");
2142 }
2143 }
2144 emit(f,"\t%s\t",s);
2145 emit_obj(f,&p->q2,t);
2146 emit(f,",");
2147 emit_obj(f,&p->z,t);
2148 emit(f,"\n");
2149 cc=&p->z;cc_t=t;
2150
2151 }
2152 if(ISLWORD(t)) cc=0;
2153
2154 continue;
2155 }
2156 ierror(0);
2157 }
2158 if(notpopped){
2159 emit(f,"\tadd\t%ld,%s\n",notpopped,regnames[sp]);
2160 pop(notpopped);notpopped=0;
2161 }
2162 function_bottom(f,v,loff);
2163}
2164
2165int shortcut(int c,int t)
2166{
2167 if(c==COMPARE||c==AND||c==OR||c==XOR) return 1;
2168 if(c==ADD||c==SUB) return 1;
2169 return 0;
2170}
2171
2172void cleanup_cg(FILE *f)
2173{
2174 struct fpconstlist *p;
2175 unsigned char *ip;
2176 if(f&&stack_check){
2177 emit(f,"\t.global\t%s__stack_check\n",idprefix);
2178 }
2179 while(p=firstfpc){
2180 if(f){
2181 new_section(f,NDATA);
2182 emit(f,"%s%d:\n\t%s\t",labprefix,p->label,dct[SHORT]);
2183 ip=(unsigned char *)&p->val.vdouble;
2184 emit(f,"0x%02x%02x,0x%02x%02x",ip[1],ip[0],ip[3],ip[2]);
2185 if((p->typ&NQ)==DOUBLE||(p->typ&NQ)==LDOUBLE){
2186 emit(f,",0x%02x%02x,0x%02x%02x",ip[5],ip[4],ip[7],ip[6]);
2187 }
2188 emit(f,"\n");
2189 }
2190 firstfpc=p->next;
2191 free(p);
2192 }
2193}
2194
2195int reg_parm(struct reg_handle *p,struct Typ *t,int mode,struct Typ *fkt)
2196{
2197 int f=t->flags&NQ;
2198 if(!ISSCALAR(f)) return 0;
2199 if(p->gpr>2||mode) return 0;
2200 if(f==LLONG||f==DOUBLE||f==LDOUBLE)
2201 return 0;
2202 else if(f==LONG||f==FLOAT||f==FPOINTER||f==HPOINTER){
2203 if(p->gpr==0) {p->gpr=2;return r8r9;}
2204 return 0;
2205 }else
2206 return r8+p->gpr++;
2207}
2208
2209void insert_const(union atyps *p,int t)
2210/* Traegt Konstante in entprechendes Feld ein. */
2211{
2212 if(!p) ierror(0);
2213/* *p = (union atyps) 0 ; /* rfi: clear unused bits */
2214 t&=NU;
2215 if(t==CHAR) {p->vchar=vchar;return;}
2216 if(t==SHORT) {p->vshort=vshort;return;}
2217 if(t==INT) {p->vint=vint;return;}
2218 if(t==LONG) {p->vlong=vlong;return;}
2219 if(t==LLONG) {p->vllong=vllong;return;}
2220 if(t==MAXINT) {p->vmax=vmax;return;}
2221 if(t==(UNSIGNED|BIT)) {if(zumeqto(zuc2zum(vuchar),ul2zum(0UL))) p->vuchar=zum2zuc(ul2zum(0UL)); else p->vuchar=zum2zuc(ul2zum(1UL));return;}
2222 if(t==(UNSIGNED|CHAR)) {p->vuchar=vuchar;return;}
2223 if(t==(UNSIGNED|SHORT)) {p->vushort=vushort;return;}
2224 if(t==(UNSIGNED|INT)) {p->vuint=vuint;return;}
2225 if(t==(UNSIGNED|LONG)) {p->vulong=vulong;return;}
2226 if(t==(UNSIGNED|LLONG)) {p->vullong=vullong;return;}
2227 if(t==(UNSIGNED|MAXINT)) {p->vumax=vumax;return;}
2228 if(t==FLOAT) {p->vfloat=vfloat;return;}
2229 if(t==DOUBLE) {p->vdouble=vdouble;return;}
2230 if(t==LDOUBLE) {p->vldouble=vldouble;return;}
2231 if(t==NPOINTER) {p->vuint=vuint;return;}
2232 if(t==FPOINTER||t==HPOINTER) {p->vulong=vulong;return;}
2233}
2234void eval_const(union atyps *p,int t)
2235/* Weist bestimmten globalen Variablen Wert einer CEXPR zu. */
2236{
2237 int f=t&NQ;
2238 if(!p) ierror(0);
2239 if(f==MAXINT||(f>=BIT&&f<=LLONG)){
2240 if(!(t&UNSIGNED)){
2241 if(f==CHAR) vmax=zc2zm(p->vchar);
2242 else if(f==SHORT)vmax=zs2zm(p->vshort);
2243 else if(f==INT) vmax=zi2zm(p->vint);
2244 else if(f==LONG) vmax=zl2zm(p->vlong);
2245 else if(f==LLONG) vmax=zll2zm(p->vllong);
2246 else if(f==MAXINT) vmax=p->vmax;
2247 else ierror(0);
2248 vumax=zm2zum(vmax);
2249 vldouble=zm2zld(vmax);
2250 }else{
2251 if(f==CHAR) vumax=zuc2zum(p->vuchar);
2252 else if(f==SHORT)vumax=zus2zum(p->vushort);
2253 else if(f==INT) vumax=zui2zum(p->vuint);
2254 else if(f==LONG) vumax=zul2zum(p->vulong);
2255 else if(f==LLONG) vumax=zull2zum(p->vullong);
2256 else if(f==MAXINT) vumax=p->vumax;
2257 else ierror(0);
2258 vmax=zum2zm(vumax);
2259 vldouble=zum2zld(vumax);
2260 }
2261 }else{
2262 if(ISPOINTER(f)){
2263 if(f==NPOINTER)
2264 vumax=zui2zum(p->vuint);
2265 else
2266 vumax=zul2zum(p->vulong);
2267 vmax=zum2zm(vumax);vldouble=zum2zld(vumax);
2268 }else{
2269 if(f==FLOAT) vldouble=zf2zld(p->vfloat);
2270 else if(f==DOUBLE) vldouble=zd2zld(p->vdouble);
2271 else vldouble=p->vldouble;
2272 vmax=zld2zm(vldouble);
2273 vumax=zld2zum(vldouble);
2274 }
2275 }
2276 vfloat=zld2zf(vldouble);
2277 vdouble=zld2zd(vldouble);
2278 vuchar=zum2zuc(vumax);
2279 vushort=zum2zus(vumax);
2280 vuint=zum2zui(vumax);
2281 vulong=zum2zul(vumax);
2282 vullong=zum2zull(vumax);
2283 vchar=zm2zc(vmax);
2284 vshort=zm2zs(vmax);
2285 vint=zm2zi(vmax);
2286 vlong=zm2zl(vmax);
2287 vllong=zm2zll(vmax);
2288}
2289void printval(FILE *f,union atyps *p,int t)
2290/* Gibt atyps aus. */
2291{
2292 t&=NU;
2293 if(t==BIT){fprintf(f,"B");vmax=zc2zm(p->vchar);fprintf(f,"%d",!zmeqto(vmax,l2zm(0L)));}
2294 if(t==(UNSIGNED|BIT)){fprintf(f,"UB");vumax=zuc2zum(p->vuchar);fprintf(f,"%d",!zumeqto(vmax,ul2zum(0UL)));}
2295 if(t==CHAR){fprintf(f,"C");vmax=zc2zm(p->vchar);printzm(f,vmax);}
2296 if(t==(UNSIGNED|CHAR)){fprintf(f,"UC");vumax=zuc2zum(p->vuchar);printzum(f,vumax);}
2297 if(t==SHORT){fprintf(f,"S");vmax=zs2zm(p->vshort);printzm(f,vmax);}
2298 if(t==(UNSIGNED|SHORT)){fprintf(f,"US");vumax=zus2zum(p->vushort);printzum(f,vumax);}
2299 if(t==FLOAT){fprintf(f,"F");vldouble=zf2zld(p->vfloat);printzld(f,vldouble);}
2300 if(t==DOUBLE){fprintf(f,"D");vldouble=zd2zld(p->vdouble);printzld(f,vldouble);}
2301 if(t==LDOUBLE){fprintf(f,"LD");printzld(f,p->vldouble);}
2302 if(t==INT){fprintf(f,"I");vmax=zi2zm(p->vint);printzm(f,vmax);}
2303 if(t==(UNSIGNED|INT)||t==NPOINTER){fprintf(f,"UI");vumax=zui2zum(p->vuint);printzum(f,vumax);}
2304 if(t==LONG){fprintf(f,"L");vmax=zl2zm(p->vlong);printzm(f,vmax);}
2305 if(t==(UNSIGNED|LONG)||t==FPOINTER||t==HPOINTER){fprintf(f,"UL");vumax=zul2zum(p->vulong);printzum(f,vumax);}
2306 if(t==LLONG){fprintf(f,"LL");vmax=zll2zm(p->vllong);printzm(f,vmax);}
2307 if(t==(UNSIGNED|LLONG)){fprintf(f,"ULL");vumax=zull2zum(p->vullong);printzum(f,vumax);}
2308 if(t==MAXINT) printzm(f,p->vmax);
2309 if(t==(UNSIGNED|MAXINT)) printzum(f,p->vumax);
2310}
2311void emitval(FILE *f,union atyps *p,int t)
2312/* Gibt atyps aus. */
2313{
2314 t&=NU;
2315 if(t==BIT){vmax=zc2zm(p->vchar);emit(f,"%d",!zmeqto(vmax,l2zm(0L)));}
2316 if(t==(UNSIGNED|BIT)){vumax=zuc2zum(p->vuchar);emit(f,"%d",!zumeqto(vumax,ul2zum(0UL)));}
2317 if(t==CHAR){vmax=zc2zm(p->vchar);emitzm(f,vmax);}
2318 if(t==(UNSIGNED|CHAR)){vumax=zuc2zum(p->vuchar);emitzum(f,vumax);}
2319 if(t==SHORT){vmax=zs2zm(p->vshort);emitzm(f,vmax);}
2320 if(t==(UNSIGNED|SHORT)){vumax=zus2zum(p->vushort);emitzum(f,vumax);}
2321 if(t==FLOAT){vldouble=zf2zld(p->vfloat);emitzld(f,vldouble);}
2322 if(t==DOUBLE){vldouble=zd2zld(p->vdouble);emitzld(f,vldouble);}
2323 if(t==LDOUBLE){emitzld(f,p->vldouble);}
2324 if(t==INT){vmax=zi2zm(p->vint);emitzm(f,vmax);}
2325 if(t==(UNSIGNED|INT)||t==NPOINTER){vumax=zui2zum(p->vuint);emitzum(f,vumax);}
2326 if(t==LONG){vmax=zl2zm(p->vlong);emitzm(f,vmax);}
2327 if(t==(UNSIGNED|LONG)||t==FPOINTER||t==HPOINTER){vumax=zul2zum(p->vulong);emitzum(f,vumax);}
2328 if(t==LLONG){vmax=zll2zm(p->vllong);emitzm(f,vmax);}
2329 if(t==(UNSIGNED|LLONG)){vumax=zull2zum(p->vullong);emitzum(f,vumax);}
2330 if(t==MAXINT) emitzm(f,p->vmax);
2331 if(t==(UNSIGNED|MAXINT)) emitzum(f,p->vumax);
2332}
2333void conv_typ(struct Typ *p)
2334/* Erzeugt extended types in einem Typ. */
2335{
2336 char *attr;
2337 while(p){
2338 if(ISPOINTER(p->flags)){
2339 p->flags=((p->flags&~NU)|POINTER_TYPE(p->next));
2340 if(attr=p->next->attr){
2341 if(strstr(attr,STR_NEAR))
2342 p->flags=((p->flags&~NU)|NPOINTER);
2343 if(strstr(attr,STR_FAR))
2344 p->flags=((p->flags&~NU)|FPOINTER);
2345 if(strstr(attr,STR_HUGE))
2346 p->flags=((p->flags&~NU)|HPOINTER);
2347 }
2348 }
2349 if(ISINT(p->flags)&&(attr=p->attr)&&strstr(attr,"bit"))
2350 p->flags=((p->flags&~NU)|BIT);
2351 p=p->next;
2352 }
2353}
2354
2355void init_db(FILE *f)
2356{
2357}
2358
2359void cleanup_db(FILE *f)
2360{
2361}
2362
2363char *use_libcall(int c,int t,int t2)
2364{
2365 static char fname[16];
2366 char *ret=0,*tt;
2367
2368 if(c==COMPARE){
2369 if((t&NQ)==LLONG||ISFLOAT(t)){
2370 sprintf(fname,"__cmp%s%s%ld",(t&UNSIGNED)?"u":"s",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*16);
2371 ret=fname;
2372 }
2373 }else{
2374 t&=NU;
2375 t2&=NU;
2376 if(t==LDOUBLE) t=DOUBLE;
2377 if(t2==LDOUBLE) t2=DOUBLE;
2378 if(c==CONVERT){
2379 if(t==t2) return 0;
2380 if(t==FLOAT&&t2==DOUBLE) return "__flt64toflt32";
2381 if(t==DOUBLE&&t2==FLOAT) return "__flt32toflt64";
2382
2383 if(ISFLOAT(t)){
2384 sprintf(fname,"__%cint%ldtoflt%d",(t2&UNSIGNED)?'u':'s',zm2l(sizetab[t2&NQ])*16,(t==FLOAT)?32:64);
2385 ret=fname;
2386 }
2387 if(ISFLOAT(t2)){
2388 sprintf(fname,"__flt%dto%cint%ld",((t2&NU)==FLOAT)?32:64,(t&UNSIGNED)?'u':'s',zm2l(sizetab[t&NQ])*16);
2389 ret=fname;
2390 }
2391 if((t&NQ)==LLONG||(t2&NQ)==LLONG){
2392 sprintf(fname,"__%cint%ldto%cint%ld",(t2&UNSIGNED)?'u':'s',zm2l(sizetab[t2&NQ])*16,(t&UNSIGNED)?'u':'s',zm2l(sizetab[t&NQ])*16);
2393 ret=fname;
2394 }
2395 }
2396 if(ISINT(t)&&ISLWORD(t)){
2397 if(c==MINUS||c==KOMPLEMENT||c==ADD||c==SUB||c==OR||c==AND||c==XOR)
2398 return 0;
2399 }
2400 if((t&NQ)==LONG||(t&NQ)==LLONG||ISFLOAT(t)||(SOFTMUL&&(c==MULT||c==DIV||c==MOD))){
2401 if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==KOMPLEMENT||c==MINUS){
2402 if(c!=DIV&&c!=MOD&&c!=RSHIFT&&c!=COMPARE)
2403 t&=~UNSIGNED;
2404 sprintf(fname,"__%s%s%s%ld",ename[c],(t&UNSIGNED)?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*16);
2405 ret=fname;
2406 }
2407 }
2408 }
2409
2410
2411 return ret;
2412}