blob: 2e43d73dcc0b720faa75d1292aad7159340f5c81 [file] [log] [blame]
PulkoMandy17fc7592022-07-28 18:27:54 +02001/* MEGA65 45GS02 backend for vbcc
2 (c) Volker Barthelmann 2020
3 (c) Paul Gardner-Stephen 2020
4
5*/
6
7#include "supp.h"
8#include "vbc.h"
9
10#include <math.h>
11
12static char FILE_[]=__FILE__;
13
14/* Public data that MUST be there. */
15
16/* Name and copyright. */
17char cg_copyright[]="vbcc 45GS02 (MEGA65) code-generator V0.1 (c) in 2020 by Volker Barthelmann, Paul Gardner-Stephen";
18
19/* Commandline-flags the code-generator accepts:
20 0: just a flag
21 VALFLAG: a value must be specified
22 STRINGFLAG: a string can be specified
23 FUNCFLAG: a function will be called
24 apart from FUNCFLAG, all other versions can only be specified once */
25int g_flags[MAXGF]={0,0,
26 VALFLAG,0,0,
27 0,0,
28 VALFLAG,VALFLAG,0,0,
29 VALFLAG,0,0,0,
30 0,0,0,
31 0};
32
33/* the flag-name, do not use names beginning with l, L, I, D or U, because
34 they collide with the frontend */
35char *g_flags_name[MAXGF]={"std-syntax","no-rax",
36 "volatile-regs","ieee","no-peephole",
37 "cbmascii","softstack",
38 "reg-args","int-args","mainargs","no-bank-vars",
39 "common-banknr","btmp-zpage","oldfp","large",
40 "glob-acc","avoid-bank-switch","manual-banking",
41 "atascii"};
42
43/* the results of parsing the command-line-flags will be stored here */
44union ppi g_flags_val[MAXGF];
45
46/* Alignment-requirements for all types in bytes. */
47zmax align[MAX_TYPE+1];
48
49/* Alignment that is sufficient for every object. */
50zmax maxalign;
51
52/* CHAR_BIT for the target machine. */
53zmax char_bit;
54
55/* sizes of the basic types (in bytes) */
56zmax sizetab[MAX_TYPE+1];
57
58/* Minimum and Maximum values each type can have. */
59/* Must be initialized in init_cg(). */
60zmax t_min[MAX_TYPE+1];
61zumax t_max[MAX_TYPE+1];
62zumax tu_max[MAX_TYPE+1];
63
64/* Names of all registers. will be initialized in init_cg(),
65 register number 0 is invalid, valid registers start at 1 */
66char *regnames[MAXR+1];
67
68/* The Size of each register in bytes. */
69zmax regsize[MAXR+1];
70
71/* a type which can store each register. */
72struct Typ *regtype[MAXR+1];
73
74/* regsa[reg]!=0 if a certain register is allocated and should */
75/* not be used by the compiler pass. */
76int regsa[MAXR+1];
77
78/* Specifies which registers may be scratched by functions. */
79int regscratch[MAXR+1];
80
81/* specifies the priority for the register-allocator, if the same
82 estimated cost-saving can be obtained by several registers, the
83 one with the highest priority will be used */
84int reg_prio[MAXR+1];
85
86/* an empty reg-handle representing initial state */
87struct reg_handle empty_reg_handle={0,0};
88
89/* Names of target-specific variable attributes. */
90char *g_attr_name[]={"__interrupt","__zpage","__nocpr",0};
91
92#define INTERRUPT 1
93#define ZPAGE 2
94#define NOCOMPRESS 4
95
96/****************************************/
97/* Private data and functions. */
98/****************************************/
99
100#define STDSYNTAX (g_flags[0]&USEDFLAG)
101#define NORAX (g_flags[1]&USEDFLAG)
102#define VOL_GPRS ((g_flags[2]&USEDFLAG)?g_flags_val[2].l:NUM_GPRS/2)
103#define IEEE (g_flags[3]&USEDFLAG)
104#define NOPEEP (g_flags[4]&USEDFLAG)
105#define CBMASCII (g_flags[5]&USEDFLAG)
106#define SOFTSTACK (g_flags[6]&USEDFLAG)
107#define GPR_ARGS ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:8)
108#define MAINARGS (g_flags[9]&USEDFLAG)
109#define NOBANKVARS (g_flags[10]&USEDFLAG)
110#define COMMONBANK ((g_flags[11]&USEDFLAG)?g_flags_val[11].l:0)
111#define BIGZPAGE (g_flags[12]&USEDFLAG)
112#define OLDFP (g_flags[13]&USEDFLAG)
113#define LARGE (g_flags[14]&USEDFLAG)
114#define GLOBACC (g_flags[15]&USEDFLAG)
115#define NOSWITCH (g_flags[16]&USEDFLAG)
116#define NOBANKING (g_flags[17]&USEDFLAG)
117#define ATASCII (g_flags[18]&USEDFLAG)
118
119
120
121#define STR_NEAR "near"
122#define STR_FAR "far"
123#define STR_HUGE "huge"
124
125#define PLA (-1)
126#define JMPIND (-2)
127
128static void function_top(FILE *,struct Var *,long);
129static void function_bottom(FILE *f,struct Var *,long);
130
131#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
132#define isacc(x) (isreg(x)&&(p->x.reg==ra||p->x.reg==rax))
133#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
134
135#define isptr(r) ((r)>=FIRST_PAIR&&(r)<=LAST_PAIR)
136
137static int q1reg,q2reg,zreg;
138
139static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
140static char *logicals[]={"ora","eor","and"};
141static char *arithmetics[]={"slw","srw","adc","sbc","mullw","divw","mod"};
142
143/* alignment of basic data-types, used to initialize align[] */
144static long malign[MAX_TYPE+1]= {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
145/* sizes of basic data-types, used to initialize sizetab[] */
146static long msizetab[MAX_TYPE+1]={1,1,2,2,4,8,4,4,4,0,2,3,3,0,0,0,1,0};
147static char *mregnames[MAXR+1];
148
149/* Typenames (needed because of HAVE_EXT_TYPES). */
150char *typname[]={"strange","char","short","int","long","long long",
151 "float","double","long double","void",
152 "near-pointer","far-pointer","huge-pointer",
153 "array","struct","union","enum","function"};
154
155
156/* used to initialize regtyp[] */
157static struct Typ ityp={INT},ctyp={CHAR},ftyp={FLOAT},lltyp={LLONG};
158
159/* macros defined by the backend */
160static char *marray[]={"__section(x)=__vattr(\"section(\"#x\")\")",
161 "__m65__",
162 "__SIZE_T_INT",
163 "__bank(x)=__vattr(\"bank(\"#x\")\")",
164 "__far=__attr(\"far\")",
165 "__near=__attr(\"near\")",
166 "__huge=__attr(\"huge\")",
167 0};
168
169/* special registers */
170static int ra=1, rx=2, ry=3, rz=4, sp1=5,sp2=6,sp=7,fp,fp1,fp2;
171static int t4=LAST_GPR,t3=LAST_GPR-1,t2=LAST_GPR-2,t1=LAST_GPR-3;
172static int rax=8;
173static int raxyz=9;
174static int yval;
175#define NOVAL 1000
176
177static int t1,t2,f1,f2; /*tODO: remove*/
178
179static int pushedacc,pushedx,nopeep,cbmascii,atascii,ieee;
180static int pass;
181static int libsave;
182static struct rpair rp2;
183static int cbank;
184static Var bankv;
185static int bankvoffset;
186static int bankcnum;
187static obj zstore;
188static int zstoreflag;
189
190#define SECLEN 128
191char *use_sec;
192int use_bank=-1;
193
194#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])
195static char *sdt[MAX_TYPE+1]={"??","c","s","i","l","ll","f","d","ld","v","p"};
196static char *udt[MAX_TYPE+1]={"??","uc","us","ui","ul","ull","f","d","ld","v","p"};
197
198/* perhaps provide version with 8bit int? */
199#define ISCHAR(t) ((t&NQ)==CHAR)
200#define ISSHORT(t) ((t&NQ)==SHORT||(t&NQ)==INT||(t&NQ)==POINTER)
201#define ISFPOINTER(t) ((t&NQ)==FPOINTER)
202#define ISLONG(t) ((t&NQ)==LONG)
203#define ISLLONG(t) ((t&NQ)==LLONG)
204
205/* am */
206#define IMM_IND 1
207#define GPR_IND 2
208#define ABS_IND 3
209
210/* sections */
211#define DATA 0
212#define BSS 1
213#define CODE 2
214#define RODATA 3
215#define SPECIAL 4
216
217static long stack;
218static int stack_valid;
219static int section=-1,newobj;
220static char *codename="\tsection\ttext",
221 *dataname="\tsection\tdata",
222 *bssname="\tsection\tbss",
223 *rodataname="\tsection\trodata";
224
225/* return-instruction */
226static char *ret;
227
228/* label at the end of the function (if any) */
229static int exit_label;
230
231/* assembly-prefixes for labels and external identifiers */
232static char *labprefix="l",*idprefix="_";
233
234/* variables to calculate the size and partitioning of the stack-frame
235 in the case of FIXED_SP */
236static long frameoffset,pushed,maxpushed,framesize;
237
238static long localsize,rsavesize,rscnt,argsize;
239
240static void emit_obj(FILE *f,struct obj *p,int t);
241
242/* calculate the actual current offset of an object relativ to the
243 stack-pointer; we use a layout like this:
244 ------------------------------------------------
245 | arguments to this function |
246 ------------------------------------------------
247 | caller-save registers [size=rsavesize] |
248 ------------------------------------------------
249 | local variables [size=localsize] |
250 ------------------------------------------------
251 | arguments to called functions [size=argsize] |
252 ------------------------------------------------
253 All sizes will be aligned as necessary.
254 In the case of FIXED_SP, the stack-pointer will be adjusted at
255 function-entry to leave enough space for the arguments and have it
256 aligned to 16 bytes. Therefore, when calling a function, the
257 stack-pointer is always aligned to 16 bytes.
258 For a moving stack-pointer, the stack-pointer will usually point
259 to the bottom of the area for local variables, but will move while
260 arguments are put on the stack.
261
262 This is just an example layout. Other layouts are also possible.
263*/
264
265static int bank(Var *v)
266{
267 char *s=v->vattr;
268 int n,r;
269 if(!NOBANKING&&s&&(s=strstr(s,"bank("))){
270 if(sscanf(s+5,"%i",&n)==1)
271 return n;
272 }
273 return -1;
274}
275
276static void ebank(FILE *f,int b)
277{
278 if(b>=0) emit(f,"%d",b);
279 emit(f,"\n");
280}
281
282static long real_offset(struct obj *o)
283{
284 long off=zm2l(o->v->offset);
285 if(off<0){
286 /* function parameter */
287 off=localsize+rsavesize-off-zm2l(maxalign);
288 }
289
290 off+=argsize;
291 off+=zm2l(o->val.vmax);
292 return off;
293}
294
295/* Initializes an addressing-mode structure and returns a pointer to
296 that object. Will not survive a second call! */
297static struct obj *cam(int flags,int base,long offset)
298{
299 static struct obj obj;
300 static struct AddressingMode am;
301 obj.am=&am;
302 am.flags=flags;
303 am.base=base;
304 am.offset=offset;
305 return &obj;
306}
307
308/* changes to a special section, used for __section() */
309static int special_section(FILE *f,struct Var *v)
310{
311 char *sec;
312 if(v->tattr&ZPAGE){
313 emit(f,"\tsection\tzpage\n");
314 }else{
315 if(!v->vattr) return 0;
316 sec=strstr(v->vattr,"section(");
317 if(!sec) return 0;
318 sec+=strlen("section(");
319 emit(f,"\tsection\t");
320 while(*sec&&*sec!=')') emit_char(f,*sec++);
321 emit(f,"\n");
322 }
323 if(f) section=SPECIAL;
324 return 1;
325}
326
327
328
329#define chk_coll(x) do{if((x)==r||(x)==r1||(x)==r2) return 0; \
330 if(reg_pair((x),&rp)&&(rp.r1==r||rp.r2==r)) return 0;}while(0)
331
332static int scratch(IC *p,int r)
333{
334 int r1,r2;
335 if(!p) return 1;
336 if(reg_pair(r,&rp)){
337 r1=rp.r1;
338 r2=rp.r2;
339 }else{
340 r1=0;
341 r2=0;
342 }
343 if(isreg(z)&&p->z.reg==r){
344 if(!(p->q2.flags&REG))
345 return 1;
346 if(p->q2.reg==r||p->q2.reg==r1||p->q2.reg==r2)
347 return 0;
348 if(reg_pair(p->q2.reg,&rp))
349 if(rp.r1==r||rp.r2==r)
350 return 0;
351 return 1;
352 }
353 while(p){
354 if(p->code==LABEL||p->code==CALL)
355 return 0;
356 if(p->code>=BEQ&&p->code<=BRA)
357 return 0;
358 if(p->code==FREEREG||p->code==ALLOCREG){
359 if(p->q1.reg==r)
360 return 1;
361 if(reg_pair(p->q1.reg,&rp)&&(rp.r1==r||rp.r2==r))
362 return 1;
363 }
364 if(p->q1.am) chk_coll(p->q1.am->base);
365 if(p->q2.am) chk_coll(p->q2.am->base);
366 if(p->z.am) chk_coll(p->z.am->base);
367 if(p->q1.flags&REG) chk_coll(p->q1.reg);
368 if(p->q2.flags&REG) chk_coll(p->q2.reg);
369 if(p->z.flags&REG){
370 if(p->z.flags&DREFOBJ)
371 chk_coll(p->z.reg);
372 else{
373 if(p->z.reg==r)
374 return 1;
375 if(reg_pair(p->z.reg,&rp)&&(rp.r1==r||rp.r2==r))
376 return 1;
377 }
378 }
379
380 p=p->next;
381 }
382 return 1;
383}
384
385static int rsavecur;
386static int in_isr;
387
388static int get_reg(FILE *f,IC *p,int t)
389{
390 int r,r1,r2,pass,flag;
391
392 for(pass=0;pass<5;pass++){
393 for(r=MAXR;r>sp;r--){
394 if(reg_pair(r,&rp)){
395 r1=rp.r1;
396 r2=rp.r2;
397 }else{
398 r1=0;
399 r2=0;
400 }
401 if((pass==0||pass==3)&&(!regscratch[r]||in_isr))
402 continue;
403 if(pass<3){
404 if(regs[r]) continue;
405 if(r1&&(regs[r1]||regs[r2])) continue;
406 }
407 if(pass==2&&!(regs[r]&4))
408 continue;
409 if((p->q1.flags&REG)&&(p->q1.reg==r||p->q1.reg==r1||p->q1.reg==r2)) continue;
410 if((p->q2.flags&REG)&&(p->q2.reg==r||p->q2.reg==r1||p->q2.reg==r2)) continue;
411 if((p->z.flags&REG)&&(p->z.reg==r||p->z.reg==r1||p->z.reg==r2)) continue;
412 if(regok(r,t,1)){
413 flag=8;
414 if(regs[r]){
415 flag|=2;
416 if(p->code==COMPARE||p->code==TEST)
417 ierror(0);
418 if(regs[ra]){
419 emit(f,"\ttay\n");
420 yval=NOVAL;
421 }
422 if(r1){
423 emit(f,"\tlda\t%s\n",mregnames[r1]);
424 emit(f,"\tpha\n");
425 emit(f,"\tlda\t%s\n",mregnames[r2]);
426 emit(f,"\tpha\n");
427 }else{
428 emit(f,"\tlda\t%s\n",mregnames[r]);
429 emit(f,"\tpha\n");
430 }
431 if(regs[ra])
432 emit(f,"\ttya\n");
433 }
434 if(r1){
435 regs[r1]|=flag;
436 regs[r2]|=flag;
437 }
438 regs[r]|=flag;
439 regused[r]=1;
440 regused[r1]=1;
441 regused[r2]=1;
442 return r;
443 }
444 }
445 }
446 pric2(stdout,p);
447 ierror(0);
448}
449
450static void get_acc(FILE *f, IC *p,int t)
451{
452 int r;
453 if(isacc(z)) return;
454 t&=NQ;
455 if(ISCHAR(t)){
456 if(1/*!isreg(q1)||(p->q1.reg!=ra&&p->q1.reg!=rax)*/){
457 if((regs[ra]||regs[rax])&&!scratch(p,ra)&&!pushedacc){
458 if(optsize||(regs[t1]&&regs[t2]&&regs[t3]&&regs[t4])){
459 emit(f,"\tpha\n");
460 pushedacc=-1;
461 }else{
462 r=get_reg(f,p,CHAR);
463 emit(f,"\tsta\t%s\n",mregnames[r]);
464 pushedacc=r;
465 }
466 }
467 }
468 }else{
469 if(1/*!isreg(q1)||p->q1.reg!=rax*/){
470 if((regs[ra]||regs[rax])&&(!scratch(p,ra)||!scratch(p,rax))&&!pushedacc){
471 r=get_reg(f,p,CHAR);
472 emit(f,"\tsta\t%s\n",mregnames[r]);
473 pushedacc=r;
474 }
475 if((regs[rx]||regs[rax])&&!scratch(p,rax)&&!pushedx){
476 r=get_reg(f,p,CHAR);
477 emit(f,"\tstx\t%s\n",mregnames[r]);
478 pushedx=r;
479 }
480 }
481 }
482}
483
484static int cmp_get_acc(FILE *f,IC *p,IC *branch)
485{
486 if(!regs[ra]&&!regs[rax])
487 return 0;
488 if(branch==0&&pushedacc)
489 return 0;
490 if(branch&&isreg(q1)&&(p->q1.reg==ra||p->q1.reg==rax))
491 if(branch->code==BEQ||branch->code==BNE||(p->typf&UNSIGNED))
492 return 0;
493 if(scratch(p,ra))
494 return 0;
495 if(!regs[rx]&&!regs[rax]){
496 emit(f,"\ttax\n");
497 pushedacc=rx;
498 }
499 emit(f,"\tpha\n");
500 pushedacc=-1;
501 return pushedacc;
502}
503
504static void reload_acc_opt(FILE *f,IC *p)
505{
506 if(pushedacc==0) return;
507 if(pushedacc>0){
508 while(p){
509 if(p->code!=FREEREG) break;
510 if(p->q1.reg==ra||p->q1.reg==rax){
511 pushedacc=0;
512 return;
513 }
514 p=p->next;
515 }
516 }
517 if(pushedacc==-1)
518 emit(f,"\tpla\n");
519 else if(pushedacc==rx)
520 emit(f,"\ttxa\n");
521 else if(pushedacc==ry)
522 emit(f,"\ttya\n");
523 else if(pushedacc){
524 emit(f,"\tlda\t%s\n",mregnames[pushedacc]);
525 regs[pushedacc]&=~8;
526 }
527 pushedacc=0;
528}
529
530static void reload_acc(FILE *f)
531{
532 reload_acc_opt(f,0);
533}
534
535static void push(int i)
536{
537 pushed-=i;
538 if(pushed<maxpushed)
539 maxpushed=pushed;
540}
541
542static void pop(int i)
543{
544 pushed+=i;
545 if(pushed>0) ierror(0);
546}
547
548static int indirect(obj *o)
549{
550 if((o->flags&(DREFOBJ|KONST))==DREFOBJ)
551 return 1;
552 if((o->flags&(REG|VAR))!=VAR)
553 return 0;
554 if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)
555 return 1;
556 return 0;
557}
558
559void convfloat(void)
560{
561}
562
563void sety(FILE *f,int val)
564{
565 if(yval==val)
566 return;
567 if(val-yval==1)
568 emit(f,"\tiny\n");
569 else if(yval-val==1)
570 emit(f,"\tdey\n");
571 else{
572 emit(f,"\tldy\t#%d\n",val);
573 if(val<0||val>255)
574 ierror(0);
575 }
576 yval=val;
577}
578
579static void cnv_fp(void)
580{
581 double d,mant;
582 int exp;
583 unsigned long t;
584
585 if(ieee){
586 vfloat=zld2zf(vldouble);
587 memcpy((void*)&vmax,(void*)&vfloat,4);
588 }else{
589 d=zld2d(vldouble);
590 mant=frexp(d,&exp);
591 exp=(exp+127)&255;
592 t=((unsigned long)(mant*8388608))&0xffffff;
593 t|=((long)exp)<<24;
594
595 t=((t&0xff)<<24)|((t&0xff00)<<8)|((t&0xff0000)>>8)|((t&0xff000000)>>24);
596 vmax=l2zm((long)t);
597 }
598}
599
600static void emit_ieee(FILE *f,union atyps *p,int t)
601{
602 unsigned char *ip=(unsigned char *)&p->vdouble;
603 emit(f,"0x%02x%02x,0x%02x%02x",ip[1],ip[0],ip[3],ip[2]);
604 if(t==DOUBLE||t==LDOUBLE)
605 emit(f,",0x%02x%02x,0x%02x%02x",ip[5],ip[4],ip[7],ip[6]);
606 emit(f,"\n");
607}
608
609static void emit_lobyte(FILE *f,obj *o,int t)
610{
611 if(o->flags&KONST){
612 if(o->flags&DREFOBJ){
613 eval_const(&o->val,o->dtyp);
614 emit(f,"%d",zm2l(vmax));
615 }else{
616 eval_const(&o->val,t);
617 if(ISFLOAT(t)) cnv_fp();
618 emit(f,"#%d",zm2l(vmax)&255);
619 }
620 }else if(o->flags&VARADR){
621 emit(f,"#<(");
622 emit_obj(f,o,t);
623 emit(f,")");
624 }else if((o->flags&(REG|DREFOBJ))==REG){
625 if(!reg_pair(o->reg,&rp))
626 emit(f,"%s",mregnames[o->reg]);
627 else
628 emit(f,"%s",mregnames[rp.r1]);
629 }else{
630 emit_obj(f,o,t);
631 }
632}
633
634static void emit_hibyte(FILE *f,obj *o,int t)
635{
636 if(o->flags&KONST){
637 if(o->flags&DREFOBJ){
638 eval_const(&o->val,o->dtyp);
639 emit(f,"%d",zm2l(vmax)+1);
640 }else{
641 eval_const(&o->val,t);
642 if(ISFLOAT(t)) cnv_fp();
643 emit(f,"#%d",(zm2l(vmax)>>8)&255);
644 }
645 }else if(o->flags&VARADR){
646 emit(f,"#>(");
647 emit_obj(f,o,t);
648 emit(f,")");
649 }else if((o->flags&(REG|DREFOBJ))==REG){
650 if(o->reg>=FIRST_BIG&&o->reg<=LAST_BIGP){
651 emit(f,"%s+1",mregnames[o->reg]);
652 }else{
653 if(!reg_pair(o->reg,&rp))
654 ierror(0);
655 emit(f,"%s",mregnames[rp.r2]);
656 }
657 }else{
658 if(o->flags&VARADR)
659 emit(f,"#");
660 if(!(o->flags&DREFOBJ))
661 o->val.vmax=zmadd(o->val.vmax,Z1);
662 emit_obj(f,o,t);
663 if(!(o->flags&DREFOBJ))
664 o->val.vmax=zmsub(o->val.vmax,Z1);
665 }
666}
667
668static void emit_byte3(FILE *f,obj *o,int t)
669{
670 if(o->flags&KONST){
671 if(o->flags&DREFOBJ){
672 eval_const(&o->val,o->dtyp);
673 emit(f,"%d",zm2l(vmax)+2);
674 }else{
675 eval_const(&o->val,t);
676 if(ISFLOAT(t)) cnv_fp();
677 emit(f,"#%d",(zm2l(vmax)>>16)&255);
678 }
679 }else if((o->flags&(REG|DREFOBJ))==REG){
680 emit(f,"%s+2",mregnames[o->reg]);
681 }else if(o->flags&VARADR){
682 emit(f,"#%d",bank(o->v));
683 }else{
684 if(!(o->flags&DREFOBJ))
685 o->val.vmax=zmadd(o->val.vmax,l2zm(2L));
686 emit_obj(f,o,t);
687 if(!(o->flags&DREFOBJ))
688 o->val.vmax=zmsub(o->val.vmax,l2zm(2L));
689 }
690}
691
692static void emit_byte4(FILE *f,obj *o,int t)
693{
694 if(o->flags&KONST){
695 if(o->flags&DREFOBJ){
696 eval_const(&o->val,o->dtyp);
697 emit(f,"%d",zm2l(vmax)+3);
698 }else{
699 eval_const(&o->val,t);
700 if(ISFLOAT(t)) cnv_fp();
701 emit(f,"#%d",(zm2l(vmax)>>24)&255);
702 }
703 }else if((o->flags&(REG|DREFOBJ))==REG){
704 emit(f,"%s+3",mregnames[o->reg]);
705 }else{
706 if(!(o->flags&DREFOBJ))
707 o->val.vmax=zmadd(o->val.vmax,l2zm(3L));
708 emit_obj(f,o,t);
709 if(!(o->flags&DREFOBJ))
710 o->val.vmax=zmsub(o->val.vmax,l2zm(3L));
711 }
712}
713
714static void do_lobyte(FILE *f,char *s,obj *o,int type)
715{
716 if(o->am){
717 if(o->am->flags==IMM_IND)
718 sety(f,o->am->offset);
719 else if(o->am->flags==GPR_IND||o->am->flags==ABS_IND){
720 if(o->am->offset==ra)
721 emit(f,"\ttay\n");
722 else
723 emit(f,"\tldy\t%s\n",mregnames[o->am->idx]);
724 yval=NOVAL;
725 }else
726 ierror(0);
727 }else if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
728 sety(f,0);
729 }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
730 sety(f,(int)real_offset(o));
731 }
732 emit(f,"\t%s\t",s);
733 emit_lobyte(f,o,type);
734 emit(f,"\n");
735}
736
737static void do_hibyte(FILE *f,char *s,obj *o,int type)
738{
739 int ami=0;
740 if(o->am){
741 if(o->am->flags==IMM_IND)
742 sety(f,o->am->offset+1);
743 else if(o->am->flags==ABS_IND){
744 if(o->am->offset==ra)
745 emit(f,"\ttay\n");
746 else
747 emit(f,"\tldy\t%s\n",mregnames[o->am->idx]);
748 o->am->offset++;ami=1;
749 yval=NOVAL;
750 }else
751 ierror(0);
752 }else if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
753 sety(f,1);
754 }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
755 sety(f,(int)real_offset(o)+1);
756 }
757 emit(f,"\t%s\t",s);
758 emit_hibyte(f,o,type);
759 emit(f,"\n");
760 if(ami) o->am->offset--;
761}
762
763static void do_byte3(FILE *f,char *s,obj *o,int type)
764{
765 int ami=0;
766 if(o->am){
767 if(o->am->flags==IMM_IND)
768 sety(f,o->am->offset+2);
769 else if(o->am->flags==ABS_IND){
770 if(o->am->offset==ra)
771 emit(f,"\ttay\n");
772 else
773 emit(f,"\tldy\t%s\n",mregnames[o->am->idx]);
774 yval=NOVAL;
775 o->am->offset+=2;ami=1;
776 }else
777 ierror(0);
778 }else if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
779 sety(f,2);
780 }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
781 sety(f,(int)real_offset(o)+2);
782 }
783 emit(f,"\t%s\t",s);
784 emit_byte3(f,o,type);
785 emit(f,"\n");
786 if(ami) o->am->offset-=2;
787}
788
789static void do_byte4(FILE *f,char *s,obj *o,int type)
790{
791 int ami=0;
792 if(o->am){
793 if(o->am->flags==IMM_IND)
794 sety(f,o->am->offset+3);
795 else if(o->am->flags==ABS_IND){
796 if(o->am->offset==ra)
797 emit(f,"\ttay\n");
798 else
799 emit(f,"\tldy\t%s\n",mregnames[o->am->idx]);
800 yval=NOVAL;
801 o->am->offset+=3;ami=1;
802 }else
803 ierror(0);
804 }else if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
805 sety(f,3);
806 }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
807 sety(f,(int)real_offset(o)+3);
808 }
809 emit(f,"\t%s\t",s);
810 emit_byte4(f,o,type);
811 emit(f,"\n");
812 if(ami) o->am->offset-=3;
813}
814
815static void load_lobyte(FILE *f,obj *o,int t)
816{
817 if((o->flags&(REG|DREFOBJ))==REG){
818 if(o->reg==ra||o->reg==rax)
819 return;
820 if(o->reg==rx){
821 emit(f,"\ttxa\n");
822 return;
823 }
824 }
825 do_lobyte(f,"lda",o,t);
826}
827
828static void load_hibyte(FILE *f,obj *o,int t)
829{
830 if((o->flags&REG)&&(o->reg==rx||o->reg==rax))
831 emit(f,"\ttxa\n");
832 else
833 do_hibyte(f,"lda",o,t);
834}
835
836static void store_lobyte(FILE *f,obj *o,int t)
837{
838 if((o->flags&(REG|DREFOBJ))==REG){
839 if(o->reg==ra||o->reg==rax)
840 return;
841 if(o->reg==rx){
842 emit(f,"\ttax\n");
843 return;
844 }
845 }
846 do_lobyte(f,"sta",o,t);
847}
848
849static void store_hibyte(FILE *f,obj *o,int t)
850{
851 if((o->flags&REG)&&(o->reg==rx||o->reg==rax))
852 emit(f,"\ttax\n");
853 else
854 do_hibyte(f,"sta",o,t);
855}
856
857static void load_acc(FILE *f,obj *o,int type)
858{
859 if((o->flags&REG)&&(o->reg==ra||o->reg==rax))
860 return;
861 if(!ISCHAR(type)){
862 if(indirect(o)){
863 do_hibyte(f,"lda",o,type);
864 emit(f,"\ttax\n");
865 }else
866 do_hibyte(f,"ldx",o,type);
867 }
868 if((o->flags&(REG|DREFOBJ))==REG&&o->reg==rx)
869 emit(f,"\ttxa\n");
870 else
871 do_lobyte(f,"lda",o,type);
872}
873
874static void store_acc(FILE *f,obj *o,int type)
875{
876 if((o->flags&(DREFOBJ|KONST))==DREFOBJ&&((!(o->flags&REG))||!isptr(o->reg))){
877 ierror(0);
878 }
879 if((o->flags&REG)&&(o->reg==ra||o->reg==rax))
880 return;
881 if((o->flags&REG)&&o->reg==rx){
882 emit(f,"\ttax\n");
883 return;
884 }
885 store_lobyte(f,o,type);
886 if(!ISCHAR(type)){
887 if(indirect(o)){
888 /*TODO: save accu */
889 emit(f,"\ttxa\n");
890 store_hibyte(f,o,type);
891 }else
892 do_hibyte(f,"stx",o,type);
893 }
894}
895
896static void load_reg(FILE *f,int r,struct obj *o,int type)
897{
898 static obj ro;
899 ro.flags=REG;
900 ro.reg=r;
901 load_lobyte(f,o,type);
902 store_lobyte(f,&ro,type);
903 if(!ISCHAR(type)){
904 load_hibyte(f,o,type);
905 store_hibyte(f,&ro,type);
906 }
907}
908
909static void store_reg(FILE *f,int r,struct obj *o,int type)
910{
911 static obj ro;
912 if(r==rx){
913 if((o->flags&(REG|DREFOBJ))==REG){
914 if(o->reg==rx)
915 return;
916 if(o->reg==ra){
917 emit(f,"\ttxa\n");
918 return;
919 }
920 }
921 }
922 ro.flags=REG;
923 ro.reg=r;
924 if(r!=ra&&r!=rax)
925 load_acc(f,&ro,type);
926 store_acc(f,o,type);
927}
928
929static struct fpconstlist {
930 struct fpconstlist *next;
931 int label;
932 int t;
933 union atyps val;
934} *firstfpc;
935
936static int addfpconst(struct obj *o,int t)
937{
938 struct fpconstlist *p=firstfpc;
939 t&=NQ;
940 if(t==LDOUBLE) t=DOUBLE;
941 for(p=firstfpc;p;p=p->next){
942 if(t==p->t){
943 eval_const(&p->val,t);
944 if(t==FLOAT&&zldeqto(vldouble,zf2zld(o->val.vfloat))) return p->label;
945 if(t==DOUBLE&&zldeqto(vldouble,zd2zld(o->val.vdouble))) return p->label;
946 if(t==LONG&&zmeqto(vmax,zl2zm(o->val.vlong))) return p->label;
947 if(t==LLONG&&zmeqto(vmax,zll2zm(o->val.vllong))) return p->label;
948 }
949 }
950 p=mymalloc(sizeof(struct fpconstlist));
951 p->next=firstfpc;
952 p->t=t;
953 p->label=++label;
954 p->val=o->val;
955 firstfpc=p;
956 return p->label;
957}
958
959/* generate code to load the address of a local variable into register r */
960static void load_laddr(FILE *f,int r,struct obj *o)
961{
962 long l=real_offset(o);
963 /* assumes acc is available */
964 if(!reg_pair(r,&rp)) ierror(0);
965 emit(f,"\tlda\t%s\n",mregnames[fp]);
966 if(l!=0)
967 emit(f,"\tclc\n");
968 if(l&255)
969 emit(f,"\tadc\t#%ld\n",l&255);
970 emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
971 emit(f,"\tlda\t%s\n",mregnames[fp2]);
972 if(l!=0)
973 emit(f,"\tadc\t#%ld\n",(l>>8)&255);
974 emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
975}
976
977/* generate code to load the address of a variable into register r */
978static void load_address(FILE *f,int r,struct obj *o,int t)
979{
980 if(o->flags&DREFOBJ){
981 o->flags&=~DREFOBJ;
982 load_reg(f,r,o,POINTER);
983 o->flags|=DREFOBJ;
984 }else if((o->flags&(REG|DREFOBJ))==REG){
985 if(!reg_pair(r,&rp)) ierror(0);
986 emit(f,"\tlda\t#>%s\n",mregnames[o->reg]);
987 emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
988 emit(f,"\tlda\t#<%s\n",mregnames[o->reg]);
989 emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
990 }else if(o->flags&VAR){
991 if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
992 load_laddr(f,r,o);
993 }else{
994 o->flags|=VARADR;
995 load_reg(f,r,o,POINTER);
996 o->flags&=~VARADR;
997 }
998 }else if((o->flags&(KONST|DREFOBJ))==KONST){
999 int l=addfpconst(o,t);
1000 if(!ieee) ierror(0);
1001 if(!reg_pair(r,&rp)) ierror(0);
1002 emit(f,"\tlda\t#>%s%d\n",labprefix,l);
1003 emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
1004 emit(f,"\tlda\t#<%s%d\n",labprefix,l);
1005 emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
1006 }else
1007 ierror(0);
1008}
1009
1010
1011/* Yields log2(x)+1 or 0. */
1012static long pof2(zumax x)
1013{
1014 zumax p;int ln=1;
1015 p=ul2zum(1L);
1016 while(ln<=32&&zumleq(p,x)){
1017 if(zumeqto(x,p)) return ln;
1018 ln++;p=zumadd(p,p);
1019 }
1020 return 0;
1021}
1022
1023static void incmem(FILE *f,obj *o,int t,int op,int x)
1024{
1025 int i;
1026 char *s;
1027
1028 // PGS: All registers and pseudo registers on the M65 target
1029 // live in zero-page, so we can use INW and DEW for fast
1030 // increment/decrement.
1031 if (o->flags&REG) {
1032 switch(op) {
1033 case ADD:
1034 if(ISCHAR(t)){
1035 emit(f,"\tinc\t");
1036 emit_obj(f,o,t);
1037 emit(f,"\n");
1038 } else {
1039 emit(f,"\tinw\t");
1040 emit_obj(f,o,t);
1041 emit(f,"\n");
1042 }
1043 return;
1044 break;
1045 case SUB:
1046 if(ISCHAR(t)){
1047 emit(f,"\tdec\t");
1048 emit_obj(f,o,t);
1049 emit(f,"\n");
1050 } else {
1051 emit(f,"\tdew\t");
1052 emit_obj(f,o,t);
1053 emit(f,"\n");
1054 }
1055 return;
1056 break;
1057 }
1058 }
1059
1060 if(op==ADD)
1061 s="inc";
1062 else if(op==SUB)
1063 s="dec";
1064 else if(op==LSHIFT)
1065 s="asl";
1066 else if(op==RSHIFT&&(t&UNSIGNED))
1067 s="clc\n\tror";
1068 else if(op==RSHIFT){
1069 s="cmp\t#128\n\tror";
1070 }else
1071 ierror(0);
1072 if(ISCHAR(t)){
1073 for(i=0;i<x;i++){
1074 emit(f,"\t%s\t",s);
1075 emit_obj(f,o,t);
1076 emit(f,"\n");
1077 }
1078 }else{
1079 for(i=0;i<x;i++){
1080 if(op==SUB){
1081 /* caller mus make sure accu is available */
1082 load_lobyte(f,o,t);
1083 emit(f,"\tbne\t%s%d\n",labprefix,++label);
1084 emit(f,"\tdec\t");
1085 emit_hibyte(f,o,t);
1086 emit(f,"\n");
1087 emit(f,"%s%d:\n",labprefix,label);
1088 emit(f,"\tdec\t");
1089 emit_lobyte(f,o,t);
1090 emit(f,"\n");
1091 }else if(op==ADD){
1092 emit(f,"\t%s\t",s);
1093 emit_lobyte(f,o,t);
1094 emit(f,"\n");
1095 emit(f,"\tbne\t%s%d\n",labprefix,++label);
1096 emit(f,"\t%s\t",s);
1097 emit_hibyte(f,o,t);
1098 emit(f,"\n");
1099 emit(f,"%s%d:\n",labprefix,label);
1100 }else if(op==LSHIFT){
1101 // 4510 / 45GS02 have ASW/ROW operations
1102 // for left-shifting 16-bit values
1103
1104 emit(f,"\tasw\t");
1105 emit_lobyte(f,o,t);
1106 emit(f,"\n");
1107
1108 }else if(op==RSHIFT&&(t&UNSIGNED)){
1109 emit(f,"\tclc\n");
1110 emit(f,"\tror\t");
1111 emit_hibyte(f,o,t);
1112 emit(f,"\n");
1113 emit(f,"\tror\t");
1114 emit_lobyte(f,o,t);
1115 emit(f,"\n");
1116 }else if(op==RSHIFT){
1117 load_hibyte(f,o,t);
1118 emit(f,"\tcmp\t#128\n");
1119 emit(f,"\tror\t");
1120 emit_hibyte(f,o,t);
1121 emit(f,"\n");
1122 emit(f,"\tror\t");
1123 emit_lobyte(f,o,t);
1124 emit(f,"\n");
1125 }else{
1126 printf("op=%d\n",op);
1127 ierror(0);
1128 }
1129 }
1130 }
1131}
1132
1133static void preload_obj(FILE *f,IC *p,obj *o)
1134{
1135 int r;long of;
1136
1137 if((p->typf&VOLATILE)||(p->typf2&VOLATILE)||
1138 ((p->q1.flags&DREFOBJ)&&(p->q1.dtyp&(VOLATILE|PVOLATILE)))||
1139 ((p->q2.flags&DREFOBJ)&&(p->q2.dtyp&(VOLATILE|PVOLATILE)))||
1140 ((p->z.flags&DREFOBJ)&&(p->z.dtyp&(VOLATILE|PVOLATILE))))
1141 emit(f,"; volatile barrier\n");
1142
1143
1144 if((o->flags&(VAR|REG))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)&&(of=real_offset(o))+zm2l(szof(o->v->vtyp))>255){
1145 r=get_reg(f,p,POINTER);
1146 if(o->flags&DREFOBJ)
1147 get_acc(f,p,INT);
1148 else
1149 cmp_get_acc(f,p,0);
1150 if(!reg_pair(r,&rp)) ierror(0);
1151 emit(f,"\tlda\t%s\n",mregnames[fp1]);
1152 emit(f,"\tclc\n");
1153 if(of&0xff)
1154 emit(f,"\tadc\t#%ld\n",of&0xff);
1155 emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
1156 emit(f,"\tlda\t%s\n",mregnames[fp2]);
1157 if(1/*of&0xff00*/)
1158 emit(f,"\tadc\t#%ld\n",(of>>8)&0xff);
1159 emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
1160 o->flags|=REG;
1161 o->reg=r;
1162 if(o->flags&DREFOBJ){
1163 sety(f,0);
1164 emit(f,"\tlda\t(%s),y\n",mregnames[r]);
1165 emit(f,"\ttxa\n");
1166 sety(f,1);
1167 emit(f,"\tlda\t(%s),y\n",mregnames[r]);
1168 emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
1169 emit(f,"\tstx\t%s\n",mregnames[rp.r1]);
1170 }else{
1171 o->flags|=DREFOBJ;
1172 o->dtyp=POINTER;
1173 }
1174 }
1175
1176 if((o->flags&(DREFOBJ|KONST))==DREFOBJ&&(!(o->flags&REG)||!isptr(o->reg))&&(!(o->flags&VAR)||!(o->v->tattr&ZPAGE))&&!ISFPOINTER(o->dtyp)){
1177 cmp_get_acc(f,p,0);
1178 r=get_reg(f,p,POINTER);
1179 o->flags&=~DREFOBJ;
1180 load_reg(f,r,o,POINTER);
1181 o->flags|=REG|DREFOBJ;
1182 o->reg=r;
1183 }
1184}
1185
1186static void far_copy(FILE *f,IC *p)
1187{
1188 int b;long l;
1189 get_acc(f,p,INT);
1190 if(p->code==PUSH){
1191 if(!reg_pair(LAST_PAIR,&rp)) ierror(0);
1192 emit(f,"\tlda\t%s\n",mregnames[sp]);
1193 if(pushed) emit(f,"\tclc\n");
1194 if(pushed&0xff) emit(f,"\tadc\t#%d\n",(pushed&0xff));
1195 emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
1196 emit(f,"\tlda\t%s+1\n",mregnames[sp]);
1197 if(pushed) emit(f,"\tadc\t#%d\n",((pushed>>8)&0xff));
1198 emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
1199 pushed+=zm2l(p->q2.val.vmax);
1200 emit(f,"\tldx\t#%d\n",bankcnum);
1201 }else if(p->z.flags&DREFOBJ){
1202 if(!reg_pair(LAST_PAIR,&rp)) ierror(0);
1203 p->z.flags&=~DREFOBJ;
1204 load_lobyte(f,&p->z,FPOINTER);
1205 emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
1206 load_hibyte(f,&p->z,FPOINTER);
1207 emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
1208 if(indirect(&p->z)){
1209 do_byte3(f,"lda",&p->z,FPOINTER);
1210 emit(f,"\ttax\n");
1211 }else
1212 do_byte3(f,"ldx",&p->z,FPOINTER);
1213 }else{
1214 load_address(f,LAST_PAIR,&p->z,POINTER);
1215 b=bank(p->z.v);
1216 emit(f,"\tldx\t#%d\n",b>=0?b:bankcnum);
1217 }
1218 if(p->q1.flags&DREFOBJ){
1219 if(!reg_pair(LAST_PAIR-1,&rp)) ierror(0);
1220 p->q1.flags&=~DREFOBJ;
1221 load_lobyte(f,&p->q1,FPOINTER);
1222 emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
1223 load_hibyte(f,&p->q1,FPOINTER);
1224 emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
1225 if(indirect(&p->q1)){
1226 do_byte3(f,"lda",&p->q1,FPOINTER);
1227 emit(f,"\ttay\n");
1228 }else
1229 do_byte3(f,"ldy",&p->q1,FPOINTER);
1230 }else{
1231 load_address(f,LAST_PAIR-1,&p->q1,POINTER);
1232 b=bank(p->q1.v);
1233 sety(f,b>=0?b:bankcnum);
1234 }
1235 l=zm2l(p->q2.val.vmax);
1236 emit(f,"\tlda\t#%d\n",(l>>8)&0xff);
1237 emit(f,"\tsta\t%s__bankcopy_len+1\n",idprefix);
1238 emit(f,"\tlda\t#%d\n",(l)&0xff);
1239 emit(f,"\tsta\t%s__bankcopy_len\n",idprefix);
1240 emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
1241 emit(f,"\tjsr\t%s__bankcopy\n",idprefix);
1242 yval=NOVAL;
1243}
1244
1245static void load_far(FILE *f,IC *p,obj *o,int t)
1246{
1247 int pushed=0;
1248 if(!(o->flags&DREFOBJ)) ierror(0);
1249 o->flags&=~DREFOBJ;
1250 t&=NQ;
1251 if(zmeqto(sizetab[t],Z0)) return;
1252 /*get_acc(f,p,INT);*/
1253 if(pushedacc==t3||pushedacc==t4) ierror(0);
1254 if(pushedx==t3||pushedx==t4) ierror(0);
1255 if(regs[ra]||regs[rax]){
1256 if(isacc(q1)||isacc(q2)||!isacc(z)){
1257 pushed=1;
1258 emit(f,"\tpha\n");
1259 if(regs[rax]) emit(f,"\ttxa\n\tpha\n");
1260 }
1261 }
1262 load_reg(f,LAST_PAIR,o,POINTER);
1263 if(!indirect(o))
1264 do_byte3(f,"ldy",o,CHAR);
1265 else{
1266 do_byte3(f,"lda",o,CHAR);
1267 emit(f,"\ttay\n");
1268 }
1269 emit(f,"\tldx\t#%d\n",bankvoffset);
1270 emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
1271 emit(f,"\tjsr\t%s__bankload%d\n",idprefix,(int)zm2l(sizetab[t]));
1272 yval=NOVAL;
1273 o->flags=VAR;
1274 o->v=&bankv;
1275 o->val.vmax=l2zm((long)bankvoffset);
1276 bankvoffset+=zm2l(sizetab[t]);
1277 if(pushed){
1278 if(regs[rax]) emit(f,"\tpla\n\ttax\n");
1279 emit(f,"\tpla\n");
1280 }
1281}
1282
1283static void load_banked(FILE *f,IC *p,obj *o,int t)
1284{
1285 int pushed=0,m;
1286 if(o->flags&DREFOBJ) t=o->dtyp;
1287 t&=NQ;
1288 if(zmeqto(sizetab[t],Z0)) return;
1289 /*get_acc(f,p,INT);*/
1290 if(pushedacc==t3||pushedacc==t4) ierror(0);
1291 if(pushedx==t3||pushedx==t4) ierror(0);
1292 if(regs[ra]||regs[rax]){
1293 if(isacc(q1)||isacc(q2)||!isacc(z)){
1294 pushed=1;
1295 emit(f,"\tpha\n");
1296 if(regs[rax]) emit(f,"\ttxa\n\tpha\n");
1297 }
1298 }
1299 m=o->flags;
1300 o->flags&=~DREFOBJ;
1301 load_address(f,LAST_PAIR,o,POINTER);
1302 o->flags=m;
1303 emit(f,"\tldx\t#%d\n",bankvoffset);
1304 emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
1305 sety(f,bank(o->v));
1306 emit(f,"\tjsr\t%s__bankload%d\n",idprefix,(int)zm2l(sizetab[t]));
1307 yval=NOVAL;
1308 o->v=&bankv;
1309 o->val.vmax=l2zm((long)bankvoffset);
1310 bankvoffset+=zm2l(sizetab[t]);
1311 if(pushed){
1312 if(regs[rax]) emit(f,"\tpla\n\ttax\n");
1313 emit(f,"\tpla\n");
1314 }
1315}
1316
1317static void preload(FILE *f,IC *p)
1318{
1319 int r,mra=regs[ra],mrax=regs[rax];
1320 int bq1=-1,bq2=-1,bz=-1,sb=-1,zbuf=0;
1321
1322 if(p->code==GETRETURN&&p->q1.reg==ra&&!regs[ra])
1323 regs[ra]=1;
1324
1325 if(p->code==GETRETURN&&p->q1.reg==rax&&!regs[rax])
1326 regs[rax]=1;
1327
1328 bankvoffset=0;
1329
1330 if(!NOBANKVARS){
1331 if((p->q1.flags&(VAR|VARADR))==VAR) bq1=bank(p->q1.v);
1332 if((p->q2.flags&(VAR|VARADR))==VAR) bq2=bank(p->q2.v);
1333 if((p->z.flags&(VAR|VARADR))==VAR) bz=bank(p->z.v);
1334
1335 if((p->q1.flags&(VAR|VARADR))==(VAR|VARADR)){
1336 r=bank(p->q1.v);
1337 /*if(r>=0&&r!=cbank) ierror(0);*/
1338 }
1339
1340 if((p->code==ASSIGN||p->code==PUSH)&&!zmleq(p->q2.val.vmax,l2zm(4L))){
1341 if(p->q1.flags&DREFOBJ) preload_obj(f,p,&p->q1);
1342 if(p->z.flags&DREFOBJ) preload_obj(f,p,&p->z);
1343 return;
1344 }
1345
1346 if(p->code!=CALL){
1347 /* TODO: some optimizations possible */
1348 if(bq1>=0&&bq1!=cbank){
1349 if(cbank<0&&!NOSWITCH)
1350 sb=bq1;
1351 else
1352 load_banked(f,p,&p->q1,q1typ(p));
1353 }
1354 if(bq2>=0&&bq2!=cbank){
1355 if((bq2==sb||(cbank<0&&sb<0))&&!NOSWITCH)
1356 sb=bq2;
1357 else
1358 load_banked(f,p,&p->q2,q2typ(p));
1359 }
1360 if(bz>=0&&bz!=cbank&&(p->z.flags&DREFOBJ)){
1361 if((bz==sb||(cbank<0&&sb<0))||!NOSWITCH)
1362 sb=bz;
1363 else
1364 load_banked(f,p,&p->z,ztyp(p));
1365 }
1366
1367 if(sb>=0){
1368 if(NOSWITCH) ierror(0);
1369 sety(f,sb);
1370 emit(f,"\tjsr\t%s__bankswitch\n",idprefix);
1371 yval=NOVAL;
1372 }
1373 }
1374 }
1375
1376 if((p->q1.flags&DREFOBJ)&&ISFPOINTER(p->q1.dtyp)&&p->code!=CALL) load_far(f,p,&p->q1,q1typ(p));
1377 if((p->q2.flags&DREFOBJ)&&ISFPOINTER(p->q2.dtyp)) load_far(f,p,&p->q2,q2typ(p));
1378
1379 if(isacc(q2)){
1380 static obj o;
1381 int t=q2typ(p);
1382 r=get_reg(f,p,t);
1383 o.flags=REG;
1384 o.reg=r;
1385 store_acc(f,&o,t);
1386 p->q2.reg=r;
1387 }
1388
1389 if(p->code!=ADDRESS){
1390 preload_obj(f,p,&p->q1);
1391 if((p->q1.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR|REG)&&
1392 (p->q2.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR)&&
1393 p->q1.v==p->q2.v){
1394 p->q2.flags|=REG;
1395 p->q2.reg=p->q1.reg;
1396 }
1397 if((p->q1.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR|REG)&&
1398 (p->z.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR)&&
1399 p->q1.v==p->z.v){
1400 p->z.flags|=REG;
1401 p->z.reg=p->q1.reg;
1402 }
1403 }
1404
1405 preload_obj(f,p,&p->q2);
1406 if((p->q2.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR|REG)&&
1407 (p->z.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR)&&
1408 p->q2.v==p->z.v){
1409 p->z.flags|=REG;
1410 p->z.reg=p->q1.reg;
1411 }
1412
1413
1414 if((p->z.flags&DREFOBJ)&&ISFPOINTER(p->z.dtyp)) zbuf=1;
1415 if((p->z.flags&(VAR|DREFOBJ))==VAR){
1416 bz=bank(p->z.v);
1417 if(bz>=0&&bz!=cbank) zbuf=1;
1418 }
1419
1420 if(zbuf&&!NOBANKVARS){
1421 zstore=p->z;
1422 p->z.flags=VAR;
1423 p->z.v=&bankv;
1424 p->z.val.vmax=l2zm((long)bankvoffset);
1425 zstoreflag=1;
1426 /*bankvoffset+=zm2l(sizetab[p->typf&NQ]);*/
1427 }else{
1428 preload_obj(f,p,&p->z);
1429
1430 if(isreg(z)){
1431 r=0;
1432 if(p->q1.am&&p->q1.am->base==p->z.reg){
1433 r=get_reg(f,p,POINTER);
1434 cmp_get_acc(f,p,0);
1435 if(!reg_pair(p->q1.am->base,&rp)) ierror(0);
1436 if(!reg_pair(r,&rp2)) ierror(0);
1437 emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
1438 emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
1439 emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
1440 emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
1441 p->q1.am->base=p->q1.reg=r;
1442 }else if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q1.reg==p->z.reg){
1443 r=get_reg(f,p,POINTER);
1444 cmp_get_acc(f,p,0);
1445 if(!reg_pair(p->z.reg,&rp)) ierror(0);
1446 if(!reg_pair(r,&rp2)) ierror(0);
1447 emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
1448 emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
1449 emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
1450 emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
1451 p->q1.reg=r;
1452 }
1453 if(p->q2.am&&p->q2.am->base==p->z.reg){
1454 if(r==0){
1455 r=get_reg(f,p,POINTER);
1456 cmp_get_acc(f,p,0);
1457 if(!reg_pair(p->q2.am->base,&rp)) ierror(0);
1458 if(!reg_pair(r,&rp2)) ierror(0);
1459 emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
1460 emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
1461 emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
1462 emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
1463 }
1464 p->q2.am->base=p->q2.reg=r;
1465 }else if((p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q2.reg==p->z.reg){
1466 if(r==0){
1467 r=get_reg(f,p,POINTER);
1468 cmp_get_acc(f,p,0);
1469 if(!reg_pair(p->z.reg,&rp)) ierror(0);
1470 if(!reg_pair(r,&rp2)) ierror(0);
1471 emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
1472 emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
1473 emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
1474 emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
1475 }
1476 p->q2.reg=r;
1477 }
1478 }
1479 if(isacc(z)){
1480 if(isacc(q2)){
1481 if(p->q2.reg==rax){
1482 r=get_reg(f,p,INT);
1483 if(!reg_pair(r,&rp)) ierror(0);
1484 emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
1485 emit(f,"\tstx\t%s\n",mregnames[rp.r2]);
1486 }else{
1487 r=get_reg(f,p,CHAR);
1488 emit(f,"\tsta\t%s\n",mregnames[r]);
1489 }
1490 p->q2.reg=r;
1491 if(isacc(q1))
1492 p->q1.reg=r;
1493 }
1494 }
1495 }
1496
1497 reload_acc(f);
1498
1499 regs[ra]=mra;
1500 regs[rax]=mrax;
1501}
1502
1503
1504/* compare if two objects are the same */
1505static int compare_objects(struct obj *o1,struct obj *o2)
1506{
1507 if((o1->flags&(REG|DREFOBJ))==REG&&(o2->flags&(REG|DREFOBJ))==REG&&o1->reg==o2->reg)
1508 return 1;
1509 if(o1->flags==o2->flags&&o1->am==o2->am){
1510 if(!(o1->flags&VAR)||(o1->v==o2->v&&zmeqto(o1->val.vmax,o2->val.vmax))){
1511 if(!(o1->flags&REG)||o1->reg==o2->reg){
1512 return 1;
1513 }
1514 }
1515 }
1516 return 0;
1517}
1518
1519/* save the result (in zreg) into p->z */
1520void save_result(FILE *f,struct IC *p)
1521{
1522 ierror(0);
1523}
1524
1525/* prints an object */
1526static void emit_obj(FILE *f,struct obj *p,int t)
1527{
1528 if(p->am){
1529 if(p->am->flags==IMM_IND)
1530 emit(f,"(%s),y ;am(%ld)",mregnames[p->am->base],p->am->offset);
1531 else if(p->am->flags==GPR_IND)
1532 emit(f,"(%s),y ;am(%s)",mregnames[p->am->base],mregnames[p->am->idx]);
1533 else if(p->am->flags==ABS_IND){
1534 emit(f,"%ld",p->am->offset);
1535 if(p->am->v){
1536 Var *v=p->am->v;
1537 if(v->storage_class==EXTERN)
1538 emit(f,"+%s%s",idprefix,v->identifier);
1539 else
1540 emit(f,"+%s%ld",labprefix,zm2l(v->offset));
1541 }
1542 emit(f,",y ;am(%s)",mregnames[p->am->idx]);
1543 }else
1544 ierror(0);
1545 return;
1546 }
1547 if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
1548 emitval(f,&p->val,p->dtyp&NU);
1549 return;
1550 }
1551 if(p->flags&DREFOBJ) emit(f,"(");
1552 if(p->flags&REG){
1553 emit(f,"%s",mregnames[p->reg]);
1554 }else if(p->flags&VAR) {
1555 if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER)
1556 emit(f,"(%s),y",mregnames[fp]);
1557 else{
1558 if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,MAXINT);emit(f,"+");}
1559 if(p->v->storage_class==STATIC){
1560 emit(f,"%s%ld",labprefix,zm2l(p->v->offset));
1561 }else{
1562 emit(f,"%s%s",idprefix,p->v->identifier);
1563 }
1564 }
1565 }
1566 if(p->flags&KONST){
1567 if(/*ieee&&((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE)*/ISFLOAT(t))
1568 emit(f,"%s%d",labprefix,addfpconst(p,t));
1569 else
1570 emitval(f,&p->val,t&NU);
1571 }
1572 if(p->flags&DREFOBJ) emit(f,"),y");
1573}
1574
1575/* Test if there is a sequence of FREEREGs containing FREEREG reg.
1576 Used by peephole. */
1577static int exists_freereg(struct IC *p,int reg)
1578{
1579 while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
1580 if(p->code==FREEREG&&p->q1.reg==reg) return 1;
1581 p=p->next;
1582 }
1583 return 0;
1584}
1585
1586char amode_buff[8192];
1587char *render_amode(struct AddressingMode *am)
1588{
1589 return "(amode: not implemented)";
1590}
1591
1592char val_buff[8192];
1593char *render_val(union atyps val)
1594{
1595 snprintf(val_buff,8192,"(val: %02x...)",
1596 val.vuchar);
1597 return val_buff;
1598}
1599
1600char var_buff[8192];
1601char *render_var(struct Var *v)
1602{
1603 if (!v) return "<null>";
1604 snprintf(var_buff,8192,"(var id=%s)",v->identifier);
1605 return var_buff;
1606}
1607
1608char obj_buff[8192];
1609char *render_obj(struct obj o)
1610{
1611 // XXX Calling render_var() can result in segfaults
1612 snprintf(obj_buff,8192,"(flags=%d, reg=%d, dtype=%d, var=%s, amode=%s, val=%s)",
1613 o.flags,o.reg,o.dtyp,"render_var(o.v)",render_amode(o.am),render_val(o.val));
1614 return obj_buff;
1615}
1616
1617/* search for possible addressing-modes */
1618static void peephole(struct IC *p)
1619{
1620 int c,c2,r;struct IC *p2;struct AddressingMode *am;
1621
1622 fprintf(stderr,"peephole() called.\n");
1623
1624 /*
1625 XXX PGS Things to consider adding here:
1626 1. Removal of dead loads when we know a register already has loaded the target we want.
1627 2. Removal of dead stores to local stack variables that never get read before returning from a function?
1628 3. Removal of SP decrement and increment, when no use of local stack is made.
1629 4. Promoting stack variables to global variables where it saves time and/or space?
1630 5. Using Z as a temporary scratch register for local variables, where it doesn't upset
1631 other things?
1632 */
1633
1634
1635 for(;p;p=p->next){
1636 fprintf(stderr," Instruction @ %p : ",p);
1637 fprintf(stderr,"code=%d, ",p->code);
1638 fprintf(stderr,"\n q1=%s, ",render_obj(p->q1));
1639 fprintf(stderr,"\n q2=%s, ",render_obj(p->q2));
1640 fprintf(stderr,"\n z=%s, ",render_obj(p->z));
1641 fprintf(stderr,"\n");
1642
1643 c=p->code;
1644 if(c!=FREEREG&&c!=ALLOCREG&&(c!=SETRETURN||!isreg(q1)||p->q1.reg!=p->z.reg)) exit_label=0;
1645 if(c==LABEL) exit_label=p->typf;
1646
1647 /* Try const(reg) */
1648 if((c==ADDI2P||c==SUBIFP)&&isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&!ISFPOINTER(p->typf2)){
1649 int base;zmax of;struct obj *o;
1650 eval_const(&p->q2.val,p->typf);
1651 if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
1652 if(zmleq(Z0,of)&&zmleq(of,l2zm(255L))){
1653 r=p->z.reg;
1654 if(isreg(q1)&&isptr(p->q1.reg)) base=p->q1.reg; else base=r;
1655 o=0;
1656 for(p2=p->next;p2;p2=p2->next){
1657 c2=p2->code;
1658 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
1659 if(c2!=FREEREG&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r) break;
1660 if(c2!=FREEREG&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==r) break;
1661 if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/){
1662 int t,mc;
1663 if((c2==ASSIGN|c2==PUSH)&&(p2->typf&NQ)==CHAR&&!zmeqto(p2->q2.val.vmax,Z1))
1664 mc=1;
1665 else
1666 mc=0;
1667 if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
1668 if(o||mc) break;
1669 t=q1typ(p2)&NQ;
1670 if(t>POINTER||ISFLOAT(t)) break;
1671 o=&p2->q1;
1672 }
1673 if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
1674 if(o||mc) break;
1675 t=q2typ(p2)&NQ;
1676 if(t>POINTER||ISFLOAT(t)) break;
1677 o=&p2->q2;
1678 }
1679 if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
1680 if(o||mc) break;
1681 t=ztyp(p2)&NQ;
1682 if(t>POINTER||ISFLOAT(t)) break;
1683 o=&p2->z;
1684 }
1685 }
1686 if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG){
1687 int m;
1688 if(c2==FREEREG)
1689 m=p2->q1.reg;
1690 else{
1691 m=p2->z.reg;
1692 if(o==&p->q1||o==&p->q2) break;
1693 }
1694 if(m==r){
1695 if(o){
1696 o->am=am=mymalloc(sizeof(*am));
1697 am->flags=IMM_IND;
1698 am->base=base;
1699 am->offset=(int)zm2l(of);
1700 if(isreg(q1)&&isptr(p->q1.reg)){
1701 p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
1702 }else{
1703 p->code=c=ASSIGN;p->q2.flags=0;
1704 p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ];
1705 }
1706 }
1707 break;
1708 }
1709 if(c2!=FREEREG&&m==base) break;
1710 continue;
1711 }
1712 }
1713 }
1714 }
1715 /* Try reg,reg */
1716 if(c==ADDI2P&&(p->typf&NU)==(UNSIGNED|CHAR)&&!ISFPOINTER(p->typf2)&&isreg(q2)&&p->q2.reg!=ra&&isreg(z)&&(isreg(q1)||p->q2.reg!=p->z.reg)){
1717 int base,idx,ind;struct obj *o;
1718 r=p->z.reg;idx=p->q2.reg;
1719 if(isreg(q1)) base=p->q1.reg; else base=r;
1720 if((p->q1.flags&VARADR)||(p->q1.flags&(KONST|DREFOBJ))==KONST)
1721 ind=0;
1722 else
1723 ind=1;
1724 o=0;
1725 for(p2=p->next;p2;p2=p2->next){
1726 c2=p2->code;
1727 if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
1728 if(c2!=FREEREG&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r) break;
1729 if(c2!=FREEREG&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==r) break;
1730 if((p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==idx&&idx!=r) break;
1731
1732 if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/){
1733 if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
1734 if(o||(ind&&(q1typ(p2)&NQ)!=CHAR)) break;
1735 o=&p2->q1;
1736 }
1737 if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
1738 if(o||(ind&&(q2typ(p2)&NQ)!=CHAR)) break;
1739 o=&p2->q2;
1740 }
1741 if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
1742 if(o||(ind&&(ztyp(p2)&NQ)!=CHAR)) break;
1743 o=&p2->z;
1744 }
1745 }
1746 if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG){
1747 int m;
1748 if(c2==FREEREG)
1749 m=p2->q1.reg;
1750 else
1751 m=p2->z.reg;
1752 if(m==r){
1753 if(o){
1754 o->am=am=mymalloc(sizeof(*am));
1755 am->idx=idx;
1756 if(ind){
1757 am->flags=GPR_IND;
1758 am->base=base;
1759 if(isreg(q1)){
1760 p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
1761 }else{
1762 p->code=c=ASSIGN;p->q2.flags=0;
1763 p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ];
1764 }
1765 }else{
1766 am->flags=ABS_IND;
1767 am->base=0;
1768 eval_const(&p->q1.val,MAXINT);
1769 am->offset=zm2l(vmax);
1770 if(p->q1.flags&VARADR)
1771 am->v=p->q1.v;
1772 else
1773 am->v=0;
1774 p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
1775 }
1776 }
1777 break;
1778 }
1779 if(c2!=FREEREG&&m==base) break;
1780 continue;
1781 }
1782 }
1783 }
1784 }
1785}
1786
1787static void pr(FILE *f,struct IC *p)
1788{
1789 int r;
1790
1791 if(zstoreflag){
1792 int off;
1793 if(p->z.flags!=VAR||p->z.v!=&bankv) ierror(0);
1794 off=(int)zm2l(p->z.val.vmax);
1795 p->z=zstore;
1796 get_acc(f,p,INT);
1797 if(zstore.flags&DREFOBJ){
1798 if(!ISFPOINTER(zstore.dtyp)) ierror(0);
1799 zstore.flags&=~DREFOBJ;
1800 load_reg(f,LAST_PAIR,&zstore,POINTER);
1801 if(indirect(&zstore)){
1802 do_byte3(f,"lda",&zstore,FPOINTER);
1803 emit(f,"\ttay\n");
1804 }else
1805 do_byte3(f,"ldy",&zstore,FPOINTER);
1806 yval=NOVAL;
1807 }else{
1808 load_address(f,LAST_PAIR,&zstore,p->typf);
1809 r=bank(zstore.v);
1810 sety(f,r>=0?r:bankcnum);
1811 }
1812 emit(f,"\tldx\t#%d\n",off);
1813 emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
1814 emit(f,"\tjsr\t%s__bankstore%d\n",idprefix,(int)zm2l(sizetab[p->typf&NQ]));
1815 yval=NOVAL;
1816 zstoreflag=0;
1817 }
1818
1819 for(r=1;r<=MAXR;r++){
1820 if(regs[r]&8)
1821 regs[r]&=~8;
1822 }
1823 for(r=FIRST_GPR;r<=LAST_GPR;r++){
1824 int ta=0;
1825 if(regs[r]&2){
1826 if(regs[ra]&&!pushedacc){
1827 emit(f,"\ttay\n");
1828 yval=NOVAL;
1829 ta=1;
1830 }
1831 emit(f,"\tpla\n");
1832 emit(f,"\tsta\t%s\n",mregnames[r]);
1833 regs[r]&=~2;
1834 }
1835 if(ta)
1836 emit(f,"\ttya\n");
1837 }
1838 if(pushedx){
1839 emit(f,"\tldx\t%s\n",mregnames[pushedx]);
1840 pushedx=0;
1841 }
1842
1843 reload_acc_opt(f,p->next);
1844}
1845
1846struct cmplist {struct cmplist *next;int from,to,mode;} *first_cmplist;
1847
1848static void add_cmplist(int from, int to, int mode)
1849{
1850 struct cmplist *new;
1851 new=mymalloc(sizeof(*new));
1852 new->next=first_cmplist;
1853 new->from=from;
1854 new->to=to;
1855 new->mode=mode;
1856 first_cmplist=new;
1857}
1858
1859static void incsp(FILE *f,long of)
1860{
1861 if(of==0) return;
1862 if(of==1||of==-1){
1863 static obj o;
1864 o.flags=REG;
1865 o.reg=sp;
1866 if(of==1)
1867 incmem(f,&o,INT,ADD,1);
1868 else
1869 incmem(f,&o,INT,SUB,1);
1870 }else if(of==256){
1871 emit(f,"\tinc\t%s+1\n",mregnames[sp]);
1872 }else if(of==-256){
1873 emit(f,"\tdec\t%s+1\n",mregnames[sp]);
1874 }else{
1875 long abs;
1876 if(of>0){
1877 abs=of;
1878 emit(f,"\tclc\n");
1879 }else{
1880 abs=-of;
1881 emit(f,"\tsec\n");
1882 }
1883 if(abs&255){
1884 emit(f,"\tlda\t%s\n",mregnames[sp]);
1885 if(of>0){
1886 emit(f,"\tadc\t#%ld\n",abs&255);
1887 }else{
1888 emit(f,"\tsbc\t#%ld\n",abs&255);
1889 }
1890 emit(f,"\tsta\t%s\n",mregnames[sp]);
1891 }
1892 if((abs&0xff00)==0){
1893 if(of>0){
1894 emit(f,"\tbcc\t%s%d\n",labprefix,++label);
1895 emit(f,"\tinc\t%s+1\n",mregnames[sp]);
1896 emit(f,"%s%d:\n",labprefix,label);
1897 }else{
1898 emit(f,"\tbcs\t%s%d\n",labprefix,++label);
1899 emit(f,"\tdec\t%s+1\n",mregnames[sp]);
1900 emit(f,"%s%d:\n",labprefix,label);
1901 }
1902 }else{
1903 emit(f,"\tlda\t%s+1\n",mregnames[sp]);
1904 if(of>0)
1905 emit(f,"\tadc\t#%ld\n",(abs>>8)&255);
1906 else
1907 emit(f,"\tsbc\t#%ld\n",(abs>>8)&255);
1908 emit(f,"\tsta\t%s+1\n",mregnames[sp]);
1909 }
1910 }
1911}
1912
1913/* generates the function entry code */
1914static void function_top(FILE *f,struct Var *v,long offset)
1915{
1916 int i,r,of;
1917 rsavesize=0;
1918 libsave=1;
1919
1920 if(!optsize||(v->tattr&NOCOMPRESS)) emit(f,";vcprmin=10000\n");
1921 if(vlas) emit(f,"___fo\tset\t%ld\n",(long)argsize);
1922 r=0;
1923 for(i=FIRST_GPR;i<=LAST_GPR;i++){
1924 if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
1925 if(i!=LAST_GPR-VOL_GPRS+1&&r==0) libsave=0;
1926 rsavesize++;
1927 r=1;
1928 }else{
1929 if(i==LAST_GPR-VOL_GPRS+1) libsave=0;
1930 r=0;
1931 }
1932 }
1933 rscnt=rsavesize;
1934 if(rscnt&&!SOFTSTACK){
1935 if(optspeed||rscnt<2)
1936 rsavesize=0;
1937 else if(!optsize&&rscnt<=5)
1938 rsavesize=0;
1939 }
1940
1941 if(!special_section(f,v)){emit(f,codename);ebank(f,bank(v));if(f) section=CODE;}
1942 if(v->storage_class==EXTERN){
1943 if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC)
1944 emit(f,"\tglobal\t%s%s\n",idprefix,v->identifier);
1945 emit(f,"%s%s:\n",idprefix,v->identifier);
1946 }else
1947 emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
1948
1949 offset=localsize+argsize+rsavesize;
1950
1951 if(in_isr){
1952 emit(f,"\tpha\n");
1953 emit(f,"\tphx\n");
1954 emit(f,"\tphy\n");
1955 emit(f,"\tphz\n");
1956 if(offset||function_calls){
1957 emit(f,"\tlda\t%s\n",mregnames[sp]);
1958 emit(f,"\tpha\n");
1959 emit(f,"\tlda\t%s+1\n",mregnames[sp]);
1960 emit(f,"\tpha\n");
1961 emit(f,"\tlda\t#<(___isrstack-%ld)\n",offset);
1962 emit(f,"\tsta\t%s\n",mregnames[sp]);
1963 emit(f,"\tlda\t#>(___isrstack-%ld)\n",offset);
1964 emit(f,"\tsta\t%s+1\n",mregnames[sp]);
1965 }
1966 }
1967
1968 if(MAINARGS&&v->storage_class==EXTERN&&!strcmp(v->identifier,"main")&&v->vtyp->exact->count>1)
1969 emit(f,"\tjsr\tinitmainargs\n");
1970
1971 yval=NOVAL;
1972 of=argsize+localsize;
1973
1974 if(rsavesize>0&&of+rsavesize>255){
1975 offset-=rsavesize;
1976 incsp(f,-rsavesize);
1977 of=0;
1978 }else{
1979 incsp(f,-offset);
1980 offset=0;
1981 }
1982
1983
1984 if(!libsave||rscnt!=rsavesize||optspeed||rscnt<=1||(rscnt<=3&&(!optsize)))
1985 libsave=0;
1986
1987 if(libsave){
1988 sety(f,of+rsavesize-1);
1989 emit(f,"\tjsr\t%s__rsave%ld\n",idprefix,rscnt);
1990 yval=of;
1991 }else{
1992 for(i=FIRST_GPR;i<=LAST_GPR;i++){
1993 if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
1994 if(rscnt!=rsavesize){
1995 emit(f,"\tlda\t%s\n",mregnames[i]);
1996 emit(f,"\tpha\n");
1997 }else{
1998 sety(f,of++);
1999 emit(f,"\tlda\t%s\n",mregnames[i]);
2000 emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
2001 }
2002 }
2003 }
2004 }
2005
2006
2007
2008 incsp(f,-offset);
2009
2010 if(vlas){
2011 emit(f,"\tlda\t%s\n",mregnames[sp]);
2012 emit(f,"\tsta\t%s\n",mregnames[fp]);
2013 emit(f,"\tlda\t%s\n",mregnames[sp2]);
2014 emit(f,"\tsta\t%s\n",mregnames[fp2]);
2015 }
2016}
2017
2018/* generates the function exit code */
2019static void function_bottom(FILE *f,struct Var *v,long offset)
2020{
2021 int i,of,ar;
2022 struct cmplist *p;
2023 offset=localsize+argsize+rsavesize;
2024 of=argsize+localsize;
2025
2026 i=freturn(v->vtyp->next);
2027 if(i==ra||i==rax) ar=1; else ar=0;
2028
2029 if(rscnt!=rsavesize){
2030 if(ar&&!pushedacc){
2031 pushedacc=t4;
2032 emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
2033 }
2034 for(i=LAST_GPR;i>=FIRST_GPR;i--){
2035 if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
2036 emit(f,"\tpla\n");
2037 emit(f,"\tsta\t%s\n",mregnames[i]);
2038 }
2039 }
2040 }
2041 if(rsavesize>0&&of+rsavesize>255){
2042 if(of!=1&&ar&&!pushedacc){
2043 pushedacc=t4;
2044 emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
2045 }
2046 incsp(f,of);
2047 offset-=of;
2048 of=0;
2049 }
2050 if(rsavesize>0){
2051 if(ar&&!pushedacc){
2052 pushedacc=t4;
2053 emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
2054 }
2055 }
2056 if(rsavesize){
2057 if(libsave){
2058 sety(f,of+rsavesize-1);
2059 emit(f,"\tjsr\t%s__rload%ld\n",idprefix,rscnt);
2060 yval=of;
2061 }else{
2062 for(i=FIRST_GPR;i<=LAST_GPR;i++){
2063 if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
2064 sety(f,of++);
2065 emit(f,"\tlda\t(%s),y\n",mregnames[sp]);
2066 emit(f,"\tsta\t%s\n",mregnames[i]);
2067 }
2068 }
2069 }
2070 }
2071 if(in_isr){
2072 if(offset||function_calls){
2073 emit(f,"\tpla\n");
2074 emit(f,"\tsta\t%s+1\n",mregnames[sp]);
2075 emit(f,"\tpla\n");
2076 emit(f,"\tsta\t%s\n",mregnames[sp]);
2077 }
2078 }else if(offset==2&&!pushedacc){
2079 emit(f,"\tinc\t%s\n",mregnames[sp]);
2080 emit(f,"\tbeq\t%s%d\n",labprefix,++label);
2081 emit(f,"\tinc\t%s\n",mregnames[sp]);
2082 emit(f,"\tbeq\t%s%d\n",labprefix,++label);
2083 reload_acc(f);
2084 emit(f,ret);
2085 emit(f,"%s%d:\n",labprefix,label-1);
2086 emit(f,"\tinc\t%s\n",mregnames[sp]);
2087 emit(f,"%s%d:\n",labprefix,label);
2088 emit(f,"\tinc\t%s+1\n",mregnames[sp]);
2089 }else{
2090 if(offset!=0&&ar&&!pushedacc){
2091 pushedacc=t4;
2092 emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
2093 }
2094 incsp(f,offset);
2095 }
2096
2097 reload_acc(f);
2098
2099 if(in_isr){
2100 emit(f,"\tplz\n");
2101 emit(f,"\tply\n");
2102 emit(f,"\tplx\n");
2103 emit(f,"\tpla\n");
2104 }
2105 emit(f,ret);
2106
2107 for(p=first_cmplist;p;){
2108 struct cmplist *m;
2109 emit(f,"%s%d:\n",labprefix,p->from);
2110 if(p->mode==JMPIND){
2111 /* indirect call */
2112 emit(f,"\tjmp\t(%s)\n",mregnames[p->to]);
2113 }else{
2114 pushedacc=p->mode;
2115 reload_acc(f);
2116 emit(f,"\tjmp\t%s%d\n",labprefix,p->to);
2117 }
2118 m=p;
2119 p=p->next;
2120 free(m);
2121 }
2122 first_cmplist=0;
2123 pushedacc=0;
2124}
2125
2126/****************************************/
2127/* End of private data and functions. */
2128/****************************************/
2129
2130/* Does necessary initializations for the code-generator. Gets called */
2131/* once at the beginning and should return 0 in case of problems. */
2132int init_cg(void)
2133{
2134 int i;
2135 /* Initialize some values which cannot be statically initialized */
2136 /* because they are stored in the target's arithmetic. */
2137 maxalign=l2zm(1L);
2138 char_bit=l2zm(8L);
2139 stackalign=l2zm(1);
2140
2141 if(IEEE){
2142 ieee=1;
2143 msizetab[DOUBLE]=msizetab[LDOUBLE]=l2zm(8L);
2144 }
2145
2146
2147 mregnames[0]=regnames[0]="noreg";
2148 for(i=FIRST_GPR;i<=LAST_GPR;i++){
2149 regnames[i]=mymalloc(10);
2150 sprintf(regnames[i],"r%d",i-FIRST_GPR);
2151 mregnames[i]=regnames[i];
2152 regsize[i]=l2zm(1L);
2153 regtype[i]=&ctyp;
2154 }
2155 for(i=FIRST_PAIR;i<=LAST_PAIR;i++){
2156 int sr=(i-FIRST_PAIR)*2+FIRST_GPR;
2157 regnames[i]=mymalloc(10);
2158 sprintf(regnames[i],"%s/%s",mregnames[sr],mregnames[sr+1]);
2159 mregnames[i]=regnames[sr];
2160 regsize[i]=l2zm(2L);
2161 regtype[i]=&ityp;
2162 }
2163 for(i=FIRST_BIG;i<=LAST_BIG;i++){
2164 regnames[i]=mymalloc(10);
2165 sprintf(regnames[i],"btmp%d",i-FIRST_BIG);
2166 mregnames[i]=regnames[i];
2167 regsize[i]=msizetab[FLOAT];
2168 regtype[i]=&ftyp;
2169 regsa[i]=0;
2170 regscratch[i]=1;
2171 }
2172 for(i=FIRST_BIGP;i<=LAST_BIGP;i++){
2173 int sr=(i-FIRST_BIGP)*2+FIRST_BIG;
2174 regnames[i]=mymalloc(20);
2175 sprintf(regnames[i],"%s/%s",mregnames[sr],mregnames[sr+1]);
2176 mregnames[i]=regnames[sr];
2177 regsize[i]=msizetab[LLONG];
2178 regtype[i]=&lltyp;
2179 regsa[i]=0;
2180 regscratch[i]=1;
2181 }
2182
2183 mregnames[ra] = regnames[ra] = "a";
2184 mregnames[rx] = regnames[rx] = "x";
2185 mregnames[ry] = regnames[ry] = "y";
2186 mregnames[rz] = regnames[rz] = "z";
2187 regsize[ra]=regsize[rx]=regsize[ry]=l2zm(1L);
2188 regtype[ra]=regtype[rx]=regtype[ry]=&ctyp;
2189 mregnames[sp]=regnames[sp] = "sp";
2190 mregnames[sp1]=regnames[sp1] = "sp";
2191 mregnames[sp2]=regnames[sp2] = "sp+1";
2192
2193 mregnames[rax]=regnames[rax] = "ax";
2194 regsize[rax]=regsize[sp]=l2zm(2L);
2195 regtype[rax]=regtype[sp]=&ityp;
2196
2197 reg_prio[ra]=reg_prio[rax]=100;
2198 reg_prio[rx]=50;
2199
2200 mregnames[raxyz]=regnames[raxyz] = "axyz";
2201 regsize[raxyz]=l2zm(3L);
2202 regtype[raxyz]=&lltyp;
2203
2204 /* Use multiple ccs. */
2205 multiple_ccs=0;
2206
2207 short_push=1;
2208
2209 static_cse=0;
2210
2211 dref_cse=1;
2212
2213 /*prefer_statics=1; TODO */
2214
2215
2216 if(optsize){
2217 clist_copy_stack=2;
2218 clist_copy_pointer=2;
2219 clist_copy_static=2;
2220 }else if(optspeed){
2221 clist_copy_stack=64;
2222 clist_copy_pointer=64;
2223 clist_copy_static=64;
2224 }else{
2225 clist_copy_stack=8;
2226 clist_copy_pointer=8;
2227 clist_copy_static=8;
2228 }
2229
2230 /* Initialize the min/max-settings. Note that the types of the */
2231 /* host system may be different from the target system and you may */
2232 /* only use the smallest maximum values ANSI guarantees if you */
2233 /* want to be portable. */
2234 /* That's the reason for the subtraction in t_min[INT]. Long could */
2235 /* be unable to represent -2147483648 on the host system. */
2236 t_min[CHAR]=l2zm(-128L);
2237 t_min[SHORT]=l2zm(-32768L);
2238 t_min[LONG]=zmsub(l2zm(-2147483647L),l2zm(1L));
2239 t_min[INT]=t_min(SHORT);
2240 t_min[LLONG]=zmlshift(l2zm(1L),l2zm(63L));
2241 t_min[MAXINT]=t_min(LLONG);
2242 t_max[CHAR]=ul2zum(127L);
2243 t_max[SHORT]=ul2zum(32767UL);
2244 t_max[LONG]=ul2zum(2147483647UL);
2245 t_max[INT]=t_max(SHORT);
2246 t_max[LLONG]=zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL));
2247 t_max[MAXINT]=t_max(LLONG);
2248 tu_max[CHAR]=ul2zum(255UL);
2249 tu_max[SHORT]=ul2zum(65535UL);
2250 tu_max[LONG]=ul2zum(4294967295UL);
2251 tu_max[INT]=t_max(UNSIGNED|SHORT);
2252 tu_max[LLONG]=zumkompl(ul2zum(0UL));
2253 tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
2254
2255 /* Reserve a few registers for use by the code-generator. */
2256 /* This is not optimal but simple. */
2257 regsa[raxyz]=regsa[rz]=regsa[ry]=regsa[sp]=regsa[sp1]=regsa[sp2]=REGSA_NEVER;
2258 regsa[t1]=regsa[t2]=regsa[t3]=regsa[t4]=REGSA_NEVER;
2259 regscratch[ra]=regscratch[rx]=regscratch[rax]=1;
2260 if(!GLOBACC)
2261 regsa[ra]=regsa[rx]=regsa[rax]=REGSA_TEMPS;
2262 regscratch[sp]=regscratch[sp1]=regscratch[sp2]=regscratch[ry]=regscratch[rz]=0;
2263 regscratch[t1]=regscratch[t2]=regscratch[t3]=regscratch[t4]=1;
2264
2265 for(i=FIRST_GPR;i<=LAST_GPR-VOL_GPRS;i++){
2266 regscratch[i]=1;
2267 if(i&1)
2268 regscratch[FIRST_PAIR+(i-FIRST_GPR)/2]=1;
2269 }
2270
2271 target_macros=marray;
2272
2273 declare_builtin("__mulint16",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
2274 declare_builtin("__muluint16",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
2275 declare_builtin("__divuint16",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
2276 declare_builtin("__divint16",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
2277 declare_builtin("__moduint16",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
2278 declare_builtin("__modint16",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
2279
2280 declare_builtin("__mulint32",LONG,LONG,FIRST_BIG+1,LONG,FIRST_BIG+2,1,0);
2281 declare_builtin("__muluint32",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG+1,UNSIGNED|LONG,FIRST_BIG+2,1,0);
2282 declare_builtin("__divint32",LONG,LONG,FIRST_BIG,LONG,FIRST_BIG+1,1,0);
2283 declare_builtin("__divuint32",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG,UNSIGNED|LONG,FIRST_BIG+1,1,0);
2284 declare_builtin("__modint32",LONG,LONG,FIRST_BIG,LONG,FIRST_BIG+1,1,0);
2285 declare_builtin("__moduint32",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG,UNSIGNED|LONG,FIRST_BIG+1,1,0);
2286
2287 declare_builtin("__mulint64",LLONG,LLONG,0,LLONG,0,1,0);
2288 declare_builtin("__addint64",LLONG,LLONG,0,LLONG,0,1,0);
2289 declare_builtin("__subint64",LLONG,LLONG,0,LLONG,0,1,0);
2290 declare_builtin("__andint64",LLONG,LLONG,0,LLONG,0,1,0);
2291 declare_builtin("__orint64",LLONG,LLONG,0,LLONG,0,1,0);
2292 declare_builtin("__eorint64",LLONG,LLONG,0,LLONG,0,1,0);
2293 declare_builtin("__negint64",LLONG,LLONG,0,0,0,1,0);
2294 declare_builtin("__lslint64",LLONG,LLONG,0,INT,0,1,0);
2295
2296 declare_builtin("__divint64",LLONG,LLONG,0,LLONG,0,1,0);
2297 declare_builtin("__divuint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
2298 declare_builtin("__modint64",LLONG,LLONG,0,LLONG,0,1,0);
2299 declare_builtin("__moduint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
2300 declare_builtin("__lsrint64",LLONG,LLONG,0,INT,0,1,0);
2301 declare_builtin("__lsruint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,INT,0,1,0);
2302 declare_builtin("__cmpsint64",INT,LLONG,0,LLONG,0,1,0);
2303 declare_builtin("__cmpuint64",INT,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
2304
2305 declare_builtin("__sint32toflt32",FLOAT,LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
2306 declare_builtin("__uint32toflt32",FLOAT,UNSIGNED|LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
2307 declare_builtin("__flt32tosint32",LONG,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
2308 declare_builtin("__flt32touint32",UNSIGNED|LONG,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
2309 declare_builtin("__sint16toflt32",FLOAT,INT,FIRST_PAIR,0,0,1,0);
2310 declare_builtin("__uint16toflt32",FLOAT,UNSIGNED|INT,FIRST_PAIR,0,0,1,0);
2311 declare_builtin("__flt32tosint16",INT,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
2312 declare_builtin("__flt32touint16",UNSIGNED|INT,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
2313
2314 declare_builtin("__sint32toflt64",DOUBLE,LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
2315 declare_builtin("__uint32toflt64",DOUBLE,UNSIGNED|LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
2316 declare_builtin("__flt64tosint32",LONG,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
2317 declare_builtin("__flt64touint32",UNSIGNED|LONG,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
2318 declare_builtin("__sint16toflt64",DOUBLE,INT,FIRST_PAIR,0,0,1,0);
2319 declare_builtin("__uint16toflt64",DOUBLE,UNSIGNED|INT,FIRST_PAIR,0,0,1,0);
2320 declare_builtin("__flt64tosint16",INT,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
2321 declare_builtin("__flt64touint16",UNSIGNED|INT,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
2322
2323 declare_builtin("__flt64toflt32",FLOAT,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
2324 declare_builtin("__flt32toflt64",DOUBLE,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
2325
2326 declare_builtin("__addflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
2327 declare_builtin("__subflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
2328 declare_builtin("__mulflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
2329 declare_builtin("__divflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
2330 declare_builtin("__negflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
2331 declare_builtin("__cmpsflt32",CHAR,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
2332
2333#if 0
2334 for(i=1;i<MAXR;i++){
2335 printf("%02d %s scratch=%d ",i,regnames[i],regscratch[i]);
2336 if(reg_pair(i,&rp))
2337 printf("pair(%s,%s)",regnames[rp.r1],regnames[rp.r2]);
2338 printf("\n");
2339 }
2340#endif
2341
2342 if(NOPEEP) nopeep=1;
2343 if(CBMASCII) cbmascii=1;
2344 if(ATASCII) atascii=1;
2345
2346
2347 for(i=0;i<=MAX_TYPE;i++){
2348 sizetab[i]=l2zm(msizetab[i]);
2349 align[i]=l2zm(malign[i]);
2350 }
2351
2352 bankv.storage_class=EXTERN;
2353 bankv.identifier="__bankv";
2354 bankv.vtyp=new_typ();
2355 bankv.vtyp->flags=CHAR;
2356
2357 bankcnum=COMMONBANK;
2358
2359 return 1;
2360}
2361
2362void init_db(FILE *f)
2363{
2364}
2365
2366int freturn(struct Typ *t)
2367/* Returns the register in which variables of type t are returned. */
2368/* If the value cannot be returned in a register returns 0. */
2369/* A pointer MUST be returned in a register. The code-generator */
2370/* has to simulate a pseudo register if necessary. */
2371{
2372 int typ=t->flags&NQ;
2373 if(ISSTRUCT(typ)||ISUNION(typ)||typ==VOID)
2374 return 0;
2375 if(OLDFP&&ISFLOAT(typ)) return FIRST_GPR;
2376 if(typ==LONG||typ==FLOAT||ISFPOINTER(typ)||(!ieee&&(typ==DOUBLE||typ==LDOUBLE)))
2377 return FIRST_BIG;
2378 if(typ==LLONG||(ieee&&(typ==DOUBLE||typ==LDOUBLE)))
2379 return FIRST_BIGP;
2380 if(zmleq(szof(t),l2zm(1L)))
2381 return ra;
2382 if(zmleq(szof(t),l2zm(2L)))
2383 return rax;
2384 else
2385 return 0;
2386}
2387
2388int reg_pair(int r,struct rpair *p)
2389/* Returns 0 if the register is no register pair. If r */
2390/* is a register pair non-zero will be returned and the */
2391/* structure pointed to p will be filled with the two */
2392/* elements. */
2393{
2394 if(r>=FIRST_PAIR&&r<=LAST_PAIR){
2395 p->r1=(r-FIRST_PAIR)*2+FIRST_GPR;
2396 p->r2=p->r1+1;
2397 return 1;
2398 }else if(r>=FIRST_BIGP&&r<=LAST_BIGP){
2399 p->r1=(r-FIRST_BIGP)*2+FIRST_BIG;
2400 p->r2=p->r1+1;
2401 return 1;
2402 }else if(r==rax){
2403 p->r1=ra;
2404 p->r2=rx;
2405 return 1;
2406 }else if(r==raxyz) {
2407 // TODO: PGS: How do we declare a reg pair that is made of 4 regs, not 2?
2408 p->r1=ra;
2409 p->r2=rx;
2410 return 1;
2411 }else if(r==sp){
2412 p->r1=sp1;
2413 p->r2=sp2;
2414 return 1;
2415 }
2416 return 0;
2417}
2418
2419/* estimate the cost-saving if object o from IC p is placed in
2420 register r */
2421int cost_savings(struct IC *p,int r,struct obj *o)
2422{
2423 int c=p->code;
2424 /*TODO: adapt this */
2425 if(o->flags&VKONST){
2426 return 0;
2427 if(o==&p->q1&&p->code==ASSIGN&&(p->z.flags&DREFOBJ))
2428 return 4;
2429 else
2430 return 2;
2431 }
2432 if(o->flags&DREFOBJ){
2433 if(isptr(r))
2434 return 4;
2435 if(r==rax)
2436 return INT_MIN;
2437 }
2438 if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 6;
2439 if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 6;
2440 if(r==ra)
2441 return 5;
2442 if(r==rx)
2443 return 4;
2444 if(r==rax)
2445 return 2;
2446 return 2;
2447}
2448
2449int regok(int r,int t,int mode)
2450/* Returns 0 if register r cannot store variables of */
2451/* type t. If t==POINTER and mode!=0 then it returns */
2452/* non-zero only if the register can store a pointer */
2453/* and dereference a pointer to mode. */
2454{
2455 if(r==0)
2456 return 0;
2457 if(r==rax&&NORAX)
2458 return 0;
2459 t&=NQ;
2460 if(ISCHAR(t))
2461 if(r==ra/*||r==rx*/||(r>=FIRST_GPR&&r<=LAST_GPR))
2462 return 1;
2463 if(ISSHORT(t)){
2464 if(r==rax){
2465 if(t==POINTER&&mode<0)
2466 return 1;
2467 if(t!=POINTER)
2468 return 1;
2469 }
2470 if(r>=FIRST_PAIR&&r<=LAST_PAIR)
2471 return 1;
2472 }
2473 if(r>=FIRST_BIG&&r<=LAST_BIG){
2474 if(t==LONG||t==FLOAT||((t==DOUBLE||t==LDOUBLE)&&!ieee))
2475 return 1;
2476 if(t==FPOINTER)
2477 return 1;
2478 }
2479 if(r>=FIRST_BIGP&&r<=LAST_BIGP){
2480 if(t==LLONG||((t==DOUBLE||t==LDOUBLE)&&ieee))
2481 return 1;
2482 }
2483 return 0;
2484}
2485
2486int dangerous_IC(struct IC *p)
2487/* Returns zero if the IC p can be safely executed */
2488/* without danger of exceptions or similar things. */
2489/* vbcc may generate code in which non-dangerous ICs */
2490/* are sometimes executed although control-flow may */
2491/* never reach them (mainly when moving computations */
2492/* out of loops). */
2493/* Typical ICs that generate exceptions on some */
2494/* machines are: */
2495/* - accesses via pointers */
2496/* - division/modulo */
2497/* - overflow on signed integer/floats */
2498{
2499 int c=p->code;
2500 if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
2501 return 1;
2502 if((c==DIV||c==MOD)&&!isconst(q2))
2503 return 1;
2504 return 0;
2505}
2506
2507int must_convert(int o,int t,int const_expr)
2508/* Returns zero if code for converting np to type t */
2509/* can be omitted. */
2510/* On the PowerPC cpu pointers and 32bit */
2511/* integers have the same representation and can use */
2512/* the same registers. */
2513{
2514 int op=o&NQ,tp=t&NQ;
2515
2516 if(op==tp) return 0;
2517 if(ISCHAR(op)&&ISCHAR(tp)) return 0;
2518 if(ISSHORT(op)&&ISSHORT(tp)) return 0;
2519 if(!ieee&&ISFLOAT(op)&&ISFLOAT(tp)) return 0;
2520 if(op==DOUBLE&&tp==LDOUBLE) return 0;
2521 if(op==LDOUBLE&&tp==DOUBLE) return 0;
2522
2523 return 1;
2524}
2525
2526void gen_ds(FILE *f,zmax size,struct Typ *t)
2527/* This function has to create <size> bytes of storage */
2528/* initialized with zero. */
2529{
2530 if(STDSYNTAX)
2531 emit(f,"\tspace\t%ld\n",zm2l(size));
2532 else
2533 emit(f,"\treserve\t%ld\n",zm2l(size));
2534 newobj=0;
2535}
2536
2537void gen_align(FILE *f,zmax align)
2538/* This function has to make sure the next data is */
2539/* aligned to multiples of <align> bytes. */
2540{
2541 if(zm2l(align)>1) emit(f,"\talign 1\n");
2542}
2543
2544void gen_var_head(FILE *f,struct Var *v)
2545/* This function has to create the head of a variable */
2546/* definition, i.e. the label and information for */
2547/* linkage etc. */
2548{
2549 int constflag,b=bank(v);char *sec;
2550 if(v->clist) constflag=is_const(v->vtyp);
2551 if(v->storage_class==STATIC){
2552 if(ISFUNC(v->vtyp->flags)) return;
2553 if(v->tattr&ZPAGE)
2554 emit(f,"\tzpage\t%s%ld\n",labprefix,zm2l(v->offset));
2555 if(!special_section(f,v)){
2556 if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))){emit(f,dataname);ebank(f,b);if(f) section=DATA;}
2557 if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)){emit(f,rodataname);ebank(f,b);if(f) section=RODATA;}
2558 if(!v->clist){emit(f,bssname);ebank(f,b);if(f) section=BSS;}
2559 }
2560 gen_align(f,falign(v->vtyp));
2561 emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
2562 newobj=1;
2563 }
2564 if(v->storage_class==EXTERN){
2565 emit(f,"\tglobal\t%s%s\n",idprefix,v->identifier);
2566 if(v->tattr&ZPAGE)
2567 emit(f,"\tzpage\t%s%s\n",idprefix,v->identifier);
2568 if(v->flags&(DEFINED|TENTATIVE)){
2569 if(!special_section(f,v)){
2570 if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))){emit(f,dataname);ebank(f,b);if(f) section=DATA;}
2571 if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)){emit(f,rodataname);ebank(f,b);if(f) section=RODATA;}
2572 if(!v->clist){emit(f,bssname);ebank(f,b);if(f) section=BSS;}
2573 }
2574
2575 gen_align(f,falign(v->vtyp));
2576 emit(f,"%s%s:\n",idprefix,v->identifier);
2577 newobj=1;
2578 }
2579 }
2580}
2581
2582void gen_dc(FILE *f,int t,struct const_list *p)
2583/* This function has to create static storage */
2584/* initialized with const-list p. */
2585{
2586 if(ISCHAR(t))
2587 emit(f,"\tbyte\t");
2588 else
2589 emit(f,"\tword\t");
2590 if(!p->tree){
2591 if(ISLONG(t)||ISFLOAT(t)){
2592 if(ieee&&ISFLOAT(t)){
2593 emit_ieee(f,&p->val,t&NQ);
2594 }else{
2595 eval_const(&p->val,t&NU);
2596 if(ISFLOAT(t)) cnv_fp();
2597 gval.vmax=zmand(vmax,l2zm(0xffffL));
2598 emitval(f,&gval,MAXINT);
2599 emit(f,",");
2600 gval.vmax=zmand(zmrshift(vmax,l2zm(16L)),l2zm(0xffffL));
2601 emitval(f,&gval,MAXINT);
2602 }
2603 }else{
2604 if(ISFPOINTER(t)){
2605 eval_const(&p->val,t&NU);
2606 emit(f,"%ld\n",(long)zm2l(vmax)&0xffff);
2607 emit(f,"\tbyte\t%d\n",(int)((zm2l(vmax)>>16)&0xff));
2608 }else
2609 emitval(f,&p->val,t&NU);
2610 }
2611 }else{
2612 emit_obj(f,&p->tree->o,t&NU);
2613 if(ISFPOINTER(t)){
2614 int b;
2615 if((p->tree->o.flags&(VAR|VARADR))!=(VAR|VARADR)) ierror(0);
2616 b=bank(p->tree->o.v);
2617 emit(f,"\n\tbyte\t%d",b>=0?b:bankcnum);
2618 }
2619 }
2620 emit(f,"\n");newobj=0;
2621}
2622
2623
2624/* The main code-generation routine. */
2625/* f is the stream the code should be written to. */
2626/* p is a pointer to a doubly linked list of ICs */
2627/* containing the function body to generate code for. */
2628/* v is a pointer to the function. */
2629/* offset is the size of the stackframe the function */
2630/* needs for local variables. */
2631
2632void gen_code(FILE *f,struct IC *p,struct Var *v,zmax offset)
2633/* The main code-generation. */
2634{
2635 int c,t,i;
2636 struct IC *mi;
2637 FILE *rf=f;
2638 static char *dbgfile;
2639 static int dbgline;
2640
2641 if(vlas){
2642 fp=FPVLA_REG;
2643 if(!reg_pair(fp,&rp)) ierror(0);
2644 fp1=rp.r1;
2645 fp2=rp.r2;
2646 regused[fp]=regused[fp1]=regused[fp2]=1;
2647 }else{
2648 fp=sp;
2649 fp1=sp1;
2650 fp2=sp2;
2651 }
2652 argsize=0;
2653 localsize=offset;
2654 if(DEBUG&1) printf("gen_code()\n");
2655
2656 cbank=bank(v);
2657
2658 if(!v->fi) v->fi=new_fi();
2659 v->fi->flags|=ALL_REGS;
2660
2661 for(pass=0;pass<2;pass++){
2662
2663 if(DEBUG&1) printf("pass %d\n",pass);
2664
2665 if(pass==0){
2666 f=0;
2667 mi=clone_ic(p);
2668 }else
2669 f=rf;
2670
2671 for(c=1;c<=MAXR;c++) regs[c]=0; /*regsa[c];*/
2672 maxpushed=0;
2673
2674 /*FIXME*/
2675 if(v->tattr&INTERRUPT){
2676 ret="\trti\n";
2677 in_isr=1;
2678 }else{
2679 ret="\trts\n";
2680 in_isr=0;
2681 }
2682
2683 if(!nopeep) peephole(pass==0?p:mi);
2684
2685 function_top(f,v,localsize);
2686
2687 pushed=0;
2688
2689 yval=NOVAL;
2690
2691 dbgfile=0;
2692 dbgline=0;
2693
2694 for(p=pass==0?p:mi;p;pr(f,p),p=p->next){
2695
2696
2697
2698 if(DEBUG&1) pric2(stdout,p);
2699
2700 if(debug_info){
2701 if(p->file&&p->line){
2702 if(p->file!=dbgfile||p->line!=dbgline){
2703 dbgfile=p->file;
2704 dbgline=p->line;
2705 emit(f,"; %d \"%s\"\n",dbgline,dbgfile);
2706 }
2707 }
2708 }
2709
2710 c=p->code;t=p->typf;
2711
2712 if(c==NOP) {p->z.flags=0;continue;}
2713 if(c==ALLOCREG){
2714 regs[p->q1.reg]=1;
2715 if(reg_pair(p->q1.reg,&rp)){
2716 regs[rp.r1]=1;
2717 regs[rp.r2]=1;
2718 }
2719 continue;
2720 }
2721 if(c==FREEREG){
2722 regs[p->q1.reg]=0;
2723 if(reg_pair(p->q1.reg,&rp)){
2724 regs[rp.r1]=0;
2725 regs[rp.r2]=0;
2726 }
2727 continue;
2728 }
2729 if(c==LABEL) {emit(f,"%s%d:\n",labprefix,t);yval=NOVAL;continue;}
2730 if(c==BRA){
2731 yval=NOVAL;
2732 if(t==exit_label&&localsize+argsize+rsavesize+rscnt==0)
2733 emit(f,ret);
2734 else
2735 emit(f,"\tjmp\t%s%d\n",labprefix,t);
2736 continue;
2737 }
2738 if(c>=BEQ&&c<BRA){
2739 yval=NOVAL;
2740 continue;
2741 }
2742
2743 if(c==MOVETOREG){
2744 p->code=c=ASSIGN;
2745 p->typf=t=regtype[p->z.reg]->flags;
2746 p->q2.val.vmax=sizetab[regtype[p->z.reg]->flags];
2747 }
2748 if(c==MOVEFROMREG){
2749 p->code=c=ASSIGN;
2750 p->typf=t=regtype[p->q1.reg]->flags;
2751 p->q2.val.vmax=sizetab[regtype[p->q1.reg]->flags];
2752 }
2753 if(c==CONVERT&&ISCHAR(t)&&ISCHAR(p->typf2)){
2754 p->code=c=ASSIGN;
2755 p->q2.val.vmax=sizetab[CHAR];
2756 }
2757 if(c==CONVERT&&msizetab[t&NQ]==3&&msizetab[p->typf2&NQ]==3){
2758 p->code=c=ASSIGN;
2759 p->q2.val.vmax=sizetab[SHORT];
2760 }
2761 if(c==CONVERT&&ISSHORT(t)&&ISSHORT(p->typf2)){
2762 p->code=c=ASSIGN;
2763 p->q2.val.vmax=sizetab[SHORT];
2764 }
2765 if(c==CONVERT&&ISLONG(t)&&ISLONG(p->typf2)){
2766 p->code=c=ASSIGN;
2767 p->q2.val.vmax=sizetab[LONG];
2768 }
2769 if(c==CONVERT&&ISLLONG(t)&&ISLLONG(p->typf2)){
2770 p->code=c=ASSIGN;
2771 p->q2.val.vmax=sizetab[LLONG];
2772 }
2773 if(c==CONVERT&&ISFLOAT(t)&&ISFLOAT(p->typf2)){
2774 p->code=c=ASSIGN;
2775 p->q2.val.vmax=sizetab[t&NQ];
2776 }
2777
2778
2779 /* switch commutative operands if suitable */
2780 if(c==ADD||c==MULT||c==AND||c==XOR||c==OR||(c==ADDI2P&&ISSHORT(t)&&!ISFPOINTER(p->typf2))){
2781 if(compare_objects(&p->q2,&p->z)||isacc(q2)){
2782 struct obj tmp;
2783 tmp=p->q1;
2784 p->q1=p->q2;
2785 p->q2=tmp;
2786 }
2787 }
2788
2789 if(c==COMPARE&&(p->q1.flags&(KONST|DREFOBJ))==KONST){
2790 obj tmp;
2791 tmp=p->q1;
2792 p->q1=p->q2;
2793 p->q2=tmp;
2794 }
2795
2796 c=p->code;
2797 if(c==SUBPFP) c=SUB;
2798 /*if(c==ADDI2P) c=ADD;*/
2799 /*if(c==SUBIFP) c=SUB;*/
2800
2801
2802 if(c==MINUS){
2803 if(isacc(q1)&&isacc(z)){
2804 emit(f,"\tneg\n");
2805 if(!ISCHAR(t)){
2806 emit(f,"\tpha\n");
2807 emit(f,"\ttxa\n");
2808 emit(f,"\teor\t#255\n");
2809 emit(f,"\tadc\t#0\n");
2810 emit(f,"\ttax\n");
2811 emit(f,"\tpla\n");
2812 }
2813 continue;
2814 }
2815 p->code=c=SUB;
2816 p->q2=p->q1;
2817 p->q1.flags=KONST;
2818 gval.vmax=Z0;
2819 eval_const(&gval,MAXINT);
2820 insert_const(&p->q1.val,t);
2821 }
2822
2823 preload(f,p);
2824
2825 if(c==CONVERT){
2826 int to=q1typ(p)&NU;
2827 t&=NU;
2828 if(ISCHAR(t)){
2829 get_acc(f,p,CHAR);
2830 load_lobyte(f,&p->q1,to);
2831 store_lobyte(f,&p->z,t);
2832 continue;
2833 }
2834 if(ISLONG(to)){
2835 if(!isacc(z))
2836 get_acc(f,p,CHAR);
2837 if(zm2l(sizetab[t&NQ])==3){
2838 do_byte3(f,"lda",&p->q1,to);
2839 do_byte3(f,"sta",&p->z,t);
2840 }
2841 if(zm2l(sizetab[t&NQ])>=2){
2842 load_hibyte(f,&p->q1,to);
2843 store_hibyte(f,&p->z,t);
2844 }
2845 load_lobyte(f,&p->q1,to);
2846 store_lobyte(f,&p->z,t);
2847 continue;
2848 }
2849 if(ISSHORT(to)){
2850 if((t&UNSIGNED)||ISFPOINTER(t))
2851 get_acc(f,p,CHAR);
2852 else
2853 get_acc(f,p,SHORT);
2854 load_lobyte(f,&p->q1,to);
2855 store_lobyte(f,&p->z,t);
2856 load_hibyte(f,&p->q1,to);
2857 store_hibyte(f,&p->z,t);
2858 if(ISFPOINTER(t)){
2859 int b=-1;
2860 if((p->q1.flags&(VARADR|DREFOBJ))==VARADR) b=bank(p->q1.v);
2861 emit(f,"\tlda\t#%d\n",b>=0?b:bankcnum);
2862 do_byte3(f,"sta",&p->z,t);
2863 continue;
2864 }
2865 if(to&UNSIGNED){
2866 emit(f,"\tlda\t#0\n");
2867 do_byte3(f,"sta",&p->z,t);
2868 do_byte4(f,"sta",&p->z,t);
2869 }else{
2870 emit(f,"\tldx\t#0\n");
2871 emit(f,"\tcmp\t#0\n");
2872 emit(f,"\tbpl\t%s%d\n",labprefix,++label);
2873 emit(f,"\tdex\n");
2874 emit(f,"%s%d:\n",labprefix,label);
2875 if(indirect(&p->z)){
2876 emit(f,"\ttxa\n");
2877 do_byte3(f,"sta",&p->z,t);
2878 do_byte4(f,"sta",&p->z,t);
2879 }else{
2880 do_byte3(f,"stx",&p->z,t);
2881 do_byte4(f,"stx",&p->z,t);
2882 }
2883 }
2884 continue;
2885 }
2886 if(ISCHAR(to)){
2887 if(to&UNSIGNED){
2888 get_acc(f,p,CHAR);
2889 if(ISLONG(t)){
2890 load_lobyte(f,&p->q1,to);
2891 store_lobyte(f,&p->z,t);
2892 emit(f,"\tlda\t#0\n");
2893 store_hibyte(f,&p->z,t);
2894 do_byte3(f,"sta",&p->z,t);
2895 if(ISLONG(t))
2896 do_byte4(f,"sta",&p->z,t);
2897 continue;
2898 }
2899 if(isacc(z))
2900 emit(f,"\tldx\t#0\n");
2901 else if(isacc(q1)){
2902 emit(f,"\tldx\t#0\n");
2903 store_acc(f,&p->z,t);
2904 continue;
2905 }else{
2906 emit(f,"\tlda\t#0\n");
2907 store_hibyte(f,&p->z,t);
2908 }
2909 load_lobyte(f,&p->q1,to);
2910 store_lobyte(f,&p->z,t);
2911 }else{
2912 int l=++label;
2913 get_acc(f,p,SHORT);
2914 emit(f,"\tldx\t#0\n");
2915 if(isreg(q1)&&p->q1.reg==ra)
2916 emit(f,"\tcmp\t#0\n");
2917 else
2918 load_lobyte(f,&p->q1,to);
2919 emit(f,"\tbpl\t%s%d\n",labprefix,label);
2920 emit(f,"\tdex\n");
2921 emit(f,"%s%d:\n",labprefix,label);
2922 store_lobyte(f,&p->z,t);
2923 if(indirect(&p->z)){
2924 emit(f,"\ttxa\n");
2925 store_hibyte(f,&p->z,t);
2926 if(ISLONG(t)){
2927 do_byte3(f,"sta",&p->z,t);
2928 do_byte4(f,"sta",&p->z,t);
2929 }
2930 }else{
2931 if(!isreg(z)||p->z.reg!=rax){
2932 emit(f,"\tstx\t");
2933 emit_hibyte(f,&p->z,t);
2934 emit(f,"\n");
2935 }
2936 if(ISLONG(t)){
2937 do_byte3(f,"stx",&p->z,t);
2938 do_byte4(f,"stx",&p->z,t);
2939 }
2940 }
2941 }
2942 if(ISFPOINTER(t)){
2943 emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
2944 do_byte3(f,"sta",&p->z,t);
2945 }
2946 continue;
2947 }
2948 if(ISFPOINTER(to)){
2949 get_acc(f,p,CHAR);
2950 if(zm2l(sizetab[t&NQ])>=3){
2951 do_byte3(f,"lda",&p->q1,to);
2952 do_byte3(f,"sta",&p->z,t);
2953 }
2954 if(zm2l(sizetab[t&NQ])>=2){
2955 load_hibyte(f,&p->q1,to);
2956 store_hibyte(f,&p->z,t);
2957 }
2958 load_lobyte(f,&p->q1,to);
2959 store_lobyte(f,&p->z,t);
2960
2961 continue;
2962 }
2963 ierror(0);
2964 }
2965
2966 if(c==KOMPLEMENT){
2967 get_acc(f,p,CHAR);
2968 if(ISCHAR(t)){
2969 load_acc(f,&p->q1,t);
2970 emit(f,"\teor\t#-1\n");
2971 store_acc(f,&p->z,t);
2972 }else{
2973 if(isacc(q1))
2974 emit(f,"\tpha\n");
2975 if(ISLONG(t)){
2976 do_byte4(f,"lda",&p->q1,t);
2977 emit(f,"\teor\t#-1\n");
2978 do_byte4(f,"sta",&p->z,t);
2979 do_byte3(f,"lda",&p->q1,t);
2980 emit(f,"\teor\t#-1\n");
2981 do_byte3(f,"sta",&p->z,t);
2982 }
2983 load_hibyte(f,&p->q1,t);
2984 emit(f,"\teor\t#-1\n");
2985 store_hibyte(f,&p->z,t);
2986 if(isacc(q1))
2987 emit(f,"\tpla\n");
2988 load_lobyte(f,&p->q1,t);
2989 emit(f,"\teor\t#-1\n");
2990 store_lobyte(f,&p->z,t);
2991 }
2992 continue;
2993 }
2994 if(c==SETRETURN){
2995 t&=NQ;
2996 if(isreg(q1)&&p->q1.reg==p->z.reg) continue;
2997 if(t==LONG||t==LLONG||ISFLOAT(t)||ISFPOINTER(t)){
2998 long l=zm2l(p->q2.val.vmax);
2999 int zr=p->z.reg;
3000 //get_acc(f,p,t);
3001 if((optsize||l>4)&&!ISFPOINTER(t)){
3002 int ind=indirect(&p->q1);
3003 if(ind) load_address(f,LAST_PAIR,&p->q1,t);
3004 BSET(regused,t3);
3005 BSET(regused,t4);
3006 sety(f,l-1);
3007 emit(f,"%s%d:\n",labprefix,++label);
3008 if(ind)
3009 emit(f,"\tlda\t(%s),y\n",mregnames[LAST_PAIR]);
3010 else{
3011 emit(f,"\tlda\t");
3012 if(!ISFLOAT(t)&&(p->q1.flags&(KONST|DREFOBJ))==KONST){
3013 emit(f,"%s%d",labprefix,addfpconst(&p->q1,t));
3014 }else
3015 emit_obj(f,&p->q1,t);
3016 emit(f,",y\n");
3017 }
3018 emit(f,"\tsta\t%s,y\n",mregnames[zr]);
3019 emit(f,"\tdey\n");
3020 emit(f,"\tbpl\t%s%d\n",labprefix,label);
3021 yval=255;
3022 }else{
3023 if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
3024 if(p->q1.reg==zr){
3025 int r=get_reg(f,p,POINTER);
3026 if(r==FIRST_PAIR||r==FIRST_PAIR+1)
3027 ierror(0);
3028 if(!reg_pair(r,&rp2)) ierror(0);
3029 emit(f,"\tlda\t%s\n",mregnames[zr]);
3030 emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
3031 emit(f,"\tlda\t%s+1\n",mregnames[zr]);
3032 emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
3033 p->q1.reg=r;
3034 }
3035 }
3036 load_lobyte(f,&p->q1,t);
3037 emit(f,"\tsta\t%s\n",mregnames[zr]);
3038 load_hibyte(f,&p->q1,t);
3039 emit(f,"\tsta\t%s+1\n",mregnames[zr]);
3040 do_byte3(f,"lda",&p->q1,t);
3041 emit(f,"\tsta\t%s+2\n",mregnames[zr]);
3042 if(!ISFPOINTER(t)){
3043 do_byte4(f,"lda",&p->q1,t);
3044 emit(f,"\tsta\t%s+3\n",mregnames[zr]);
3045 }
3046 /*TODO:regused OLDFP */
3047 regused[zr]=1;
3048 }
3049 continue;
3050 }
3051 //get_acc(f,p,t);
3052 load_acc(f,&p->q1,t);
3053 regused[ra]=1;
3054 regused[rx]=1;
3055 continue;
3056 }
3057 if(c==GETRETURN){
3058 t&=NQ;
3059 if(isreg(z)&&p->q1.reg==p->z.reg) continue;
3060 if(t==LONG||t==LLONG||ISFLOAT(t)||ISFPOINTER(t)){
3061 long l=zm2l(p->q2.val.vmax);
3062 int qr=p->q1.reg;
3063 if((optsize||l>4)&&!ISFPOINTER(t)){
3064 int ind=indirect(&p->z);
3065 if(ind) load_address(f,LAST_PAIR,&p->z,t);
3066 BSET(regused,t3);
3067 BSET(regused,t4);
3068 sety(f,l-1);
3069 emit(f,"%s%d:\n",labprefix,++label);
3070 emit(f,"\tlda\t%s,y\n",mregnames[qr]);
3071 if(ind)
3072 emit(f,"\tsta\t(%s),y\n",mregnames[LAST_PAIR]);
3073 else{
3074 emit(f,"\tsta\t");
3075 emit_obj(f,&p->z,t);
3076 emit(f,",y\n");
3077 }
3078 emit(f,"\tdey\n");
3079 emit(f,"\tbpl\t%s%d\n",labprefix,label);
3080 yval=255;
3081 }else{
3082 if((p->z.reg&(REG|DREFOBJ))==(REG|DREFOBJ)){
3083 if(p->z.reg==qr) ierror(0);
3084 }
3085 emit(f,"\tlda\t%s\n",mregnames[qr]);
3086 store_lobyte(f,&p->z,t);
3087 emit(f,"\tlda\t%s+1\n",mregnames[qr]);
3088 store_hibyte(f,&p->z,t);
3089 emit(f,"\tlda\t%s+2\n",mregnames[qr]);
3090 do_byte3(f,"sta",&p->z,t);
3091 if(!ISFPOINTER(t)){
3092 emit(f,"\tlda\t%s+3\n",mregnames[qr]);
3093 do_byte4(f,"sta",&p->z,t);
3094 }
3095 }
3096 continue;
3097 }
3098 if(p->q1.reg)
3099 store_acc(f,&p->z,t);
3100 continue;
3101 }
3102 if(c==CALL){
3103 int reg;
3104
3105 if(argsize<zm2l(p->q2.val.vmax)) argsize=zm2l(p->q2.val.vmax);
3106
3107 /*FIXME*/
3108#if 0
3109 if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK)){
3110 if(framesize+zum2ul(p->q1.v->fi->stack1)>stack)
3111 stack=framesize+zum2ul(p->q1.v->fi->stack1);
3112 }else
3113 stack_valid=0;
3114#endif
3115 if((p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp("__va_start",p->q1.v->identifier)){
3116 long of=va_offset(v)+localsize+rsavesize+argsize;
3117 emit(f,"\tlda\t%s\n",mregnames[fp]);
3118 if(of){
3119 emit(f,"\tclc\n");
3120 if(of&255)
3121 emit(f,"\tadc\t#%d\n",(of&255));
3122 }
3123 emit(f,"\tldx\t%s+1\n",mregnames[fp]);
3124 if(of&0xff00){
3125 emit(f,"\tpha\n");
3126 emit(f,"\ttxa\n");
3127 emit(f,"\tadc\t#%d\n",(of>>8)&255);
3128 emit(f,"\ttax\n");
3129 emit(f,"\tpla\n");
3130 }else if(of){
3131 emit(f,"\tbcc\t%s%d\n",labprefix,++label);
3132 emit(f,"\tinx\n");
3133 emit(f,"%s%d:\n",labprefix,label);
3134 }
3135 continue;
3136 }
3137 if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
3138 emit(f,";startinline\n");
3139 emit_inline_asm(f,p->q1.v->fi->inline_asm);
3140 emit(f,";endinline\n");
3141 }else if(p->q1.flags&DREFOBJ){
3142 if(ISFPOINTER(p->q1.dtyp)){
3143 p->q1.flags&=~DREFOBJ;
3144 load_reg(f,LAST_PAIR,&p->q1,POINTER);
3145 if(indirect(&p->q1)){
3146 do_byte3(f,"lda",&p->q1,FPOINTER);
3147 emit(f,"\ttay\n");
3148 }else
3149 do_byte3(f,"ldy",&p->q1,FPOINTER);
3150 emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
3151 emit(f,"\tjsr\t%s__bankjsr\n",idprefix);
3152 yval=NOVAL;
3153 }else{
3154 if(!(p->q1.flags&REG)) ierror(0);
3155 emit(f,"\tjsr\t%s%d\n",labprefix,++label);
3156 yval=NOVAL;
3157 add_cmplist(label,p->q1.reg,JMPIND);
3158 }
3159 }else{
3160 int tbank=-1;
3161 if(p->q1.flags&VAR) tbank=bank(p->q1.v);
3162 if(tbank!=cbank&&tbank>=0){
3163 if(cbank>=0){
3164 load_address(f,LAST_PAIR,&p->q1,t);
3165 sety(f,tbank);
3166 emit(f,"\tlda\t#%d\n",cbank);
3167 emit(f,"\tjsr\t%s__bankjsr\n",idprefix);
3168 yval=NOVAL;
3169 continue;
3170 }
3171 sety(f,tbank);
3172 emit(f,"\tjsr\t%s__bankswitch\n",idprefix);
3173 yval=NOVAL;
3174 }
3175 if((p->q1.flags&VAR)&&!strcmp(p->q1.v->identifier,"_fmemcpy"))
3176 emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
3177 emit(f,"\tjsr\t");
3178 emit_obj(f,&p->q1,t);
3179 emit(f,"\n");
3180 }
3181 pushed-=zm2l(p->q2.val.vmax);
3182 if(!calc_regs(p,f!=0)&&v->fi) v->fi->flags&=~ALL_REGS;
3183 yval=NOVAL;
3184 continue;
3185 }
3186 if(c==ASSIGN||c==PUSH){
3187 if(t==0) ierror(0);
3188 if((p->q1.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)==LLONG){
3189 int i;
3190 eval_const(&p->q1.val,t);
3191 for(i=0;i<8;i++){
3192 emit(f,"\tlda\t#%d\n",zm2l(vmax)&255);
3193 vmax=zmrshift(vmax,l2zm(8L));
3194 if(c==PUSH||(p->z.flags&DREFOBJ)){
3195 sety(f,i+((c==PUSH)?pushed:0));
3196 emit(f,"\tsta\t(%s),y\n",(c==PUSH)?mregnames[sp]:mregnames[p->z.reg]);
3197 }else{
3198 p->z.val.vmax=zmadd(p->z.val.vmax,l2zm((long)i));
3199 emit(f,"\tsta\t");
3200 emit_lobyte(f,&p->z,t);
3201 emit(f,"\n");
3202 p->z.val.vmax=zmsub(p->z.val.vmax,l2zm((long)i));
3203 }
3204 }
3205 if(c==PUSH) pushed+=8;
3206 continue;
3207 }
3208
3209 if(!zmleq(p->q2.val.vmax,l2zm(4L))){
3210 long len=zm2l(p->q2.val.vmax);
3211 int r1,r2,loops,looplab;
3212 if(len>32767) ierror(0);
3213 if(!NOBANKVARS){
3214 int bq=-1,bz=-1,s=-1;
3215 if((p->q1.flags&(VAR|DREFOBJ))==VAR) bq=bank(p->q1.v);
3216 if((p->z.flags&(VAR|DREFOBJ))==VAR) bz=bank(p->z.v);
3217 if(((p->q1.flags&DREFOBJ)&&ISFPOINTER(p->q1.dtyp))||
3218 ((p->z.flags&DREFOBJ)&&ISFPOINTER(p->z.dtyp))){
3219 far_copy(f,p);
3220 continue;
3221 }
3222 if(cbank<0){
3223 if(bq>=0&&bz>=0){
3224 if(bq!=bz){
3225 far_copy(f,p);
3226 continue;
3227 }
3228 s=bq;
3229 }else{
3230 if(bq>=0) s=bq;
3231 if(bz>=0) s=bz;
3232 }
3233 if(s>=0){
3234 sety(f,s);
3235 emit(f,"\tjsr\t%s__bankswitch\n",idprefix);
3236 yval=NOVAL;
3237 }
3238 }else{
3239 if((bq>=0&&bq!=cbank)||(bz>=0&&bz!=cbank)){
3240 far_copy(f,p);
3241 continue;
3242 }
3243 }
3244 }
3245 get_acc(f,p,CHAR);
3246 if((p->q1.flags&(DREFOBJ|KONST))==DREFOBJ){
3247 if(p->q1.flags&REG){
3248 r1=p->q1.reg;
3249 if(!reg_pair(r1,&rp)) ierror(0);
3250 if(len>128){
3251 emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
3252 emit(f,"\tclc\n");
3253 if(len&128)
3254 emit(f,"\tadc\t#128\n");
3255 emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
3256 if(len>255){
3257 emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
3258 emit(f,"\tadc\t#%ld\n",(len>>8)&255);
3259 emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
3260 }else{
3261 emit(f,"\tbcc\t%s%d\n",labprefix,++label);
3262 emit(f,"\tinc\t%s\n",mregnames[rp.r2]);
3263 emit(f,"%s%d:\n",labprefix,label);
3264 }
3265 }
3266 }else
3267 ierror(0);
3268 }else if(!indirect(&p->q1)&&len<=128&&(p->q1.flags&(DREFOBJ|KONST))!=KONST){
3269 r1=0;
3270 }else{
3271 Var *v=p->q1.v;
3272 /*if((p->q1.flags&(VARADR|VAR))!=VAR) ierror(0);*/
3273 r1=get_reg(f,p,POINTER);
3274 if(len>128) p->q1.val.vmax=zmadd(p->q1.val.vmax,l2zm(len&0xff80));
3275 load_address(f,r1,&p->q1,t);
3276 if(len>128) p->q1.val.vmax=zmsub(p->q1.val.vmax,l2zm(len&0xff80));
3277 }
3278 if((p->z.flags&(DREFOBJ|KONST))==DREFOBJ){
3279 if(p->z.flags&REG){
3280 r2=p->z.reg;
3281 if(!reg_pair(r2,&rp)) ierror(0);
3282 if(len>128){
3283 emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
3284 emit(f,"\tclc\n");
3285 if(len&128)
3286 emit(f,"\tadc\t#128\n");
3287 emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
3288 if(len>255){
3289 emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
3290 emit(f,"\tadc\t#%ld\n",(len>>8)&255);
3291 emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
3292 }else{
3293 emit(f,"\tbcc\t%s%d\n",labprefix,++label);
3294 emit(f,"\tinc\t%s\n",mregnames[rp.r2]);
3295 emit(f,"%s%d:\n",labprefix,label);
3296 }
3297 }
3298 }else
3299 ierror(0);
3300 }else if(c==PUSH){
3301 if(len<=128&&pushed==0){
3302 r2=sp;
3303 }else{
3304 r2=get_reg(f,p,POINTER);
3305 if(!reg_pair(r2,&rp)) ierror(0);
3306 emit(f,"\tlda\t%s\n",mregnames[sp]);
3307 emit(f,"\tclc\n");
3308 if(((pushed+(len&128))&255)!=0)
3309 emit(f,"\tadc\t#%ld\n",(pushed+(len&128))&255);
3310 emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
3311 emit(f,"\tlda\t%s\n",mregnames[sp2]);
3312 emit(f,"\tadc\t#%ld\n",((pushed+len)>>8)&255);
3313 emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
3314 }
3315 }else if(!indirect(&p->z)&&len<=128){
3316 r2=0;
3317 }else{
3318 Var *v=p->z.v;
3319 r2=get_reg(f,p,POINTER);
3320 if(len>128) p->z.val.vmax=zmadd(p->z.val.vmax,l2zm(len&0xff80));
3321 load_address(f,r2,&p->z,t);
3322 if(len>128) p->z.val.vmax=zmsub(p->z.val.vmax,l2zm(len&0xff80));
3323 }
3324 if(len>128){
3325 get_acc(f,p,POINTER); /* get x */
3326 emit(f,"\tldx\t#%ld\n",((len>>7)+1)&255);
3327 }
3328 sety(f,(len-1)&127);
3329 if((optsize&&len>4)||len>8){
3330 emit(f,"%s%d:\n",labprefix,looplab=++label);
3331 if(optsize)
3332 loops=1;
3333 else{
3334 if((len&3)==0)
3335 loops=4;
3336 else if((len&1)==0)
3337 loops=2;
3338 else
3339 loops=1;
3340 }
3341 }else
3342 loops=len;
3343 if(r1&&!reg_pair(r1,&rp)) ierror(0);
3344 if(r2&&!reg_pair(r2,&rp2)) ierror(0);
3345 for(i=0;i<loops;i++){
3346 if(r1)
3347 emit(f,"\tlda\t(%s),y\n",mregnames[rp.r1]);
3348 else{
3349 emit(f,"\tlda\t");
3350 emit_obj(f,&p->q1,t);
3351 emit(f,",y\n");
3352 }
3353 if(r2)
3354 emit(f,"\tsta\t(%s),y\n",mregnames[rp2.r1]);
3355 else{
3356 emit(f,"\tsta\t");
3357 emit_obj(f,&p->z,t);
3358 emit(f,",y\n");
3359 }
3360 emit(f,"\tdey\n");
3361 }
3362 if(loops!=len){
3363 emit(f,"\tbpl\t%s%d\n",labprefix,label);
3364 }
3365 if(len>128){
3366 emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
3367 emit(f,"\tsec\n");
3368 emit(f,"\tsbc\t#128\n");
3369 emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
3370 emit(f,"\tbcs\t%s%d\n",labprefix,++label);
3371 emit(f,"\tdec\t%s\n",mregnames[rp.r2]);
3372 emit(f,"%s%d:\n",labprefix,label);
3373 emit(f,"\tlda\t%s\n",mregnames[rp2.r1]);
3374 emit(f,"\tsec\n");
3375 emit(f,"\tsbc\t#128\n");
3376 emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
3377 emit(f,"\tbcs\t%s%d\n",labprefix,++label);
3378 emit(f,"\tdec\t%s\n",mregnames[rp2.r2]);
3379 emit(f,"%s%d:\n",labprefix,label);
3380 emit(f,"\tldy\t#127\n");
3381 emit(f,"\tdex\n");
3382 emit(f,"\tbne\t%s%d\n",labprefix,looplab);
3383 }
3384 yval=NOVAL;
3385 if(c==PUSH)
3386 pushed+=zm2l(p->q2.val.vmax);
3387 continue;
3388 }
3389 if(c==PUSH){
3390 get_acc(f,p,CHAR);
3391 load_lobyte(f,&p->q1,t);
3392 sety(f,pushed);
3393 emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
3394 if(!zmleq(p->q2.val.vmax,Z1)){
3395 load_hibyte(f,&p->q1,t);
3396 sety(f,pushed+1);
3397 emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
3398 }
3399 if(!zmleq(p->q2.val.vmax,l2zm(2L))){
3400 do_byte3(f,"lda",&p->q1,t);
3401 sety(f,pushed+2);
3402 emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
3403 }
3404 if(!zmleq(p->q2.val.vmax,l2zm(3L))){
3405 do_byte4(f,"lda",&p->q1,t);
3406 sety(f,pushed+3);
3407 emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
3408 }
3409
3410 pushed+=zm2l(p->q2.val.vmax);
3411 continue;
3412 }
3413 if(c==ASSIGN){
3414 if(isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg) continue;
3415 if(isacc(q1)){
3416 if(p->q1.reg==rax) get_acc(f,p,CHAR);
3417 store_acc(f,&p->z,t);
3418 continue;
3419 }
3420 get_acc(f,p,CHAR);
3421 if(0/*ISCHAR(t)*/){
3422 load_acc(f,&p->q1,t);
3423 store_acc(f,&p->z,t);
3424 }else{
3425 // TODO: PGS: Use AXYZ for 32-bit copy if appropriate
3426 // TOGO: PGS: Consider using AXYZ for load, even for 16 or 24-bit values
3427 if(!zmleq(p->q2.val.vmax,l2zm(3L))){
3428 do_byte4(f,"lda",&p->q1,t);
3429 do_byte4(f,"sta",&p->z,t);
3430 }
3431 if(!zmleq(p->q2.val.vmax,l2zm(2L))){
3432 do_byte3(f,"lda",&p->q1,t);
3433 do_byte3(f,"sta",&p->z,t);
3434 }
3435 if(!zmleq(p->q2.val.vmax,l2zm(1L))){
3436 load_hibyte(f,&p->q1,t);
3437 store_hibyte(f,&p->z,t);
3438 }
3439 load_lobyte(f,&p->q1,t);
3440 store_lobyte(f,&p->z,t);
3441 }
3442 }
3443 continue;
3444 }
3445 if(c==ADDRESS){
3446 long o=real_offset(&p->q1);
3447 get_acc(f,p,CHAR);
3448 emit(f,"\tlda\t%s\n",mregnames[fp1]);
3449 if(o){
3450 emit(f,"\tclc\n");
3451 if((o&255)!=0)
3452 emit(f,"\tadc\t#%ld\n",real_offset(&p->q1)&255);
3453 }
3454 store_lobyte(f,&p->z,t);
3455 if(isacc(z)) emit(f,"\tpha\n");
3456 emit(f,"\tlda\t%s\n",mregnames[fp2]);
3457 if(o!=0)
3458 emit(f,"\tadc\t#%ld\n",real_offset(&p->q1)>>8&255);
3459 store_hibyte(f,&p->z,t);
3460 if(isacc(z)) emit(f,"\tpla\n");
3461 continue;
3462 }
3463
3464 if(c==COMPARE||c==TEST){
3465 IC *branch=p->next;
3466 int pacc=0,bc,bout;
3467 while(branch){
3468 if(branch->code>=BEQ&&branch->code<BRA)
3469 break;
3470 if(branch->code!=FREEREG&&branch->code!=ALLOCREG&&branch->code!=NOP)
3471 ierror(0);
3472 branch=branch->next;
3473 }
3474 bc=branch->code;
3475 bout=branch->typf;
3476 if(c==TEST){
3477 p->q2.flags=KONST;
3478 gval.vmax=Z0;
3479 eval_const(&gval,MAXINT);
3480 insert_const(&p->q2.val,t);
3481 }
3482 if(ieee&&ISFLOAT(t)){
3483 if(!ieee) ierror(0);
3484 t&=NQ;
3485 if(regs[LAST_PAIR]) ierror(0);
3486 regs[LAST_PAIR]=1;
3487 if(regs[ra]||regs[rax])
3488 ierror(0);
3489 load_address(f,LAST_PAIR,&p->q2,t);
3490 BSET(regused,t3);
3491 BSET(regused,t4);
3492 emit(f,"\tjsr\t%s__fload%c\n",idprefix,(t==FLOAT?'s':'d'));
3493 yval=NOVAL;
3494 load_address(f,LAST_PAIR,&p->q1,t);
3495 emit(f,"\tjsr\t%s__fcmp%c\n",idprefix,(t==FLOAT?'s':'d'));
3496 yval=NOVAL;
3497 regs[LAST_PAIR]=0;
3498 if(bc==BLT||bc==BLE)
3499 emit(f,"\tbmi\t%s%d\n",labprefix,bout);
3500 else if(bc==BGT|bc==BGE)
3501 emit(f,"\tbvs\t%s%d\n",labprefix,bout);
3502 if(bc==BEQ||bc==BLE||bc==BGE)
3503 emit(f,"\tbeq\t%s%d\n",labprefix,bout);
3504 if(bc==BNE)
3505 emit(f,"\tbne\t%s%d\n",labprefix,bout);
3506 continue;
3507 }
3508 if(ISCHAR(t)){
3509 char *s;
3510 if(pacc=cmp_get_acc(f,p,branch))
3511 bout=++label;
3512 load_acc(f,&p->q1,t);
3513 if(bc==BEQ||bc==BNE||(t&UNSIGNED)){
3514 s="cmp";
3515 }else{
3516 if(bc==BLT||bc==BGE)
3517 emit(f,"\tsec\n");
3518 else
3519 emit(f,"\tclc\n");
3520 s="sbc";
3521 }
3522 if(c==TEST)
3523 emit(f,"\t%s\t#0\n",s);
3524 else
3525 do_lobyte(f,s,&p->q2,t);
3526 if(bc==BEQ)
3527 emit(f,"\tbeq\t%s%d\n",labprefix,bout);
3528 else if(bc==BNE)
3529 emit(f,"\tbne\t%s%d\n",labprefix,bout);
3530 else if(t&UNSIGNED){
3531 if(bc==BLT)
3532 emit(f,"\tbcc\t%s%d\n",labprefix,bout);
3533 else if(bc==BGE)
3534 emit(f,"\tbcs\t%s%d\n",labprefix,bout);
3535 else if(bc==BLE){
3536 emit(f,"\tbcc\t%s%d\n",labprefix,bout);
3537 emit(f,"\tbeq\t%s%d\n",labprefix,bout);
3538 }else if(bc==BGT){
3539 emit(f,";\n\tbeq\t%s%d\n",labprefix,++label);
3540 emit(f,"\tbcs\t%s%d\n",labprefix,bout);
3541 emit(f,"%s%d:\n",labprefix,label);
3542 }else
3543 ierror(0);
3544 }else{
3545 emit(f,"\tbvc\t%s%d\n",labprefix,++label);
3546 emit(f,"\teor\t#128\n");
3547 emit(f,"%s%d:\n",labprefix,label);
3548 if(bc==BLT||bc==BLE)
3549 emit(f,"\tbmi\t%s%d\n",labprefix,bout);
3550 else
3551 emit(f,"\tbpl\t%s%d\n",labprefix,bout);
3552 }
3553 if(pacc){
3554 reload_acc(f);
3555 add_cmplist(bout,branch->typf,pacc);
3556 }
3557 continue;
3558 }else if(bc==BEQ||bc==BNE||(t&UNSIGNED)||ISFPOINTER(t)){
3559 int in=0;
3560 if(pacc=cmp_get_acc(f,p,branch))
3561 bout=++label;
3562
3563 // PGS Check for special cases of comparing to constants
3564 if(!(ISLONG(t)||ISFPOINTER(t)||isacc(q1))) {
3565 // Is a 16-bit value
3566 if (p->q2.flags&KONST) {
3567 if (!(p->q2.flags&DREFOBJ)) {
3568 eval_const(&p->q2.val,t);
3569 if(ISFLOAT(t)) cnv_fp();
3570 if (zm2l(vmax)==0x100) {
3571 if (bc==BGE) {
3572 // >= $100 we can check by just reading the 2nd byte
3573 // If non-zero, then we take the branch
3574 do_hibyte(f,"lda",&p->q1,t);
3575 emit(f,"\tbne\t%s%d\n",labprefix,bout);
3576 continue;
3577 } else if (bc==BLT) {
3578 // <$100 we can check by just reading the 2nd byte
3579 // And if zero, then we take the branch
3580 do_hibyte(f,"lda",&p->q1,t);
3581 emit(f,"\tbeq\t%s%d\n",labprefix,bout);
3582 continue;
3583 }
3584 } else if (zm2l(vmax)<0x100) {
3585 // Values <$100 we can do almost as simply, but we have to
3586 // also check the low byte for exceptions.
3587 // XXX PGS TODO
3588
3589 }
3590 }
3591 }
3592 }
3593
3594 // Far-Pointers are 32-bit on M65
3595 if(ISLONG(t)||ISFPOINTER(t)){
3596 do_byte4(f,"lda",&p->q1,t);
3597 if(c==TEST)
3598 emit(f,"\tcmp\t#0\n");
3599 else
3600 do_byte4(f,"cmp",&p->q2,t);
3601 if(bc==BEQ)
3602 emit(f,"\tbne\t%s%d\n",labprefix,in=++label);
3603 else if(bc==BNE)
3604 emit(f,"\tbne\t%s%d\n",labprefix,bout);
3605 else if(bc==BLT||bc==BLE){
3606 emit(f,"\tbcc\t%s%d\n",labprefix,bout);
3607 emit(f,"\tbne\t%s%d\n",labprefix,in=++label);
3608 }else if(bc==BGE||bc==BGT){
3609 emit(f,"\tbcc\t%s%d\n",labprefix,in=++label);
3610 emit(f,"\tbne\t%s%d\n",labprefix,bout);
3611 }else
3612 ierror(0);
3613 }
3614 if(ISLONG(t)||ISFPOINTER(t)){
3615 do_byte3(f,"lda",&p->q1,t);
3616 if(c==TEST)
3617 emit(f,"\tcmp\t#0\n");
3618 else
3619 do_byte3(f,"cmp",&p->q2,t);
3620 if(bc==BEQ)
3621 emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
3622 else if(bc==BNE)
3623 emit(f,"\tbne\t%s%d\n",labprefix,bout);
3624 else if(bc==BLT||bc==BLE){
3625 emit(f,"\tbcc\t%s%d\n",labprefix,bout);
3626 emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
3627 }else if(bc==BGE||bc==BGT){
3628 emit(f,"\tbcc\t%s%d\n",labprefix,in?in:(in=++label));
3629 emit(f,"\tbne\t%s%d\n",labprefix,bout);
3630 }else
3631 ierror(0);
3632 }
3633 if(isacc(q1)){
3634 if(!indirect(&p->q2)){
3635 do_hibyte(f,"cpx",&p->q2,t);
3636 }else{
3637 int r=get_reg(f,p,CHAR);
3638 emit(f,"\tpha\n");
3639 load_hibyte(f,&p->q2,t);
3640 emit(f,"\tsta\t%s\n",mregnames[r]);
3641 emit(f,"\tpla\n");
3642 emit(f,"\tcpx\t%s\n",mregnames[r]);
3643 }
3644 }else{
3645 load_hibyte(f,&p->q1,t);
3646 if(c==TEST)
3647 emit(f,"\tcmp\t#0\n");
3648 else
3649 do_hibyte(f,"cmp",&p->q2,t);
3650 }
3651 if(bc==BEQ)
3652 emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
3653 else if(bc==BNE)
3654 emit(f,"\tbne\t%s%d\n",labprefix,bout);
3655 else if(bc==BLT||bc==BLE){
3656 emit(f,"\tbcc\t%s%d\n",labprefix,bout);
3657 emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
3658 }else if(bc==BGE||bc==BGT){
3659 emit(f,"\tbcc\t%s%d\n",labprefix,in?in:(in=++label));
3660 emit(f,"\tbne\t%s%d\n",labprefix,bout);
3661 }else
3662 ierror(0);
3663 load_lobyte(f,&p->q1,t);
3664 if(c==TEST)
3665 emit(f,"\tcmp\t#0\n");
3666 else
3667 do_lobyte(f,"cmp",&p->q2,t);
3668 if(bc==BEQ)
3669 emit(f,"\tbeq\t%s%d\n",labprefix,bout);
3670 else if(bc==BNE)
3671 emit(f,"\tbne\t%s%d\n",labprefix,bout);
3672 else if(bc==BLT)
3673 emit(f,"\tbcc\t%s%d\n",labprefix,bout);
3674 else if(bc==BGE)
3675 emit(f,"\tbcs\t%s%d\n",labprefix,bout);
3676 else if(bc==BLE){
3677 emit(f,"\tbcc\t%s%d\n",labprefix,bout);
3678 emit(f,"\tbeq\t%s%d\n",labprefix,bout);
3679 }else if(bc==BGT){
3680 emit(f,"\tbcc\t%s%d\n",labprefix,in);
3681 emit(f,"\tbne\t%s%d\n",labprefix,bout);
3682 }else
3683 ierror(0);
3684 if(in)
3685 emit(f,"%s%d:\n",labprefix,in);
3686 if(pacc){
3687 reload_acc(f);
3688 add_cmplist(bout,branch->typf,pacc);
3689 }
3690 continue;
3691 }else{
3692 if(bc==BGT||bc==BLE){
3693 obj o;
3694 if(isacc(q1)){
3695 int r;
3696 if(pacc=cmp_get_acc(f,p,branch))
3697 bout=++label;
3698 r=get_reg(f,p,CHAR);
3699 emit(f,"\tsta\t%s\n",mregnames[r]);
3700 load_lobyte(f,&p->q2,t);
3701 emit(f,"\tcmp\t%s\n",mregnames[r]);
3702 emit(f,"\tstx\t%s\n",mregnames[r]);
3703 load_hibyte(f,&p->q2,t);
3704 emit(f,"\tsbc\t%s\n",mregnames[r]);
3705 emit(f,"\tbvc\t%s%d\n",labprefix,++label);
3706 emit(f,"\teor\t#128\n");
3707 emit(f,"%s%d:\n",labprefix,label);
3708 if(bc==BGT)
3709 emit(f,"\tbmi\t%s%d\n",labprefix,bout);
3710 else
3711 emit(f,"\tbpl\t%s%d\n",labprefix,bout);
3712 if(pacc){
3713 reload_acc(f);
3714 add_cmplist(bout,branch->typf,pacc);
3715 }
3716 continue;
3717 }else{
3718 o=p->q1;p->q1=p->q2;p->q2=o;
3719 if(bc==BGT) bc=BLT; else bc=BGE;
3720 }
3721 }
3722 if(pacc=cmp_get_acc(f,p,branch))
3723 bout=++label;
3724 if(ISLONG(t)){
3725 load_lobyte(f,&p->q1,t);
3726 do_lobyte(f,"cmp",&p->q2,t);
3727 load_hibyte(f,&p->q1,t);
3728 do_hibyte(f,"sbc",&p->q2,t);
3729 do_byte3(f,"lda",&p->q1,t);
3730 do_byte3(f,"sbc",&p->q2,t);
3731 do_byte4(f,"lda",&p->q1,t);
3732 do_byte4(f,"sbc",&p->q2,t);
3733 }else{
3734 load_lobyte(f,&p->q1,t);
3735 do_lobyte(f,"cmp",&p->q2,t);
3736 load_hibyte(f,&p->q1,t);
3737 do_hibyte(f,"sbc",&p->q2,t);
3738 }
3739 emit(f,"\tbvc\t%s%d\n",labprefix,++label);
3740 emit(f,"\teor\t#128\n");
3741 emit(f,"%s%d:\n",labprefix,label);
3742 if(bc==BLT)
3743 emit(f,"\tbmi\t%s%d\n",labprefix,bout);
3744 else if(bc==BGE)
3745 emit(f,"\tbpl\t%s%d\n",labprefix,bout);
3746 else
3747 ierror(0);
3748 if(pacc){
3749 reload_acc(f);
3750 add_cmplist(bout,branch->typf,pacc);
3751 }
3752 continue;
3753 }
3754 ierror(0);
3755 }
3756 if((c==ADD||c==SUB||c==ADDI2P||c==SUBIFP)&&compare_objects(&p->q1,&p->z)&&!indirect(&p->q1)&&isconst(q2)&&!isacc(z)){
3757 long l;
3758 eval_const(&p->q2.val,q2typ(p));
3759 l=zm2l(vmax);
3760 if(c==ADDI2P/*&&(t2&NQ)==POINTER*/) {c=ADD;t=UNSIGNED|INT;}
3761 if(c==SUBIFP/*&&(t2&NQ)==POINTER*/) {c=SUB;t=UNSIGNED|INT;}
3762 if(c==SUB||c==SUBIFP) l=-l;
3763 /*TODO: allow larger types */
3764 if(l<3&&l>-3&&(t&NQ)<=INT){
3765 if(l<0){
3766 get_acc(f,p,CHAR);
3767 incmem(f,&p->z,t,SUB,-l);
3768 }else
3769 incmem(f,&p->z,t,ADD,l);
3770 continue;
3771 }
3772 }
3773
3774 if((c==LSHIFT||c==RSHIFT)&&isreg(q1)&&isreg(z)&&isconst(q2)&&p->q1.reg==p->z.reg&&p->z.reg!=ra&&p->z.reg!=rax){
3775 long l;
3776 eval_const(&p->q2.val,q2typ(p));
3777 l=zm2l(vmax);
3778 /*TODO: allow larger types */
3779 if(l<5&&(t&NQ)<=INT){
3780 if(c==RSHIFT&&!(t&UNSIGNED))
3781 get_acc(f,p,CHAR);
3782 incmem(f,&p->z,t,c,l);
3783 continue;
3784 }
3785 }
3786
3787 if(c==LSHIFT||c==RSHIFT){
3788 long l=-1;int loop=0,r,r2,r3,outl=0;
3789 if(isconst(q2)){
3790 eval_const(&p->q2.val,q2typ(p));
3791 l=zm2l(vmax);
3792 loop=0;
3793 }else
3794 loop=1;
3795 if(l>=0&&optsize){
3796 if(c==LSHIFT&&(l&7)>6)
3797 loop=1;
3798 else if(c==RSHIFT&&(t&UNSIGNED)&&(l&7)>3)
3799 loop=1;
3800 else if(c==RSHIFT&&!(t&UNSIGNED)&&(l&7)>2)
3801 loop=1;
3802 }
3803
3804 if(!ISCHAR(t))
3805 r=get_reg(f,p,CHAR);
3806 if(ISLONG(t)){
3807 r2=get_reg(f,p,CHAR);
3808 r3=get_reg(f,p,CHAR);
3809 }
3810 if(ISLONG(t)){
3811 get_acc(f,p,CHAR);
3812 if(l>=24){
3813 if(c==LSHIFT){
3814 load_lobyte(f,&p->q1,t);
3815 emit(f,"\tsta\t%s\n",mregnames[r3]);
3816 emit(f,"\tlda\t#0\n");
3817 emit(f,"\tsta\t%s\n",mregnames[r]);
3818 emit(f,"\tsta\t%s\n",mregnames[r2]);
3819 }else if(c==RSHIFT&&!(t&UNSIGNED)){
3820 do_byte4(f,"lda",&p->q1,t);
3821 emit(f,"\tsta\t%s\n",mregnames[r3]);
3822 sety(f,0);
3823 emit(f,"\tcmp\t#0\n");
3824 emit(f,"\tbpl\t%s%d\n",labprefix,++label);
3825 emit(f,"\tdey\n");
3826 emit(f,"%s%d:\n",labprefix,label);
3827 emit(f,"\tsty\t%s\n",mregnames[r]);
3828 emit(f,"\tsty\t%s\n",mregnames[r2]);
3829 emit(f,"\ttya\n");
3830 yval=NOVAL;
3831 }else{
3832 emit(f,"\tlda\t#0\n");
3833 emit(f,"\tsta\t%s\n",mregnames[r3]);
3834 emit(f,"\tsta\t%s\n",mregnames[r2]);
3835 emit(f,"\tsta\t%s\n",mregnames[r]);
3836 do_byte4(f,"lda",&p->q1,t);
3837
3838 }
3839 }else if(l>=16){
3840 if(c==LSHIFT){
3841 load_lobyte(f,&p->q1,t);
3842 emit(f,"\tsta\t%s\n",mregnames[r2]);
3843 load_hibyte(f,&p->q1,t);
3844 emit(f,"\tsta\t%s\n",mregnames[r3]);
3845 emit(f,"\tlda\t#0\n");
3846 emit(f,"\tsta\t%s\n",mregnames[r]);
3847 }else if(c==RSHIFT&&!(t&UNSIGNED)){
3848 do_byte3(f,"lda",&p->q1,t);
3849 emit(f,"\tsta\t%s\n",mregnames[r3]);
3850 do_byte4(f,"lda",&p->q1,t);
3851 emit(f,"\tsta\t%s\n",mregnames[r2]);
3852 sety(f,0);
3853 emit(f,"\tcmp\t#0\n");
3854 emit(f,"\tbpl\t%s%d\n",labprefix,++label);
3855 emit(f,"\tdey\n");
3856 emit(f,"%s%d:\n",labprefix,label);
3857 emit(f,"\tsty\t%s\n",mregnames[r]);
3858 emit(f,"\ttya\n");
3859 yval=NOVAL;
3860 }else{
3861 emit(f,"\tlda\t#0\n");
3862 emit(f,"\tsta\t%s\n",mregnames[r2]);
3863 emit(f,"\tsta\t%s\n",mregnames[r3]);
3864 do_byte4(f,"lda",&p->q1,t);
3865 emit(f,"\tsta\t%s\n",mregnames[r]);
3866 do_byte3(f,"lda",&p->q1,t);
3867
3868 }
3869 }else if(l>=8){
3870 if(c==LSHIFT){
3871 load_lobyte(f,&p->q1,t);
3872 emit(f,"\tsta\t%s\n",mregnames[r]);
3873 load_hibyte(f,&p->q1,t);
3874 emit(f,"\tsta\t%s\n",mregnames[r2]);
3875 do_byte3(f,"lda",&p->q1,t);
3876 emit(f,"\tsta\t%s\n",mregnames[r3]);
3877 emit(f,"\tlda\t#0\n");
3878 }else if(c==RSHIFT&&!(t&UNSIGNED)){
3879 load_hibyte(f,&p->q1,t);
3880 emit(f,"\tsta\t%s\n",mregnames[r3]);
3881 do_byte3(f,"lda",&p->q1,t);
3882 emit(f,"\tsta\t%s\n",mregnames[r2]);
3883 do_byte4(f,"lda",&p->q1,t);
3884 emit(f,"\tsta\t%s\n",mregnames[r]);
3885 sety(f,0);
3886 emit(f,"\tcmp\t#0\n");
3887 emit(f,"\tbpl\t%s%d\n",labprefix,++label);
3888 emit(f,"\tdey\n");
3889 emit(f,"%s%d:\n",labprefix,label);
3890 emit(f,"\ttya\n");
3891 yval=NOVAL;
3892 }else{
3893 emit(f,"\tlda\t#0\n");
3894 emit(f,"\tsta\t%s\n",mregnames[r3]);
3895 do_byte4(f,"lda",&p->q1,t);
3896 emit(f,"\tsta\t%s\n",mregnames[r2]);
3897 do_byte3(f,"lda",&p->q1,t);
3898 emit(f,"\tsta\t%s\n",mregnames[r]);
3899 load_hibyte(f,&p->q1,t);
3900
3901 }
3902 }else if(c==RSHIFT&&!(t&UNSIGNED)){
3903 load_lobyte(f,&p->q1,t);
3904 emit(f,"\tsta\t%s\n",mregnames[r3]);
3905 load_hibyte(f,&p->q1,t);
3906 emit(f,"\tsta\t%s\n",mregnames[r2]);
3907 do_byte3(f,"lda",&p->q1,t);
3908 emit(f,"\tsta\t%s\n",mregnames[r]);
3909 do_byte4(f,"lda",&p->q1,t);
3910 }else{
3911 do_byte4(f,"lda",&p->q1,t);
3912 emit(f,"\tsta\t%s\n",mregnames[r3]);
3913 do_byte3(f,"lda",&p->q1,t);
3914 emit(f,"\tsta\t%s\n",mregnames[r2]);
3915 load_hibyte(f,&p->q1,t);
3916 emit(f,"\tsta\t%s\n",mregnames[r]);
3917 load_lobyte(f,&p->q1,t);
3918 }
3919 }else
3920 get_acc(f,p,t);
3921 if(!ISLONG(t)){
3922 if(l>=8){
3923 if(!ISSHORT(t)) ierror(0);
3924 if(c==LSHIFT){
3925 if(indirect(&p->q1)){
3926 load_lobyte(f,&p->q1,t);
3927 emit(f,"\ttax\n");
3928 emit(f,"\tlda\t#0\n");
3929 }else{
3930 if(isacc(q1))
3931 emit(f,"\ttax\n");
3932 else
3933 do_lobyte(f,"ldx",&p->q1,t);
3934 emit(f,"\tlda\t#0\n");
3935 }
3936 }else{
3937 load_hibyte(f,&p->q1,t);
3938 emit(f,"\tldx\t#0\n");
3939 if(!(t&UNSIGNED)){
3940 emit(f,"\tcmp\t#0\n");
3941 emit(f,"\tbpl\t%s%d\n",labprefix,++label);
3942 emit(f,"\tdex\n");
3943 emit(f,"%s%d:\n",labprefix,label);
3944 }
3945 }
3946 }else
3947 load_acc(f,&p->q1,t);
3948 }
3949 if(ISSHORT(t))
3950 emit(f,"\tstx\t%s\n",mregnames[r]);
3951 if(l>=0) l&=7;
3952 if(loop){
3953 if(l>=0)
3954 sety(f,l);
3955 else{
3956 if(indirect(&p->q2)){
3957 emit(f,"\tpha\n");
3958 load_lobyte(f,&p->q2,q2typ(p));
3959 emit(f,"\ttay\n");
3960 emit(f,"\tpla\n");
3961 emit(f,"\tcpy\t#0\n");
3962 }else{
3963 emit(f,"\tldy\t");
3964 emit_lobyte(f,&p->q2,q2typ(p));
3965 emit(f,"\n");
3966 }
3967 outl=++label;
3968 emit(f,"\tbeq\t%s%d\n",labprefix,outl);
3969 }
3970 emit(f,"%s%d:\n",labprefix,++label);
3971 }else{
3972 if(ISCHAR(t))
3973 l&=7;
3974 else if(ISSHORT(t))
3975 l&=15;
3976 else
3977 l&=31;
3978 }
3979 while(l>0||loop){
3980 if(c==LSHIFT){
3981 emit(f,"\tasl\n");
3982 if(!ISCHAR(t))
3983 emit(f,"\trol\t%s\n",mregnames[r]);
3984 if(ISLONG(t)){
3985 emit(f,"\trol\t%s\n",mregnames[r2]);
3986 emit(f,"\trol\t%s\n",mregnames[r3]);
3987 }
3988 }else if(t&UNSIGNED){
3989 emit(f,"\tclc\n");
3990 if(ISLONG(t)){
3991 emit(f,"\tror\t%s\n",mregnames[r3]);
3992 emit(f,"\tror\t%s\n",mregnames[r2]);
3993 }
3994 if(!ISCHAR(t))
3995 emit(f,"\tror\t%s\n",mregnames[r]);
3996 emit(f,"\tror\n");
3997 }else{
3998 if(ISLONG(t)){
3999 emit(f,"\tcmp\t#128\n");
4000 emit(f,"\tror\n");
4001 emit(f,"\tror\t%s\n",mregnames[r]);
4002 emit(f,"\tror\t%s\n",mregnames[r2]);
4003 emit(f,"\tror\t%s\n",mregnames[r3]);
4004 }else{
4005 if(!ISCHAR(t)){
4006 emit(f,"\tcpx\t#128\n");
4007 emit(f,"\tror\t%s\n",mregnames[r]);
4008 }else
4009 emit(f,"\tcmp\t#128\n");
4010 emit(f,"\tror\n");
4011 }
4012 }
4013 if(loop){
4014 emit(f,"\tdey\n");
4015 emit(f,"\tbne\t%s%d\n",labprefix,label);
4016 if(outl) emit(f,"%s%d:\n",labprefix,outl);
4017 yval=0;
4018 break;
4019 }
4020 l--;
4021 }
4022 if(ISLONG(t)){
4023 if(c==RSHIFT&&!(t&UNSIGNED)){
4024 do_byte4(f,"sta",&p->z,t);
4025 emit(f,"\tlda\t%s\n",mregnames[r]);
4026 do_byte3(f,"sta",&p->z,t);
4027 emit(f,"\tlda\t%s\n",mregnames[r2]);
4028 store_hibyte(f,&p->z,t);
4029 emit(f,"\tlda\t%s\n",mregnames[r3]);
4030 store_lobyte(f,&p->z,t);
4031 }else{
4032 store_lobyte(f,&p->z,t);
4033 emit(f,"\tlda\t%s\n",mregnames[r]);
4034 store_hibyte(f,&p->z,t);
4035 emit(f,"\tlda\t%s\n",mregnames[r2]);
4036 do_byte3(f,"sta",&p->z,t);
4037 emit(f,"\tlda\t%s\n",mregnames[r3]);
4038 do_byte4(f,"sta",&p->z,t);
4039 }
4040 }else{
4041 if(!ISCHAR(t))
4042 emit(f,"\tldx\t%s\n",mregnames[r]);
4043 if(ISCHAR(t)||indirect(&p->z))
4044 store_acc(f,&p->z,t);
4045 else{
4046 store_lobyte(f,&p->z,t);
4047 if(!isreg(z)||p->z.reg!=rax){
4048 emit(f,"\tstx\t");
4049 emit_hibyte(f,&p->z,t);
4050 emit(f,"\n");
4051 }
4052 }
4053 }
4054 continue;
4055 }
4056
4057 if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD)||c==ADDI2P||c==SUBIFP){
4058 char *s;int t2=t,pt=p->typf2;
4059 if(!isacc(z))
4060 get_acc(f,p,CHAR);
4061 if(c==ADDI2P||c==SUBIFP){
4062 if(c==ADDI2P) c=ADD; else c=SUB;
4063 t=UNSIGNED|INT;
4064 if((pt&NQ)==POINTER&&(p->q1.flags&(KONST|DREFOBJ))==KONST){
4065 eval_const(&p->q1.val,POINTER);
4066 insert_const(&p->q1.val,UNSIGNED|INT);
4067 }
4068 }
4069 if(c>=OR&&c<=AND)
4070 s=logicals[c-OR];
4071 else
4072 s=arithmetics[c-LSHIFT];
4073
4074 if(ISFLOAT(t)){
4075 if(!ieee) ierror(0);
4076 t&=NQ;
4077 if(regs[LAST_PAIR]) ierror(0);
4078 get_acc(f,p,INT);
4079 regs[LAST_PAIR]=1;
4080 load_address(f,LAST_PAIR,&p->q1,t);
4081 BSET(regused,t3);
4082 BSET(regused,t4);
4083 emit(f,"\tjsr\t%s__fload%c\n",idprefix,(t==FLOAT?'s':'d'));
4084 yval=NOVAL;
4085 load_address(f,LAST_PAIR,&p->q2,t);
4086 emit(f,"\tjsr\t%s__f%s%c\n",idprefix,ename[c],(t==FLOAT?'s':'d'));
4087 yval=NOVAL;
4088 load_address(f,LAST_PAIR,&p->z,t);
4089 emit(f,"\tjsr\t%s__fstore%c\n",idprefix,(t==FLOAT?'s':'d'));
4090 yval=NOVAL;
4091 regs[LAST_PAIR]=0;
4092 continue;
4093 }else if(ISLONG(t)){
4094 if(c==ADD) emit(f,"\tclc\n");
4095 if(c==SUB) emit(f,"\tsec\n");
4096 load_lobyte(f,&p->q1,t);
4097 do_lobyte(f,s,&p->q2,t);
4098 store_lobyte(f,&p->z,t);
4099 load_hibyte(f,&p->q1,t);
4100 do_hibyte(f,s,&p->q2,t);
4101 store_hibyte(f,&p->z,t);
4102 do_byte3(f,"lda",&p->q1,t);
4103 do_byte3(f,s,&p->q2,t);
4104 do_byte3(f,"sta",&p->z,t);
4105 do_byte4(f,"lda",&p->q1,t);
4106 do_byte4(f,s,&p->q2,t);
4107 do_byte4(f,"sta",&p->z,t);
4108 continue;
4109 }else if(ISCHAR(t)){
4110 load_acc(f,&p->q1,t);
4111 if(c==ADD) emit(f,"\tclc\n");
4112 if(c==SUB) emit(f,"\tsec\n");
4113 do_lobyte(f,s,&p->q2,t);
4114 store_acc(f,&p->z,t);
4115 }else if(c==ADD||c==SUB){
4116 int a,r;long l=1;
4117 if(isconst(q2)){
4118 eval_const(&p->q2.val,t2);
4119 l=zm2l(vmax);
4120 l&=0xff00;
4121 }
4122 if(isreg(z)&&p->z.reg==rax) a=1; else a=0;
4123 if((t2&NU)==CHAR&&(p->q2.flags&(KONST|DREFOBJ))!=KONST){
4124 emit(f,"\tldx\t#0\n");
4125 }
4126 if((t2&NU)==CHAR&&(p->q2.flags&(KONST|DREFOBJ))!=KONST){
4127 load_lobyte(f,&p->q2,t);
4128 emit(f,"\tbpl\t%s%d\n",labprefix,++label);
4129 emit(f,"\tdex\n");
4130 emit(f,"%s%d:\n",labprefix,label);
4131 if(c==ADD){
4132 if(c==ADD) emit(f,"\tclc\n"); else emit(f,"\tsec\n");
4133 do_lobyte(f,s,&p->q1,t);
4134 if(isacc(z))
4135 emit(f,"\tpha\n");
4136 else
4137 store_lobyte(f,&p->z,t);
4138 emit(f,"\ttxa\n");
4139 do_hibyte(f,s,&p->q1,t);
4140 store_hibyte(f,&p->z,t);
4141 if(ISFPOINTER(pt)&&!compare_objects(&p->q1,&p->z)){
4142 do_byte3(f,"lda",&p->q1,pt);
4143 do_byte3(f,"sta",&p->z,pt);
4144 }
4145 if(isacc(z))
4146 emit(f,"\tpla\n");
4147 continue;
4148 }
4149 r=get_reg(f,p,CHAR);
4150 emit(f,"\tstx\t%s\n",mregnames[r]);
4151 }
4152 load_lobyte(f,&p->q1,t);
4153 if(c==ADD) emit(f,"\tclc\n"); else emit(f,"\tsec\n");
4154 do_lobyte(f,s,&p->q2,t2);
4155 store_lobyte(f,&p->z,t);
4156 if(l==0&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg){
4157 if(c==ADD){
4158 emit(f,"\tbcc\t%s%d\n",labprefix,++label);
4159 if(a)
4160 emit(f,"\tinx\n");
4161 else{
4162 /*if(!reg_pair(p->z.reg,&rp)) ierror(0);*/
4163 emit(f,"\tinc\t%s+1\n",mregnames[p->z.reg]);
4164 }
4165 }else{
4166 emit(f,"\tbcs\t%s%d\n",labprefix,++label);
4167 if(a)
4168 emit(f,"\tdex\n");
4169 else{
4170 if(!reg_pair(p->z.reg,&rp)) ierror(0);
4171 emit(f,"\tdec\t%s\n",mregnames[rp.r2]);
4172 }
4173 }
4174 emit(f,"%s%d:\n",labprefix,label);
4175 }else{
4176 if(a==1) emit(f,"\tpha\n");
4177 if((t2&NQ)==CHAR){
4178 if(t2&UNSIGNED){
4179 load_hibyte(f,&p->q1,t);
4180 emit(f,"\t%s\t#0\n",s);
4181 }else{
4182 load_hibyte(f,&p->q1,t);
4183 if((p->q2.flags&(KONST|DREFOBJ))==KONST){
4184 eval_const(&p->q2.val,t2);
4185 if(zmleq(Z0,vmax))
4186 emit(f,"\t%s\t#0\n",s);
4187 else
4188 emit(f,"\t%s\t#255\n",s);
4189 }else{
4190 emit(f,"\t%s\t%s\n",s,mregnames[r]);
4191 }
4192 }
4193 }else{
4194 load_hibyte(f,&p->q1,t);
4195 do_hibyte(f,s,&p->q2,t2);
4196 }
4197 store_hibyte(f,&p->z,t);
4198 if(a==1) emit(f,"\tpla\n");
4199 if(ISFPOINTER(pt)&&p->code!=SUBPFP){
4200 if(!compare_objects(&p->q1,&p->z)){
4201 do_byte3(f,"lda",&p->q1,FPOINTER);
4202 do_byte3(f,"sta",&p->z,FPOINTER);
4203 }
4204 }
4205 }
4206 }else{
4207 if(isacc(q1))
4208 emit(f,"\tpha\n");
4209 load_hibyte(f,&p->q1,t);
4210 do_hibyte(f,s,&p->q2,t);
4211 store_hibyte(f,&p->z,t);
4212 if(isacc(q1))
4213 emit(f,"\tpla\n");
4214 load_lobyte(f,&p->q1,t);
4215 do_lobyte(f,s,&p->q2,t);
4216 store_lobyte(f,&p->z,t);
4217 }
4218 continue;
4219 }
4220 pric2(stdout,p);
4221 ierror(0);
4222 }
4223
4224 function_bottom(f,v,localsize);
4225
4226 for(c=1;c<=MAXR;c++){
4227 if(regsa[c]||regused[c]){
4228 BSET(regs_modified,c);
4229 }
4230 }
4231
4232 if(stack_valid){
4233 if(!v->fi) v->fi=new_fi();
4234 v->fi->flags|=ALL_STACK;
4235 v->fi->stack1=stack;
4236 }
4237 }
4238
4239 free_IC(mi);
4240
4241 emit(f,"; stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");
4242}
4243
4244int shortcut(int code,int typ)
4245{
4246 if(code==COMPARE/*||code==MULT*/||code==ADD||code==SUB||code==AND||code==OR||code==XOR||code==LSHIFT||code==RSHIFT/*||code==MINUS*/||code==KOMPLEMENT)
4247 return 1;
4248
4249 return 0;
4250}
4251
4252static int fattr(type *p,char *s)
4253{
4254 if(p->attr&&strstr(p->attr,s))
4255 return 1;
4256 if(p->next)
4257 return fattr(p->next,s);
4258 else
4259 return 0;
4260}
4261
4262int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
4263{
4264 int f;
4265
4266 if(vararg)
4267 return 0;
4268 f=t->flags&NQ;
4269 if(OLDFP&&ISFLOAT(f)) return 0;
4270 if(d&&fattr(d,"__stackparms__"))
4271 return 0;
4272 if(d&&fattr(d,"__cc65__")){
4273 m->regs++;
4274 printf("arg=%d cnt=%d\n",m->regs,d->exact->count);
4275 if(m->regs==d->exact->count-1){
4276 if(ISCHAR(t->flags))
4277 return ra;
4278 if(ISSHORT(t->flags))
4279 return rax;
4280 }
4281 return 0;
4282 }
4283 if(ISCHAR(f)){
4284 if(!t->exact){
4285 if(m->regs>=GPR_ARGS-1)
4286 return 0;
4287 f=FIRST_GPR+m->regs;
4288 m->regs+=2;
4289 return f;
4290 }else{
4291 if(m->regs>=GPR_ARGS)
4292 return 0;
4293 else
4294 return FIRST_GPR+m->regs++;
4295 }
4296 }
4297 if(ISSHORT(f)||f==POINTER){
4298 if(m->regs>=GPR_ARGS-1)
4299 return 0;
4300 else{
4301 if(m->regs&1) m->regs+=1;
4302 m->regs+=2;
4303 return FIRST_PAIR+m->regs/2-1;
4304 }
4305 }
4306 if(f==FPOINTER||f==LONG||f==FLOAT||(!ieee&&(f==DOUBLE||f==LDOUBLE))){
4307 if(m->bregs>=4)
4308 return 0;
4309 else
4310 return FIRST_BIG+m->bregs++;
4311 }
4312 if(f==LLONG||(ieee&&(f==DOUBLE||f==LDOUBLE))){
4313 if(m->bregs>=3)
4314 return 0;
4315 else{
4316 if(m->bregs&1) m->bregs++;
4317 m->bregs+=2;
4318 return FIRST_BIGP+m->bregs/2-1;
4319 }
4320 }
4321 return 0;
4322}
4323
4324int handle_pragma(const char *s)
4325{
4326 static char sec[SECLEN];
4327 int i;
4328 if(sscanf(s,"section %127s",sec)==1){
4329 if(!strcmp(sec,"default"))
4330 use_sec=0;
4331 else
4332 use_sec=sec;
4333 return 1;
4334 }
4335 if(sscanf(s,"bank %d",&i)==1){
4336 use_bank=i;
4337 return 1;
4338 }
4339}
4340void cleanup_cg(FILE *f)
4341{
4342 int i;
4343 struct fpconstlist *p=firstfpc;
4344
4345 if(f&&p){
4346 emit(f,rodataname);emit(f,"\n");
4347 section=RODATA;
4348 }
4349 while(p=firstfpc){
4350 emit(f,"%s%d:\n\tword\t",labprefix,p->label);
4351 if(ieee)
4352 emit_ieee(f,&p->val,p->t);
4353 else{
4354 int words=zm2l(sizetab[p->t&NQ])/2;
4355 eval_const(&p->val,p->t);
4356 if(ISFLOAT(p->t)) cnv_fp();
4357 for(i=0;i<words;i++){
4358 emit(f,"%ld",zm2l(vmax)&0xffff);
4359 if(i<words-1){emit(f,",");vmax=zmrshift(vmax,l2zm(16L));}
4360 }
4361 emit(f,"\n");
4362 /*emit(f,"%ld,%ld\n",zm2l(vmax)&0xffff,zm2l(zmrshift(vmax,l2zm(16L)))&0xffff);*/
4363 }
4364 firstfpc=p->next;
4365 free(p);
4366 }
4367
4368 emit(f,"\tzpage\t%s\n",mregnames[sp]);
4369 for(i=FIRST_GPR;i<=LAST_GPR;i++)
4370 emit(f,"\tzpage\t%s\n",mregnames[i]);
4371 for(i=FIRST_BIG;i<=LAST_BIG;i++)
4372 emit(f,"\tzpage\t%s\n",mregnames[i]);
4373
4374}
4375void cleanup_db(FILE *f)
4376{
4377 if(f) section=-1;
4378}
4379
4380static char *zops[]={
4381 "adc","and","asl","bit","eor","lda","ora",
4382 "tax","txa","tay","tya","sbc"};
4383
4384static int setszflag(char *op)
4385{
4386 int i;
4387 for(i=0;i<sizeof(zops)/sizeof(zops[0]);i++)
4388 if(!strcmp(op,zops[i]))
4389 return 1;
4390 return 0;
4391}
4392
4393
4394enum peepf { NEEDSAME = 1, REMOVE1ST = 2};
4395struct peeps {char *s1,*s2,*r;enum peepf flags;};
4396
4397
4398
4399int emit_peephole(void)
4400{
4401 int entries,i,j;
4402 char *asmline[EMIT_BUF_DEPTH];
4403 char buf1[1024],buf2[1024];
4404 char op1[8],op2[8];
4405 static char ca[1024],cx[1024],cy[1024],cz[1024];
4406 static int rm,disabled;
4407
4408 fprintf(stderr,"Called emit_peephole()\n");
4409
4410 static struct peeps elim[]={
4411 "lda","sta",0,NEEDSAME,
4412 "ldx","stx",0,NEEDSAME,
4413 "sta","sta",0,NEEDSAME,
4414 "stx","stx",0,NEEDSAME,
4415 "sta","lda",0,NEEDSAME,
4416 "stx","ldx",0,NEEDSAME,
4417 "txa","tax",0,0,
4418 "tax","txa",0,0,
4419 "lda","lda",0,REMOVE1ST,
4420 "ldx","ldx",0,REMOVE1ST,
4421 "ldy","ldy",0,REMOVE1ST,
4422 "ldz","ldz",0,REMOVE1ST,
4423 "lda","pla",0,REMOVE1ST,
4424 "lda","txa",0,REMOVE1ST,
4425 "lda","tya",0,REMOVE1ST,
4426 "ldx","tax",0,REMOVE1ST,
4427 "ldy","tay",0,REMOVE1ST,
4428 "tay","ldy",0,REMOVE1ST,
4429 "taz","ldz",0,REMOVE1ST,
4430 "tax","ldx",0,REMOVE1ST,
4431 "txa","lda",0,REMOVE1ST,
4432 "tya","lda",0,REMOVE1ST,
4433 "tza","lda",0,REMOVE1ST,
4434 "lda","ldx","\ttax\n",NEEDSAME,
4435 "lda","ldy","\ttay\n",NEEDSAME,
4436 "ldx","lda","\ttxa\n",NEEDSAME,
4437 "ldy","lda","\ttya\n",NEEDSAME,
4438 "sta","ldx","\ttax\n",NEEDSAME,
4439 "sta","ldy","\ttay\n",NEEDSAME,
4440 "stx","lda","\ttxa\n",NEEDSAME,
4441 "sty","lda","\ttya\n",NEEDSAME,
4442
4443 };
4444
4445 if(nopeep) return 0;
4446
4447 i=emit_l;
4448 if(emit_f==0)
4449 entries=i-emit_f+1;
4450 else
4451 entries=EMIT_BUF_DEPTH;
4452 asmline[0]=emit_buffer[i];
4453
4454 if(!strcmp(asmline[0],";startinline\n")) disabled=1;
4455 if(!strcmp(asmline[0],";endinline\n")) disabled=0;
4456 if(disabled) return 0;
4457
4458 buf1[0]=0;op1[0]=0;
4459 if((j=sscanf(asmline[0]," %6s %999s",op1,buf1))>=1){
4460 printf("a=%s x=%s y=%s, z=%s\n",ca,cx,cy,cz);
4461 printf("\t\t%s %s\n",op1,buf1);
4462 if(!strcmp(op1,"sta")) {
4463 // Work out when we are accessing variables on the stack
4464 if (!strcmp(buf1,"(sp),y")) {
4465 // We invalidate this when Y changes
4466 snprintf(ca,1024,"(sp),y",cy);
4467 }
4468 } else if(!strcmp(op1,"sta")){
4469 // Remove writes to wherever A was loaded from
4470 if (!strcmp(buf1,ca)) {
4471 remove_asm();
4472 return rm=1;
4473 }
4474 } else if(!strcmp(op1,"lda")){
4475 if(buf1[0]=='#'){
4476 if(!strcmp(buf1,ca)){remove_asm();return rm=1;}
4477 strcpy(ca,buf1);
4478 }else {
4479 // Work out when we are accessing variables on the stack
4480 if (!strcmp(buf1,"(sp),y")) {
4481 if(!strcmp(buf1,ca)){
4482 remove_asm();
4483 return rm=1;
4484 }
4485 snprintf(ca,1024,"(sp),y",cy);
4486 }
4487 // Similarly look for register loads
4488 // We can sometimes remove some of those, too.
4489 if ((strlen(buf1)>1)&&(buf1[0]=='r')) {
4490 if (strcmp(ca,buf1))
4491 snprintf(ca,1024,"%s",buf1);
4492 else {
4493 // Don't re-load A with the same contents it already has
4494 remove_asm();
4495 return rm=1;
4496 }
4497 }
4498 }
4499 }else if(!strcmp(op1,"ldx")){
4500 if(buf1[0]=='#'){
4501 if(!rm&&!strcmp(buf1,cx)){remove_asm();return rm=1;}
4502 strcpy(cx,buf1);
4503 }else cx[0]=0;
4504 }else if(!strcmp(op1,"ldy")){
4505 if(buf1[0]=='#'){
4506 if(!rm&&!strcmp(buf1,cy)){remove_asm();return rm=1;}
4507 strcpy(cy,buf1);
4508 }else cy[0]=0;
4509 }else if(!strcmp(op1,"ldz")){
4510 if(buf1[0]=='#'){
4511 if(!rm&&!strcmp(buf1,cz)){remove_asm();return rm=1;}
4512 strcpy(cz,buf1);
4513 }else cz[0]=0;
4514 }else{
4515 // TODO: PGS: Add the AXYZ operations to the clobber lists.
4516 // Will we need to handle them specially?
4517 static char clobbernone[]="clc cld cli clv cmp cpx cpy dec inc nop pha php plp sec sed sei sta stx sty stz";
4518 static char clobbera[]="adc and asl eor lsr ora pla rol ror sbc txa tya tza neg";
4519 static char clobberx[]="dex inx tax tsx";
4520 static char clobbery[]="dey iny tay";
4521 static char clobberz[]="dez inz taz";
4522 if(strstr(clobbernone,op1)){
4523 // Invalidate A holding a stack variable byte if SP changes
4524 if (strstr(buf1,"sp")) {
4525 printf("buf1='%s'\n",buf1);
4526 if (strstr(ca,"(sp),y")) ca[0]=0;
4527 }
4528 }else if(strstr(clobbera,op1))
4529 ca[0]=0;
4530 else if(strstr(clobberx,op1))
4531 cx[0]=0;
4532 else if(strstr(clobbery,op1)) {
4533 cy[0]=0;
4534 // Invalidate A holding a stack variable byte if Y changes
4535 if (strstr(ca,"(sp),y")) ca[0]=0;
4536 }
4537 else if(strstr(clobberz,op1))
4538 cz[0]=0;
4539 else
4540 ca[0]=cx[0]=cy[0]=cz[0]=0;
4541 }
4542 }else{
4543 ca[0]=cx[0]=cy[0]=cz[0]=0;
4544 }
4545
4546 rm=0;
4547
4548 if(sscanf(asmline[0]," %6s %999s",op1,buf1)==2&&!strcmp(op1,"and")&&!strcmp(buf1,"#0")){
4549 strcpy(asmline[0],"\tlda\t#0\n");
4550 return rm=1;
4551 }
4552
4553 if(entries>=2){
4554 i--;
4555 if(i<0) i=EMIT_BUF_DEPTH-1;
4556 asmline[1]=emit_buffer[i];
4557
4558
4559 if(!strcmp(asmline[0],"; volatile barrier\n")&&!strcmp(asmline[0],asmline[1])){
4560 remove_asm();
4561 return rm=1;
4562 }
4563
4564 if(sscanf(asmline[0]," %6s",op1)==1&&!strcmp(op1,"rts")&&
4565 sscanf(asmline[1]," %6s %999s",op2,buf2)==2&&!strcmp(op2,"jsr")){
4566 sprintf(asmline[1],"\tjmp\t%s\n",buf2);
4567 remove_asm();
4568 return rm=1;
4569 }
4570
4571 for(j=0;j<sizeof(elim)/sizeof(elim[0]);j++){
4572 if(elim[j].flags&NEEDSAME){
4573 if(sscanf(asmline[0]," %6s %999s",op2,buf2)==2&&
4574 sscanf(asmline[1]," %6s %999s",op1,buf1)==2&&
4575 !strcmp(op1,elim[j].s1)&&!strcmp(op2,elim[j].s2)&&
4576 !strcmp(buf1,buf2)){
4577 if(elim[j].r){
4578 strcpy(asmline[0],elim[j].r);
4579 }else{
4580 if(elim[j].flags&REMOVE1ST)
4581 strcpy(asmline[1],asmline[0]);
4582 remove_asm();
4583 }
4584 return rm=1;
4585 }
4586 }else{
4587 if(sscanf(asmline[1]," %6s",op1)==1&&
4588 sscanf(asmline[0]," %6s",op2)==1&&
4589 !strcmp(op1,elim[j].s1)&&!strcmp(op2,elim[j].s2)){
4590 if(elim[j].flags&REMOVE1ST)
4591 strcpy(asmline[1],asmline[0]);
4592 remove_asm();
4593 return rm=1;
4594 }
4595 }
4596 }
4597
4598
4599 }
4600
4601 if(entries>=3){
4602 i--;
4603 if(i<0) i=EMIT_BUF_DEPTH-1;
4604 asmline[2]=emit_buffer[i];
4605 if(sscanf(asmline[0]," %6s %999s",op1,buf1)==2){
4606#if 0
4607 if(!strcmp(op1,"lda")&&buf1[0]=='#'){
4608 if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&&
4609 !strcmp(op2,"sta")){
4610 if(sscanf(asmline[2]," %6s %999s",op2,buf2)==2&&
4611 !strcmp(op2,"lda")&&!strcmp(buf1,buf2)){
4612 remove_asm();
4613 return rm=1;
4614 }
4615 }
4616 }
4617#endif
4618 if(!strcmp(op1,"beq")||!strcmp(op1,"bne")){
4619 if(sscanf(asmline[1]," %6s %999s",op1,buf1)==2&&
4620 !strcmp(op1,"cmp")&&!strcmp(buf1,"#0")){
4621 if(sscanf(asmline[2]," %6s",op1)==1&&
4622 setszflag(op1)){
4623 strcpy(asmline[1],asmline[0]);
4624 remove_asm();
4625 return rm=1;
4626 }
4627 }
4628 }
4629 }
4630 }
4631
4632 return 0;
4633}
4634
4635/* Return name of library function, if this node should be
4636 implemented via libcall. */
4637char *use_libcall(int c,int t,int t2)
4638{
4639 static char fname[16];
4640 char *ret=0;
4641
4642 if(c==COMPARE){
4643 if((t&NQ)==LLONG||(ISFLOAT(t)&&!ieee)){
4644 sprintf(fname,"__cmp%s%s%ld",(t&UNSIGNED)?"u":"s",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8);
4645 ret=fname;
4646 }
4647 }else{
4648 t&=NU;
4649 t2&=NU;
4650 if(ISSHORT(t)&&c!=MULT&&c!=DIV&&c!=MOD&&!ISFLOAT(t2))
4651 return 0;
4652 if(ISLONG(t)&&c!=MULT&&c!=DIV&&c!=MOD&&!ISFLOAT(t2))
4653 return 0;
4654
4655 if(!ieee&&ISFLOAT(t)) t=FLOAT;
4656 if(t==LDOUBLE) t=DOUBLE;
4657 if(t2==LDOUBLE) t2=DOUBLE;
4658 if(!ieee&&ISFLOAT(t2)) t2=FLOAT;
4659 if(c==CONVERT){
4660 if(t==t2) return 0;
4661 if(t==FLOAT&&t2==DOUBLE) return "__flt64toflt32";
4662 if(t==DOUBLE&&t2==FLOAT) return "__flt32toflt64";
4663
4664 if(ISFLOAT(t)){
4665 sprintf(fname,"__%cint%ldtoflt%d",(t2&UNSIGNED)?'u':'s',zm2l(sizetab[t2&NQ])*8,(t==FLOAT)?32:64);
4666 ret=fname;
4667 }
4668 if(ISFLOAT(t2)){
4669 sprintf(fname,"__flt%dto%cint%ld",((t2&NU)==FLOAT)?32:64,(t&UNSIGNED)?'u':'s',zm2l(sizetab[t&NQ])*8);
4670 ret=fname;
4671 }
4672 }
4673 if((t&NQ)==INT||(t&NQ)==LONG||(t&NQ)==LLONG||(!ieee&&ISFLOAT(t))){
4674 if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==KOMPLEMENT||c==MINUS){
4675 if(t==(UNSIGNED|LLONG)&&(c==MULT||c==DIV||c==MOD||c==RSHIFT)){
4676 sprintf(fname,"__%suint64",ename[c]);
4677 ret=fname;
4678 }else if((t&NQ)==LLONG){
4679 sprintf(fname,"__%sint64",ename[c]);
4680 ret=fname;
4681 }else if(t==(UNSIGNED|LONG)&&(c==DIV||c==MOD||c==RSHIFT)){
4682 sprintf(fname,"__%suint32",ename[c]);
4683 ret=fname;
4684 }else if((t&NQ)==LONG){
4685 sprintf(fname,"__%sint32",ename[c]);
4686 ret=fname;
4687 }else if(t==(UNSIGNED|INT)&&(c==DIV||c==MOD||c==RSHIFT)){
4688 sprintf(fname,"__%suint16",ename[c]);
4689 ret=fname;
4690 }else if((t&NQ)==INT){
4691 sprintf(fname,"__%sint16",ename[c]);
4692 ret=fname;
4693 }else{
4694 sprintf(fname,"__%s%s%s%ld",ename[c],(t&UNSIGNED)?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8);
4695 ret=fname;
4696 }
4697 }
4698 }
4699 }
4700
4701 return ret;
4702}
4703
4704
4705int pointer_varadr(Var *v)
4706{
4707 int b=bank(v);
4708 if(b>=0&&b!=bankcnum&&!NOBANKVARS){
4709 if(cur_funcv&&bank(cur_funcv)!=b)
4710 return FPOINTER;
4711 }
4712 return pointer_type(v->vtyp);
4713}
4714
4715int pointer_type(struct Typ *p)
4716{
4717 struct Typ *merk=p;
4718 if(!p) ierror(0);
4719 if(LARGE) return FPOINTER;
4720 while(ISARRAY(p->flags)||ISFUNC(p->flags)) p=p->next;
4721 if(p->attr){
4722 char *s;
4723 if(strstr(p->attr,STR_HUGE)) return HPOINTER;
4724 if(strstr(p->attr,STR_FAR)) return FPOINTER;
4725 if(strstr(p->attr,STR_NEAR)) return POINTER;
4726 }
4727 return POINTER;
4728}
4729
4730unsigned char cbmconv(unsigned char x)
4731{
4732 static unsigned char ctab[256]={
4733 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x14,0x09,0x0D,0x11,0x93,0x0A,0x0E,0x0F,
4734 0x10,0x0B,0x12,0x13,0x08,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
4735 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
4736 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
4737 0x40,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
4738 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0x5B,0xBF,0x5D,0x5E,0xA4,
4739 0xAD,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
4740 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0xB3,0xDD,0xAB,0xB1,0xDF,
4741 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
4742 0x90,0x91,0x92,0x0C,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
4743 0xA0,0xA1,0xA2,0xA3,0x5F,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0x7D,0xAC,0x60,0xAE,0xAF,
4744 0xB0,0x7E,0xB2,0x7B,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0x5C,
4745 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
4746 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0xDC,0x7C,0xDE,0x7F,
4747 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
4748 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
4749 };
4750
4751 static unsigned char atab[]={0xfd,8,0x7f,0x9b,11,0x7d};
4752
4753 if(cbmascii)
4754 return ctab[x&255];
4755 else if(atascii&&x>=7&&x<=12)
4756 return atab[x-7];
4757 else
4758 return x;
4759}
4760
4761void insert_const(union atyps *p,int t)
4762/* Traegt Konstante in entprechendes Feld ein. */
4763{
4764 if(!p) ierror(0);
4765/* *p = (union atyps) 0 ; /* rfi: clear unused bits */
4766 t&=NU;
4767 if(t==CHAR) {p->vchar=vchar;return;}
4768 if(t==SHORT) {p->vshort=vshort;return;}
4769 if(t==INT) {p->vint=vint;return;}
4770 if(t==LONG) {p->vlong=vlong;return;}
4771 if(t==LLONG) {p->vllong=vllong;return;}
4772 if(t==MAXINT) {p->vmax=vmax;return;}
4773 if(t==(UNSIGNED|CHAR)) {p->vuchar=vuchar;return;}
4774 if(t==(UNSIGNED|SHORT)) {p->vushort=vushort;return;}
4775 if(t==(UNSIGNED|INT)) {p->vuint=vuint;return;}
4776 if(t==(UNSIGNED|LONG)) {p->vulong=vulong;return;}
4777 if(t==(UNSIGNED|LLONG)) {p->vullong=vullong;return;}
4778 if(t==(UNSIGNED|MAXINT)) {p->vumax=vumax;return;}
4779 if(t==FLOAT) {p->vfloat=vfloat;return;}
4780 if(t==DOUBLE) {p->vdouble=vdouble;return;}
4781 if(t==LDOUBLE) {p->vldouble=vldouble;return;}
4782 if(t==POINTER) {p->vuint=vuint;return;}
4783 if(t==FPOINTER||t==HPOINTER) {p->vulong=vulong;return;}
4784}
4785
4786void eval_const(union atyps *p,int t)
4787/* Weist bestimmten globalen Variablen Wert einer CEXPR zu. */
4788{
4789 int f=t&NQ;
4790 if(!p) ierror(0);
4791 if(f==MAXINT||(f>=CHAR&&f<=LLONG)){
4792 if(!(t&UNSIGNED)){
4793 if(f==CHAR) vmax=zc2zm(p->vchar);
4794 else if(f==SHORT)vmax=zs2zm(p->vshort);
4795 else if(f==INT) vmax=zi2zm(p->vint);
4796 else if(f==LONG) vmax=zl2zm(p->vlong);
4797 else if(f==LLONG) vmax=zll2zm(p->vllong);
4798 else if(f==MAXINT) vmax=p->vmax;
4799 else ierror(0);
4800 vumax=zm2zum(vmax);
4801 vldouble=zm2zld(vmax);
4802 }else{
4803 if(f==CHAR) vumax=zuc2zum(p->vuchar);
4804 else if(f==SHORT)vumax=zus2zum(p->vushort);
4805 else if(f==INT) vumax=zui2zum(p->vuint);
4806 else if(f==LONG) vumax=zul2zum(p->vulong);
4807 else if(f==LLONG) vumax=zull2zum(p->vullong);
4808 else if(f==MAXINT) vumax=p->vumax;
4809 else ierror(0);
4810 vmax=zum2zm(vumax);
4811 vldouble=zum2zld(vumax);
4812 }
4813 }else{
4814 if(ISPOINTER(f)){
4815 if(f==POINTER)
4816 vumax=zui2zum(p->vuint);
4817 else
4818 vumax=zul2zum(p->vulong);
4819 vmax=zum2zm(vumax);vldouble=zum2zld(vumax);
4820 }else{
4821 if(f==FLOAT) vldouble=zf2zld(p->vfloat);
4822 else if(f==DOUBLE) vldouble=zd2zld(p->vdouble);
4823 else vldouble=p->vldouble;
4824 vmax=zld2zm(vldouble);
4825 vumax=zld2zum(vldouble);
4826 }
4827 }
4828 vfloat=zld2zf(vldouble);
4829 vdouble=zld2zd(vldouble);
4830 vuchar=zum2zuc(vumax);
4831 vushort=zum2zus(vumax);
4832 vuint=zum2zui(vumax);
4833 vulong=zum2zul(vumax);
4834 vullong=zum2zull(vumax);
4835 vchar=zm2zc(vmax);
4836 vshort=zm2zs(vmax);
4837 vint=zm2zi(vmax);
4838 vlong=zm2zl(vmax);
4839 vllong=zm2zll(vmax);
4840}
4841
4842void printval(FILE *f,union atyps *p,int t)
4843/* Gibt atyps aus. */
4844{
4845 t&=NU;
4846 if(t==CHAR){fprintf(f,"C");vmax=zc2zm(p->vchar);printzm(f,vmax);}
4847 if(t==(UNSIGNED|CHAR)){fprintf(f,"UC");vumax=zuc2zum(p->vuchar);printzum(f,vumax);}
4848 if(t==SHORT){fprintf(f,"S");vmax=zs2zm(p->vshort);printzm(f,vmax);}
4849 if(t==(UNSIGNED|SHORT)){fprintf(f,"US");vumax=zus2zum(p->vushort);printzum(f,vumax);}
4850 if(t==FLOAT){fprintf(f,"F");vldouble=zf2zld(p->vfloat);printzld(f,vldouble);}
4851 if(t==DOUBLE){fprintf(f,"D");vldouble=zd2zld(p->vdouble);printzld(f,vldouble);}
4852 if(t==LDOUBLE){fprintf(f,"LD");printzld(f,p->vldouble);}
4853 if(t==INT){fprintf(f,"I");vmax=zi2zm(p->vint);printzm(f,vmax);}
4854 if(t==(UNSIGNED|INT)||t==POINTER){fprintf(f,"UI");vumax=zui2zum(p->vuint);printzum(f,vumax);}
4855 if(t==LONG){fprintf(f,"L");vmax=zl2zm(p->vlong);printzm(f,vmax);}
4856 if(t==(UNSIGNED|LONG)||t==FPOINTER||t==HPOINTER){fprintf(f,"UL");vumax=zul2zum(p->vulong);printzum(f,vumax);}
4857 if(t==LLONG){fprintf(f,"LL");vmax=zll2zm(p->vllong);printzm(f,vmax);}
4858 if(t==(UNSIGNED|LLONG)){fprintf(f,"ULL");vumax=zull2zum(p->vullong);printzum(f,vumax);}
4859 if(t==MAXINT) printzm(f,p->vmax);
4860 if(t==(UNSIGNED|MAXINT)) printzum(f,p->vumax);
4861}
4862
4863void emitval(FILE *f,union atyps *p,int t)
4864/* Gibt atyps aus. */
4865{
4866 t&=NU;
4867 if(t==CHAR){vmax=zc2zm(p->vchar);emitzm(f,vmax);}
4868 if(t==(UNSIGNED|CHAR)){vumax=zuc2zum(p->vuchar);emitzum(f,vumax);}
4869 if(t==SHORT){vmax=zs2zm(p->vshort);emitzm(f,vmax);}
4870 if(t==(UNSIGNED|SHORT)){vumax=zus2zum(p->vushort);emitzum(f,vumax);}
4871 if(t==FLOAT){vldouble=zf2zld(p->vfloat);emitzld(f,vldouble);}
4872 if(t==DOUBLE){vldouble=zd2zld(p->vdouble);emitzld(f,vldouble);}
4873 if(t==LDOUBLE){emitzld(f,p->vldouble);}
4874 if(t==INT){vmax=zi2zm(p->vint);emitzm(f,vmax);}
4875 if(t==(UNSIGNED|INT)||t==POINTER){vumax=zui2zum(p->vuint);emitzum(f,vumax);}
4876 if(t==LONG){vmax=zl2zm(p->vlong);emitzm(f,vmax);}
4877 if(t==(UNSIGNED|LONG)||t==FPOINTER||t==HPOINTER){vumax=zul2zum(p->vulong);emitzum(f,vumax);}
4878 if(t==LLONG){vmax=zll2zm(p->vllong);emitzm(f,vmax);}
4879 if(t==(UNSIGNED|LLONG)){vumax=zull2zum(p->vullong);emitzum(f,vumax);}
4880 if(t==MAXINT) emitzm(f,p->vmax);
4881 if(t==(UNSIGNED|MAXINT)) emitzum(f,p->vumax);
4882}
4883
4884void conv_typ(struct Typ *p)
4885/* Erzeugt extended types in einem Typ. */
4886{
4887 char *attr;
4888 while(p){
4889 if(ISPOINTER(p->flags)){
4890 p->flags=((p->flags&~NU)|POINTER_TYPE(p->next));
4891 if(attr=p->next->attr){
4892 if(strstr(attr,STR_NEAR))
4893 p->flags=((p->flags&~NU)|POINTER);
4894 if(strstr(attr,STR_FAR))
4895 p->flags=((p->flags&~NU)|FPOINTER);
4896 if(strstr(attr,STR_HUGE))
4897 p->flags=((p->flags&~NU)|HPOINTER);
4898 }
4899 }
4900 p=p->next;
4901 }
4902}
4903
4904void add_var_hook_post(Var *v)
4905{
4906 if(use_sec&&(v->storage_class==STATIC||v->storage_class==EXTERN)){
4907 char buf[SECLEN+32];
4908 sprintf(buf,"section(\"%s\");",use_sec);
4909 add_attr(&v->vattr,buf);
4910 }
4911 if(use_bank>=0&&(v->storage_class==STATIC||v->storage_class==EXTERN)){
4912 char buf[64];
4913 /*sprintf(buf,"section(\"bank%d\");bank(%d)",use_bank,use_bank);*/
4914 sprintf(buf,"bank(%d)",use_bank);
4915 add_attr(&v->vattr,buf);
4916 }
4917}
4918
4919int decide_reverse(zmax v)
4920{
4921 if(zmeqto(v,Z1)||zmeqto(v,l2zm(2L)))
4922 return 1;
4923 if(optspeed)
4924 if(zmeqto(v,l2zm(4L))||zmeqto(v,l2zm(8L))||zmeqto(v,l2zm(256L))||zmeqto(v,l2zm(512L)))
4925 return 1;
4926
4927 return 0;
4928}
4929
4930static int is_single_eff_ic(struct IC *p)
4931{
4932 struct Var *v,*idx;
4933 if(p->code!=ADDI2P||(p->typf2&NQ)!=POINTER)
4934 return 0;
4935 if(!(p->q2.flags&KONST)){
4936 if((p->typf&NU)!=(UNSIGNED|CHAR))
4937 return 0;
4938 if((p->q2.flags&(VAR|DREFOBJ))!=VAR)
4939 return 0;
4940 if(p->q2.v->storage_class!=AUTO&&p->q2.v->storage_class!=REGISTER)
4941 return 0;
4942 idx=p->q2.v;
4943 }else{
4944 idx=0;
4945 eval_const(&p->q2.val,p->typf);
4946 /* TODO: more precise check considering data type useful? */
4947 if(!zmleq(vumax,l2zm(255L)))
4948 return 0;
4949 return 1;
4950 }
4951 if(p->q1.flags&DREFOBJ)
4952 return 0;
4953 if((p->z.flags&(VAR|DREFOBJ))!=VAR)
4954 return 0;
4955 if(p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN)
4956 return 0;
4957 v=p->z.v;
4958 for(p=p->next;p;p=p->next){
4959 int c=p->code;
4960 if(c==LABEL||(c>=BEQ&&c<=BRA))
4961 return 1; /* TODO: how elaborate should we test? */
4962 if((p->q1.flags&VAR)&&p->q1.v==v){
4963 if(p->q1.flags&DREFOBJ)
4964 return 1;
4965 else
4966 return 0;
4967 }
4968 if((p->q2.flags&VAR)&&p->q2.v==v){
4969 if(p->q2.flags&DREFOBJ)
4970 return 1;
4971 else
4972 return 0;
4973 }
4974 if((p->z.flags&VAR)&&p->z.v==v){
4975 if(p->z.flags&DREFOBJ)
4976 return 1;
4977 else
4978 return 0;
4979 }
4980 if((p->z.flags&VAR)&&p->z.v==idx)
4981 return 0;
4982 }
4983 return 0;
4984}
4985
4986void mark_eff_ics(void)
4987{
4988 struct IC *p;
4989 for(p=first_ic;p;p=p->next){
4990 if(is_single_eff_ic(p))
4991 p->flags|=EFF_IC;
4992 else
4993 p->flags&=~EFF_IC;
4994 }
4995}