PulkoMandy | 17fc759 | 2022-07-28 18:27:54 +0200 | [diff] [blame] | 1 | /* Code generator for Motorola 68hc12 microcontrollers. */ |
| 2 | |
| 3 | /*TODO: |
| 4 | regs_modified bei struct-copy |
| 5 | savings verfeinern |
| 6 | 4-Byte Copy |
| 7 | [static] testen |
| 8 | peephole-Pass um ALLOCREGs zu entfernen |
| 9 | ACC_IND (Achtung?) |
| 10 | struct-copy Problemfälle |
| 11 | banked |
| 12 | bit |
| 13 | long long, float, double, long double |
| 14 | |
| 15 | */ |
| 16 | |
| 17 | #include "supp.h" |
| 18 | #include "vbc.h" /* nicht schoen, aber ... */ |
| 19 | |
| 20 | static char FILE_[]=__FILE__; |
| 21 | |
| 22 | #include "dwarf2.c" |
| 23 | |
| 24 | /* Public data that MUST be there. */ |
| 25 | |
| 26 | /* Name and copyright. */ |
| 27 | char cg_copyright[]="vbcc code-generator for 6809/6803/68hc12 V0.2 (c) in 2000-2022 by Volker Barthelmann"; |
| 28 | |
| 29 | /* Commandline-flags the code-generator accepts */ |
| 30 | int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0, |
| 31 | 0,0,0,0, |
| 32 | 0,0}; |
| 33 | char *g_flags_name[MAXGF]={"cpu","fpu","no-delayed-popping","const-in-data", |
| 34 | "merge-constants","no-peephole","mem-cse","acc-glob", |
| 35 | "pcrel","drel","no-char-addi2p","nodx","nou"}; |
| 36 | union ppi g_flags_val[MAXGF]; |
| 37 | |
| 38 | /* Typenames (needed because of HAVE_EXT_TYPES). */ |
| 39 | char *typname[]={"strange","bit","char","short","int","long","long long", |
| 40 | "float","double","long double","void", |
| 41 | "near-pointer","far-pointer","huge-pointer", |
| 42 | "array","struct","union","enum","function"}; |
| 43 | |
| 44 | int bitsperbyte = 8; |
| 45 | int bytemask = 0xff; |
| 46 | int dbl_bytemask = 0xffff; |
| 47 | |
| 48 | /* Alignment-requirements for all types in bytes. */ |
| 49 | zmax align[MAX_TYPE+1]; |
| 50 | |
| 51 | /* Alignment that is sufficient for every object. */ |
| 52 | zmax maxalign; |
| 53 | |
| 54 | /* CHAR_BIT of the target machine. */ |
| 55 | zmax char_bit; |
| 56 | |
| 57 | /* Sizes of all elementary types in bytes. */ |
| 58 | zmax sizetab[MAX_TYPE+1]; |
| 59 | |
| 60 | /* Minimum and Maximum values each type can have. */ |
| 61 | /* Must be initialized in init_cg(). */ |
| 62 | zmax t_min[MAX_TYPE+1]; |
| 63 | zumax t_max[MAX_TYPE+1]; |
| 64 | zumax tu_max[MAX_TYPE+1]; |
| 65 | |
| 66 | /* Names of all registers. */ |
| 67 | char *regnames[]={"noreg","d","x","y","sp","u","d/x"}; |
| 68 | |
| 69 | /* The Size of each register in bytes. */ |
| 70 | zmax regsize[MAXR+1]; |
| 71 | |
| 72 | /* Type which can store each register. */ |
| 73 | struct Typ *regtype[MAXR+1]; |
| 74 | |
| 75 | /* regsa[reg]!=0 if a certain register is allocated and should */ |
| 76 | /* not be used by the compiler pass. */ |
| 77 | int regsa[MAXR+1]; |
| 78 | |
| 79 | /* Specifies which registers may be scratched by functions. */ |
| 80 | int regscratch[MAXR+1]={0,1,1,0,1,0}; |
| 81 | |
| 82 | int reg_prio[MAXR+1]={0,0,1,1,0,0}; |
| 83 | |
| 84 | struct reg_handle empty_reg_handle={0}; |
| 85 | |
| 86 | /* Names of target-specific variable attributes. */ |
| 87 | char *g_attr_name[]={"__interrupt","__dpage","__far",0}; |
| 88 | #define INTERRUPT 1 |
| 89 | #define DPAGE 2 |
| 90 | #define FAR 4 |
| 91 | |
| 92 | int MINADDI2P=CHAR; |
| 93 | |
| 94 | /****************************************/ |
| 95 | /* Some private data and functions. */ |
| 96 | /****************************************/ |
| 97 | |
| 98 | static long malign[MAX_TYPE+1]= {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; |
| 99 | static long msizetab[MAX_TYPE+1]={0,1,1,2,2,4,4,4,4,4,0,2,4,4,0,0,0,2,0}; |
| 100 | |
| 101 | struct Typ ityp={SHORT},ltyp={LONG}; |
| 102 | |
| 103 | #define DATA 0 |
| 104 | #define BSS 1 |
| 105 | #define CODE 2 |
| 106 | #define RODATA 3 |
| 107 | #define SPECIAL 4 |
| 108 | |
| 109 | static int section=-1,newobj,scnt,pushed_acc; |
| 110 | static char *codename="\t.text\n", |
| 111 | *dataname="\t.data\n", |
| 112 | *bssname="\t.section\t.bss\n", |
| 113 | *rodataname="\t.section\t.rodata\n"; |
| 114 | |
| 115 | #define IMM_IND 1 |
| 116 | #define VAR_IND 2 |
| 117 | #define POST_INC 3 |
| 118 | #define POST_DEC 4 |
| 119 | #define PRE_INC 5 |
| 120 | #define PRE_DEC 6 |
| 121 | #define ACC_IND 7 |
| 122 | #define KONSTINC 8 |
| 123 | |
| 124 | /* (user)stack-pointer, pointer-tmp, int-tmp; reserved for compiler */ |
| 125 | static int acc=1,ix=2,iy=3,sp=4,iu=5,dx=6; |
| 126 | static void pr(FILE *,struct IC *); |
| 127 | static void function_top(FILE *,struct Var *,long); |
| 128 | static void function_bottom(FILE *f,struct Var *,long); |
| 129 | |
| 130 | static char *marray[]={"__section(x,y)=__vattr(\"section(\"#x\",\"#y\")\")", |
| 131 | "__HC12__", |
| 132 | "__SIZE_T_INT=1", |
| 133 | "__direct=__vattr(\"section(\\\"dpage\\\")\")", |
| 134 | 0}; |
| 135 | |
| 136 | #define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG) |
| 137 | #define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST) |
| 138 | |
| 139 | static long loff,roff,stackoffset,notpopped,dontpop,maxpushed,stack; |
| 140 | |
| 141 | static char *x_t[]={"?","","b","","","","","","","","","","","","","",""}; |
| 142 | static char *ccs[]={"eq","ne","lt","ge","le","gt"}; |
| 143 | static char *uccs[]={"eq","ne","lo","hs","ls","hi"}; |
| 144 | static char *logicals[]={"ora","eor","and"}; |
| 145 | static char *dct[]={"",".bit",".byte",".2byte",".2byte",".4byte",".8byte",".4byte",".8byte",".8byte", |
| 146 | "(void)",".2byte",".34byte",".34byte"}; |
| 147 | static char *idprefix="",*labprefix=".l"; |
| 148 | static int exit_label,have_frame; |
| 149 | static char *ret; |
| 150 | static int stackchecklabel; |
| 151 | static int frame_used,stack_valid; |
| 152 | static int CPU=6812; |
| 153 | static int pcrel,drel; |
| 154 | static int skip_rel; |
| 155 | static char *jsrinst="jsr"; |
| 156 | static char *jmpinst="jmp"; |
| 157 | static int nodx,nou; |
| 158 | int switchsubs; |
| 159 | |
| 160 | static int cc_t; |
| 161 | static struct obj *cc; |
| 162 | |
| 163 | static struct obj mobj; |
| 164 | |
| 165 | #define STR_NEAR "near" |
| 166 | #define STR_FAR "far" |
| 167 | #define STR_HUGE "huge" |
| 168 | #define STR_BADDR "baddr" |
| 169 | |
| 170 | #define ISNULL() (zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&zldeqto(vldouble,d2zld(0.0))) |
| 171 | #define ISLWORD(t) ((t&NQ)==LONG||(t&NQ)==FPOINTER||(t&NQ)==HPOINTER||(t&NQ)==FLOAT) |
| 172 | #define ISHWORD(t) ((t&NQ)==INT||(t&NQ)==SHORT||(t&NQ)==NPOINTER) |
| 173 | #define ISCHWORD(t) ((t&NQ)==CHAR||ISHWORD(t)) |
| 174 | #define ISSTATIC(v) ((v)->storage_class==EXTERN||(v)->storage_class==STATIC) |
| 175 | #define ISBADDR(v) ((v)->vtyp->attr&&strstr(STR_BADDR,(v)->vtyp->attr)) |
| 176 | /*FIXME*/ |
| 177 | #define ISFAR(v) ((v)->vtyp->attr&&(strstr(STR_FAR,(v)->vtyp->attr)||strstr(STR_HUGE,(v)->vtyp->attr))) |
| 178 | |
| 179 | #define ISACC(x) ((x)==acc) |
| 180 | #define ISX(x) ((x)==ix) |
| 181 | #define ISY(x) ((x)==iy) |
| 182 | #define ISU(x) ((x)==iu) |
| 183 | #define ISIDX(x) (ISX(x)||ISY(x)||(ISU(x)&&CPU!=6812)) |
| 184 | #define ISRACC(x) (isreg(x)&&ISACC(p->x.reg)) |
| 185 | #define ISRX(x) (isreg(x)&&ISX(p->x.reg)) |
| 186 | #define ISRY(x) (isreg(x)&&ISY(p->x.reg)) |
| 187 | #define ISRU(x) (isreg(x)&&ISU(p->x.reg)) |
| 188 | #define ISRIDX(x) (isreg(x)&&ISIDX(p->x.reg)) |
| 189 | |
| 190 | #define CPUOPT ((g_flags[0]&USEDFLAG)?g_flags_val[0].l:6812) |
| 191 | |
| 192 | #define SPUSH(x) (CPU==6812?"\tpsh" x "\n":"\tpshs\t" x "\n") |
| 193 | #define SPUSHD (CPU==6812?"\tpshd\n":"\tpshs\tb,a\n") |
| 194 | #define SPULL(x) (CPU==6812?"\tpul" x "\n":"\tpuls\t" x "\n") |
| 195 | #define SPULLD (CPU==6812?"\tpuld\n":"\tpuls\ta,b\n") |
| 196 | #define SCMP(x) (CPU==6812?"\tcp" x "\t":"\tcmp" x "\t") |
| 197 | #define SEX (CPU==6812?"\tsex\tb,d\n":"\tsex\n") |
| 198 | |
| 199 | #define SGN16(x) (zm2l(zi2zm(zm2zi(l2zm((long)(x)))))) |
| 200 | |
| 201 | enum peepf { NEEDSAME = 1, REMOVE1ST = 2, ALLOWSFX = 4}; |
| 202 | struct peeps {char *s1,*s2,*r;enum peepf flags;}; |
| 203 | |
| 204 | static int check_sfx(char *s) |
| 205 | { |
| 206 | if(!*s) return 0; |
| 207 | s+=strlen(s)-1; |
| 208 | if(*s=='+'||*s=='-') return 1; |
| 209 | if(*s!='s'&&*s!='x'&&*s!='y'&&*s!='u') return 0; |
| 210 | s--; |
| 211 | if(*s!=',') return 0; |
| 212 | s--; |
| 213 | if(*s=='+'||*s=='-') return 1; |
| 214 | return 0; |
| 215 | } |
| 216 | |
| 217 | static int setszflag(char *op,char r) |
| 218 | { |
| 219 | static char *zb[]={"adcb","addb","andb","aslb","asrb","clrb","comb","decb","eorb","incb", |
| 220 | "ldab","ldb","lslb","lsrb","negb","orb","orab","rolb","rorb","sbcb", |
| 221 | "stb","stab","subb","tstb"}; |
| 222 | static char *zd[]={"addd","ldd","sex","std","subd"}; |
| 223 | |
| 224 | int i; |
| 225 | |
| 226 | if(r=='b'){ |
| 227 | for(i=0;i<sizeof(zb)/sizeof(*zb);i++) |
| 228 | if(!strcmp(op,zb[i])) |
| 229 | return 1; |
| 230 | } |
| 231 | if(r=='d'){ |
| 232 | for(i=0;i<sizeof(zd)/sizeof(*zd);i++) |
| 233 | if(!strcmp(op,zd[i])) |
| 234 | return 1; |
| 235 | } |
| 236 | if(r=='x'&&(!strcmp(op,"leax")||!strcmp(op,"ldx"))) return 1; |
| 237 | if(r=='y'&&(!strcmp(op,"leay")||!strcmp(op,"ldy"))) return 1; |
| 238 | if(CPU==6812){ |
| 239 | if(r=='x'&&(!strcmp(op,"dex")||!strcmp(op,"inx"))) return 1; |
| 240 | if(r=='y'&&(!strcmp(op,"dey")||!strcmp(op,"iny"))) return 1; |
| 241 | } |
| 242 | return 0; |
| 243 | } |
| 244 | |
| 245 | int emit_peephole(void) |
| 246 | { |
| 247 | int entries,i,j,v1,v2; |
| 248 | char *asmline[EMIT_BUF_DEPTH]; |
| 249 | char buf1[1024],buf2[1024]; |
| 250 | char op1[8],op2[8]; |
| 251 | |
| 252 | |
| 253 | /* TODO: adapt better */ |
| 254 | static struct peeps elim[]={ |
| 255 | "lda","sta",0,NEEDSAME, |
| 256 | "ldb","stb",0,NEEDSAME, |
| 257 | "ldaa","staa",0,NEEDSAME, |
| 258 | "ldab","stab",0,NEEDSAME, |
| 259 | "ldd","std",0,NEEDSAME, |
| 260 | "ldx","stx",0,NEEDSAME, |
| 261 | "ldy","sty",0,NEEDSAME, |
| 262 | "ldu","stu",0,NEEDSAME, |
| 263 | "sta","sta",0,NEEDSAME, |
| 264 | "stb","stb",0,NEEDSAME, |
| 265 | "staa","staa",0,NEEDSAME, |
| 266 | "stab","stab",0,NEEDSAME, |
| 267 | "std","std",0,NEEDSAME, |
| 268 | "stx","stx",0,NEEDSAME, |
| 269 | "sty","sty",0,NEEDSAME, |
| 270 | "stu","stu",0,NEEDSAME, |
| 271 | "sta","lda",0,NEEDSAME, |
| 272 | "stb","ldb",0,NEEDSAME, |
| 273 | "staa","ldaa",0,NEEDSAME, |
| 274 | "stab","ldab",0,NEEDSAME, |
| 275 | "std","ldd",0,NEEDSAME, |
| 276 | "stx","ldx",0,NEEDSAME, |
| 277 | "sty","ldy",0,NEEDSAME, |
| 278 | "stu","ldu",0,NEEDSAME, |
| 279 | #if 0 |
| 280 | "lda","lda",0,REMOVE1ST, |
| 281 | "ldaa","ldaa",0,REMOVE1ST, |
| 282 | "ldab","ldab",0,REMOVE1ST, |
| 283 | "ldb","ldb",0,REMOVE1ST, |
| 284 | "ldd","ldd",0,REMOVE1ST, |
| 285 | "ldx","ldx",0,REMOVE1ST, |
| 286 | "ldy","ldy",0,REMOVE1ST, |
| 287 | "ldu","ldu",0,REMOVE1ST, |
| 288 | "lda","pla",0,REMOVE1ST, |
| 289 | "lda","txa",0,REMOVE1ST, |
| 290 | "lda","tya",0,REMOVE1ST, |
| 291 | "ldx","tax",0,REMOVE1ST, |
| 292 | "ldy","tay",0,REMOVE1ST, |
| 293 | "tay","ldy",0,REMOVE1ST, |
| 294 | "tax","ldx",0,REMOVE1ST, |
| 295 | "txa","lda",0,REMOVE1ST, |
| 296 | "tya","lda",0,REMOVE1ST, |
| 297 | #endif |
| 298 | }; |
| 299 | |
| 300 | |
| 301 | i=emit_l; |
| 302 | if(emit_f==0) |
| 303 | entries=i-emit_f+1; |
| 304 | else |
| 305 | entries=EMIT_BUF_DEPTH; |
| 306 | asmline[0]=emit_buffer[i]; |
| 307 | if(sscanf(asmline[0]," %6s %999s",op1,buf1)==2&&!strcmp(op1,"cmpb")&&!strcmp(buf1,"#0")) |
| 308 | strcpy(asmline[0],"\ttstb\n"); |
| 309 | if(sscanf(asmline[0]," %6s %999s",op1,buf1)==2&&!strcmp(op1,"cmpd")&&!strcmp(buf1,"#0")) |
| 310 | strcpy(asmline[0],"\tsubd\t#0\n"); |
| 311 | |
| 312 | if(entries>=2){ |
| 313 | i--; |
| 314 | if(i<0) i=EMIT_BUF_DEPTH-1; |
| 315 | asmline[1]=emit_buffer[i]; |
| 316 | |
| 317 | for(j=0;j<sizeof(elim)/sizeof(elim[0]);j++){ |
| 318 | if(elim[j].flags&NEEDSAME){ |
| 319 | if(sscanf(asmline[0]," %6s %999s",op2,buf2)==2&& |
| 320 | sscanf(asmline[1]," %6s %999s",op1,buf1)==2&& |
| 321 | !strcmp(op1,elim[j].s1)&&!strcmp(op2,elim[j].s2)&& |
| 322 | !strcmp(buf1,buf2)){ |
| 323 | if(!check_sfx(buf1)&&!check_sfx(buf2)){ |
| 324 | if(elim[j].r){ |
| 325 | strcpy(asmline[0],elim[j].r); |
| 326 | }else{ |
| 327 | if(elim[j].flags&REMOVE1ST) |
| 328 | strcpy(asmline[1],asmline[0]); |
| 329 | remove_asm(); |
| 330 | } |
| 331 | return 1; |
| 332 | } |
| 333 | } |
| 334 | }else{ |
| 335 | *buf1=0;*buf2=0; |
| 336 | if(sscanf(asmline[1]," %6s %999s",op1,buf1)>=1&& |
| 337 | sscanf(asmline[0]," %6s %999s",op2,buf2)>=1&& |
| 338 | !strcmp(op1,elim[j].s1)&&!strcmp(op2,elim[j].s2)){ |
| 339 | if((elim[j].flags&ALLOWSFX)||(!check_sfx(buf1)&&!check_sfx(buf2))){ |
| 340 | if(elim[j].flags&REMOVE1ST) |
| 341 | strcpy(asmline[1],asmline[0]); |
| 342 | remove_asm(); |
| 343 | return 1; |
| 344 | } |
| 345 | } |
| 346 | } |
| 347 | } |
| 348 | |
| 349 | if(!strcmp(asmline[0],"\trts\n")&&sscanf(asmline[1]," %6s %999s",op1,buf1)==2&&!strcmp(op1,"puls")){ |
| 350 | sprintf(asmline[1]+strlen(asmline[1])-1,",pc\n"); |
| 351 | remove_asm(); |
| 352 | return 1; |
| 353 | } |
| 354 | |
| 355 | if(!strcmp(asmline[0],"\tstb\t0,s\n")&&!strcmp(asmline[1],"\tleas\t-1,s\n")){ |
| 356 | strcpy(asmline[1],"\tpshs\tb\n"); |
| 357 | remove_asm(); |
| 358 | return 1; |
| 359 | } |
| 360 | |
| 361 | if(!strcmp(asmline[0],"\tstd\t0,s\n")&&!strcmp(asmline[1],"\tleas\t-2,s\n")){ |
| 362 | strcpy(asmline[1],"\tpshs\tb,a\n"); |
| 363 | remove_asm(); |
| 364 | return 1; |
| 365 | } |
| 366 | |
| 367 | if(!strcmp(asmline[0],"\tldb\t0,s\n")&&!strcmp(asmline[1],"\tpshs\tb\n")){ |
| 368 | remove_asm(); |
| 369 | return 1; |
| 370 | } |
| 371 | |
| 372 | if(!strcmp(asmline[0],"\tldd\t0,s\n")&&!strcmp(asmline[1],"\tpshs\tb,a\n")){ |
| 373 | remove_asm(); |
| 374 | return 1; |
| 375 | } |
| 376 | |
| 377 | if(!strcmp(asmline[0],"\tpshs\tb,a\n")&&!strcmp(asmline[1],"\tpuls\ta,b\n")){ |
| 378 | strcpy(asmline[1],"\tldd\t0,s\n"); |
| 379 | remove_asm(); |
| 380 | return 1; |
| 381 | } |
| 382 | |
| 383 | if(sscanf(asmline[1]," ldd %999s",op1)>=1&&sscanf(asmline[0]," ldd %999s",op2)>=1){ |
| 384 | if(!((op2[0]=='a'||op2[0]=='b'||op2[0]=='d')&&op2[1]==',')){ |
| 385 | strcpy(asmline[1],asmline[0]); |
| 386 | remove_asm(); |
| 387 | return 1; |
| 388 | } |
| 389 | } |
| 390 | |
| 391 | if(!strcmp(asmline[0],"\ttfr\tx,d\n")&&!strcmp(asmline[1],"\ttfr\td,x\n")){ |
| 392 | remove_asm(); |
| 393 | return 1; |
| 394 | } |
| 395 | if(!strcmp(asmline[0],"\ttfr\ty,d\n")&&!strcmp(asmline[1],"\ttfr\td,y\n")){ |
| 396 | remove_asm(); |
| 397 | return 1; |
| 398 | } |
| 399 | if(!strcmp(asmline[0],"\tstd\t0,sp\n")&&!strcmp(asmline[1],"\tpshd\n")){ |
| 400 | remove_asm(); |
| 401 | return 1; |
| 402 | } |
| 403 | if(!strcmp(asmline[0],"\tldd\t0,sp\n")&&!strcmp(asmline[1],"\tpshd\n")){ |
| 404 | remove_asm(); |
| 405 | return 1; |
| 406 | } |
| 407 | |
| 408 | if(sscanf(asmline[0]," leas %d,s",&v1)==1&&sscanf(asmline[1]," leas %d,s",&v2)==1){ |
| 409 | sprintf(asmline[1],"\tleas\t%ld,s\n",SGN16(v1+v2)); |
| 410 | remove_asm(); |
| 411 | return 1; |
| 412 | } |
| 413 | |
| 414 | if(CPU!=6812&&sscanf(asmline[0]," tfr %c,%c",buf1,buf2)==2){ |
| 415 | if((*buf1=='x'||*buf1=='y'||*buf1=='u'||*buf1=='s')&& |
| 416 | (*buf2=='x'||*buf2=='y'||*buf2=='u'||*buf2=='s')){ |
| 417 | sprintf(asmline[0],"\tlea%c\t,%c\n",*buf2,*buf1); |
| 418 | } |
| 419 | } |
| 420 | if(CPU==6812&&(!strcmp(asmline[1],"\tdex\n")||!strcmp(asmline[1],"\tdey\n")||!strcmp(asmline[1],"\tsubd\t#1\n"))&& |
| 421 | (!strncmp(asmline[0],"\tbne\t",5)||!strncmp(asmline[0],"\tbeq\t",5))){ |
| 422 | char r=asmline[1][3]; |
| 423 | if(r=='b') r='d'; |
| 424 | strcpy(asmline[1],"\td"); |
| 425 | strncpy(asmline[1]+2,asmline[0]+1,4); |
| 426 | asmline[1][6]=r;asmline[1][7]=','; |
| 427 | strcpy(asmline[1]+8,asmline[0]+5); |
| 428 | remove_asm(); |
| 429 | return 1; |
| 430 | } |
| 431 | if(CPU==6812&&(!strcmp(asmline[1],"\tinx\n")||!strcmp(asmline[1],"\tiny\n")||!strcmp(asmline[1],"\taddd\t#1\n"))&& |
| 432 | (!strncmp(asmline[0],"\tbne\t",5)||!strncmp(asmline[0],"\tbeq\t",5))){ |
| 433 | char r=asmline[1][3]; |
| 434 | strcpy(asmline[1],"\ti"); |
| 435 | strncpy(asmline[1]+2,asmline[0]+1,4); |
| 436 | asmline[1][6]=r;asmline[1][7]=','; |
| 437 | strcpy(asmline[1]+8,asmline[0]+5); |
| 438 | remove_asm(); |
| 439 | return 1; |
| 440 | } |
| 441 | } |
| 442 | if(entries>=3){ |
| 443 | i--; |
| 444 | if(i<0) i=EMIT_BUF_DEPTH-1; |
| 445 | asmline[2]=emit_buffer[i]; |
| 446 | if(sscanf(asmline[0]," %6s %999s",op1,buf1)==2){ |
| 447 | if(!strcmp(op1,"beq")||!strcmp(op1,"bne")){ |
| 448 | if(!strcmp(asmline[1],"\ttstb\n")||!strcmp(asmline[1],"\tcpb\t#0\n")){ |
| 449 | if(sscanf(asmline[2]," %6s %999s",op2,buf2)>=1&& |
| 450 | setszflag(op2,'b')){ |
| 451 | strcpy(asmline[1],asmline[0]); |
| 452 | remove_asm(); |
| 453 | return 1; |
| 454 | } |
| 455 | } |
| 456 | if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&& |
| 457 | (!strcmp(op2,"subd")||!strcmp(op2,"cpd"))&&!strcmp(buf2,"#0")){ |
| 458 | if(sscanf(asmline[2]," %6s %999s",op2,buf2)>=1&& |
| 459 | setszflag(op2,'d')){ |
| 460 | strcpy(asmline[1],asmline[0]); |
| 461 | remove_asm(); |
| 462 | return 1; |
| 463 | } |
| 464 | } |
| 465 | if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&& |
| 466 | !strcmp(op2,(CPU==6812)?"cpx":"cmpx")&&!strcmp(buf2,"#0")){ |
| 467 | if(sscanf(asmline[2]," %6s %999s",op2,buf2)>=1&& |
| 468 | setszflag(op2,'x')){ |
| 469 | strcpy(asmline[1],asmline[0]); |
| 470 | remove_asm(); |
| 471 | return 1; |
| 472 | } |
| 473 | } |
| 474 | if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&& |
| 475 | !strcmp(op2,(CPU==6812)?"cpy":"cmpy")&&!strcmp(buf2,"#0")){ |
| 476 | if(sscanf(asmline[2]," %6s %999s",op2,buf2)>=1&& |
| 477 | setszflag(op2,'y')){ |
| 478 | strcpy(asmline[1],asmline[0]); |
| 479 | remove_asm(); |
| 480 | return 1; |
| 481 | } |
| 482 | } |
| 483 | } |
| 484 | } |
| 485 | } |
| 486 | return 0; |
| 487 | } |
| 488 | |
| 489 | static int special_section(FILE *f,struct Var *v) |
| 490 | { |
| 491 | char *sec; |
| 492 | if(v->tattr&DPAGE){ |
| 493 | emit(f,"\t.section\t.dpage\n"); |
| 494 | }else{ |
| 495 | if(!v->vattr) return 0; |
| 496 | sec=strstr(v->vattr,"section("); |
| 497 | if(!sec) return 0; |
| 498 | sec+=strlen("section("); |
| 499 | emit(f,"\t.section\t"); |
| 500 | while(*sec&&*sec!=')') emit_char(f,*sec++); |
| 501 | emit(f,"\n"); |
| 502 | } |
| 503 | if(f) section=SPECIAL; |
| 504 | return 1; |
| 505 | } |
| 506 | |
| 507 | static struct fpconstlist { |
| 508 | struct fpconstlist *next; |
| 509 | int label,typ; |
| 510 | union atyps val; |
| 511 | } *firstfpc; |
| 512 | |
| 513 | static int addfpconst(struct obj *o,int t) |
| 514 | { |
| 515 | struct fpconstlist *p=firstfpc; |
| 516 | t&=NQ; |
| 517 | if(g_flags[4]&USEDFLAG){ |
| 518 | for(p=firstfpc;p;p=p->next){ |
| 519 | if(t==p->typ){ |
| 520 | eval_const(&p->val,t); |
| 521 | if(t==FLOAT&&zldeqto(vldouble,zf2zld(o->val.vfloat))) return p->label; |
| 522 | if(t==DOUBLE&&zldeqto(vldouble,zd2zld(o->val.vdouble))) return p->label; |
| 523 | if(t==LDOUBLE&&zldeqto(vldouble,o->val.vldouble)) return p->label; |
| 524 | } |
| 525 | } |
| 526 | } |
| 527 | p=mymalloc(sizeof(struct fpconstlist)); |
| 528 | p->next=firstfpc; |
| 529 | p->label=++label; |
| 530 | p->typ=t; |
| 531 | p->val=o->val; |
| 532 | firstfpc=p; |
| 533 | return p->label; |
| 534 | } |
| 535 | |
| 536 | int pointer_type(struct Typ *p) |
| 537 | { |
| 538 | if(!p) ierror(0); |
| 539 | while((p->flags&NQ)==ARRAY) p=p->next; |
| 540 | if((p->flags&NQ)==FUNKT) { |
| 541 | if(p->attr) |
| 542 | if(strstr(p->attr,STR_FAR)) return FPOINTER; |
| 543 | if (p->flags&FAR) |
| 544 | return FPOINTER; |
| 545 | return NPOINTER; /*FIXME: banked*/ |
| 546 | } |
| 547 | if(p->attr){ |
| 548 | if(strstr(p->attr,STR_HUGE)) return HPOINTER; |
| 549 | if(strstr(p->attr,STR_FAR)) return FPOINTER; |
| 550 | if(strstr(p->attr,STR_NEAR)) return NPOINTER; |
| 551 | } |
| 552 | /*FIXME*/ |
| 553 | return NPOINTER; |
| 554 | } |
| 555 | static long voff(struct obj *p) |
| 556 | { |
| 557 | if(zm2l(p->v->offset)<0) |
| 558 | return loff-zm2l(p->v->offset)+zm2l(p->val.vmax)-stackoffset+1; |
| 559 | else |
| 560 | return zm2l(p->v->offset)+zm2l(p->val.vmax)-stackoffset; |
| 561 | } |
| 562 | |
| 563 | static void emit_obj(FILE *f,struct obj *p,int t) |
| 564 | /* Gibt Objekt auf Bildschirm aus */ |
| 565 | { |
| 566 | if(p->am){ |
| 567 | int flags=p->am->flags; |
| 568 | if(flags==ACC_IND){ |
| 569 | emit(f,"%s,%s",regnames[acc],regnames[p->am->base]); |
| 570 | return; |
| 571 | } |
| 572 | if(flags==KONSTINC){ |
| 573 | eval_const(&p->val,p->am->base); |
| 574 | if((t&NQ)==CHAR){ |
| 575 | vumax=zumrshift(vumax,bitsperbyte*3-bitsperbyte*p->am->offset); |
| 576 | vumax=zumand(vumax,ul2zum(tu_max[CHAR])); |
| 577 | }else{ |
| 578 | vumax=zumrshift(vumax,bitsperbyte*2-bitsperbyte*p->am->offset); |
| 579 | vumax=zumand(vumax,ul2zum(tu_max[SHORT])); |
| 580 | } |
| 581 | emit(f,"#%lu",zum2ul(vumax)); |
| 582 | return; |
| 583 | } |
| 584 | if(flags<POST_INC||flags>PRE_DEC||CPU==6812) |
| 585 | emit(f,"%ld",p->am->offset&tu_max[SHORT]); |
| 586 | if(p->am->v){ |
| 587 | if(p->am->v->storage_class==STATIC) |
| 588 | emit(f,"+%s%ld",labprefix,zm2l(p->am->v->offset)); |
| 589 | else |
| 590 | emit(f,"+(%s%s)",idprefix,p->am->v->identifier); |
| 591 | } |
| 592 | emit(f,","); |
| 593 | if(flags==PRE_INC){ |
| 594 | emit(f,"+"); |
| 595 | if(p->am->offset==2&&CPU!=6812) emit(f,"+"); |
| 596 | }else if(flags==PRE_DEC){ |
| 597 | emit(f,"-"); |
| 598 | if(p->am->offset==2&&CPU!=6812) emit(f,"-"); |
| 599 | } |
| 600 | emit(f,"%s",regnames[p->am->base]); |
| 601 | if(flags==POST_INC){ |
| 602 | emit(f,"+"); |
| 603 | if(p->am->offset==2&&CPU!=6812) emit(f,"+"); |
| 604 | }else if(flags==POST_DEC){ |
| 605 | emit(f,"-"); |
| 606 | if(p->am->offset==2&&CPU!=6812) emit(f,"-"); |
| 607 | } |
| 608 | return; |
| 609 | } |
| 610 | if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){ |
| 611 | emitval(f,&p->val,p->dtyp&NU); |
| 612 | return; |
| 613 | } |
| 614 | if(p->flags&VARADR) emit(f,"#"); |
| 615 | if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) emit(f,"0,"); |
| 616 | if((p->flags&(DREFOBJ|REG))==DREFOBJ) emit(f,"["); |
| 617 | if((p->flags&(VAR|REG))==VAR){ |
| 618 | if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){ |
| 619 | emit(f,"%ld,%s",voff(p),regnames[sp]); |
| 620 | }else{ |
| 621 | if(!zmeqto(l2zm(0L),p->val.vmax)){ |
| 622 | emit(f,"%ld",zm2l(zi2zm(zm2zi(p->val.vmax)))); |
| 623 | emit(f,"+"); |
| 624 | } |
| 625 | if(p->v->storage_class==STATIC){ |
| 626 | emit(f,"%s%ld",labprefix,zm2l(p->v->offset)); |
| 627 | }else{ |
| 628 | emit(f,"(%s%s)",idprefix,p->v->identifier); |
| 629 | } |
| 630 | if(pcrel&&!(p->flags&VARADR)&&ISFUNC(p->v->vtyp->flags)) |
| 631 | emit(f,",pc"); |
| 632 | if(drel&&!(p->flags&VARADR)&&!ISFUNC(p->v->vtyp->flags)){ |
| 633 | if(CPU==6812) ierror(0); |
| 634 | emit(f,",%s",regnames[iu]); |
| 635 | } |
| 636 | } |
| 637 | } |
| 638 | if(p->flags®){ |
| 639 | if(ISACC(p->reg)&&(t&NQ)==CHAR) |
| 640 | emit(f,"b"); |
| 641 | else |
| 642 | emit(f,"%s",regnames[p->reg]); |
| 643 | } |
| 644 | if(p->flags&KONST){ |
| 645 | if(ISFLOAT(t)){ |
| 646 | emit(f,"%s%d",labprefix,addfpconst(p,t)); |
| 647 | }else{ |
| 648 | emit(f,"#");emitval(f,&p->val,t&NU); |
| 649 | } |
| 650 | } |
| 651 | if((p->flags&(DREFOBJ|REG))==DREFOBJ){ |
| 652 | if(p->v->storage_class==EXTERN||p->v->storage_class==STATIC){ |
| 653 | if(is_const(p->v->vtyp)){ |
| 654 | if(!pcrel&&CPU==6812) emit(f,",pc"); |
| 655 | }else{ |
| 656 | if(!drel&&CPU==6812) emit(f,",pc"); |
| 657 | } |
| 658 | } |
| 659 | emit(f,"]"); |
| 660 | } |
| 661 | } |
| 662 | |
| 663 | static void dwarf2_print_frame_location(FILE *f,struct Var *v) |
| 664 | { |
| 665 | /*FIXME: needs a location list and correct register translation */ |
| 666 | struct obj o; |
| 667 | o.flags=REG; |
| 668 | o.reg=sp; |
| 669 | o.val.vmax=l2zm(0L); |
| 670 | o.v=0; |
| 671 | dwarf2_print_location(f,&o); |
| 672 | } |
| 673 | static int dwarf2_regnumber(int r) |
| 674 | { |
| 675 | /*FIXME: always returns D as accumulator, even if byte size */ |
| 676 | static int dwarf_regs[MAXR+1]={-1,3,7,8,15}; |
| 677 | return dwarf_regs[r]; |
| 678 | } |
| 679 | static zmax dwarf2_fboffset(struct Var *v) |
| 680 | { |
| 681 | /*FIXME*/ |
| 682 | if(!v||(v->storage_class!=AUTO&&v->storage_class!=REGISTER)) ierror(0); |
| 683 | if(!zmleq(l2zm(0L),v->offset)) |
| 684 | return l2zm((long)(loff-zm2l(v->offset))); |
| 685 | else |
| 686 | return v->offset; |
| 687 | } |
| 688 | |
| 689 | /* test operand for mov instruction */ |
| 690 | static int mov_op(struct obj *o) |
| 691 | { |
| 692 | long off; |
| 693 | if(CPU!=6812) return 0; |
| 694 | if(o->am){ |
| 695 | int f=o->am->flags; |
| 696 | if(f==POST_INC||f==PRE_INC||f==POST_DEC||f==PRE_DEC||f==ACC_IND) |
| 697 | return 1; |
| 698 | if(f==IMM_IND){ |
| 699 | if(o->am->v) return 0; |
| 700 | off=o->am->offset; |
| 701 | if(off>=-256&&off<=255) |
| 702 | return 1; |
| 703 | else |
| 704 | return 0; |
| 705 | } |
| 706 | ierror(0); |
| 707 | } |
| 708 | if(o->flags&(KONST|VARADR)) return 1; |
| 709 | if((o->flags&(REG|DREFOBJ))==(REG|DREFOBJ)) return 1; |
| 710 | if((o->flags&(VAR|REG|DREFOBJ))==VAR){ |
| 711 | if(o->v->storage_class==STATIC||o->v->storage_class==EXTERN) |
| 712 | return 1; |
| 713 | off=voff(o); |
| 714 | if(off>=-256&&off<=255) |
| 715 | return 1; |
| 716 | else |
| 717 | return 0; |
| 718 | } |
| 719 | return 0; |
| 720 | } |
| 721 | |
| 722 | /* add an offset to an object describing a memory address */ |
| 723 | static void inc_addr(struct obj *o,long val,int t) |
| 724 | { |
| 725 | if(o->am){ |
| 726 | int f=o->am->flags; |
| 727 | if(f==IMM_IND||f==KONSTINC) |
| 728 | o->am->offset+=val; |
| 729 | else if(f==POST_INC||f==POST_DEC||f==PRE_INC||f==PRE_DEC){ |
| 730 | struct AddressingMode *old=o->am; |
| 731 | o->am=mymalloc(sizeof(*o->am)); |
| 732 | o->am->flags=IMM_IND; |
| 733 | o->am->base=old->base; |
| 734 | o->am->v=0; |
| 735 | if(f==POST_DEC) o->am->offset=old->offset-val; |
| 736 | else if(f==POST_INC) o->am->offset=-old->offset+val; |
| 737 | else if(f==PRE_DEC) o->am->offset=val; |
| 738 | else o->am->offset=-val; |
| 739 | }else |
| 740 | ierror(0); |
| 741 | }else if(o->flags&DREFOBJ){ |
| 742 | struct AddressingMode *am; |
| 743 | o->am=am=mymalloc(sizeof(*am)); |
| 744 | am->flags=IMM_IND; |
| 745 | if(!o->reg) ierror(0); |
| 746 | am->base=o->reg; |
| 747 | am->offset=zm2l(val); |
| 748 | am->v=0; |
| 749 | }else if(o->flags&KONST){ |
| 750 | struct AddressingMode *am; |
| 751 | if(o->am) ierror(0); |
| 752 | o->am=am=mymalloc(sizeof(*am)); |
| 753 | am->flags=KONSTINC; |
| 754 | am->offset=zm2l(val); |
| 755 | am->base=t; |
| 756 | }else{ |
| 757 | o->val.vmax=zmadd(o->val.vmax,val); |
| 758 | } |
| 759 | } |
| 760 | |
| 761 | /* pushed on the stack by a callee, no pop needed */ |
| 762 | static void callee_push(long l) |
| 763 | { |
| 764 | if(l-stackoffset>stack) |
| 765 | stack=l-stackoffset; |
| 766 | } |
| 767 | static void push(long l) |
| 768 | { |
| 769 | stackoffset-=l; |
| 770 | if(stackoffset<maxpushed) maxpushed=stackoffset; |
| 771 | if(-maxpushed>stack) stack=-maxpushed; |
| 772 | } |
| 773 | static void pop(long l) |
| 774 | { |
| 775 | stackoffset+=l; |
| 776 | } |
| 777 | static void gen_pop(FILE *f,long l) |
| 778 | { |
| 779 | if(l==0) return; |
| 780 | if(l==1&&CPU==6812){ |
| 781 | emit(f,"\tins\n"); |
| 782 | #if 0 /* might clobber return register */ |
| 783 | }else if(l==2&&!regs[acc]){ |
| 784 | emit(f,SPULLD); |
| 785 | BSET(regs_modified,acc); |
| 786 | }else if(l==2&&!regs[ix]){ |
| 787 | emit(f,SPULL("x")); |
| 788 | BSET(regs_modified,ix); |
| 789 | }else if(l==2&&!regs[iy]){ |
| 790 | emit(f,SPULL("y")); |
| 791 | BSET(regs_modified,iy); |
| 792 | #endif |
| 793 | }else{ |
| 794 | emit(f,"\tleas\t%u,%s\n",SGN16(l),regnames[sp]); |
| 795 | } |
| 796 | pop(l); |
| 797 | } |
| 798 | static void pr(FILE *f,struct IC *p) |
| 799 | { |
| 800 | int r; |
| 801 | if(pushed_acc){ |
| 802 | emit(f,SPULLD); |
| 803 | pop(2); |
| 804 | pushed_acc=0; |
| 805 | } |
| 806 | for(r=MAXR;r>=1;r--){ |
| 807 | if(regs[r]&8){ |
| 808 | emit(f,"\t%s%s\n",CPU==6812?"pul":"puls\t",regnames[r]); |
| 809 | pop(2); |
| 810 | } |
| 811 | regs[r]&=~12; |
| 812 | } |
| 813 | } |
| 814 | static void function_top(FILE *f,struct Var *v,long offset) |
| 815 | /* erzeugt Funktionskopf */ |
| 816 | { |
| 817 | int i; |
| 818 | emit(f,"# offset=%ld\n",offset); |
| 819 | have_frame=0;stack_valid=1;stack=0; |
| 820 | if(!special_section(f,v)&§ion!=CODE){emit(f,codename);if(f) section=CODE;} |
| 821 | if(v->storage_class==EXTERN){ |
| 822 | if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC) |
| 823 | emit(f,"\t.global\t%s%s\n",idprefix,v->identifier); |
| 824 | emit(f,"%s%s:\n",idprefix,v->identifier); |
| 825 | }else{ |
| 826 | emit(f,"%s%ld:\n",labprefix,zm2l(v->offset)); |
| 827 | } |
| 828 | roff=0; |
| 829 | for(i=MAXR;i>0;i--){ |
| 830 | if(regused[i]&&!regscratch[i]&&!regsa[i]){ |
| 831 | have_frame=1; |
| 832 | loff+=2; |
| 833 | roff+=2; |
| 834 | if(i==iy) emit(f,SPUSH("y")); |
| 835 | else if(i==iu){ |
| 836 | if(CPU!=6812&®used[iy]){ |
| 837 | emit(f,"\tpshs\tu,y\n"); |
| 838 | loff+=2;roff+=2;i=iy; |
| 839 | }else |
| 840 | emit(f,SPUSH("u")); |
| 841 | }else |
| 842 | ierror(0); |
| 843 | } |
| 844 | } |
| 845 | if(stack_check){ |
| 846 | stackchecklabel=++label; |
| 847 | emit(f,"\tldy\t#%s%d\n",labprefix,stackchecklabel); |
| 848 | /* FIXME: banked */ |
| 849 | emit(f,"\t%s\t%s__stack_check\n",jsrinst,idprefix); |
| 850 | } |
| 851 | if(offset){ |
| 852 | if(CPU==6812&&offset==1) |
| 853 | emit(f,SPUSH("b")); |
| 854 | else if(CPU==6812&&offset==2) |
| 855 | emit(f,SPUSHD); |
| 856 | else |
| 857 | emit(f,"\tleas\t%ld,%s\n",SGN16(-offset),regnames[sp]); |
| 858 | have_frame=1; |
| 859 | } |
| 860 | } |
| 861 | static void function_bottom(FILE *f,struct Var *v,long offset) |
| 862 | /* erzeugt Funktionsende */ |
| 863 | { |
| 864 | int i; |
| 865 | offset-=roff; |
| 866 | if(offset){ |
| 867 | if(offset==1&&CPU==6812) |
| 868 | emit(f,"\tins\n"); |
| 869 | else if(offset==2&&CPU==6812&&!zmeqto(szof(v->vtyp->next),l2zm(4L))) |
| 870 | emit(f,SPULL("x")); |
| 871 | else if(offset==2&&CPU==6812&®used[iy]) |
| 872 | emit(f,SPULL("y")); |
| 873 | else |
| 874 | emit(f,"\tleas\t%ld,%s\n",SGN16(offset),regnames[sp]); |
| 875 | } |
| 876 | for(i=1;i<=MAXR;i++){ |
| 877 | if(regused[i]&&!regscratch[i]&&!regsa[i]){ |
| 878 | have_frame=1; |
| 879 | if(i==iy){ |
| 880 | if(CPU!=6812&®used[iu]&&!regscratch[iu]&&!regsa[iu]){ |
| 881 | emit(f,"\tpuls\tu,y\n"); |
| 882 | i=iu; |
| 883 | }else |
| 884 | emit(f,SPULL("y")); |
| 885 | }else if(i==iu) emit(f,SPULL("u")); |
| 886 | else |
| 887 | ierror(0); |
| 888 | } |
| 889 | } |
| 890 | if(ret) emit(f,"\t%s\n",ret); |
| 891 | if(v->storage_class==EXTERN){ |
| 892 | emit(f,"\t.type\t%s%s,@function\n",idprefix,v->identifier); |
| 893 | emit(f,"\t.size\t%s%s,$-%s%s\n",idprefix,v->identifier,idprefix,v->identifier); |
| 894 | }else{ |
| 895 | emit(f,"\t.type\t%s%ld,@function\n",labprefix,zm2l(v->offset)); |
| 896 | emit(f,"\t.size\t%s%ld,$-%s%ld\n",labprefix,zm2l(v->offset),labprefix,zm2l(v->offset)); |
| 897 | } |
| 898 | if(stack_check) |
| 899 | emit(f,"\t.equ\t%s%d,%ld\n",labprefix,stackchecklabel,offset-maxpushed); |
| 900 | if(stack_valid){ |
| 901 | if(!v->fi) v->fi=new_fi(); |
| 902 | v->fi->flags|=ALL_STACK; |
| 903 | v->fi->stack1=l2zm(stack+offset); |
| 904 | emit(f,"# stacksize=%ld\n",stack+offset); |
| 905 | emit(f,"\t.equ\t%s__stack_%s,%ld\n",idprefix,v->identifier,stack+offset); |
| 906 | } |
| 907 | } |
| 908 | static int compare_objects(struct obj *o1,struct obj *o2) |
| 909 | { |
| 910 | if(o1->flags==o2->flags&&o1->am==o2->am){ |
| 911 | if(!(o1->flags&VAR)||(o1->v==o2->v&&zmeqto(o1->val.vmax,o2->val.vmax))){ |
| 912 | if(!(o1->flags®)||o1->reg==o2->reg){ |
| 913 | return 1; |
| 914 | } |
| 915 | } |
| 916 | } |
| 917 | return 0; |
| 918 | } |
| 919 | |
| 920 | /*FIXME*/ |
| 921 | static void clear_ext_ic(struct ext_ic *p) |
| 922 | { |
| 923 | p->flags=0; |
| 924 | p->r=0; |
| 925 | p->offset=0; |
| 926 | } |
| 927 | static long pof2(zumax x) |
| 928 | /* Yields log2(x)+1 oder 0. */ |
| 929 | { |
| 930 | zumax p;int ln=1; |
| 931 | p=ul2zum(1L); |
| 932 | while(ln<=32&&zumleq(p,x)){ |
| 933 | if(zumeqto(x,p)) return ln; |
| 934 | ln++;p=zumadd(p,p); |
| 935 | } |
| 936 | return 0; |
| 937 | } |
| 938 | static void peephole(struct IC *p) |
| 939 | { |
| 940 | int c,c2,r,t;struct IC *p2; |
| 941 | struct AddressingMode *am; |
| 942 | zmax incmin,incmax; |
| 943 | if(CPU==6812){ |
| 944 | incmin=l2zm(-8L); |
| 945 | incmax=l2zm(8L); |
| 946 | }else{ |
| 947 | incmin=l2zm(-2L); |
| 948 | incmax=l2zm(2L); |
| 949 | } |
| 950 | frame_used=0; |
| 951 | for(;p;p=p->next){ |
| 952 | c=p->code; |
| 953 | if(!frame_used){ |
| 954 | if((p->q1.flags&(REG|VAR))==VAR&&!ISSTATIC(p->q1.v)) frame_used=1; |
| 955 | if((p->q2.flags&(REG|VAR))==VAR&&!ISSTATIC(p->q2.v)) frame_used=1; |
| 956 | if((p->z.flags&(REG|VAR))==VAR&&!ISSTATIC(p->z.v)) frame_used=1; |
| 957 | } |
| 958 | /* letztes Label merken */ |
| 959 | if(c!=FREEREG&&c!=ALLOCREG&&(c!=SETRETURN||!isreg(q1)||p->q1.reg!=p->z.reg)) exit_label=0; |
| 960 | if(c==LABEL) exit_label=p->typf; |
| 961 | #if 0 |
| 962 | /* and x,#const;bne/beq, FIXME */ |
| 963 | if(c==AND&&isconst(q2)&&isreg(z)){ |
| 964 | long bit; |
| 965 | eval_const(&p->q2.val,p->typf); |
| 966 | if(bit=pof2(vumax)){ |
| 967 | struct IC *cmp=0;int fr=0; |
| 968 | for(p2=p->next;p2;p2=p2->next){ |
| 969 | c2=p2->code; |
| 970 | if(c2==TEST){ |
| 971 | if((p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==p->z.reg){ |
| 972 | cmp=p2;continue; |
| 973 | } |
| 974 | } |
| 975 | if(c2==COMPARE&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==p->z.reg&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){ |
| 976 | eval_const(&p2->q2.val,p2->typf); |
| 977 | if(ISNULL()){ |
| 978 | cmp=p2;continue; |
| 979 | } |
| 980 | break; |
| 981 | } |
| 982 | if(c2==FREEREG&&p2->q1.reg==p->z.reg) {fr++;continue;} |
| 983 | if((c2==BNE||c2==BEQ)&&cmp&&fr==1){ |
| 984 | p->ext.flags=EXT_IC_BTST; |
| 985 | p2->ext.flags=EXT_IC_BTST; |
| 986 | p2->ext.offset=bit-1; |
| 987 | cmp->code=NOP; |
| 988 | cmp->q1.flags=cmp->q2.flags=cmp->z.flags=0; |
| 989 | break; |
| 990 | } |
| 991 | if(((p2->q1.flags®)&&p2->q1.reg==p->z.reg)||((p2->q2.flags®)&&p2->q2.reg==p->z.reg)||((p2->z.flags®)&&p2->z.reg==p->z.reg)) break; |
| 992 | if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break; |
| 993 | } |
| 994 | } |
| 995 | } |
| 996 | #endif |
| 997 | /* Try d,idx */ |
| 998 | if(c==ADDI2P&&ISRACC(q2)&&ISRIDX(z)&&(ISRIDX(q1)||p->q2.reg!=p->z.reg)){ |
| 999 | int base,idx;struct obj *o; |
| 1000 | r=p->z.reg;idx=p->q2.reg; |
| 1001 | if(isreg(q1)) base=p->q1.reg; else base=r; |
| 1002 | o=0; |
| 1003 | for(p2=p->next;p2;p2=p2->next){ |
| 1004 | c2=p2->code; |
| 1005 | if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break; |
| 1006 | if(c2!=FREEREG&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r) break; |
| 1007 | if(c2!=FREEREG&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==r) break; |
| 1008 | if((p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==idx&&idx!=r) break; |
| 1009 | |
| 1010 | if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/){ |
| 1011 | if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){ |
| 1012 | if(o||!ISCHWORD(q1typ(p2))) break; |
| 1013 | o=&p2->q1; |
| 1014 | } |
| 1015 | if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){ |
| 1016 | break; /*TODO: check what is possible */ |
| 1017 | if(o||!ISCHWORD(q2typ(p2))) break; |
| 1018 | o=&p2->q2; |
| 1019 | } |
| 1020 | if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){ |
| 1021 | break; /*TODO: check what is possible */ |
| 1022 | if(o||!ISCHWORD(ztyp(p2))) break; |
| 1023 | o=&p2->z; |
| 1024 | } |
| 1025 | } |
| 1026 | if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG){ |
| 1027 | int m; |
| 1028 | if(c2==FREEREG) |
| 1029 | m=p2->q1.reg; |
| 1030 | else |
| 1031 | m=p2->z.reg; |
| 1032 | if(m==r){ |
| 1033 | if(o){ |
| 1034 | o->am=am=mymalloc(sizeof(*am)); |
| 1035 | am->flags=ACC_IND; |
| 1036 | am->base=base; |
| 1037 | if(idx!=acc) ierror(0); |
| 1038 | am->offset=idx; |
| 1039 | if(isreg(q1)){ |
| 1040 | p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0; |
| 1041 | }else{ |
| 1042 | p->code=c=ASSIGN;p->q2.flags=0; |
| 1043 | p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ]; |
| 1044 | } |
| 1045 | } |
| 1046 | break; |
| 1047 | } |
| 1048 | if(c2!=FREEREG&&m==base) break; |
| 1049 | continue; |
| 1050 | } |
| 1051 | /* better no instructions between, accu used too much */ |
| 1052 | if(c2!=FREEREG&&c2!=ALLOCREG&&!o) break; |
| 1053 | } |
| 1054 | } |
| 1055 | /* POST_INC/DEC in q1 */ |
| 1056 | if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){ |
| 1057 | r=p->q1.reg; t=q1typ(p); |
| 1058 | if(ISCHWORD(t)&&ISIDX(r)&&(!(p->q2.flags®)||p->q2.reg!=r)&&(!(p->z.flags®)||p->z.reg!=r)){ |
| 1059 | for(p2=p->next;p2;p2=p2->next){ |
| 1060 | c2=p2->code; |
| 1061 | if((c2==ADD||c2==ADDI2P||(CPU==6812&&(c2==SUB||c2==SUBIFP)))&&(p2->q1.flags&(REG|DREFOBJ))==REG&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){ |
| 1062 | eval_const(&p2->q2.val,p2->typf2); |
| 1063 | if(c2==SUB||c2==SUBIFP) vmax=zmsub(l2zm(0L),vmax); |
| 1064 | if(zmleq(vmax,incmax)&&zmleq(incmin,vmax)){ |
| 1065 | p2->code=NOP; |
| 1066 | p2->q1.flags=p2->q2.flags=p2->z.flags=0; |
| 1067 | p->q1.am=mymalloc(sizeof(*am)); |
| 1068 | p->q1.am->base=r; |
| 1069 | p->q1.am->v=0; |
| 1070 | if(zmleq(vmax,l2zm(0L))){ |
| 1071 | p->q1.am->flags=POST_DEC; |
| 1072 | p->q1.am->offset=-zm2l(vmax); |
| 1073 | }else{ |
| 1074 | p->q1.am->flags=POST_INC; |
| 1075 | p->q1.am->offset=zm2l(vmax); |
| 1076 | } |
| 1077 | }else break; |
| 1078 | } |
| 1079 | if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break; |
| 1080 | if(((p2->q1.flags®)&&p2->q1.reg==r)||((p2->q2.flags®)&&p2->q2.reg==r)||((p2->z.flags®)&&p2->z.reg==r)) break; |
| 1081 | } |
| 1082 | } |
| 1083 | } |
| 1084 | /* POST_INC/DEC in q2 */ |
| 1085 | if(!p->q2.am&&(p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){ |
| 1086 | r=p->q2.reg; t=q2typ(p); |
| 1087 | if(ISCHWORD(t)&&ISIDX(r)&&(!(p->q1.flags®)||p->q1.reg!=r)&&(!(p->z.flags®)||p->z.reg!=r)){ |
| 1088 | for(p2=p->next;p2;p2=p2->next){ |
| 1089 | c2=p2->code; |
| 1090 | if((c2==ADD||c2==ADDI2P||(CPU==6812&&(c2==SUB||c2==SUBIFP)))&&(p2->q1.flags&(REG|DREFOBJ))==REG&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){ |
| 1091 | eval_const(&p2->q2.val,p2->typf2); |
| 1092 | if(c2==SUB||c2==SUBIFP) vmax=zmsub(l2zm(0L),vmax); |
| 1093 | if(zmleq(vmax,incmax)&&zmleq(incmin,vmax)){ |
| 1094 | p2->code=NOP; |
| 1095 | p2->q1.flags=p2->q2.flags=p2->z.flags=0; |
| 1096 | p->q2.am=mymalloc(sizeof(*am)); |
| 1097 | p->q2.am->base=r; |
| 1098 | p->q2.am->v=0; |
| 1099 | if(zmleq(vmax,l2zm(0L))){ |
| 1100 | p->q2.am->flags=POST_DEC; |
| 1101 | p->q2.am->offset=-zm2l(vmax); |
| 1102 | }else{ |
| 1103 | p->q2.am->flags=POST_INC; |
| 1104 | p->q2.am->offset=zm2l(vmax); |
| 1105 | } |
| 1106 | }else break; |
| 1107 | } |
| 1108 | if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break; |
| 1109 | if(((p2->q1.flags®)&&p2->q1.reg==r)||((p2->q2.flags®)&&p2->q2.reg==r)||((p2->z.flags®)&&p2->z.reg==r)) break; |
| 1110 | } |
| 1111 | } |
| 1112 | } |
| 1113 | /* POST_INC/DEC in z */ |
| 1114 | if(!p->z.am&&(p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){ |
| 1115 | r=p->z.reg; t=ztyp(p); |
| 1116 | if(ISCHWORD(t)&&ISIDX(r)&&(!(p->q1.flags®)||p->q1.reg!=r)&&(!(p->q2.flags®)||p->q2.reg!=r)){ |
| 1117 | for(p2=p->next;p2;p2=p2->next){ |
| 1118 | c2=p2->code; |
| 1119 | if((c2==ADD||c2==ADDI2P||(CPU==6812&&(c2==SUB||c2==SUBIFP)))&&(p2->q1.flags&(REG|DREFOBJ))==REG&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){ |
| 1120 | eval_const(&p2->q2.val,p2->typf2); |
| 1121 | if(c2==SUB||c2==SUBIFP) vmax=zmsub(l2zm(0L),vmax); |
| 1122 | if(zmleq(vmax,incmax)&&zmleq(incmin,vmax)){ |
| 1123 | p2->code=NOP; |
| 1124 | p2->q1.flags=p2->q2.flags=p2->z.flags=0; |
| 1125 | p->z.am=mymalloc(sizeof(*am)); |
| 1126 | p->z.am->base=r; |
| 1127 | p->z.am->v=0; |
| 1128 | if(zmleq(vmax,l2zm(0L))){ |
| 1129 | p->z.am->flags=POST_DEC; |
| 1130 | p->z.am->offset=-zm2l(vmax); |
| 1131 | }else{ |
| 1132 | p->z.am->flags=POST_INC; |
| 1133 | p->z.am->offset=zm2l(vmax); |
| 1134 | } |
| 1135 | }else break; |
| 1136 | } |
| 1137 | if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break; |
| 1138 | if(((p2->q1.flags®)&&p2->q1.reg==r)||((p2->q2.flags®)&&p2->q2.reg==r)||((p2->z.flags®)&&p2->z.reg==r)) break; |
| 1139 | } |
| 1140 | } |
| 1141 | } |
| 1142 | |
| 1143 | /* R,#c */ |
| 1144 | if((c==ADDI2P||c==SUBIFP)&&ISHWORD(p->typf)&&((p->typf2&NQ)==NPOINTER||(p->typf2&NQ)==FPOINTER)&&isreg(z)&&((p->q2.flags&(KONST|DREFOBJ))==KONST||(!drel&&(p->q1.flags&VARADR)))){ |
| 1145 | int base;zmax of;struct obj *o;struct Var *v; |
| 1146 | if(p->q1.flags&VARADR){ |
| 1147 | v=p->q1.v; |
| 1148 | of=p->q1.val.vmax; |
| 1149 | r=p->z.reg; |
| 1150 | if(isreg(q2)&&ISIDX(p->q2.reg)) |
| 1151 | base=p->q2.reg; |
| 1152 | else |
| 1153 | base=r; |
| 1154 | }else{ |
| 1155 | eval_const(&p->q2.val,p->typf); |
| 1156 | if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax; |
| 1157 | v=0; |
| 1158 | r=p->z.reg; |
| 1159 | if(isreg(q1)&&ISIDX(p->q1.reg)) base=p->q1.reg; else base=r; |
| 1160 | } |
| 1161 | o=0; |
| 1162 | for(p2=p->next;p2;p2=p2->next){ |
| 1163 | c2=p2->code; |
| 1164 | if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break; |
| 1165 | if(c2!=FREEREG&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r) break; |
| 1166 | if(c2!=FREEREG&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==r) break; |
| 1167 | if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/){ |
| 1168 | if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){ |
| 1169 | if(o||!ISHWORD(q1typ(p2))) break; |
| 1170 | o=&p2->q1; |
| 1171 | } |
| 1172 | if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){ |
| 1173 | if(o||!ISHWORD(q2typ(p2))) break; |
| 1174 | o=&p2->q2; |
| 1175 | } |
| 1176 | if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){ |
| 1177 | if(o||!ISHWORD(ztyp(p2))) break; |
| 1178 | o=&p2->z; |
| 1179 | } |
| 1180 | } |
| 1181 | if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG){ |
| 1182 | int m; |
| 1183 | if(c2==FREEREG) |
| 1184 | m=p2->q1.reg; |
| 1185 | else |
| 1186 | m=p2->z.reg; |
| 1187 | if(m==r){ |
| 1188 | if(o){ |
| 1189 | o->am=am=mymalloc(sizeof(*am)); |
| 1190 | am->flags=IMM_IND; |
| 1191 | am->base=base; |
| 1192 | am->offset=zm2l(of); |
| 1193 | am->v=v; |
| 1194 | if(!v){ |
| 1195 | if(isreg(q1)&&ISIDX(p->q1.reg)){ |
| 1196 | p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0; |
| 1197 | }else{ |
| 1198 | p->code=c=ASSIGN;p->q2.flags=0; |
| 1199 | p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ]; |
| 1200 | } |
| 1201 | }else{ |
| 1202 | if(isreg(q2)&&ISIDX(p->q2.reg)){ |
| 1203 | p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0; |
| 1204 | }else{ |
| 1205 | p->code=c=ASSIGN;p->q1=p->q2;p->q2.flags=0; |
| 1206 | p->q2.val.vmax=sizetab[p->typf&NQ]; |
| 1207 | } |
| 1208 | } |
| 1209 | } |
| 1210 | break; |
| 1211 | } |
| 1212 | if(/*get_reg!! c2!=FREEREG&&*/m==base) break; |
| 1213 | continue; |
| 1214 | } |
| 1215 | } |
| 1216 | } |
| 1217 | } |
| 1218 | } |
| 1219 | |
| 1220 | static struct obj *cam(int flags,int base,long offset,struct Var *v) |
| 1221 | /* Initializes an addressing-mode structure and returns a pointer to */ |
| 1222 | /* that object. Will not survive a second call! */ |
| 1223 | { |
| 1224 | static struct obj obj; |
| 1225 | static struct AddressingMode am; |
| 1226 | obj.am=&am; |
| 1227 | am.flags=flags; |
| 1228 | am.base=base; |
| 1229 | am.offset=offset; |
| 1230 | am.v=v; |
| 1231 | return &obj; |
| 1232 | } |
| 1233 | |
| 1234 | static void get_acc(FILE *f,struct IC *p) |
| 1235 | { |
| 1236 | if(regs[acc]){ |
| 1237 | if(p->q2.am) |
| 1238 | if(p->q2.am->flags==ACC_IND) ierror(0); |
| 1239 | else |
| 1240 | if((p->q2.flags®)&&ISACC(p->q2.reg)) ierror(0); |
| 1241 | if(p->z.am) |
| 1242 | if(p->z.am->flags==ACC_IND) ierror(0); |
| 1243 | else |
| 1244 | if((p->z.flags®)&&ISACC(p->z.reg)) ierror(0); |
| 1245 | if(regs[acc]){ |
| 1246 | emit(f,SPUSHD); |
| 1247 | push(2); |
| 1248 | pushed_acc=1; |
| 1249 | } |
| 1250 | } |
| 1251 | } |
| 1252 | static int get_idx(FILE *f,IC *p) |
| 1253 | { |
| 1254 | int r; |
| 1255 | for(r=1;r<=MAXR;r++){ |
| 1256 | if(ISIDX(r)){ |
| 1257 | if(!regs[r]){ |
| 1258 | regs[r]|=4; |
| 1259 | return r; |
| 1260 | } |
| 1261 | } |
| 1262 | } |
| 1263 | for(r=1;r<=MAXR;r++){ |
| 1264 | if(ISIDX(r)){ |
| 1265 | if((!(p->q1.flags®)||p->q1.reg!=r)&& |
| 1266 | (!(p->q2.flags®)||p->q2.reg!=r)&& |
| 1267 | (!(p->z.flags®)||p->z.reg!=r)){ |
| 1268 | emit(f,"\t%s%s\n",CPU==6812?"psh":"pshs\t",regnames[r]); |
| 1269 | regs[r]|=8; |
| 1270 | push(2); |
| 1271 | return r; |
| 1272 | } |
| 1273 | } |
| 1274 | } |
| 1275 | ierror(0); |
| 1276 | } |
| 1277 | static int get_reg(FILE *f,struct IC *p,int t) |
| 1278 | { |
| 1279 | int reg; |
| 1280 | if(!regs[acc]) |
| 1281 | reg=acc; |
| 1282 | else if(ISHWORD(t)&&!regs[ix]) |
| 1283 | reg=ix; |
| 1284 | #if 0 |
| 1285 | else if(ISHWORD(t)&&!regs[iy]) |
| 1286 | reg=iy; |
| 1287 | #endif |
| 1288 | else{ |
| 1289 | get_acc(f,p); |
| 1290 | reg=acc; |
| 1291 | } |
| 1292 | BSET(regs_modified,reg); |
| 1293 | return reg; |
| 1294 | } |
| 1295 | static void load_reg(FILE *f,int r,struct obj *o,int t) |
| 1296 | { |
| 1297 | if(!o->am){ |
| 1298 | if((o->flags&(REG|DREFOBJ))==REG){ |
| 1299 | if(o->reg==r) return; |
| 1300 | emit(f,"\ttfr\t%s,%s\n",regnames[o->reg],regnames[r]); |
| 1301 | return; |
| 1302 | } |
| 1303 | if(r==acc&&(o->flags&(KONST|DREFOBJ))==KONST){ |
| 1304 | eval_const(&o->val,t); |
| 1305 | if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))){ |
| 1306 | if(CPU!=6812&&!optsize) |
| 1307 | emit(f,"\tldd\t#0\n"); |
| 1308 | else |
| 1309 | emit(f,"\tclra\n\tclrb\n"); |
| 1310 | cc=o;cc_t=t; |
| 1311 | return; |
| 1312 | } |
| 1313 | } |
| 1314 | } |
| 1315 | if(o->flags&VARADR){ |
| 1316 | char *base=0; |
| 1317 | if(pcrel&&ISFUNC(o->v->vtyp->flags)) |
| 1318 | base="pc"; |
| 1319 | if(drel&&!ISFUNC(o->v->vtyp->flags)) |
| 1320 | base=regnames[iu]; |
| 1321 | if(base&&!skip_rel){ |
| 1322 | if(ISACC(r)) |
| 1323 | emit(f,"\ttfr\t%s,d\n",base); |
| 1324 | if(ISIDX(r)) |
| 1325 | emit(f,"\tlea%s\t",regnames[r]); |
| 1326 | else{ |
| 1327 | if(*base=='p') emit(f,"%s%d:\n",labprefix,++label); |
| 1328 | emit(f,"\taddd\t#"); |
| 1329 | } |
| 1330 | emitzm(f,o->val.vmax); |
| 1331 | emit(f,"+"); |
| 1332 | if(o->v->storage_class==EXTERN) |
| 1333 | emit(f,"%s%s",idprefix,o->v->identifier); |
| 1334 | else |
| 1335 | emit(f,"%s%ld",labprefix,zm2l(o->v->offset)); |
| 1336 | if(ISIDX(r)) |
| 1337 | emit(f,",%s",base); |
| 1338 | else if(*base=='p') |
| 1339 | emit(f,"-%s%d",labprefix,label); |
| 1340 | emit(f,"\n"); |
| 1341 | cc=o;cc_t=t; |
| 1342 | return; |
| 1343 | } |
| 1344 | skip_rel=0; |
| 1345 | } |
| 1346 | emit(f,"\tld%s\t",(r==acc&&(t&NQ)==CHAR)?(CPU==6812?"ab":"b"):regnames[r]); |
| 1347 | emit_obj(f,o,t);emit(f,"\n"); |
| 1348 | cc=o;cc_t=t; |
| 1349 | } |
| 1350 | static void store_reg(FILE *f,int r,struct obj *o,int t) |
| 1351 | { |
| 1352 | if((o->flags&(REG|DREFOBJ))==REG){ |
| 1353 | if(o->reg==r) return; |
| 1354 | emit(f,"\ttfr\t%s,%s\n",regnames[r],regnames[o->reg]); |
| 1355 | }else{ |
| 1356 | if(r==acc&&(t&NQ)==CHAR) |
| 1357 | emit(f,"\tst%s\t",(CPU==6812)?"ab":"b"); |
| 1358 | else |
| 1359 | emit(f,"\tst%s\t",regnames[r]); |
| 1360 | emit_obj(f,o,t);emit(f,"\n"); |
| 1361 | cc=o;cc_t=t; |
| 1362 | } |
| 1363 | } |
| 1364 | static void load_addr(FILE *f,int r,struct obj *o) |
| 1365 | { |
| 1366 | if(o->am){ |
| 1367 | if(o->am->flags==IMM_IND){ |
| 1368 | if(o->am->base==r&&o->am->offset==0&&!o->am->v) return; |
| 1369 | if(ISIDX(r)){ |
| 1370 | emit(f,"\tlea%s\t",regnames[r]); |
| 1371 | emit_obj(f,o,0); |
| 1372 | emit(f,"\n"); |
| 1373 | }else{ |
| 1374 | if(r!=acc) ierror(0); |
| 1375 | emit(f,"\ttfr\t%s,%s\n",regnames[o->am->base],regnames[r]); |
| 1376 | emit(f,"\taddd\t#%ld\n",o->am->offset); |
| 1377 | if(o->am->v){ |
| 1378 | if(o->am->v->storage_class==STATIC) |
| 1379 | emit(f,"+%s%ld",labprefix,zm2l(o->am->v->offset)); |
| 1380 | else |
| 1381 | emit(f,"+%s%s",idprefix,o->am->v->identifier); |
| 1382 | } |
| 1383 | emit(f,"\n"); |
| 1384 | cc=0; |
| 1385 | } |
| 1386 | return; |
| 1387 | } |
| 1388 | ierror(0); |
| 1389 | } |
| 1390 | if(o->flags&DREFOBJ){ |
| 1391 | o->flags&=~DREFOBJ; |
| 1392 | load_reg(f,r,o,o->dtyp); |
| 1393 | o->flags|=DREFOBJ; |
| 1394 | return; |
| 1395 | } |
| 1396 | if((o->flags&(VAR|VARADR))==VAR){ |
| 1397 | if(o->v->storage_class==STATIC||o->v->storage_class==EXTERN){ |
| 1398 | o->flags|=VARADR; |
| 1399 | load_reg(f,r,o,POINTER_TYPE(o->v->vtyp)); |
| 1400 | o->flags&=~VARADR; |
| 1401 | return; |
| 1402 | } |
| 1403 | if(voff(o)==0){ |
| 1404 | emit(f,"\ttfr\t%s,%s\n",regnames[sp],regnames[r]); |
| 1405 | return; |
| 1406 | } |
| 1407 | if(ISIDX(r)){ |
| 1408 | emit(f,"\tlea%s\t",regnames[r]); |
| 1409 | emit_obj(f,o,0); |
| 1410 | emit(f,"\n"); |
| 1411 | }else{ |
| 1412 | if(r!=acc) ierror(0); |
| 1413 | emit(f,"\ttfr\t%s,%s\n",regnames[sp],regnames[r]); |
| 1414 | emit(f,"\taddd\t#%ld\n",voff(o)); |
| 1415 | cc=0; |
| 1416 | } |
| 1417 | return; |
| 1418 | } |
| 1419 | ierror(0); |
| 1420 | } |
| 1421 | |
| 1422 | static int scratchreg(int r,struct IC *p) |
| 1423 | { |
| 1424 | int c; |
| 1425 | while(1){ |
| 1426 | p=p->next; |
| 1427 | if(!p||((c=p->code)==FREEREG&&p->q1.reg==r)) return 1; |
| 1428 | if(c==CALL||(c>=BEQ&&c<=BRA)) return 0; |
| 1429 | if((p->q1.flags®)&&p->q1.reg==r) return 0; |
| 1430 | if((p->q2.flags®)&&p->q2.reg==r) return 0; |
| 1431 | if((p->z.flags®)&&p->z.reg==r) return 0; |
| 1432 | } |
| 1433 | } |
| 1434 | |
| 1435 | /****************************************/ |
| 1436 | /* End of private fata and functions. */ |
| 1437 | /****************************************/ |
| 1438 | |
| 1439 | |
| 1440 | int init_cg(void) |
| 1441 | /* Does necessary initializations for the code-generator. Gets called */ |
| 1442 | /* once at the beginning and should return 0 in case of problems. */ |
| 1443 | { |
| 1444 | int i; |
| 1445 | |
| 1446 | CPU=CPUOPT; |
| 1447 | |
| 1448 | if (CPU==680912) { |
| 1449 | bitsperbyte = 12; |
| 1450 | bytemask = 0xfff; |
| 1451 | dbl_bytemask = 0xffffff; |
| 1452 | } |
| 1453 | |
| 1454 | /* Initialize some values which cannot be statically initialized */ |
| 1455 | /* because they are stored in the target's arithmetic. */ |
| 1456 | maxalign=l2zm(1L); |
| 1457 | char_bit=l2zm((long)bitsperbyte); |
| 1458 | for(i=0;i<=MAX_TYPE;i++){ |
| 1459 | sizetab[i]=l2zm(msizetab[i]); |
| 1460 | align[i]=l2zm(malign[i]); |
| 1461 | } |
| 1462 | for(i=1;i<=iu;i++){ |
| 1463 | regsize[i]=l2zm(2L);regtype[i]=&ityp; |
| 1464 | } |
| 1465 | regsize[dx]=l2zm(4L);regtype[i]=<yp; |
| 1466 | |
| 1467 | /* Initialize the min/max-settings. Note that the types of the */ |
| 1468 | /* host system may be different from the target system and you may */ |
| 1469 | /* only use the smallest maximum values ANSI guarantees if you */ |
| 1470 | /* want to be portable. */ |
| 1471 | /* That's the reason for the subtraction in t_min[INT]. Long could */ |
| 1472 | /* be unable to represent -2147483648 on the host system. */ |
| 1473 | if (CPU==680912) { |
| 1474 | t_min[CHAR]=l2zm(-2048L); |
| 1475 | t_min[SHORT]=l2zm(-8388608L); |
| 1476 | t_min[INT]=t_min[SHORT]; |
| 1477 | t_min[LONG]=zmsub(l2zm(0x800000000000LL),l2zm(1L)); |
| 1478 | t_min[LLONG]=zmlshift(l2zm(1L),l2zm(63L)); |
| 1479 | t_min[MAXINT]=t_min(LLONG); |
| 1480 | t_max[CHAR]=ul2zum(2047L); |
| 1481 | t_max[SHORT]=ul2zum(8388607UL); |
| 1482 | t_max[INT]=t_max[SHORT]; |
| 1483 | t_max[LONG]=ul2zum(0x7fffffffffffULL); |
| 1484 | t_max[LLONG]=zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL)); |
| 1485 | t_max[MAXINT]=t_max(LLONG); |
| 1486 | tu_max[CHAR]=ul2zum(4095UL); |
| 1487 | tu_max[SHORT]=ul2zum(16777215UL); |
| 1488 | tu_max[INT]=tu_max[SHORT]; |
| 1489 | tu_max[LONG]=ul2zum(0xffffffffffffULL); |
| 1490 | tu_max[LLONG]=zumkompl(ul2zum(0UL)); |
| 1491 | tu_max[MAXINT]=t_max(UNSIGNED|LLONG); |
| 1492 | } |
| 1493 | else { |
| 1494 | t_min[CHAR]=l2zm(-128L); |
| 1495 | t_min[SHORT]=l2zm(-32768L); |
| 1496 | t_min[INT]=t_min[SHORT]; |
| 1497 | t_min[LONG]=zmsub(l2zm(-2147483647L),l2zm(1L)); |
| 1498 | t_min[LLONG]=zmlshift(l2zm(1L),l2zm(63L)); |
| 1499 | t_min[MAXINT]=t_min(LLONG); |
| 1500 | t_max[CHAR]=ul2zum(127L); |
| 1501 | t_max[SHORT]=ul2zum(32767UL); |
| 1502 | t_max[INT]=t_max[SHORT]; |
| 1503 | t_max[LONG]=ul2zum(2147483647UL); |
| 1504 | t_max[LLONG]=zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL)); |
| 1505 | t_max[MAXINT]=t_max(LLONG); |
| 1506 | tu_max[CHAR]=ul2zum(255UL); |
| 1507 | tu_max[SHORT]=ul2zum(65535UL); |
| 1508 | tu_max[INT]=tu_max[SHORT]; |
| 1509 | tu_max[LONG]=ul2zum(4294967295UL); |
| 1510 | tu_max[LLONG]=zumkompl(ul2zum(0UL)); |
| 1511 | tu_max[MAXINT]=t_max(UNSIGNED|LLONG); |
| 1512 | } |
| 1513 | |
| 1514 | if(g_flags[9]&USEDFLAG) drel=1; |
| 1515 | if(g_flags[10]&USEDFLAG) MINADDI2P=SHORT; |
| 1516 | if(g_flags[11]&USEDFLAG) nodx=1; |
| 1517 | if(g_flags[12]&USEDFLAG) nou=1; |
| 1518 | |
| 1519 | if(CPU==6812) switchsubs=1; |
| 1520 | |
| 1521 | /* Reserve a few registers for use by the code-generator. */ |
| 1522 | regsa[sp]=REGSA_NEVER; |
| 1523 | regscratch[sp]=0; |
| 1524 | |
| 1525 | if(CPU==6812||drel||nou){ |
| 1526 | regsa[iu]=REGSA_NEVER; |
| 1527 | regscratch[iu]=0; |
| 1528 | } |
| 1529 | |
| 1530 | if(CPU!=6812){ |
| 1531 | regnames[sp]="s"; |
| 1532 | logicals[0]="or"; |
| 1533 | } |
| 1534 | |
| 1535 | if(!(g_flags[6]&USEDFLAG)){ |
| 1536 | extern int static_cse,dref_cse; |
| 1537 | static_cse=0; |
| 1538 | dref_cse=0; |
| 1539 | } |
| 1540 | |
| 1541 | if(!(g_flags[7]&USEDFLAG)){ |
| 1542 | regsa[acc]=REGSA_TEMPS; |
| 1543 | regsa[dx]=REGSA_TEMPS; |
| 1544 | } |
| 1545 | |
| 1546 | if(g_flags[8]&USEDFLAG){ |
| 1547 | pcrel=1; |
| 1548 | jsrinst="lbsr"; |
| 1549 | jmpinst="lbra"; |
| 1550 | rodataname="\t.data\n"; |
| 1551 | } |
| 1552 | |
| 1553 | if(CPU==6809) |
| 1554 | marray[1]="__6809__"; |
| 1555 | if(CPU==6309) |
| 1556 | marray[1]="__6309__"; |
| 1557 | if(CPU==680912) |
| 1558 | marray[1]="__680912__"; |
| 1559 | target_macros=marray; |
| 1560 | |
| 1561 | |
| 1562 | declare_builtin("__mulint16",INT,INT,acc,INT,0,1,0); |
| 1563 | declare_builtin("__divint16",INT,INT,ix,INT,acc,1,0); |
| 1564 | declare_builtin("__divuint16",UNSIGNED|INT,UNSIGNED|INT,ix,UNSIGNED|INT,acc,1,0); |
| 1565 | declare_builtin("__modint16",INT,INT,ix,INT,acc,1,0); |
| 1566 | declare_builtin("__moduint16",UNSIGNED|INT,UNSIGNED|INT,ix,UNSIGNED|INT,acc,1,0); |
| 1567 | |
| 1568 | |
| 1569 | /* TODO: set argument registers */ |
| 1570 | declare_builtin("__mulint32",LONG,LONG,0,LONG,0,1,0); |
| 1571 | declare_builtin("__addint32",LONG,LONG,0,LONG,0,1,0); |
| 1572 | declare_builtin("__subint32",LONG,LONG,0,LONG,0,1,0); |
| 1573 | declare_builtin("__andint32",LONG,LONG,0,LONG,0,1,0); |
| 1574 | declare_builtin("__orint32",LONG,LONG,0,LONG,0,1,0); |
| 1575 | declare_builtin("__eorint32",LONG,LONG,0,LONG,0,1,0); |
| 1576 | declare_builtin("__negint32",LONG,LONG,0,0,0,1,0); |
| 1577 | declare_builtin("__lslint32",LONG,LONG,0,INT,0,1,0); |
| 1578 | |
| 1579 | declare_builtin("__divint32",LONG,LONG,0,LONG,0,1,0); |
| 1580 | declare_builtin("__divuint32",UNSIGNED|LONG,UNSIGNED|LONG,0,UNSIGNED|LONG,0,1,0); |
| 1581 | declare_builtin("__modint32",LONG,LONG,0,LONG,0,1,0); |
| 1582 | declare_builtin("__moduint32",UNSIGNED|LONG,UNSIGNED|LONG,0,UNSIGNED|LONG,0,1,0); |
| 1583 | declare_builtin("__lsrsint32",LONG,LONG,0,INT,0,1,0); |
| 1584 | declare_builtin("__lsruint32",UNSIGNED|LONG,UNSIGNED|LONG,0,INT,0,1,0); |
| 1585 | declare_builtin("__cmpsint32",INT,LONG,0,LONG,0,1,0); |
| 1586 | declare_builtin("__cmpuint32",INT,UNSIGNED|LONG,0,UNSIGNED|LONG,0,1,0); |
| 1587 | declare_builtin("__sint32toflt32",FLOAT,LONG,0,0,0,1,0); |
| 1588 | declare_builtin("__uint32toflt32",FLOAT,UNSIGNED|LONG,0,0,0,1,0); |
| 1589 | declare_builtin("__sint32toflt64",DOUBLE,LONG,0,0,0,1,0); |
| 1590 | declare_builtin("__uint32toflt64",DOUBLE,UNSIGNED|LONG,0,0,0,1,0); |
| 1591 | declare_builtin("__flt32tosint32",LONG,FLOAT,0,0,0,1,0); |
| 1592 | declare_builtin("__flt32touint32",UNSIGNED|LONG,FLOAT,0,0,0,1,0); |
| 1593 | declare_builtin("__flt64tosint32",LONG,DOUBLE,0,0,0,1,0); |
| 1594 | declare_builtin("__flt64touint32",UNSIGNED|LONG,DOUBLE,0,0,0,1,0); |
| 1595 | |
| 1596 | |
| 1597 | |
| 1598 | declare_builtin("__mulint64",LLONG,LLONG,0,LLONG,0,1,0); |
| 1599 | declare_builtin("__addint64",LLONG,LLONG,0,LLONG,0,1,0); |
| 1600 | declare_builtin("__subint64",LLONG,LLONG,0,LLONG,0,1,0); |
| 1601 | declare_builtin("__andint64",LLONG,LLONG,0,LLONG,0,1,0); |
| 1602 | declare_builtin("__orint64",LLONG,LLONG,0,LLONG,0,1,0); |
| 1603 | declare_builtin("__eorint64",LLONG,LLONG,0,LLONG,0,1,0); |
| 1604 | declare_builtin("__negint64",LLONG,LLONG,0,0,0,1,0); |
| 1605 | declare_builtin("__lslint64",LLONG,LLONG,0,INT,0,1,0); |
| 1606 | |
| 1607 | declare_builtin("__divsint64",LLONG,LLONG,0,LLONG,0,1,0); |
| 1608 | declare_builtin("__divuint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0); |
| 1609 | declare_builtin("__modsint64",LLONG,LLONG,0,LLONG,0,1,0); |
| 1610 | declare_builtin("__moduint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0); |
| 1611 | declare_builtin("__lsrsint64",LLONG,LLONG,0,INT,0,1,0); |
| 1612 | declare_builtin("__lsruint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,INT,0,1,0); |
| 1613 | declare_builtin("__cmpsint64",INT,LLONG,0,LLONG,0,1,0); |
| 1614 | declare_builtin("__cmpuint64",INT,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0); |
| 1615 | declare_builtin("__sint64toflt32",FLOAT,LLONG,0,0,0,1,0); |
| 1616 | declare_builtin("__uint64toflt32",FLOAT,UNSIGNED|LLONG,0,0,0,1,0); |
| 1617 | declare_builtin("__sint64toflt64",DOUBLE,LLONG,0,0,0,1,0); |
| 1618 | declare_builtin("__uint64toflt64",DOUBLE,UNSIGNED|LLONG,0,0,0,1,0); |
| 1619 | declare_builtin("__flt32tosint64",LLONG,FLOAT,0,0,0,1,0); |
| 1620 | declare_builtin("__flt32touint64",UNSIGNED|LLONG,FLOAT,0,0,0,1,0); |
| 1621 | declare_builtin("__flt64tosint64",LLONG,DOUBLE,0,0,0,1,0); |
| 1622 | declare_builtin("__flt64touint64",UNSIGNED|LLONG,DOUBLE,0,0,0,1,0); |
| 1623 | |
| 1624 | declare_builtin("__flt32toflt64",DOUBLE,FLOAT,0,0,0,1,0); |
| 1625 | declare_builtin("__flt64toflt32",FLOAT,DOUBLE,0,0,0,1,0); |
| 1626 | |
| 1627 | |
| 1628 | declare_builtin("__addflt32",FLOAT,FLOAT,0,FLOAT,0,1,0); |
| 1629 | declare_builtin("__subflt32",FLOAT,FLOAT,0,FLOAT,0,1,0); |
| 1630 | declare_builtin("__mulflt32",FLOAT,FLOAT,0,FLOAT,0,1,0); |
| 1631 | declare_builtin("__divflt32",FLOAT,FLOAT,0,FLOAT,0,1,0); |
| 1632 | declare_builtin("__negflt32",FLOAT,FLOAT,0,FLOAT,0,1,0); |
| 1633 | declare_builtin("__cmpflt32",INT,FLOAT,0,FLOAT,0,1,0); |
| 1634 | |
| 1635 | declare_builtin("__addflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0); |
| 1636 | declare_builtin("__subflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0); |
| 1637 | declare_builtin("__mulflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0); |
| 1638 | declare_builtin("__divflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0); |
| 1639 | declare_builtin("__negflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0); |
| 1640 | declare_builtin("__cmpflt64",INT,DOUBLE,0,DOUBLE,0,1,0); |
| 1641 | |
| 1642 | |
| 1643 | return 1; |
| 1644 | } |
| 1645 | |
| 1646 | int freturn(struct Typ *t) |
| 1647 | /* Returns the register in which variables of type t are returned. */ |
| 1648 | /* If the value cannot be returned in a register returns 0. */ |
| 1649 | { |
| 1650 | int f=t->flags&NQ; |
| 1651 | if(ISSCALAR(f)){ |
| 1652 | if(ISHWORD(f)||f==CHAR) |
| 1653 | return acc; |
| 1654 | else if(ISLWORD(f)) |
| 1655 | return dx; |
| 1656 | } |
| 1657 | return 0; |
| 1658 | } |
| 1659 | |
| 1660 | int regok(int r,int t,int mode) |
| 1661 | /* Returns 0 if register r cannot store variables of */ |
| 1662 | /* type t. If t==POINTER and mode!=0 then it returns */ |
| 1663 | /* non-zero only if the register can store a pointer */ |
| 1664 | /* and dereference a pointer to mode. */ |
| 1665 | { |
| 1666 | if(!ISSCALAR(t)) return 0; |
| 1667 | if(r==dx){ |
| 1668 | if(ISLWORD(t)&&(optflags&2)&&!nodx) return 1; |
| 1669 | return 0; |
| 1670 | } |
| 1671 | if(mode==-1){ |
| 1672 | if(ISHWORD(t)) return 1; |
| 1673 | if((t&NQ)==CHAR&&ISACC(r)) return 1; |
| 1674 | }else{ |
| 1675 | if(ISIDX(r)){ |
| 1676 | if(ISPOINTER(t)&&ISHWORD(t)) |
| 1677 | return 1; |
| 1678 | } |
| 1679 | if(ISACC(r)){ |
| 1680 | if((t&NQ)==CHAR) |
| 1681 | return 1; |
| 1682 | if(ISINT(t)&&ISHWORD(t)) |
| 1683 | return 1; |
| 1684 | } |
| 1685 | } |
| 1686 | return 0; |
| 1687 | } |
| 1688 | |
| 1689 | int reg_pair(int r,struct rpair *p) |
| 1690 | /* Returns 0 if the register is no register pair. If r */ |
| 1691 | /* is a register pair non-zero will be returned and the */ |
| 1692 | /* structure pointed to p will be filled with the two */ |
| 1693 | /* elements. */ |
| 1694 | { |
| 1695 | if(r==dx){ |
| 1696 | p->r1=acc; |
| 1697 | p->r2=ix; |
| 1698 | return 1; |
| 1699 | } |
| 1700 | return 0; |
| 1701 | } |
| 1702 | |
| 1703 | int cost_savings(struct IC *p,int r,struct obj *o) |
| 1704 | { |
| 1705 | /*FIXME*/ |
| 1706 | int c=p->code; |
| 1707 | if(r==dx){ |
| 1708 | if(c==GETRETURN||c==SETRETURN||c==PUSH||c==ASSIGN) return 8; |
| 1709 | return INT_MIN; |
| 1710 | } |
| 1711 | if(o->flags&VKONST){ |
| 1712 | struct obj *co=&o->v->cobj; |
| 1713 | if(o->flags&DREFOBJ) |
| 1714 | return 0; |
| 1715 | if(o==&p->q1&&p->code==ASSIGN&&((p->z.flags&DREFOBJ)||p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN)){ |
| 1716 | return 2; |
| 1717 | } |
| 1718 | return 0; |
| 1719 | } |
| 1720 | if((o->flags&DREFOBJ)){ |
| 1721 | if(!ISIDX(r)) return INT_MIN; |
| 1722 | if(p->q2.flags&&o!=&p->z) |
| 1723 | return 6; |
| 1724 | else |
| 1725 | return 6; |
| 1726 | }else if(c==GETRETURN&&p->q1.reg==r){ |
| 1727 | return 4; |
| 1728 | }else if(c==SETRETURN&&p->z.reg==r){ |
| 1729 | return 4; |
| 1730 | }else if(c==CONVERT&&((p->typf&NQ)==CHAR||(p->typf2&NQ)==CHAR)&®ok(r,CHAR,0)){ |
| 1731 | return 3; |
| 1732 | } |
| 1733 | if(o==&p->z&&r==acc){ |
| 1734 | if(c==SUB||c==SUBIFP||c==SUBPFP||c==AND||c==OR||c==XOR) |
| 1735 | return 6; |
| 1736 | if((c==ADD||c==ADDI2P)&&!(p->q1.flags&(KONST|VKONST))&&!(p->q2.flags&(KONST|VKONST))) |
| 1737 | return 4; |
| 1738 | if(c==MULT) return 5; |
| 1739 | if(c==ASSIGN&&(p->q1.flags&KONST)){ |
| 1740 | eval_const(&p->q1.val,p->typf); |
| 1741 | if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))) |
| 1742 | return 3; |
| 1743 | } |
| 1744 | } |
| 1745 | #if 1 |
| 1746 | if((o==&p->q2/*||o==&p->z*/)&&!(o->flags&DREFOBJ)&&!ISACC(o->reg)&&(c==MULT||c==DIV||c==MOD)) |
| 1747 | return INT_MIN; |
| 1748 | #endif |
| 1749 | if(c==COMPARE||c==TEST){ |
| 1750 | if(r==ix) return 3; |
| 1751 | if(r==iy) return 2; |
| 1752 | if(r==iu) return 1; |
| 1753 | } |
| 1754 | return 2; |
| 1755 | } |
| 1756 | |
| 1757 | int dangerous_IC(struct IC *p) |
| 1758 | /* Returns zero if the IC p can be safely executed */ |
| 1759 | /* without danger of exceptions or similar things. */ |
| 1760 | /* vbcc may generate code in which non-dangerous ICs */ |
| 1761 | /* are sometimes executed although control-flow may */ |
| 1762 | /* never reach them (mainly when moving computations */ |
| 1763 | /* out of loops). */ |
| 1764 | /* Typical ICs that generate exceptions on some */ |
| 1765 | /* machines are: */ |
| 1766 | /* - accesses via pointers */ |
| 1767 | /* - division/modulo */ |
| 1768 | /* - overflow on signed integer/floats */ |
| 1769 | { |
| 1770 | int c=p->code; |
| 1771 | if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ)) |
| 1772 | return 1; |
| 1773 | if((c==DIV||c==MOD)&&!isconst(q2)) |
| 1774 | return 1; |
| 1775 | return 0; |
| 1776 | } |
| 1777 | |
| 1778 | /* Return name of library function, if this node should be |
| 1779 | implemented via libcall. */ |
| 1780 | char *use_libcall(int c,int t,int t2) |
| 1781 | { |
| 1782 | static char fname[16]; |
| 1783 | char *ret=0; |
| 1784 | |
| 1785 | if(c==COMPARE){ |
| 1786 | if((t&NQ)==LLONG||ISFLOAT(t)){ |
| 1787 | sprintf(fname,"__cmp%s%s%ld",(t&UNSIGNED)?"u":"s",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8); |
| 1788 | ret=fname; |
| 1789 | } |
| 1790 | }else{ |
| 1791 | t&=NU; |
| 1792 | t2&=NU; |
| 1793 | if(t==LDOUBLE) t=DOUBLE; |
| 1794 | if(t2==LDOUBLE) t2=DOUBLE; |
| 1795 | if(c==CONVERT){ |
| 1796 | if(t==t2) return 0; |
| 1797 | if(t==FLOAT&&t2==DOUBLE) return "__flt64toflt32"; |
| 1798 | if(t==DOUBLE&&t2==FLOAT) return "__flt32toflt64"; |
| 1799 | |
| 1800 | if(ISFLOAT(t)){ |
| 1801 | sprintf(fname,"__%cint%ldtoflt%d",(t2&UNSIGNED)?'u':'s',zm2l(sizetab[t2&NQ])*8,(t==FLOAT)?32:64); |
| 1802 | ret=fname; |
| 1803 | } |
| 1804 | if(ISFLOAT(t2)){ |
| 1805 | sprintf(fname,"__flt%dto%cint%ld",((t2&NU)==FLOAT)?32:64,(t&UNSIGNED)?'u':'s',zm2l(sizetab[t&NQ])*8); |
| 1806 | ret=fname; |
| 1807 | } |
| 1808 | } |
| 1809 | if((t&NQ)==LLONG||ISFLOAT(t)){ |
| 1810 | if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==KOMPLEMENT||c==MINUS){ |
| 1811 | if(t==(UNSIGNED|LLONG)&&(c==DIV||c==MOD||c==RSHIFT)){ |
| 1812 | sprintf(fname,"__%suint64",ename[c]); |
| 1813 | ret=fname; |
| 1814 | }else if((t&NQ)==LLONG){ |
| 1815 | sprintf(fname,"__%sint64",ename[c]); |
| 1816 | ret=fname; |
| 1817 | }else if(t==(UNSIGNED|LONG)&&(c==DIV||c==MOD||c==RSHIFT)){ |
| 1818 | sprintf(fname,"__%suint32",ename[c]); |
| 1819 | ret=fname; |
| 1820 | }else if((t&NQ)==LONG){ |
| 1821 | sprintf(fname,"__%sint32",ename[c]); |
| 1822 | ret=fname; |
| 1823 | }else{ |
| 1824 | sprintf(fname,"__%s%s%s%ld",ename[c],(c!=MULT&&(t&UNSIGNED))?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8); |
| 1825 | ret=fname; |
| 1826 | } |
| 1827 | } |
| 1828 | } |
| 1829 | if((c==MULT&&(CPU==6809||(t&NQ)==LONG))||c==DIV||c==MOD){ |
| 1830 | sprintf(fname,"__%s%s%s%ld",ename[c],(c!=MULT&&(t&UNSIGNED))?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8); |
| 1831 | ret=fname; |
| 1832 | } |
| 1833 | } |
| 1834 | |
| 1835 | return ret; |
| 1836 | } |
| 1837 | |
| 1838 | |
| 1839 | |
| 1840 | int must_convert(int o,int t,int const_expr) |
| 1841 | /* Returns zero if code for converting np to type t */ |
| 1842 | /* can be omitted. */ |
| 1843 | { |
| 1844 | int op=o&NQ,tp=t&NQ; |
| 1845 | if(op==tp) return 0; |
| 1846 | if(ISHWORD(op)&&ISHWORD(tp)) return 0; |
| 1847 | if(ISFLOAT(op)||ISFLOAT(tp)) return 1; |
| 1848 | if(ISLWORD(op)&&ISLWORD(tp)) return 0; |
| 1849 | return 1; |
| 1850 | } |
| 1851 | |
| 1852 | void gen_ds(FILE *f,zmax size,struct Typ *t) |
| 1853 | /* This function has to create <size> bytes of storage */ |
| 1854 | /* initialized with zero. */ |
| 1855 | { |
| 1856 | if(newobj&§ion!=SPECIAL) |
| 1857 | emit(f,"%ld\n",zm2l(size)); |
| 1858 | else |
| 1859 | emit(f,"\t.space\t%ld\n",zm2l(size)); |
| 1860 | newobj=0; |
| 1861 | } |
| 1862 | |
| 1863 | void gen_align(FILE *f,zmax align) |
| 1864 | /* This function has to make sure the next data is */ |
| 1865 | /* aligned to multiples of <align> bytes. */ |
| 1866 | { |
| 1867 | /* nothing to do */ |
| 1868 | } |
| 1869 | |
| 1870 | void gen_var_head(FILE *f,struct Var *v) |
| 1871 | /* This function has to create the head of a variable */ |
| 1872 | /* definition, i.e. the label and information for */ |
| 1873 | /* linkage etc. */ |
| 1874 | { |
| 1875 | int constflag; |
| 1876 | if(v->clist) constflag=is_const(v->vtyp); |
| 1877 | if(v->storage_class==STATIC){ |
| 1878 | if(ISFUNC(v->vtyp->flags)) return; |
| 1879 | if(v->tattr&DPAGE) |
| 1880 | emit(f,"\t.direct\t%s%ld\n",labprefix,zm2l(v->offset)); |
| 1881 | if(!special_section(f,v)){ |
| 1882 | if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))&§ion!=DATA){ |
| 1883 | emit(f,dataname);if(f) section=DATA; |
| 1884 | } |
| 1885 | if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&§ion!=RODATA){ |
| 1886 | emit(f,rodataname);if(f) section=RODATA; |
| 1887 | } |
| 1888 | if(!v->clist&§ion!=BSS){ |
| 1889 | emit(f,bssname);if(f) section=BSS; |
| 1890 | } |
| 1891 | } |
| 1892 | emit(f,"\t.type\t%s%ld,@object\n",labprefix,zm2l(v->offset)); |
| 1893 | emit(f,"\t.size\t%s%ld,%ld\n",labprefix,zm2l(v->offset),zm2l(szof(v->vtyp))); |
| 1894 | if(v->clist||section==SPECIAL) |
| 1895 | emit(f,"%s%ld:\n",labprefix,zm2l(v->offset)); |
| 1896 | else |
| 1897 | emit(f,"\t.lcomm\t%s%ld,",labprefix,zm2l(v->offset)); |
| 1898 | newobj=1; |
| 1899 | } |
| 1900 | if(v->storage_class==EXTERN){ |
| 1901 | if(v->flags&(DEFINED|TENTATIVE)){ |
| 1902 | emit(f,"\t.global\t%s%s\n",idprefix,v->identifier); |
| 1903 | if(v->tattr&DPAGE) |
| 1904 | emit(f,"\t.direct\t%s%s\n",idprefix,v->identifier); |
| 1905 | if(!special_section(f,v)){ |
| 1906 | if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))&§ion!=DATA){ |
| 1907 | emit(f,dataname);if(f) section=DATA; |
| 1908 | } |
| 1909 | if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&§ion!=RODATA){ |
| 1910 | emit(f,rodataname);if(f) section=RODATA; |
| 1911 | } |
| 1912 | if(!v->clist&§ion!=BSS){ |
| 1913 | emit(f,bssname);if(f) section=BSS; |
| 1914 | } |
| 1915 | } |
| 1916 | emit(f,"\t.type\t%s%s,@object\n",idprefix,v->identifier); |
| 1917 | emit(f,"\t.size\t%s%s,%ld\n",idprefix,v->identifier,zm2l(szof(v->vtyp))); |
| 1918 | if(v->clist||section==SPECIAL) |
| 1919 | emit(f,"%s%s:\n",idprefix,v->identifier); |
| 1920 | else |
| 1921 | emit(f,"\t.global\t%s%s\n\t.lcomm\t%s%s,",idprefix,v->identifier,idprefix,v->identifier); |
| 1922 | newobj=1; |
| 1923 | } |
| 1924 | } |
| 1925 | } |
| 1926 | |
| 1927 | void gen_dc(FILE *f,int t,struct const_list *p) |
| 1928 | /* This function has to create static storage */ |
| 1929 | /* initialized with const-list p. */ |
| 1930 | { |
| 1931 | emit(f,"\t%s\t",dct[t&NQ]); |
| 1932 | if(!p->tree){ |
| 1933 | if(ISFLOAT(t)){ |
| 1934 | /* auch wieder nicht sehr schoen und IEEE noetig */ |
| 1935 | unsigned char *ip; |
| 1936 | ip=(unsigned char *)&p->val.vdouble; |
| 1937 | emit(f,"0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]); |
| 1938 | if((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE){ |
| 1939 | emit(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]); |
| 1940 | } |
| 1941 | }else{ |
| 1942 | emitval(f,&p->val,(t&NU)|UNSIGNED); |
| 1943 | } |
| 1944 | }else{ |
| 1945 | int m=p->tree->o.flags,md=drel,mp=pcrel; |
| 1946 | p->tree->o.flags&=~VARADR; |
| 1947 | drel=0;pcrel=0; |
| 1948 | emit_obj(f,&p->tree->o,t&NU); |
| 1949 | p->tree->o.flags=m; |
| 1950 | drel=md;pcrel=mp; |
| 1951 | } |
| 1952 | emit(f,"\n");newobj=0; |
| 1953 | } |
| 1954 | |
| 1955 | |
| 1956 | static void preload(FILE *f,IC *p) |
| 1957 | { |
| 1958 | int t,r; |
| 1959 | |
| 1960 | if((p->typf&VOLATILE)||(p->typf2&VOLATILE)|| |
| 1961 | ((p->q1.flags&DREFOBJ)&&(p->q1.dtyp&(VOLATILE|PVOLATILE)))|| |
| 1962 | ((p->q2.flags&DREFOBJ)&&(p->q2.dtyp&(VOLATILE|PVOLATILE)))|| |
| 1963 | ((p->z.flags&DREFOBJ)&&(p->z.dtyp&(VOLATILE|PVOLATILE)))) |
| 1964 | emit(f,"; volatile barrier\n"); |
| 1965 | |
| 1966 | t=q1typ(p); |
| 1967 | if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ|KONST))==DREFOBJ&&ISLWORD(t)){ |
| 1968 | r=get_idx(f,p); |
| 1969 | p->q1.flags&=~DREFOBJ; |
| 1970 | load_reg(f,r,&p->q1,INT); |
| 1971 | p->q1.flags|=(REG|DREFOBJ); |
| 1972 | p->q1.reg=r; |
| 1973 | } |
| 1974 | t=q2typ(p); |
| 1975 | if(!p->q2.am&&(p->q2.flags&(REG|DREFOBJ|KONST))==DREFOBJ&&ISLWORD(t)){ |
| 1976 | r=get_idx(f,p); |
| 1977 | p->q2.flags&=~DREFOBJ; |
| 1978 | load_reg(f,r,&p->q2,INT); |
| 1979 | p->q2.flags|=(REG|DREFOBJ); |
| 1980 | p->q2.reg=r; |
| 1981 | }else if(isreg(z)&&(((p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q2.reg==p->z.reg)||(p->q2.am&&p->q2.am->base==p->z.reg))){ |
| 1982 | r=get_idx(f,p); |
| 1983 | p->q2.flags&=~DREFOBJ; |
| 1984 | load_reg(f,r,&p->q2,INT); |
| 1985 | p->q2.flags|=(REG|DREFOBJ); |
| 1986 | p->q2.reg=r; |
| 1987 | } |
| 1988 | t=ztyp(p); |
| 1989 | if(!p->z.am&&(p->z.flags&(REG|DREFOBJ|KONST))==DREFOBJ&&ISLWORD(t)){ |
| 1990 | r=get_idx(f,p); |
| 1991 | p->z .flags&=~DREFOBJ; |
| 1992 | load_reg(f,r,&p->z ,INT); |
| 1993 | p->z .flags|=(REG|DREFOBJ); |
| 1994 | p->z .reg=r; |
| 1995 | } |
| 1996 | } |
| 1997 | |
| 1998 | /* The main code-generation routine. */ |
| 1999 | /* f is the stream the code should be written to. */ |
| 2000 | /* p is a pointer to a doubly linked list of ICs */ |
| 2001 | /* containing the function body to generate code for. */ |
| 2002 | /* v is a pointer to the function. */ |
| 2003 | /* offset is the size of the stackframe the function */ |
| 2004 | /* needs for local variables. */ |
| 2005 | void gen_code(FILE *f,struct IC *fp,struct Var *v,zmax offset) |
| 2006 | { |
| 2007 | int c,t,lastcomp=0,reg,short_add,bit_reverse,need_return=0; |
| 2008 | struct obj *bit_obj;char *bit_reg; |
| 2009 | static int idone; |
| 2010 | struct obj o; |
| 2011 | IC *p,*p2; |
| 2012 | if(v->tattr&INTERRUPT) |
| 2013 | ret="rti"; |
| 2014 | else if (v->tattr&FAR) |
| 2015 | ret="rtf"; |
| 2016 | else |
| 2017 | ret="rts"; /*FIXME: banked */ |
| 2018 | if(DEBUG&1) printf("gen_code()\n"); |
| 2019 | for(p=fp;p;p=p->next) clear_ext_ic(&p->ext); |
| 2020 | emit(f,"#off1=%ld\n",zm2l(offset)); |
| 2021 | if(!(g_flags[5]&USEDFLAG)){ |
| 2022 | peephole(fp); |
| 2023 | if(!frame_used) offset=l2zm(0L); |
| 2024 | } |
| 2025 | for(c=1;c<=MAXR;c++) regs[c]=(regsa[c]==REGSA_NEVER)?1:0; |
| 2026 | for(c=1;c<=MAXR;c++){ |
| 2027 | if(regscratch[c]&&(regsa[c]||regused[c])){ |
| 2028 | BSET(regs_modified,c); |
| 2029 | } |
| 2030 | } |
| 2031 | t=0; |
| 2032 | for(p=fp;p;p=p->next){ |
| 2033 | c=p->code; |
| 2034 | if(c==ALLOCREG){ regs[p->q1.reg]=1; if(p->q1.reg==dx) regs[acc]=regs[ix]=1;} |
| 2035 | if(c==FREEREG){ regs[p->q1.reg]=0; if(p->q1.reg==dx) regs[acc]=regs[ix]=0;} |
| 2036 | if((c==LSHIFT||c==RSHIFT)&&(p->typf&NQ)>=LONG) regused[iy]=1; |
| 2037 | if(c==PUSH&&(p->q1.flags&(REG|DREFOBJ))!=REG){ |
| 2038 | if(zmeqto(p->q2.val.vmax,Z1)){ |
| 2039 | if(regs[acc]) t=(t>2)?t:2; |
| 2040 | }else if(zmeqto(p->q2.val.vmax,l2zm(2L))){ |
| 2041 | if(regs[acc]&®s[ix]&®s[iy]&&(CPU==6812||regs[iu])) t=(t>2)?t:2; |
| 2042 | }else if(zmeqto(p->q2.val.vmax,l2zm(4L))){ |
| 2043 | if(regs[acc]) t=(t>2)?t:2; |
| 2044 | }else{ |
| 2045 | /* TODO: finer check */ |
| 2046 | if(drel||!regsa[iu]) |
| 2047 | t=(t>8)?t:8; |
| 2048 | else |
| 2049 | t=(t>6)?t:6; |
| 2050 | } |
| 2051 | } |
| 2052 | } |
| 2053 | emit(f,"#toff=%d\n",t); |
| 2054 | loff=zm2l(offset)+t; |
| 2055 | function_top(f,v,loff); |
| 2056 | stackoffset=notpopped=dontpop=maxpushed=0; |
| 2057 | for(p=fp;p;pr(f,p),p=p->next){ |
| 2058 | c=p->code;t=p->typf; |
| 2059 | if(debug_info) |
| 2060 | dwarf2_line_info(f,p); |
| 2061 | short_add=0; |
| 2062 | if(c==NOP) continue; |
| 2063 | if(c==ALLOCREG){ |
| 2064 | regs[p->q1.reg]=1; |
| 2065 | if(p->q1.reg==dx) regs[acc]=regs[ix]=1; |
| 2066 | continue; |
| 2067 | } |
| 2068 | if(c==FREEREG){ |
| 2069 | regs[p->q1.reg]=0; |
| 2070 | if(p->q1.reg==dx) regs[acc]=regs[ix]=0; |
| 2071 | continue; |
| 2072 | } |
| 2073 | if(notpopped&&!dontpop){ |
| 2074 | int flag=0; |
| 2075 | if(c==LABEL||c==COMPARE||c==TEST||c==BRA){ |
| 2076 | gen_pop(f,notpopped); |
| 2077 | notpopped=0; |
| 2078 | } |
| 2079 | } |
| 2080 | if(c==LABEL) {cc=0;emit(f,"%s%d:\n",labprefix,t);continue;} |
| 2081 | if(c>=BEQ&&c<=BGT&&t==exit_label) need_return=1; |
| 2082 | if(c==BRA){ |
| 2083 | if(p->typf==exit_label&&!have_frame){ |
| 2084 | emit(f,"\t%s\n",ret); |
| 2085 | }else{ |
| 2086 | if(t==exit_label) need_return=1; |
| 2087 | emit(f,"\tbra\t%s%d\n",labprefix,t); |
| 2088 | } |
| 2089 | cc=0;continue; |
| 2090 | } |
| 2091 | if(c>=BEQ&&c<BRA){ |
| 2092 | if((lastcomp&UNSIGNED)||ISPOINTER(lastcomp)) |
| 2093 | emit(f,"\tb%s\t%s%d\n",uccs[c-BEQ],labprefix,t); |
| 2094 | else |
| 2095 | emit(f,"\tb%s\t%s%d\n",ccs[c-BEQ],labprefix,t); |
| 2096 | continue; |
| 2097 | } |
| 2098 | if(c==MOVETOREG){ |
| 2099 | load_reg(f,p->z.reg,&p->q1,SHORT); |
| 2100 | continue; |
| 2101 | } |
| 2102 | if(c==MOVEFROMREG){ |
| 2103 | store_reg(f,p->q1.reg,&p->z,SHORT); |
| 2104 | continue; |
| 2105 | } |
| 2106 | |
| 2107 | /*if(ISFLOAT(t)) {pric2(stdout,p);ierror(0);}*/ |
| 2108 | |
| 2109 | if((t&NQ)==BIT){ |
| 2110 | ierror(0); |
| 2111 | } |
| 2112 | |
| 2113 | if(c==CONVERT&&ISLWORD(t)&&ISLWORD(p->typf2)){ |
| 2114 | p->code=c=ASSIGN; |
| 2115 | p->q2.val.vmax=l2zm(4L); |
| 2116 | } |
| 2117 | |
| 2118 | if((p->q2.flags®)&&ISACC(p->q2.reg)&&(c==ADD||c==MULT||c==AND||c==OR||c==XOR)){ |
| 2119 | obj o=p->q1; |
| 2120 | p->q1=p->q2; |
| 2121 | p->q2=o; |
| 2122 | } |
| 2123 | |
| 2124 | if(c==TEST){ |
| 2125 | lastcomp=t; |
| 2126 | p->code=c=COMPARE; |
| 2127 | gval.vmax=l2zm(0L); |
| 2128 | p->q2.flags=KONST; |
| 2129 | eval_const(&gval,MAXINT); |
| 2130 | insert_const(&p->q2.val,t); |
| 2131 | } |
| 2132 | |
| 2133 | if(c==SUBPFP){ |
| 2134 | p->code=c=SUB; |
| 2135 | p->typf=t=(UNSIGNED|INT); |
| 2136 | } |
| 2137 | |
| 2138 | |
| 2139 | |
| 2140 | if((c==ASSIGN||c==PUSH)&&zmeqto(p->q2.val.vmax,l2zm(4L))) |
| 2141 | p->typf=t=LONG; |
| 2142 | |
| 2143 | preload(f,p); |
| 2144 | |
| 2145 | if(c==ADDI2P||c==SUBIFP){ |
| 2146 | if((p->typf2&NQ)!=HPOINTER){ |
| 2147 | if(p->q2.flags&KONST){ |
| 2148 | eval_const(&p->q2.val,p->typf); |
| 2149 | insert_const(&p->q2.val,p->typf2); |
| 2150 | p->typf=t=(UNSIGNED|SHORT); |
| 2151 | }else{ |
| 2152 | if(ISLWORD(t)) inc_addr(&p->q2,2,t); |
| 2153 | if((t&NQ)==CHAR) short_add=t; |
| 2154 | p->typf=t=(UNSIGNED|SHORT); |
| 2155 | } |
| 2156 | }else if(ISHWORD(t)){ |
| 2157 | if((t&NQ)==LLONG) |
| 2158 | inc_addr(&p->q2,4,t); |
| 2159 | else if((t&NQ)!=LONG) |
| 2160 | short_add=t; |
| 2161 | p->typf=t=(UNSIGNED|LONG); |
| 2162 | } |
| 2163 | p->code=c=(c==ADDI2P)?ADD:SUB; |
| 2164 | } |
| 2165 | |
| 2166 | if(c==COMPARE&&ISLWORD(t)){ |
| 2167 | IC *branch=p->next; |
| 2168 | int r; |
| 2169 | while(branch&&branch->code==FREEREG) branch=branch->next; |
| 2170 | if(!branch) ierror(0); |
| 2171 | c=branch->code; |
| 2172 | if(c<BEQ||c>BGT) ierror(0); |
| 2173 | if(!regs[ix]) |
| 2174 | r=ix; |
| 2175 | else |
| 2176 | r=get_reg(f,p,INT); |
| 2177 | |
| 2178 | if(c==BEQ||c==BNE){ |
| 2179 | inc_addr(&p->q1,0,t); |
| 2180 | inc_addr(&p->q2,0,t); |
| 2181 | load_reg(f,r,&p->q1,INT); |
| 2182 | emit(f,"\t%s%s\t",CPU==6812?"cp":"cmp",regnames[r]); |
| 2183 | emit_obj(f,&p->q2,INT); |
| 2184 | emit(f,"\n"); |
| 2185 | if(pushed_acc) emit(f,SPULLD); |
| 2186 | emit(f,"\tbne\t%s%d\n",labprefix,c==BEQ?++label:branch->typf); |
| 2187 | if(pushed_acc) emit(f,SPUSHD); |
| 2188 | inc_addr(&p->q1,2,t); |
| 2189 | inc_addr(&p->q2,2,t); |
| 2190 | load_reg(f,r,&p->q1,INT); |
| 2191 | emit(f,"\t%s%s\t",CPU==6812?"cp":"cmp",regnames[r]); |
| 2192 | emit_obj(f,&p->q2,INT); |
| 2193 | emit(f,"\n"); |
| 2194 | pr(f,p); |
| 2195 | if(c==BEQ){ |
| 2196 | emit(f,"\tbeq\t%s%d\n",labprefix,branch->typf); |
| 2197 | emit(f,"%s%d:\n",labprefix,label); |
| 2198 | }else |
| 2199 | emit(f,"\tbne\t%s%d\n",labprefix,branch->typf); |
| 2200 | }else{ |
| 2201 | inc_addr(&p->q1,0,t); |
| 2202 | inc_addr(&p->q2,0,t); |
| 2203 | load_reg(f,r,&p->q1,INT); |
| 2204 | emit(f,"\t%s%s\t",CPU==6812?"cp":"cmp",regnames[r]); |
| 2205 | emit_obj(f,&p->q2,INT); |
| 2206 | emit(f,"\n"); |
| 2207 | label++; |
| 2208 | if(pushed_acc) emit(f,SPULLD); |
| 2209 | if(t&UNSIGNED){ |
| 2210 | if(c==BLT||c==BGT) |
| 2211 | emit(f,"\tb%s\t%s%d\n",(c==BLT)?"lo":"hi",labprefix,branch->typf); |
| 2212 | else |
| 2213 | emit(f,"\tb%s\t%s%d\n",(c==BGE)?"lo":"hi",labprefix,label); |
| 2214 | }else{ |
| 2215 | if(c==BLT||c==BGT) |
| 2216 | emit(f,"\tb%s\t%s%d\n",(c==BLT)?"lt":"gt",labprefix,branch->typf); |
| 2217 | else |
| 2218 | emit(f,"\tb%s\t%s%d\n",(c==BGE)?"lt":"gt",labprefix,label); |
| 2219 | } |
| 2220 | emit(f,"\tbne\t%s%d\n",labprefix,(c==BLT||c==BGT)?label:branch->typf); |
| 2221 | if(pushed_acc) emit(f,SPUSHD); |
| 2222 | inc_addr(&p->q1,2,t); |
| 2223 | inc_addr(&p->q2,2,t); |
| 2224 | load_reg(f,r,&p->q1,INT); |
| 2225 | emit(f,"\t%s%s\t",CPU==6812?"cp":"cmp",regnames[r]); |
| 2226 | emit_obj(f,&p->q2,INT); |
| 2227 | emit(f,"\n"); |
| 2228 | pr(f,p); |
| 2229 | emit(f,"\tb%s\t%s%d\n",uccs[c-BEQ],labprefix,branch->typf); |
| 2230 | emit(f,"%s%d:\n",labprefix,label); |
| 2231 | } |
| 2232 | branch->code=NOP; |
| 2233 | continue; |
| 2234 | } |
| 2235 | |
| 2236 | if(ISLWORD(t)&&(c==LSHIFT||c==RSHIFT)){ |
| 2237 | int cnt=-1000,i,r=0; |
| 2238 | int px=0,py=0,pa=0; |
| 2239 | if(isconst(q2)){ |
| 2240 | eval_const(&p->q2.val,p->typf2); |
| 2241 | cnt=(int)zm2l(vmax); |
| 2242 | if(cnt==1&&compare_objects(&p->q1,&p->z)){ |
| 2243 | if(c==LSHIFT) |
| 2244 | emit(f,"\tlsl\t"); |
| 2245 | else |
| 2246 | emit(f,"\t%s\t",(t&UNSIGNED)?"lsr":"asr"); |
| 2247 | inc_addr(&p->z,c==LSHIFT?3:0,t); |
| 2248 | emit_obj(f,&p->z,t); |
| 2249 | emit(f,"\n"); |
| 2250 | emit(f,"\t%s\t",(c==LSHIFT)?"rol":"ror"); |
| 2251 | inc_addr(&p->z,c==LSHIFT?-1:1,t); |
| 2252 | emit_obj(f,&p->z,t); |
| 2253 | emit(f,"\n"); |
| 2254 | emit(f,"\t%s\t",(c==LSHIFT)?"rol":"ror"); |
| 2255 | inc_addr(&p->z,c==LSHIFT?-1:1,t); |
| 2256 | emit_obj(f,&p->z,t); |
| 2257 | emit(f,"\n"); |
| 2258 | emit(f,"\t%s\t",(c==LSHIFT)?"rol":"ror"); |
| 2259 | inc_addr(&p->z,c==LSHIFT?-1:1,t); |
| 2260 | emit_obj(f,&p->z,t); |
| 2261 | emit(f,"\n"); |
| 2262 | continue; |
| 2263 | } |
| 2264 | } |
| 2265 | inc_addr(&p->q1,2,t); |
| 2266 | inc_addr(&p->z,2,t); |
| 2267 | |
| 2268 | if(ISRACC(q2)||(regs[acc]&&!scratchreg(acc,p))){ |
| 2269 | emit(f,SPUSHD); |
| 2270 | push(2); |
| 2271 | pa=1; |
| 2272 | } |
| 2273 | |
| 2274 | if(cnt<0||(optsize&&cnt>1)||(cnt>3&&!optspeed)){ |
| 2275 | if(regs[ix]&&!scratchreg(ix,p)) {px=1;emit(f,SPUSH("x"));push(2);} |
| 2276 | if(regs[iy]&&!scratchreg(iy,p)) {py=1;emit(f,SPUSH("y"));push(2);} |
| 2277 | } |
| 2278 | |
| 2279 | if(!compare_objects(&p->q1,&p->z)){ |
| 2280 | load_reg(f,acc,&p->q1,INT); |
| 2281 | store_reg(f,acc,&p->z,INT); |
| 2282 | } |
| 2283 | inc_addr(&p->q1,-2,t); |
| 2284 | inc_addr(&p->z,-2,t); |
| 2285 | load_reg(f,acc,&p->q1,INT); |
| 2286 | if(cnt<0||(optsize&&cnt>1)||(cnt>3&&!optspeed)){ |
| 2287 | if((p->q2.flags®)&&p->q2.reg==ix){ |
| 2288 | if((p->z.flags®)&&p->z.reg==iy) ierror(0); |
| 2289 | }else |
| 2290 | load_addr(f,ix,&p->z); |
| 2291 | if(ISRACC(q2)){ |
| 2292 | if(scratchreg(acc,p)&&(px+py==0)){ |
| 2293 | emit(f,SPULL("y")); |
| 2294 | pop(2);pa=0; |
| 2295 | }else |
| 2296 | emit(f,"\tldy\t%d,%s\n",(px+py)*2,regnames[sp]); |
| 2297 | }else |
| 2298 | load_reg(f,iy,&p->q2,p->typf2); /*TODO: types!=INT?? */ |
| 2299 | if((p->q2.flags®)&&p->q2.reg==ix) |
| 2300 | load_addr(f,ix,&p->z); |
| 2301 | if(c==LSHIFT) |
| 2302 | emit(f,"\t%s\t%s__lsll\n",jsrinst,idprefix); |
| 2303 | else |
| 2304 | emit(f,"\t%s\t%s__%s\n",jsrinst,idprefix,(t&UNSIGNED)?"lsrl":"asrl"); |
| 2305 | if(py) {emit(f,SPULL("y"));pop(2);} |
| 2306 | if(px) {emit(f,SPULL("x"));pop(2);} |
| 2307 | }else{ |
| 2308 | inc_addr(&p->z,c==LSHIFT?3:2,t); |
| 2309 | for(i=0;i<cnt;i++){ |
| 2310 | if(c==LSHIFT){ |
| 2311 | emit(f,"\tlsl\t"); |
| 2312 | emit_obj(f,&p->z,CHAR); |
| 2313 | emit(f,"\n"); |
| 2314 | inc_addr(&p->z,-1,t); |
| 2315 | emit(f,"\trol\t"); |
| 2316 | emit_obj(f,&p->z,CHAR); |
| 2317 | emit(f,"\n"); |
| 2318 | inc_addr(&p->z,1,t); |
| 2319 | emit(f,"\trolb\n"); |
| 2320 | emit(f,"\trola\n"); |
| 2321 | }else{ |
| 2322 | emit(f,"\t%s\n",(t&UNSIGNED)?"lsra":"asra"); |
| 2323 | emit(f,"\trorb\n"); |
| 2324 | emit(f,"\tror\t"); |
| 2325 | emit_obj(f,&p->z,CHAR); |
| 2326 | emit(f,"\n"); |
| 2327 | inc_addr(&p->z,1,t); |
| 2328 | emit(f,"\tror\t"); |
| 2329 | emit_obj(f,&p->z,CHAR); |
| 2330 | emit(f,"\n"); |
| 2331 | inc_addr(&p->z,-1,t); |
| 2332 | } |
| 2333 | } |
| 2334 | inc_addr(&p->z,c==LSHIFT?-3:-2,t); |
| 2335 | store_reg(f,acc,&p->z,INT); |
| 2336 | } |
| 2337 | if(pa) {emit(f,SPULLD);pop(2);} |
| 2338 | continue; |
| 2339 | } |
| 2340 | |
| 2341 | if(ISLWORD(t)&&c!=GETRETURN&&c!=SETRETURN&&c!=COMPARE&&c!=CONVERT&&c!=ADDRESS){ |
| 2342 | if(c==PUSH&&isreg(q1)&&p->q1.reg==dx){ |
| 2343 | if(CPU==6812){ |
| 2344 | emit(f,"\tpshd\n"); |
| 2345 | emit(f,"\tpshx\n"); |
| 2346 | }else{ |
| 2347 | //emit(f,"\tpshs\ta,b,x\n"); |
| 2348 | emit(f,"\tpshs\tb,a\n"); |
| 2349 | emit(f,"\tpshs\tx\n"); |
| 2350 | } |
| 2351 | push(4); |
| 2352 | continue; |
| 2353 | } |
| 2354 | if(c==ASSIGN&&isreg(q1)&&p->q1.reg==dx){ |
| 2355 | inc_addr(&p->z,2,t); |
| 2356 | store_reg(f,ix,&p->z,INT); |
| 2357 | inc_addr(&p->z,-2,t); |
| 2358 | store_reg(f,acc,&p->z,INT); |
| 2359 | continue; |
| 2360 | } |
| 2361 | if(c==ASSIGN&&isreg(z)&&p->z.reg==dx){ |
| 2362 | inc_addr(&p->q1,2,t); |
| 2363 | load_reg(f,ix,&p->q1,INT); |
| 2364 | inc_addr(&p->q1,-2,t); |
| 2365 | load_reg(f,acc,&p->q1,INT); |
| 2366 | continue; |
| 2367 | } |
| 2368 | if(c==PUSH){ |
| 2369 | if(regs[acc]) emit(f,"\tstd\t%ld,%s\n",loff-roff-2-stackoffset,regnames[sp]); |
| 2370 | }else |
| 2371 | get_acc(f,p); |
| 2372 | /*TODO: acc in IC, constants */ |
| 2373 | inc_addr(&p->q1,2,t); |
| 2374 | if(c==MINUS){ |
| 2375 | if(CPU!=6812&&!optsize) |
| 2376 | emit(f,"\tldd\t#0\n"); |
| 2377 | else |
| 2378 | emit(f,"\tclra\n\tclrb\n"); |
| 2379 | }else |
| 2380 | load_reg(f,acc,&p->q1,INT); |
| 2381 | if(c==ADD||c==SUB){ |
| 2382 | inc_addr(&p->q2,2,t); |
| 2383 | emit(f,"\t%s\t",c==ADD?"addd":"subd"); |
| 2384 | emit_obj(f,&p->q2,INT); |
| 2385 | emit(f,"\n"); |
| 2386 | }else if(c==ASSIGN||c==PUSH){ |
| 2387 | }else if(c==MINUS){ |
| 2388 | emit(f,"\tsubd\t"); |
| 2389 | emit_obj(f,&p->q1,INT); |
| 2390 | emit(f,"\n"); |
| 2391 | }else if(c==KOMPLEMENT){ |
| 2392 | emit(f,"\tcoma\n"); |
| 2393 | emit(f,"\tcomb\n"); |
| 2394 | }else{ |
| 2395 | if(c==AND) |
| 2396 | emit(f,"\tandb\t"); |
| 2397 | else if(c==OR) |
| 2398 | emit(f,"\tor%sb\t",CPU==6812?"a":""); |
| 2399 | else if(c==XOR) |
| 2400 | emit(f,"\teorb\t"); |
| 2401 | inc_addr(&p->q2,3,t); |
| 2402 | emit_obj(f,&p->q2,CHAR); |
| 2403 | emit(f,"\n"); |
| 2404 | if(c==AND) |
| 2405 | emit(f,"\tanda\t"); |
| 2406 | else if(c==OR) |
| 2407 | emit(f,"\tor%sa\t",CPU==6812?"a":""); |
| 2408 | else if(c==XOR) |
| 2409 | emit(f,"\teora\t"); |
| 2410 | inc_addr(&p->q2,-1,t); |
| 2411 | emit_obj(f,&p->q2,CHAR); |
| 2412 | emit(f,"\n"); |
| 2413 | } |
| 2414 | if(c==PUSH){ |
| 2415 | if(CPU==6812) |
| 2416 | emit(f,"\tpshd\n"); |
| 2417 | else |
| 2418 | emit(f,"\tpshs\tb,a\n"); |
| 2419 | push(2);dontpop+=2; |
| 2420 | }else{ |
| 2421 | inc_addr(&p->z,2,t); |
| 2422 | store_reg(f,acc,&p->z,INT); |
| 2423 | } |
| 2424 | inc_addr(&p->q1,-2,t); |
| 2425 | if(c==MINUS) |
| 2426 | emit(f,"\tldd\t#0\n"); |
| 2427 | else |
| 2428 | load_reg(f,acc,&p->q1,INT); |
| 2429 | if(c==ADD) |
| 2430 | emit(f,"\tadcb\t"); |
| 2431 | else if(c==SUB) |
| 2432 | emit(f,"\tsbcb\t"); |
| 2433 | else if(c==AND) |
| 2434 | emit(f,"\tandb\t"); |
| 2435 | else if(c==OR) |
| 2436 | emit(f,"\tor%sb\t",CPU==6812?"a":""); |
| 2437 | else if(c==XOR) |
| 2438 | emit(f,"\teorb\t"); |
| 2439 | else if(c==KOMPLEMENT) |
| 2440 | emit(f,"\tcomb\n"); |
| 2441 | else if(c==MINUS){ |
| 2442 | inc_addr(&p->q1,1,t); |
| 2443 | emit(f,"\tsbcb\t"); |
| 2444 | emit_obj(f,&p->q1,CHAR); |
| 2445 | emit(f,"\n"); |
| 2446 | } |
| 2447 | if(p->q2.flags){ |
| 2448 | inc_addr(&p->q2,-1,t); |
| 2449 | emit_obj(f,&p->q2,CHAR); |
| 2450 | emit(f,"\n"); |
| 2451 | } |
| 2452 | if(c==ADD) |
| 2453 | emit(f,"\tadca\t"); |
| 2454 | else if(c==SUB) |
| 2455 | emit(f,"\tsbca\t"); |
| 2456 | else if(c==AND) |
| 2457 | emit(f,"\tanda\t"); |
| 2458 | else if(c==OR) |
| 2459 | emit(f,"\tor%sa\t",CPU==6812?"a":""); |
| 2460 | else if(c==XOR) |
| 2461 | emit(f,"\teora\t"); |
| 2462 | else if(c==KOMPLEMENT) |
| 2463 | emit(f,"\tcoma\n"); |
| 2464 | else if(c==MINUS){ |
| 2465 | inc_addr(&p->q1,-1,t); |
| 2466 | emit(f,"\tsbca\t"); |
| 2467 | emit_obj(f,&p->q1,CHAR); |
| 2468 | emit(f,"\n"); |
| 2469 | } |
| 2470 | if(p->q2.flags){ |
| 2471 | inc_addr(&p->q2,-1,t); |
| 2472 | emit_obj(f,&p->q2,CHAR); |
| 2473 | emit(f,"\n"); |
| 2474 | } |
| 2475 | if(c==PUSH){ |
| 2476 | if(CPU==6812) |
| 2477 | emit(f,"\tpshd\n"); |
| 2478 | else |
| 2479 | emit(f,"\tpshs\tb,a\n"); |
| 2480 | push(2);dontpop+=2; |
| 2481 | if(regs[acc]) emit(f,"\tldd\t%ld,%s\n",loff-roff-2-stackoffset,regnames[sp]); |
| 2482 | }else{ |
| 2483 | inc_addr(&p->z,-2,t); |
| 2484 | store_reg(f,acc,&p->z,INT); |
| 2485 | } |
| 2486 | continue; |
| 2487 | } |
| 2488 | |
| 2489 | |
| 2490 | if(c==COMPARE){ |
| 2491 | int vadr; |
| 2492 | if(drel&&(p->q1.flags&VARADR)&&!ISFUNC(p->q1.v->vtyp->flags)) vadr=1; |
| 2493 | else if(drel&&(p->q2.flags&VARADR)&&!ISFUNC(p->q2.v->vtyp->flags)) vadr=2; |
| 2494 | else if(pcrel&&(p->q1.flags&VARADR)&&ISFUNC(p->q1.v->vtyp->flags)) vadr=1; |
| 2495 | else if(pcrel&&(p->q2.flags&VARADR)&&ISFUNC(p->q2.v->vtyp->flags)) vadr=2; |
| 2496 | else vadr=0; |
| 2497 | if(vadr!=1&&(vadr==2||isconst(q1)||ISRACC(q2))){ |
| 2498 | struct IC *p2; |
| 2499 | o=p->q1;p->q1=p->q2;p->q2=o; |
| 2500 | p2=p->next; |
| 2501 | while(p2&&p2->code==FREEREG) p2=p2->next; |
| 2502 | if(!p2||p2->code<BEQ||p2->code>BGT) ierror(0); |
| 2503 | if(p2->code==BLT) p2->code=BGT; |
| 2504 | else if(p2->code==BGT) p2->code=BLT; |
| 2505 | else if(p2->code==BLE) p2->code=BGE; |
| 2506 | else if(p2->code==BGE) p2->code=BLE; |
| 2507 | } |
| 2508 | /* case with two relative addresses */ |
| 2509 | if(drel&&(p->q2.flags&VARADR)&&!ISFUNC(p->q2.v->vtyp->flags)) skip_rel=1; |
| 2510 | if(pcrel&&(p->q2.flags&VARADR)&&ISFUNC(p->q2.v->vtyp->flags)) skip_rel=1; |
| 2511 | } |
| 2512 | #if 0 |
| 2513 | /* TODO: fix cc */ |
| 2514 | if(c==COMPARE&&isconst(q2)){ |
| 2515 | eval_const(&p->q2.val,t); |
| 2516 | if(ISNULL()){ |
| 2517 | if(cc&&(cc_t&NU)==(t&NU)&&compare_objects(cc,&p->q1)){ |
| 2518 | lastcomp=t;continue; |
| 2519 | } |
| 2520 | } |
| 2521 | } |
| 2522 | #endif |
| 2523 | |
| 2524 | if(!short_add) |
| 2525 | switch_IC(p); |
| 2526 | |
| 2527 | if(c==CONVERT){ |
| 2528 | int to=p->typf2&NU; |
| 2529 | if(to==INT) to=SHORT; |
| 2530 | if(to==(UNSIGNED|INT)||to==NPOINTER) to=(UNSIGNED|SHORT); |
| 2531 | if(to==FPOINTER||to==HPOINTER) to=(UNSIGNED|LONG); |
| 2532 | if((t&NU)==INT) t=SHORT; |
| 2533 | if((t&NU)==(UNSIGNED|INT)||(t&NU)==NPOINTER) t=(UNSIGNED|SHORT); |
| 2534 | if((t&NQ)==FPOINTER||(t&NQ)==HPOINTER) t=(UNSIGNED|LONG); |
| 2535 | /*if((t&NQ)>=LONG||(to&NQ)>=LONG) ierror(0);*/ |
| 2536 | if((to&NQ)<=LONG&&(t&NQ)<=LONG){ |
| 2537 | if((to&NQ)<(t&NQ)){ |
| 2538 | if(ISLWORD(t)){ |
| 2539 | get_acc(f,p); |
| 2540 | load_reg(f,acc,&p->q1,to); |
| 2541 | if((to&NU)==CHAR) |
| 2542 | emit(f,SEX); |
| 2543 | else if((to&NU)==(UNSIGNED|CHAR)) |
| 2544 | emit(f,"\tclra\n"); |
| 2545 | inc_addr(&p->z,2,t); |
| 2546 | store_reg(f,acc,&p->z,INT); |
| 2547 | inc_addr(&p->z,-2,t); |
| 2548 | if(to&UNSIGNED){ |
| 2549 | emit(f,"\tclra\n\tclrb\n"); |
| 2550 | }else{ |
| 2551 | if(CPU==6812) |
| 2552 | emit(f,"\texg\ta,b\n"); |
| 2553 | else |
| 2554 | emit(f,"\ttfr\ta,b\n"); |
| 2555 | emit(f,SEX); |
| 2556 | emit(f,"\ttfr\ta,b\n"); |
| 2557 | } |
| 2558 | store_reg(f,acc,&p->z,INT); |
| 2559 | continue; |
| 2560 | } |
| 2561 | /*emit(f,"#conv RACC=%d, regs=%d scratch=%d\n",(int)ISRACC(z),regs[acc],scratchreg(acc,p));*/ |
| 2562 | if(!ISRACC(z)) |
| 2563 | get_acc(f,p); |
| 2564 | load_reg(f,acc,&p->q1,to); |
| 2565 | if(to&UNSIGNED) |
| 2566 | emit(f,"\tclra\n"); |
| 2567 | else |
| 2568 | emit(f,SEX); |
| 2569 | store_reg(f,acc,&p->z,t); |
| 2570 | cc=&p->z;cc_t=t; |
| 2571 | continue; |
| 2572 | }else if((to&NQ)>(t&NQ)){ |
| 2573 | if(!ISRACC(z)&&!ISRACC(q1)) |
| 2574 | get_acc(f,p); |
| 2575 | if(ISLWORD(to)) |
| 2576 | inc_addr(&p->q1,2,to); |
| 2577 | load_reg(f,acc,&p->q1,to); |
| 2578 | store_reg(f,acc,&p->z,t); |
| 2579 | continue; |
| 2580 | }else{ |
| 2581 | c=ASSIGN; |
| 2582 | p->q2.val.vmax=sizetab[t&NQ]; |
| 2583 | } |
| 2584 | } |
| 2585 | } |
| 2586 | if(c==KOMPLEMENT){ |
| 2587 | cc=0; |
| 2588 | if(compare_objects(&p->q1,&p->z)&&!isreg(q1)&&(p->q1.flags&(REG|DREFOBJ))!=DREFOBJ&&(!p->q1.am||p->q1.am->flags!=ACC_IND)){ |
| 2589 | emit(f,"\tcom\t"); |
| 2590 | emit_obj(f,&p->z,t); |
| 2591 | emit(f,"\n"); |
| 2592 | if(ISHWORD(t)){ |
| 2593 | mobj=p->z; |
| 2594 | inc_addr(&mobj,1,t); |
| 2595 | emit(f,"\tcom\t"); |
| 2596 | emit_obj(f,&mobj,INT); |
| 2597 | emit(f,"\n"); |
| 2598 | } |
| 2599 | continue; |
| 2600 | } |
| 2601 | if((!isreg(z)||p->z.reg!=acc)&®s[acc]&&!scratchreg(acc,p)) |
| 2602 | get_acc(f,p); |
| 2603 | load_reg(f,acc,&p->q1,t); |
| 2604 | emit(f,"\tcoma\n\tcomb\n"); |
| 2605 | store_reg(f,acc,&p->z,t); |
| 2606 | continue; |
| 2607 | } |
| 2608 | if(c==MINUS){ |
| 2609 | if((!isreg(z)||p->z.reg!=acc)&®s[acc]&&!scratchreg(acc,p)) |
| 2610 | get_acc(f,p); |
| 2611 | if(isreg(q1)){ |
| 2612 | load_reg(f,acc,&p->q1,t); |
| 2613 | emit(f,"\tnega\n\tnegb\n\tsbca\t#0\n"); |
| 2614 | }else{ |
| 2615 | if(CPU!=6812&&!optsize) |
| 2616 | emit(f,"\tldd\t#0\n"); |
| 2617 | else |
| 2618 | emit(f,"\tclra\n\tclrb\n"); |
| 2619 | emit(f,"\tsubd\t"); |
| 2620 | emit_obj(f,&p->q1,t); |
| 2621 | emit(f,"\n"); |
| 2622 | } |
| 2623 | cc=&p->z;cc_t=t; |
| 2624 | store_reg(f,acc,&p->z,t); |
| 2625 | continue; |
| 2626 | } |
| 2627 | if(c==SETRETURN){ |
| 2628 | if(isreg(q1)&&p->q1.reg==p->z.reg) continue; |
| 2629 | if(p->z.reg){ |
| 2630 | if(ISLWORD(t)){ |
| 2631 | inc_addr(&p->q1,0,t); |
| 2632 | load_reg(f,ix,&p->q1,INT); |
| 2633 | BSET(regs_modified,ix); |
| 2634 | inc_addr(&p->q1,2,t); |
| 2635 | } |
| 2636 | load_reg(f,acc,&p->q1,t); |
| 2637 | BSET(regs_modified,acc); |
| 2638 | |
| 2639 | } |
| 2640 | continue; |
| 2641 | } |
| 2642 | if(c==GETRETURN){ |
| 2643 | if(isreg(z)&&p->z.reg==p->q1.reg) continue; |
| 2644 | if(p->q1.reg){ |
| 2645 | if(ISLWORD(t)){ |
| 2646 | store_reg(f,ix,&p->z,INT); |
| 2647 | BSET(regs_modified,ix); |
| 2648 | inc_addr(&p->z,2,t); |
| 2649 | } |
| 2650 | store_reg(f,acc,&p->z,(t&NQ)==CHAR?t:INT); |
| 2651 | } |
| 2652 | continue; |
| 2653 | } |
| 2654 | if(c==CALL){ |
| 2655 | int reg,jmp=0; |
| 2656 | cc=0; |
| 2657 | if(!calc_regs(p,f!=0)&&v->fi) v->fi->flags&=~ALL_REGS; |
| 2658 | if((p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp("__va_start",p->q1.v->identifier)){ |
| 2659 | long of=va_offset(v)+loff+2; |
| 2660 | emit(f,"\ttfr\t%s,d\n",regnames[sp]); |
| 2661 | if(of) emit(f,"\taddd\t#%ld\n",of); |
| 2662 | continue; |
| 2663 | } |
| 2664 | if((p->q1.flags&VAR)&&p->q1.v->fi&&p->q1.v->fi->inline_asm){ |
| 2665 | emit_inline_asm(f,p->q1.v->fi->inline_asm); |
| 2666 | jmp=1; |
| 2667 | }else{ |
| 2668 | if(stackoffset==0&&!have_frame&&!strcmp(ret,"rts")){ |
| 2669 | struct IC *p2; |
| 2670 | jmp=1; |
| 2671 | for(p2=p->next;p2;p2=p2->next){ |
| 2672 | if(p2->code!=FREEREG&&p2->code!=ALLOCREG&&p2->code!=LABEL){ |
| 2673 | jmp=0;break; |
| 2674 | } |
| 2675 | } |
| 2676 | } |
| 2677 | if(p->q1.flags&DREFOBJ){ |
| 2678 | /*FIXME: test this*/ |
| 2679 | if(jmp) |
| 2680 | emit(f,"\tjmp\t"); |
| 2681 | else |
| 2682 | emit(f,"\tjsr\t"); |
| 2683 | if (p->q1.v->tattr&FAR) |
| 2684 | emit(f,"\tfar\t"); |
| 2685 | emit_obj(f,&p->q1,t); |
| 2686 | emit(f,"\n"); |
| 2687 | }else{ |
| 2688 | if(jmp){ |
| 2689 | emit(f,"\t%s\t",jmpinst); /*emit(f,"\tbra\t");*/ |
| 2690 | /*if(!need_return) ret=0;*/ /*TODO: works with optimizer? */ |
| 2691 | }else{ |
| 2692 | emit(f,"\t%s\t",jsrinst); /*emit(f,"\tbsr\t");*/ |
| 2693 | } |
| 2694 | if (p->q1.v->tattr&FAR) |
| 2695 | emit(f,"\tfar\t"); |
| 2696 | if(pcrel){ |
| 2697 | pcrel=0; |
| 2698 | emit_obj(f,&p->q1,t); |
| 2699 | pcrel=1; |
| 2700 | }else |
| 2701 | emit_obj(f,&p->q1,t); |
| 2702 | emit(f,"\n"); |
| 2703 | } |
| 2704 | } |
| 2705 | if(stack_valid){ |
| 2706 | int i; |
| 2707 | if(p->call_cnt<=0){ |
| 2708 | err_ic=p;if(f) error(320); |
| 2709 | stack_valid=0; |
| 2710 | } |
| 2711 | for(i=0;stack_valid&&i<p->call_cnt;i++){ |
| 2712 | if(p->call_list[i].v->fi&&(p->call_list[i].v->fi->flags&ALL_STACK)){ |
| 2713 | /*FIXME: size of return addr depends on mode */ |
| 2714 | if(!jmp) push(2); |
| 2715 | callee_push(zm2l(p->call_list[i].v->fi->stack1)); |
| 2716 | if(!jmp) pop(2); |
| 2717 | }else{ |
| 2718 | err_ic=p;if(f) error(317,p->call_list[i].v->identifier); |
| 2719 | stack_valid=0; |
| 2720 | } |
| 2721 | } |
| 2722 | } |
| 2723 | if(!zmeqto(l2zm(0L),p->q2.val.vmax)){ |
| 2724 | notpopped+=zm2l(p->q2.val.vmax); |
| 2725 | dontpop-=zm2l(p->q2.val.vmax); |
| 2726 | if(!(g_flags[2]&USEDFLAG)&&stackoffset==-notpopped){ |
| 2727 | /* Entfernen der Parameter verzoegern */ |
| 2728 | }else{ |
| 2729 | gen_pop(f,zm2l(p->q2.val.vmax)); |
| 2730 | notpopped-=zm2l(p->q2.val.vmax); |
| 2731 | } |
| 2732 | } |
| 2733 | continue; |
| 2734 | } |
| 2735 | if(c==ASSIGN||c==PUSH){ |
| 2736 | if(c==PUSH) dontpop+=zm2l(p->q2.val.vmax); |
| 2737 | if(!zmleq(p->q2.val.vmax,l2zm(2L))){ |
| 2738 | unsigned long size;int qr=0,zr=0,cr=0,px=0,py=0,pu=0,pd=0,lq=0,lz=0; |
| 2739 | size=zm2l(p->q2.val.vmax); |
| 2740 | if(c==ASSIGN){ |
| 2741 | if(!p->z.am&&(p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&ISIDX(p->z.reg)){ |
| 2742 | zr=p->z.reg;lz=1; |
| 2743 | } |
| 2744 | } |
| 2745 | if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&ISIDX(p->q1.reg)&&p->q1.reg!=zr){ |
| 2746 | qr=p->q1.reg;lq=1; |
| 2747 | } |
| 2748 | if(!qr){ |
| 2749 | if(zr==ix) qr=iy; |
| 2750 | else if(zr==iy||zr==iu) qr=ix; |
| 2751 | else{qr=ix;zr=iy;} |
| 2752 | }else if(!zr){ |
| 2753 | if(qr==ix) zr=iy; else zr=ix; |
| 2754 | } |
| 2755 | if(CPU!=6812){ |
| 2756 | if(qr!=iu&&zr!=iu) cr=iu; |
| 2757 | if(qr!=ix&&zr!=ix) cr=ix; |
| 2758 | if(qr!=iy&&zr!=iy) cr=iy; |
| 2759 | if(!cr) ierror(0); |
| 2760 | } |
| 2761 | if(c==PUSH){ |
| 2762 | emit(f,"\tleas\t%ld,%s\n",SGN16(-size),regnames[sp]); |
| 2763 | push(size); |
| 2764 | } |
| 2765 | if(CPU!=6812&&(drel||!regused[iu]||(regs[iu]&&!scratchreg(iu,p)))){ |
| 2766 | if(c==PUSH) |
| 2767 | emit(f,"\tstu\t%ld,%s\n",loff-roff-8-stackoffset,regnames[sp]); |
| 2768 | else{ |
| 2769 | emit(f,SPUSH("u")); |
| 2770 | push(2); |
| 2771 | } |
| 2772 | pu=1; |
| 2773 | } |
| 2774 | if(!regused[iy]||(regs[iy]&&!scratchreg(iy,p))){ |
| 2775 | if(c==PUSH) |
| 2776 | emit(f,"\tsty\t%ld,%s\n",loff-roff-4-stackoffset,regnames[sp]); |
| 2777 | else{ |
| 2778 | emit(f,SPUSH("y")); |
| 2779 | push(2); |
| 2780 | } |
| 2781 | py=1; |
| 2782 | } |
| 2783 | if(regs[ix]&&!scratchreg(ix,p)){ |
| 2784 | if(c==PUSH) |
| 2785 | emit(f,"\tstx\t%ld,%s\n",loff-roff-2-stackoffset,regnames[sp]); |
| 2786 | else{ |
| 2787 | emit(f,SPUSH("x")); |
| 2788 | push(2); |
| 2789 | } |
| 2790 | px=1; |
| 2791 | } |
| 2792 | if(!lq) load_addr(f,qr,&p->q1); |
| 2793 | if(c==PUSH) |
| 2794 | emit(f,"\ttfr\t%s,%s\n",regnames[sp],regnames[zr]); |
| 2795 | else |
| 2796 | if(!lz) load_addr(f,zr,&p->z); |
| 2797 | if(size<=6||(size<=16&&!optsize)){ |
| 2798 | if(CPU!=6812){ |
| 2799 | if(!scratchreg(acc,p)){ |
| 2800 | if(c==PUSH) |
| 2801 | emit(f,"\tstd\t%ld,%s\n",loff-roff-6-stackoffset,regnames[sp]); |
| 2802 | else{ |
| 2803 | emit(f,SPUSHD); |
| 2804 | push(2); |
| 2805 | } |
| 2806 | pd=2; |
| 2807 | } |
| 2808 | } |
| 2809 | while(size>2){ |
| 2810 | if(CPU==6812) |
| 2811 | emit(f,"\tmovw\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
| 2812 | else |
| 2813 | emit(f,"\tldd\t,%s++\n\tstd\t,%s++\n",regnames[qr],regnames[zr]); |
| 2814 | size-=2; |
| 2815 | } |
| 2816 | if(CPU==6812) |
| 2817 | emit(f,"\tmov%c\t0,%s,0,%s\n",size==2?'w':'b',regnames[qr],regnames[zr]); |
| 2818 | else |
| 2819 | emit(f,"\tld%c\t,%s\n\tst%c\t,%s\n",size==2?'d':'b',regnames[qr],size==2?'d':'b',regnames[zr]); |
| 2820 | }else{ |
| 2821 | int l=++label,cnt=(int)(optsize?size:size/8); |
| 2822 | if(regs[acc]&&!scratchreg(acc,p)){ |
| 2823 | if(c==PUSH) |
| 2824 | emit(f,"\tst%c\t%ld,%s\n",(CPU!=6812&&cnt<=bytemask)?'b':'d',loff-roff-6-stackoffset,regnames[sp]); |
| 2825 | else{ |
| 2826 | if(CPU!=6812&&cnt<=bytemask){ |
| 2827 | emit(f,SPUSH("b")); |
| 2828 | push(1); |
| 2829 | }else{ |
| 2830 | emit(f,SPUSHD); |
| 2831 | push(2); |
| 2832 | } |
| 2833 | } |
| 2834 | pd=(CPU!=6812&&cnt<=bytemask)?1:2; |
| 2835 | } |
| 2836 | if(CPU!=6812&&cnt<=bytemask) |
| 2837 | emit(f,"\tldb\t#%lu\n",cnt); |
| 2838 | else |
| 2839 | emit(f,"\tldd\t#%lu\n",cnt); |
| 2840 | cc=0; |
| 2841 | #if 0 |
| 2842 | if(CPU!=6812&&((!regsa[iu]&®s[iu])||drel)){ |
| 2843 | if(c==PUSH){ |
| 2844 | emit(f,"\tstu\t%ld,%s\n",loff-roff-8-stackoffset,regnames[sp]); |
| 2845 | }else{ |
| 2846 | emit(f,SPUSH("u"));push(2); |
| 2847 | } |
| 2848 | } |
| 2849 | #endif |
| 2850 | emit(f,"%s%d:\n",labprefix,l); |
| 2851 | if(CPU==6812){ |
| 2852 | if(optsize){ |
| 2853 | emit(f,"\tmovb\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
| 2854 | }else{ |
| 2855 | emit(f,"\tmovw\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
| 2856 | emit(f,"\tmovw\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
| 2857 | emit(f,"\tmovw\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
| 2858 | emit(f,"\tmovw\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
| 2859 | size=size&7; |
| 2860 | } |
| 2861 | emit(f,"\tdbne\td,%s%d\n",labprefix,l); |
| 2862 | }else{ |
| 2863 | if(optsize){ |
| 2864 | emit(f,"\tld%s\t,%s+\n\tst%s\t,%s+\n",regnames[cr],regnames[qr],regnames[cr],regnames[zr]); |
| 2865 | size&=1; |
| 2866 | }else{ |
| 2867 | emit(f,"\tld%s\t,%s++\n\tst%s\t,%s++\n",regnames[cr],regnames[qr],regnames[cr],regnames[zr]); |
| 2868 | emit(f,"\tld%s\t,%s++\n\tst%s\t,%s++\n",regnames[cr],regnames[qr],regnames[cr],regnames[zr]); |
| 2869 | emit(f,"\tld%s\t,%s++\n\tst%s\t,%s++\n",regnames[cr],regnames[qr],regnames[cr],regnames[zr]); |
| 2870 | emit(f,"\tld%s\t,%s++\n\tst%s\t,%s++\n",regnames[cr],regnames[qr],regnames[cr],regnames[zr]); |
| 2871 | size&=7; |
| 2872 | } |
| 2873 | if(cnt<=bytemask) |
| 2874 | emit(f,"\tdecb\n"); |
| 2875 | else |
| 2876 | emit(f,"\tsubd\t#1\n"); |
| 2877 | emit(f,"\tbne\t%s%d\n",labprefix,l); |
| 2878 | } |
| 2879 | #if 0 |
| 2880 | if(CPU!=6812&&((!regsa[iu]&®s[iu])||drel)){ |
| 2881 | if(c==PUSH){ |
| 2882 | emit(f,"\tldu\t%ld,%s\n",loff-roff-8-stackoffset,regnames[sp]); |
| 2883 | }else{ |
| 2884 | emit(f,SPULL("u"));pop(2); |
| 2885 | } |
| 2886 | } |
| 2887 | #endif |
| 2888 | while(size>=2){ |
| 2889 | if(CPU==6812) |
| 2890 | emit(f,"\tmovw\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
| 2891 | else |
| 2892 | emit(f,"\tldd\t,%s++\n\tstd\t,%s++\n",regnames[qr],regnames[zr]); |
| 2893 | size-=2; |
| 2894 | } |
| 2895 | if(size){ |
| 2896 | if(CPU==6812) |
| 2897 | emit(f,"\tmovb\t0,%s,0,%s\n",regnames[qr],regnames[zr]); |
| 2898 | else |
| 2899 | emit(f,"\tldb\t,%s\n\tstb\t,%s\n",regnames[qr],regnames[zr]); |
| 2900 | } |
| 2901 | } |
| 2902 | if(pd){ |
| 2903 | if(c==PUSH) |
| 2904 | emit(f,"\tld%c\t%ld,%s\n",(pd==1)?'b':'d',loff-roff-6-stackoffset,regnames[sp]); |
| 2905 | else{ |
| 2906 | if(pd==1){ |
| 2907 | emit(f,SPULL("b")); |
| 2908 | pop(1); |
| 2909 | }else{ |
| 2910 | emit(f,SPULLD); |
| 2911 | pop(2); |
| 2912 | } |
| 2913 | } |
| 2914 | } |
| 2915 | if(px){ |
| 2916 | if(c==PUSH) |
| 2917 | emit(f,"\tldx\t%ld,%s\n",loff-roff-2-stackoffset,regnames[sp]); |
| 2918 | else{ |
| 2919 | emit(f,SPULL("x")); |
| 2920 | pop(2); |
| 2921 | } |
| 2922 | } |
| 2923 | if(py){ |
| 2924 | if(c==PUSH) |
| 2925 | emit(f,"\tldy\t%ld,%s\n",loff-roff-4-stackoffset,regnames[sp]); |
| 2926 | else{ |
| 2927 | emit(f,SPULL("y")); |
| 2928 | pop(2); |
| 2929 | } |
| 2930 | } |
| 2931 | if(pu){ |
| 2932 | if(c==PUSH) |
| 2933 | emit(f,"\tldu\t%ld,%s\n",loff-roff-8-stackoffset,regnames[sp]); |
| 2934 | else{ |
| 2935 | emit(f,SPULL("u")); |
| 2936 | pop(2); |
| 2937 | } |
| 2938 | } |
| 2939 | continue; |
| 2940 | } |
| 2941 | if(!ISSCALAR(t)) t=zmeqto(p->q2.val.vmax,l2zm(1L))?CHAR:INT; |
| 2942 | if((t&NQ)==CHAR&&!zmeqto(p->q2.val.vmax,l2zm(1L))) t=INT; |
| 2943 | if(mov_op(&p->q1)&&(c==PUSH||mov_op(&p->z))){ |
| 2944 | emit(f,"\tmov%c\t",ISHWORD(t)?'w':'b'); |
| 2945 | emit_obj(f,&p->q1,t); |
| 2946 | if(c==ASSIGN){ |
| 2947 | emit(f,","); |
| 2948 | emit_obj(f,&p->z,t); |
| 2949 | emit(f,"\n"); |
| 2950 | }else{ |
| 2951 | emit(f,",%d,-%s\n",ISHWORD(t)?2:1,regnames[sp]); |
| 2952 | push(ISHWORD(t)?2:1); |
| 2953 | } |
| 2954 | continue; |
| 2955 | } |
| 2956 | if(((regs[acc]&®s[ix])||(t&NQ)==CHAR)&&(p->q1.flags&KONST)&&!isreg(z)){ |
| 2957 | eval_const(&p->q1.val,t); |
| 2958 | if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&((p->z.flags&(REG|DREFOBJ))!=DREFOBJ||(t&NQ)==CHAR)&&(!p->z.am||p->z.am->flags!=ACC_IND||(t&NQ)==CHAR)){ |
| 2959 | emit(f,"\tclr\t"); |
| 2960 | if(c==ASSIGN){ |
| 2961 | emit_obj(f,&p->z,t);emit(f,"\n"); |
| 2962 | }else{ |
| 2963 | emit(f,CPU==6812?"1,-sp\n":",-s\n"); |
| 2964 | push(1); |
| 2965 | } |
| 2966 | if(!ISHWORD(t)) continue; |
| 2967 | emit(f,"\tclr\t"); |
| 2968 | if(c==ASSIGN){ |
| 2969 | mobj=p->z; |
| 2970 | inc_addr(&mobj,1,t); |
| 2971 | emit_obj(f,&mobj,t);emit(f,"\n"); |
| 2972 | }else{ |
| 2973 | emit(f,CPU==6812?"1,-sp\n":",-s\n"); |
| 2974 | push(1); |
| 2975 | } |
| 2976 | continue; |
| 2977 | } |
| 2978 | |
| 2979 | } |
| 2980 | if(c==PUSH){ |
| 2981 | int st=0; |
| 2982 | if(isreg(q1)){ |
| 2983 | reg=p->q1.reg; |
| 2984 | }else{ |
| 2985 | if((t&NQ)==CHAR||!regs[acc]||scratchreg(acc,p)) reg=acc; |
| 2986 | else if(!regs[ix]||scratchreg(ix,p)) reg=ix; |
| 2987 | else if(regused[iy]&&(!regs[iy]||scratchreg(iy,p))) reg=iy; |
| 2988 | else if(regused[iu]&&!drel&&CPU!=6812&&(!regs[iu]||scratchreg(iu,p))) reg=iu; |
| 2989 | else reg=acc; |
| 2990 | if(regs[reg]&&!scratchreg(reg,p)){ |
| 2991 | st=1; |
| 2992 | emit(f,"\tst%s\t%ld,%s\n",regnames[reg],(long)loff-roff-2-stackoffset,regnames[sp]); |
| 2993 | } |
| 2994 | load_reg(f,reg,&p->q1,t); |
| 2995 | } |
| 2996 | if((t&NQ)==CHAR) |
| 2997 | emit(f,SPUSH("b")); |
| 2998 | else if(reg==ix) |
| 2999 | emit(f,SPUSH("x")); |
| 3000 | else if(reg==iy) |
| 3001 | emit(f,SPUSH("y")); |
| 3002 | else if(reg==iu) |
| 3003 | emit(f,SPUSH("u")); |
| 3004 | else |
| 3005 | emit(f,SPUSHD); |
| 3006 | push(zm2l(p->q2.val.vmax)); |
| 3007 | if(st) |
| 3008 | emit(f,"\tld%s\t%ld,%s\n",regnames[reg],(long)loff-roff-2-stackoffset,regnames[sp]); |
| 3009 | continue; |
| 3010 | } |
| 3011 | if(c==ASSIGN){ |
| 3012 | if(isreg(q1)&&isreg(z)){ |
| 3013 | if(p->q1.reg!=p->z.reg) |
| 3014 | emit(f,"\ttfr\t%s,%s\n",regnames[p->q1.reg],regnames[p->z.reg]); |
| 3015 | }else if(isreg(q1)){ |
| 3016 | store_reg(f,p->q1.reg,&p->z,t); |
| 3017 | }else if(isreg(z)){ |
| 3018 | load_reg(f,p->z.reg,&p->q1,t); |
| 3019 | }else{ |
| 3020 | reg=get_reg(f,p,t); |
| 3021 | load_reg(f,reg,&p->q1,t); |
| 3022 | store_reg(f,reg,&p->z,t); |
| 3023 | } |
| 3024 | continue; |
| 3025 | } |
| 3026 | ierror(0); |
| 3027 | } |
| 3028 | if(c==ADDRESS){ |
| 3029 | int px=0; |
| 3030 | if(isreg(z)){ |
| 3031 | reg=p->z.reg; |
| 3032 | }else if(!regs[ix]){ |
| 3033 | reg=ix; |
| 3034 | }else if(!regs[iy]){ |
| 3035 | reg=iy; |
| 3036 | }else{ |
| 3037 | /*FIXME: test if x used in q1 */ |
| 3038 | px=1; |
| 3039 | emit(f,SPUSH("x")); |
| 3040 | reg=ix; |
| 3041 | push(2); |
| 3042 | } |
| 3043 | load_addr(f,reg,&p->q1); |
| 3044 | if(!(p->z.flags®)||p->z.reg!=reg) |
| 3045 | store_reg(f,reg,&p->z,p->typf2); |
| 3046 | if(px){ |
| 3047 | emit(f,SPULL("x")); |
| 3048 | pop(2); |
| 3049 | } |
| 3050 | continue; |
| 3051 | } |
| 3052 | |
| 3053 | if((c==MULT||c==DIV||(c==MOD&&(p->typf&UNSIGNED)))&&isconst(q2)){ |
| 3054 | long ln; |
| 3055 | eval_const(&p->q2.val,t); |
| 3056 | if(zmleq(l2zm(0L),vmax)&&zumleq(ul2zum(0UL),vumax)){ |
| 3057 | if((ln=pof2(vumax))&&ln<5){ |
| 3058 | if(c==MOD){ |
| 3059 | vmax=zmsub(vmax,l2zm(1L)); |
| 3060 | c=p->code=c=AND; |
| 3061 | }else{ |
| 3062 | vmax=l2zm(ln-1); |
| 3063 | if(c==DIV) p->code=c=RSHIFT; else p->code=c=LSHIFT; |
| 3064 | } |
| 3065 | c=p->code; |
| 3066 | gval.vmax=vmax; |
| 3067 | eval_const(&gval,MAXINT); |
| 3068 | if(c==AND){ |
| 3069 | insert_const(&p->q2.val,t); |
| 3070 | }else{ |
| 3071 | insert_const(&p->q2.val,t); |
| 3072 | p->typf2=INT; |
| 3073 | } |
| 3074 | } |
| 3075 | } |
| 3076 | } |
| 3077 | if(c==MOD||c==DIV){ |
| 3078 | ierror(0); |
| 3079 | continue; |
| 3080 | } |
| 3081 | |
| 3082 | |
| 3083 | if((c==ADD||c==SUB)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&(p->q1.flags&(REG|DREFOBJ))!=REG&&(p->q1.flags&(REG|DREFOBJ))!=DREFOBJ&&!p->q1.am&&!p->z.am&&compare_objects(&p->q1,&p->z)){ |
| 3084 | eval_const(&p->q2.val,t); |
| 3085 | if(c==SUB) vmax=zmsub(Z0,vmax); |
| 3086 | if((t&NQ)==CHAR&&zmeqto(vmax,Z1)){ |
| 3087 | emit(f,"\tinc\t"); |
| 3088 | emit_obj(f,&p->z,t); |
| 3089 | emit(f,"\n"); |
| 3090 | continue; |
| 3091 | }else if((t&NQ)==CHAR&&zmeqto(vmax,l2zm(-1L))){ |
| 3092 | emit(f,"\tdec\t"); |
| 3093 | emit_obj(f,&p->z,t); |
| 3094 | emit(f,"\n"); |
| 3095 | continue; |
| 3096 | }else if(((t&NQ)==SHORT||(t&NQ)==INT)&&zmeqto(vmax,l2zm(1L))){ |
| 3097 | inc_addr(&p->z,1,t); |
| 3098 | emit(f,"\tinc\t"); |
| 3099 | emit_obj(f,&p->z,t); |
| 3100 | emit(f,"\n"); |
| 3101 | emit(f,"\tbne\t%s%d\n",labprefix,++label); |
| 3102 | inc_addr(&p->z,-1,t); |
| 3103 | emit(f,"\tinc\t"); |
| 3104 | emit_obj(f,&p->z,t); |
| 3105 | emit(f,"\n"); |
| 3106 | emit(f,"%s%d:\n",labprefix,label); |
| 3107 | continue; |
| 3108 | }else if(regs[acc]&&((t&NQ)==SHORT||(t&NQ)==INT)&&zmeqto(vmax,l2zm(-1L))){ |
| 3109 | inc_addr(&p->z,1,t); |
| 3110 | emit(f,"\ttst\t"); |
| 3111 | emit_obj(f,&p->z,t); |
| 3112 | emit(f,"\n"); |
| 3113 | emit(f,"\tbne\t%s%d\n",labprefix,++label); |
| 3114 | inc_addr(&p->z,-1,t); |
| 3115 | emit(f,"\tdec\t"); |
| 3116 | emit_obj(f,&p->z,t); |
| 3117 | emit(f,"\n"); |
| 3118 | emit(f,"%s%d:\n",labprefix,label); |
| 3119 | inc_addr(&p->z,1,t); |
| 3120 | emit(f,"\tdec\t"); |
| 3121 | emit_obj(f,&p->z,t); |
| 3122 | emit(f,"\n"); |
| 3123 | continue; |
| 3124 | } |
| 3125 | } |
| 3126 | |
| 3127 | if((c>=LSHIFT&&c<=MOD)||c==ADDI2P||c==SUBIFP||c==SUBPFP||(c>=OR&&c<=AND)||c==COMPARE){ |
| 3128 | char *s; |
| 3129 | /*FIXME: nicht immer besser*/ |
| 3130 | if(ISLWORD(t)&&c==LSHIFT&&isconst(q2)){ |
| 3131 | eval_const(&p->q2.val,t); |
| 3132 | if(zm2l(vmax)==1){ |
| 3133 | p->code=c=ADD; |
| 3134 | p->q2=p->q1; |
| 3135 | } |
| 3136 | } |
| 3137 | if((c==ADD||c==ADDI2P||c==MULT||(c>=OR&&c<=AND))&&isreg(q2)&&!isreg(q1)&&!short_add){ |
| 3138 | o=p->q1;p->q1=p->q2;p->q2=o; |
| 3139 | } |
| 3140 | if((c==ADD||c==MULT||(c>=OR&&c<=AND))&&isreg(q2)&&p->q2.reg==acc&&!short_add){ |
| 3141 | o=p->q1;p->q1=p->q2;p->q2=o; |
| 3142 | } |
| 3143 | if(c==MULT||c==MOD){ |
| 3144 | if((!isreg(z)||p->z.reg!=acc)&®s[acc]&&!scratchreg(acc,p)) |
| 3145 | get_acc(f,p); |
| 3146 | reg=acc; |
| 3147 | /*FIXME: y bzw. x-Register*/ |
| 3148 | }else if(c==LSHIFT||c==RSHIFT||c==AND||c==OR||c==XOR){ |
| 3149 | if((!isreg(z)||p->z.reg!=acc)&®s[acc]&&!scratchreg(acc,p)) |
| 3150 | get_acc(f,p); |
| 3151 | reg=acc; |
| 3152 | }else if(c==DIV){ |
| 3153 | reg=ix; |
| 3154 | ierror(0); |
| 3155 | }else if(isreg(z)){ |
| 3156 | reg=p->z.reg; |
| 3157 | }else if(isreg(q1)&&(c==COMPARE||scratchreg(p->q1.reg,p))){ |
| 3158 | reg=p->q1.reg; |
| 3159 | }else{ |
| 3160 | if(c==ADD||c==SUB||c==ADDI2P||c==SUBIFP||c==COMPARE){ |
| 3161 | if(ISRACC(q2)) |
| 3162 | reg=acc; |
| 3163 | else |
| 3164 | reg=get_reg(f,p,t); |
| 3165 | }else{ |
| 3166 | get_acc(f,p); |
| 3167 | reg=acc; |
| 3168 | } |
| 3169 | } |
| 3170 | if(c==ADD||c==ADDI2P||c==SUB||c==SUBIFP){ |
| 3171 | int opdone=0; |
| 3172 | if(isreg(q1)){ |
| 3173 | if(ISIDX(reg)&&ISIDX(p->q1.reg)&&isconst(q2)){ |
| 3174 | eval_const(&p->q2.val,short_add?short_add:q2typ(p)); |
| 3175 | if(CPU==6812&&p->q1.reg==reg&&zmeqto(vmax,l2zm(1L))&&zumeqto(vumax,ul2zum(1UL))){ |
| 3176 | emit(f,"\t%s%s\n",c==SUB?"de":"in",regnames[reg]); |
| 3177 | /*FIXME: condition-codes for bne/beq could be used */ |
| 3178 | }else{ |
| 3179 | emit(f,"\tlea%s\t%ld,%s\n",regnames[reg],c==SUB?SGN16(-zm2l(vmax)):SGN16(zm2l(vmax)),regnames[p->q1.reg]); |
| 3180 | } |
| 3181 | opdone=1; |
| 3182 | }else if((c==ADD||c==ADDI2P)&&ISIDX(reg)&&ISIDX(p->q1.reg)&&ISRACC(q2)){ |
| 3183 | emit(f,"\tlea%s\t%s,%s\n",regnames[reg],((t&NQ)==CHAR||(short_add&NQ)==CHAR)?"b":"d",regnames[p->q1.reg]); |
| 3184 | opdone=1; |
| 3185 | }else if((c==ADD||c==ADDI2P)&&ISIDX(reg)&&ISACC(p->q1.reg)&&ISRIDX(q2)){ |
| 3186 | emit(f,"\tlea%s\t%s,%s\n",regnames[reg],(t&NQ)==CHAR?"b":"d",regnames[p->q2.reg]); |
| 3187 | opdone=1; |
| 3188 | }else if((c==ADD||c==ADDI2P)&&p->q1.reg==acc&&ISIDX(reg)&&!short_add){ |
| 3189 | load_reg(f,reg,&p->q2,t); |
| 3190 | emit(f,"\tlea%s\t%s,%s\n",regnames[reg],(t&NQ)==CHAR?"b":"d",regnames[reg]); |
| 3191 | opdone=1; |
| 3192 | }else if((c==ADD||c==ADDI2P)&&p->q1.reg==acc&&ISIDX(reg)&&(short_add&NU)==(UNSIGNED|CHAR)&&scratchreg(acc,p)){ |
| 3193 | emit(f,"\taddb\t"); |
| 3194 | emit_obj(f,&p->q2,short_add); |
| 3195 | emit(f,"\n"); |
| 3196 | emit(f,"\tadca\t#0\n"); |
| 3197 | emit(f,"\ttfr\td,y\n"); |
| 3198 | opdone=1; |
| 3199 | }else if((c==ADD||c==ADDI2P)&&ISACC(p->q1.reg)&&ISRACC(z)&&isreg(q2)&&ISIDX(p->q2.reg)){ |
| 3200 | if(!scratchreg(p->q2.reg,p)) emit(f,"\texg\t%s,%s\n",regnames[acc],regnames[p->q2.reg]); |
| 3201 | emit(f,"\tlea%s\t%s,%s\n",regnames[p->q2.reg],regnames[acc],regnames[p->q2.reg]); |
| 3202 | emit(f,"\texg\t%s,%s\n",regnames[acc],regnames[p->q2.reg]); |
| 3203 | opdone=1; |
| 3204 | }else if(p->q1.reg!=reg){ |
| 3205 | if(c==ADD||c==ADDI2P||!ISRACC(q2)) |
| 3206 | emit(f,"\ttfr\t%s,%s\n",regnames[p->q1.reg],regnames[reg]); |
| 3207 | } |
| 3208 | }else if(short_add&&c==SUB&®==acc&&!(short_add&UNSIGNED)){ |
| 3209 | load_reg(f,reg,&p->q2,short_add); |
| 3210 | emit(f,"\tclra\n"); |
| 3211 | emit(f,"\tnegb\n"); |
| 3212 | emit(f,"\tsbca\t#0\n"); |
| 3213 | emit(f,"\taddd\t"); |
| 3214 | emit_obj(f,&p->q1,t); |
| 3215 | emit(f,"\n"); |
| 3216 | store_reg(f,reg,&p->z,ztyp(p)); |
| 3217 | continue; |
| 3218 | }else if(short_add&&c==ADD&®==acc){ |
| 3219 | load_reg(f,reg,&p->q2,short_add); |
| 3220 | if(short_add&UNSIGNED) |
| 3221 | emit(f,"\tclra\n"); |
| 3222 | else |
| 3223 | emit(f,SEX); |
| 3224 | emit(f,"\taddd\t"); |
| 3225 | emit_obj(f,&p->q1,t); |
| 3226 | emit(f,"\n"); |
| 3227 | store_reg(f,reg,&p->z,ztyp(p)); |
| 3228 | continue; |
| 3229 | }else{ |
| 3230 | if(!ISRACC(q2)) |
| 3231 | load_reg(f,reg,&p->q1,q1typ(p)); |
| 3232 | } |
| 3233 | if(!opdone){ |
| 3234 | if(reg==acc){ |
| 3235 | if(ISRACC(q2)){ |
| 3236 | if(!ISRACC(z)) get_acc(f,p); |
| 3237 | if(c==ADD||c==ADDI2P){ |
| 3238 | if(short_add){ |
| 3239 | if(short_add&UNSIGNED) |
| 3240 | emit(f,"\tclra\n"); |
| 3241 | else |
| 3242 | emit(f,SEX); |
| 3243 | emit(f,"\taddd\t"); |
| 3244 | emit_obj(f,&p->q1,t); |
| 3245 | emit(f,"\n"); |
| 3246 | }else{ |
| 3247 | if(CPU==6812) |
| 3248 | emit(f,"\tasld\n"); /* only cases with q1=q2=acc should remain */ |
| 3249 | else{ |
| 3250 | emit(f,"\taslb\n"); |
| 3251 | if((t&NQ)!=CHAR) |
| 3252 | emit(f,"\trola\n"); |
| 3253 | } |
| 3254 | } |
| 3255 | }else{ |
| 3256 | if(short_add){ |
| 3257 | if(short_add&UNSIGNED) |
| 3258 | emit(f,"\tld%sa\t#255\n",(CPU==6812)?"a":""); |
| 3259 | else{ |
| 3260 | emit(f,SEX); |
| 3261 | emit(f,"\tnega\n"); |
| 3262 | } |
| 3263 | emit(f,"\tnegb\n\tsbca\t#0\n"); |
| 3264 | }else if((t&NQ)!=CHAR){ |
| 3265 | emit(f,"\tnega\n\tnegb\n\tsbca\t#0\n"); |
| 3266 | }else{ |
| 3267 | emit(f,"\tnegb\n"); |
| 3268 | } |
| 3269 | |
| 3270 | if(ISRIDX(q1)){ |
| 3271 | emit(f,"\t%s%s\n",CPU==6812?"psh":"pshs\t",regnames[p->q1.reg]); |
| 3272 | emit(f,"\taddd\t%s\n",CPU==6812?"1,s+":",s++"); |
| 3273 | }else{ |
| 3274 | emit(f,"\taddd\t"); |
| 3275 | emit_obj(f,&p->q1,t); |
| 3276 | emit(f,"\n"); |
| 3277 | } |
| 3278 | } |
| 3279 | }else{ |
| 3280 | if(ISRIDX(q2)){ |
| 3281 | if(CPU==6812) |
| 3282 | emit(f,"\tpsh%s\n",regnames[p->q2.reg]); |
| 3283 | else |
| 3284 | emit(f,"\tpshs\t%s\n",regnames[p->q2.reg]); |
| 3285 | push(2);pop(2); |
| 3286 | if(CPU==6812) |
| 3287 | emit(f,"\t%sd\t2,%s+\n",(c==ADD||c==ADDI2P)?"add":"sub",regnames[sp]); |
| 3288 | else |
| 3289 | emit(f,"\t%sd\t,%s++\n",(c==ADD||c==ADDI2P)?"add":"sub",regnames[sp]); |
| 3290 | }else{ |
| 3291 | emit(f,"\t%s%s\t",(c==ADD||c==ADDI2P)?"add":"sub",(short_add||(t&NQ)==CHAR)?"b":"d"); |
| 3292 | emit_obj(f,&p->q2,short_add?short_add:t);emit(f,"\n"); |
| 3293 | if(short_add){ |
| 3294 | if(short_add&UNSIGNED) |
| 3295 | emit(f,"\t%s\t#0\n",c==ADD?"adca":"sbca"); |
| 3296 | else |
| 3297 | ierror(0); |
| 3298 | } |
| 3299 | if(drel&&(p->q2.flags&VARADR)){ |
| 3300 | if(CPU==6812) ierror(0); |
| 3301 | emit(f,"\tpshs\t%s\n",regnames[iu]);push(2); |
| 3302 | emit(f,"\t%sd\t,%s++\n",(c==ADD||c==ADDI2P)?"add":"sub",regnames[sp]); |
| 3303 | pop(2); |
| 3304 | } |
| 3305 | } |
| 3306 | } |
| 3307 | cc=&p->z;cc_t=t; |
| 3308 | }else{ |
| 3309 | if(isconst(q2)){ |
| 3310 | long l; |
| 3311 | eval_const(&p->q2.val,short_add?short_add:t); |
| 3312 | l=zm2l(vmax); |
| 3313 | if(c==SUB) l=-l; |
| 3314 | /*FIXME: condition-codes for bne/beq could be used */ |
| 3315 | if(l==1&®==ix&&CPU==6812){ |
| 3316 | emit(f,"\tinx\n"); |
| 3317 | }else if(l==1&®==iy&&CPU==6812){ |
| 3318 | emit(f,"\tiny\n"); |
| 3319 | }else if(l==-1&®==ix&&CPU==6812){ |
| 3320 | emit(f,"\tdex\n"); |
| 3321 | }else if(l==-1&®==iy&&CPU==6812){ |
| 3322 | emit(f,"\tdey\n"); |
| 3323 | }else{ |
| 3324 | emit(f,"\tlea%s\t%ld,%s\n",regnames[reg],SGN16(l),regnames[reg]); |
| 3325 | } |
| 3326 | }else{ |
| 3327 | if(c!=ADD&&c!=ADDI2P){ |
| 3328 | if(!ISRACC(q2)){ |
| 3329 | if(!scratchreg(acc,p)) |
| 3330 | get_acc(f,p); |
| 3331 | load_reg(f,acc,&p->q2,t); |
| 3332 | if((t&NQ)!=CHAR){ |
| 3333 | emit(f,"\tnega\n\tnegb\n\tsbca\t#0\n"); |
| 3334 | }else{ |
| 3335 | emit(f,"\tnegb\n"); |
| 3336 | } |
| 3337 | /*load_reg(f,reg,&p->q1,t);*/ |
| 3338 | }else{ |
| 3339 | get_acc(f,p); |
| 3340 | load_reg(f,reg,&p->q1,t); |
| 3341 | if((t&NQ)==CHAR) |
| 3342 | emit(f,"\tnegb\n"); |
| 3343 | else |
| 3344 | emit(f,"\tnega\n\tnegb\n\tsbca\t#0\n"); |
| 3345 | } |
| 3346 | }else if(!ISRACC(q2)){ |
| 3347 | get_acc(f,p); |
| 3348 | if(short_add){ |
| 3349 | load_reg(f,acc,&p->q2,short_add); |
| 3350 | if(short_add&UNSIGNED){ |
| 3351 | if(reg==ix){ |
| 3352 | emit(f,"\tabx\n"); |
| 3353 | store_reg(f,reg,&p->z,ztyp(p)); |
| 3354 | continue; |
| 3355 | }else{ |
| 3356 | emit(f,"\tclra\n"); |
| 3357 | } |
| 3358 | }else |
| 3359 | t=CHAR; |
| 3360 | }else |
| 3361 | load_reg(f,acc,&p->q2,t); |
| 3362 | }else{ |
| 3363 | load_reg(f,reg,&p->q1,t); |
| 3364 | if(short_add&UNSIGNED) |
| 3365 | emit(f,"\tclra\n"); |
| 3366 | emit(f,"\tlea%s\t%s,%s\n",regnames[reg],((t&NU)==CHAR||(short_add&NU)==CHAR)?"b":"d",regnames[reg]); |
| 3367 | store_reg(f,reg,&p->z,ztyp(p)); |
| 3368 | continue; |
| 3369 | } |
| 3370 | emit(f,"\tlea%s\t%s,%s\n",regnames[reg],(t&NQ)==CHAR?"b":"d",regnames[reg]); |
| 3371 | } |
| 3372 | } |
| 3373 | } |
| 3374 | store_reg(f,reg,&p->z,ztyp(p)); |
| 3375 | continue; |
| 3376 | } |
| 3377 | if(c!=LSHIFT&&c!=RSHIFT) |
| 3378 | load_reg(f,reg,&p->q1,t); |
| 3379 | if(c==MULT){ |
| 3380 | if(CPU==6812){ |
| 3381 | int py=0; |
| 3382 | if(reg!=acc) ierror(reg); |
| 3383 | if(!ISRY(q2)&®s[iy]){ |
| 3384 | emit(f,"\tpshy\n"); |
| 3385 | push(2); |
| 3386 | py=1; |
| 3387 | } |
| 3388 | load_reg(f,iy,&p->q2,t); |
| 3389 | emit(f,"\temul\n"); |
| 3390 | if(py){ |
| 3391 | emit(f,SPULL("y")); |
| 3392 | pop(2); |
| 3393 | } |
| 3394 | store_reg(f,acc,&p->z,t); |
| 3395 | continue; |
| 3396 | }else |
| 3397 | ierror(0); |
| 3398 | } |
| 3399 | if(c==LSHIFT||c==RSHIFT){ |
| 3400 | if(isconst(q2)){ |
| 3401 | int l,oldl; |
| 3402 | load_reg(f,acc,&p->q1,t); |
| 3403 | eval_const(&p->q2.val,t); |
| 3404 | oldl=l=zm2l(vmax); |
| 3405 | if(l>=24){ |
| 3406 | if(CPU!=6812&&!optsize) |
| 3407 | emit(f,"\tldd\t#0\n"); |
| 3408 | else |
| 3409 | emit(f,"\tclra\n\tclrb\n"); |
| 3410 | l=0; |
| 3411 | } |
| 3412 | if(l>=8){ |
| 3413 | if(c==LSHIFT) |
| 3414 | emit(f,"\t%s\n\tclrb\n",(CPU==6812)?"tba":"tfr\tb,a"); |
| 3415 | else{ |
| 3416 | if(t&UNSIGNED) |
| 3417 | emit(f,"\ttfr\ta,b\n\tclra\n"); |
| 3418 | else{ |
| 3419 | emit(f,"\ttfr\ta,b\n"); |
| 3420 | emit(f,SEX); |
| 3421 | } |
| 3422 | } |
| 3423 | l-=8; |
| 3424 | } |
| 3425 | while(l--){ |
| 3426 | if(c==RSHIFT){ |
| 3427 | if(t&UNSIGNED){ |
| 3428 | if((t&NQ)==CHAR) |
| 3429 | emit(f,"\tlsrb\n"); |
| 3430 | else |
| 3431 | emit(f,CPU==6809?"\tlsra\n\trorb\n":"\tlsrd\n"); |
| 3432 | }else{ |
| 3433 | if(oldl>12||(t&NQ)==CHAR) |
| 3434 | emit(f,"\tasrb\n"); |
| 3435 | else |
| 3436 | emit(f,"\tasra\n\trorb\n"); |
| 3437 | } |
| 3438 | }else{ |
| 3439 | if((t&NQ)==CHAR) |
| 3440 | emit(f,"\taslb\n"); |
| 3441 | else |
| 3442 | emit(f,CPU==6809?"\taslb\n\trola\n":"\tasld\n"); |
| 3443 | } |
| 3444 | } |
| 3445 | }else{ |
| 3446 | int px;char *s; |
| 3447 | if(regs[ix]&&!scratchreg(ix,p)&&(!isreg(z)||p->z.reg!=ix)){ |
| 3448 | emit(f,SPUSH("x")); |
| 3449 | push(2);px=1; |
| 3450 | }else |
| 3451 | px=0; |
| 3452 | if((p->typf2&NQ)==CHAR){ |
| 3453 | load_reg(f,acc,&p->q2,p->typf2); |
| 3454 | emit(f,(p->typf2&UNSIGNED)?"\tclra\n":SEX); |
| 3455 | emit(f,"\ttfr\td,x\n"); |
| 3456 | }else |
| 3457 | load_reg(f,ix,&p->q2,t); |
| 3458 | load_reg(f,acc,&p->q1,p->typf); |
| 3459 | if((t&NQ)==CHAR) |
| 3460 | emit(f,(p->typf2&UNSIGNED)?"\tclra\n":SEX); |
| 3461 | if(c==LSHIFT) s="lsl"; |
| 3462 | else if(t&UNSIGNED) s="lsr"; |
| 3463 | else s="asr"; |
| 3464 | emit(f,"\t.global\t%s__%s\n",idprefix,s); |
| 3465 | emit(f,"\t%s\t%s__%s\n",jsrinst,idprefix,s); |
| 3466 | if(px){ |
| 3467 | emit(f,SPULL("x")); |
| 3468 | /*emit(f,"\tpul%s\n",regnames[ix]);*/ |
| 3469 | pop(2); |
| 3470 | } |
| 3471 | } |
| 3472 | cc=0; |
| 3473 | store_reg(f,acc,&p->z,t); |
| 3474 | continue; |
| 3475 | } |
| 3476 | if(c>=OR&&c<=AND){ |
| 3477 | s=logicals[c-OR]; |
| 3478 | if(p->q2.am&&p->q2.am->flags==ACC_IND){ |
| 3479 | mobj=p->q1;p->q1=p->q2;p->q2=mobj; |
| 3480 | } |
| 3481 | if(p->q2.flags&KONST){ |
| 3482 | unsigned long l,h; |
| 3483 | eval_const(&p->q2.val,t); |
| 3484 | l=zum2ul(vumax); |
| 3485 | if((t&NQ)!=CHAR){ |
| 3486 | h=(l>>bitsperbyte)&bytemask; |
| 3487 | if(c==AND&&h==0) |
| 3488 | emit(f,"\tclra\n"); |
| 3489 | else if(c==XOR&&h==bytemask) |
| 3490 | emit(f,"\tcoma\n"); |
| 3491 | else if((c==AND&&h!=bytemask)||(c==OR&&h!=0)||(c==XOR&&h!=0)) |
| 3492 | emit(f,"\t%sa\t#%lu\n",s,h); |
| 3493 | } |
| 3494 | h=l&bytemask; |
| 3495 | if(c==AND&&h==0) |
| 3496 | emit(f,"\tclrb\n"); |
| 3497 | else if(c==XOR&&h==bytemask) |
| 3498 | emit(f,"\tcomb\n"); |
| 3499 | else if((c==AND&&h!=bytemask)||(c==OR&&h!=0)||(c==XOR&&h!=0)) |
| 3500 | emit(f,"\t%sb\t#%lu\n",s,h); |
| 3501 | }else{ |
| 3502 | if(isreg(q2)){ |
| 3503 | if(p->q2.reg==acc){ |
| 3504 | if(c==XOR){ |
| 3505 | emit(f,"\tclrb\n"); |
| 3506 | if((t&NQ)!=CHAR) emit(f,"\tclra\n"); |
| 3507 | } |
| 3508 | }else{ |
| 3509 | if((t&NQ)==CHAR){ |
| 3510 | emit(f,SPUSH("a")); |
| 3511 | push(1); |
| 3512 | emit(f,"\t%sa\t%s,%s+\n",s,CPU==6812?"1":"",regnames[sp]); |
| 3513 | pop(1); |
| 3514 | }else{ |
| 3515 | emit(f,"\t%s%s\n",(CPU==6812)?"psh":"pshs\t",regnames[p->q2.reg]); |
| 3516 | push(2); |
| 3517 | emit(f,"\t%sa\t%s,%s+\n",s,CPU==6812?"1":"",regnames[sp]); |
| 3518 | emit(f,"\t%sb\t%s,%s+\n",s,CPU==6812?"1":"",regnames[sp]); |
| 3519 | pop(2); |
| 3520 | } |
| 3521 | } |
| 3522 | }else if((p->q2.flags&(REG|DREFOBJ))==DREFOBJ&&(t&NQ)!=CHAR){ |
| 3523 | int xr=0; |
| 3524 | if(!regs[ix]) xr=ix; |
| 3525 | else if(!regs[iy]) xr=iy; |
| 3526 | else{ |
| 3527 | xr=ix; |
| 3528 | emit(f,"\t%s%s\n",(CPU==6812)?"psh":"pshs\t",regnames[xr]); |
| 3529 | push(2); |
| 3530 | |
| 3531 | } |
| 3532 | BSET(regs_modified,xr); |
| 3533 | load_addr(f,xr,&p->q2); |
| 3534 | if((t&NQ)==CHAR) |
| 3535 | emit(f,"\t%sb\t0,%s\n",s,regnames[xr]); |
| 3536 | else{ |
| 3537 | emit(f,"\t%sa\t0,%s\n",s,regnames[xr]); |
| 3538 | emit(f,"\t%sb\t1,%s\n",s,regnames[xr]); |
| 3539 | } |
| 3540 | if(regs[ix]&&xr==ix){ |
| 3541 | emit(f,SPULL("x")); |
| 3542 | pop(2); |
| 3543 | } |
| 3544 | }else{ |
| 3545 | emit(f,"\t%sb\t",s); |
| 3546 | if((t&NQ)!=CHAR) inc_addr(&p->q2,1,t); |
| 3547 | emit_obj(f,&p->q2,t); |
| 3548 | emit(f,"\n"); |
| 3549 | if((t&NQ)!=CHAR){ |
| 3550 | inc_addr(&p->q2,-1,t); |
| 3551 | emit(f,"\t%sa\t",s); |
| 3552 | emit_obj(f,&p->q2,t); |
| 3553 | emit(f,"\n"); |
| 3554 | } |
| 3555 | } |
| 3556 | } |
| 3557 | cc=0; |
| 3558 | store_reg(f,reg,&p->z,t); |
| 3559 | continue; |
| 3560 | }else if(c==COMPARE){ |
| 3561 | lastcomp=t; |
| 3562 | if(isreg(q2)){ |
| 3563 | emit(f,"\t%s%s\n",(CPU==6812)?"psh":"pshs\t",regnames[p->q2.reg]); |
| 3564 | push(2); |
| 3565 | } |
| 3566 | if(reg==acc){ |
| 3567 | if((t&NQ)==CHAR) |
| 3568 | emit(f,"\tcmpb\t"); |
| 3569 | else |
| 3570 | emit(f,SCMP("d")); |
| 3571 | }else if(reg==ix){ |
| 3572 | emit(f,SCMP("x")); |
| 3573 | }else if(reg==iy){ |
| 3574 | emit(f,SCMP("y")); |
| 3575 | }else if(reg==iu){ |
| 3576 | emit(f,SCMP("u")); |
| 3577 | }else |
| 3578 | ierror(0); |
| 3579 | if(isreg(q2)){ |
| 3580 | if(CPU==6812) |
| 3581 | emit(f,"2,%s+\n",regnames[sp]); |
| 3582 | else |
| 3583 | emit(f,",%s++\n",regnames[sp]); |
| 3584 | pop(2); |
| 3585 | }else{ |
| 3586 | emit_obj(f,&p->q2,t);emit(f,"\n"); |
| 3587 | } |
| 3588 | continue; |
| 3589 | } |
| 3590 | ierror(0); |
| 3591 | } |
| 3592 | pric2(stdout,p); |
| 3593 | ierror(0); |
| 3594 | } |
| 3595 | if(notpopped){ |
| 3596 | gen_pop(f,notpopped); |
| 3597 | notpopped=0; |
| 3598 | } |
| 3599 | function_bottom(f,v,loff); |
| 3600 | if(debug_info){ |
| 3601 | emit(f,"%s%d:\n",labprefix,++label); |
| 3602 | dwarf2_function(f,v,label); |
| 3603 | if(f) section=-1; |
| 3604 | } |
| 3605 | } |
| 3606 | |
| 3607 | int shortcut(int c,int t) |
| 3608 | { |
| 3609 | if(c==COMPARE||c==ADD||c==SUB||c==AND||c==OR||c==XOR) return 1; |
| 3610 | if((c==LSHIFT||c==RSHIFT)&&ISCHWORD(t&NQ)) return 1; |
| 3611 | return 0; |
| 3612 | } |
| 3613 | |
| 3614 | void cleanup_cg(FILE *f) |
| 3615 | { |
| 3616 | struct fpconstlist *p; |
| 3617 | unsigned char *ip; |
| 3618 | if(f&&stack_check) |
| 3619 | emit(f,"\t.global\t%s__stack_check\n",idprefix); |
| 3620 | while(p=firstfpc){ |
| 3621 | if(f){ |
| 3622 | if(section!=RODATA){ |
| 3623 | emit(f,rodataname);if(f) section=RODATA; |
| 3624 | } |
| 3625 | emit(f,"%s%d\n\t%s\t",labprefix,p->label,dct[LONG]); |
| 3626 | ip=(unsigned char *)&p->val.vdouble; |
| 3627 | emit(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]); |
| 3628 | if((p->typ&NQ)==DOUBLE||(p->typ&NQ)==LDOUBLE){ |
| 3629 | emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]); |
| 3630 | } |
| 3631 | emit(f,"\n"); |
| 3632 | } |
| 3633 | firstfpc=p->next; |
| 3634 | free(p); |
| 3635 | } |
| 3636 | } |
| 3637 | |
| 3638 | int reg_parm(struct reg_handle *p,struct Typ *t,int mode,struct Typ *fkt) |
| 3639 | { |
| 3640 | if(p->gpr) return 0; |
| 3641 | if(ISSCALAR(t->flags)&&!ISFLOAT(t->flags)&&!ISLWORD(t->flags)){ |
| 3642 | p->gpr=1; |
| 3643 | return acc; |
| 3644 | } |
| 3645 | return 0; |
| 3646 | } |
| 3647 | |
| 3648 | void insert_const(union atyps *p,int t) |
| 3649 | /* Traegt Konstante in entprechendes Feld ein. */ |
| 3650 | { |
| 3651 | if(!p) ierror(0); |
| 3652 | t&=NU; |
| 3653 | if(t==BIT) {if(zmeqto(zc2zm(vchar),l2zm(0L))) p->vchar=zm2zc(l2zm(0L)); else p->vchar=zm2zc(l2zm(1L));return;} |
| 3654 | if(t==CHAR) {p->vchar=vchar;return;} |
| 3655 | if(t==SHORT) {p->vshort=vshort;return;} |
| 3656 | if(t==INT) {p->vint=vint;return;} |
| 3657 | if(t==LONG) {p->vlong=vlong;return;} |
| 3658 | if(t==LLONG) {p->vllong=vllong;return;} |
| 3659 | if(t==MAXINT) {p->vmax=vmax;return;} |
| 3660 | if(t==(UNSIGNED|BIT)) {if(zumeqto(zuc2zum(vuchar),ul2zum(0UL))) p->vuchar=zum2zuc(ul2zum(0UL)); else p->vuchar=zum2zuc(ul2zum(1UL));return;} |
| 3661 | if(t==(UNSIGNED|CHAR)) {p->vuchar=vuchar;return;} |
| 3662 | if(t==(UNSIGNED|SHORT)) {p->vushort=vushort;return;} |
| 3663 | if(t==(UNSIGNED|INT)) {p->vuint=vuint;return;} |
| 3664 | if(t==(UNSIGNED|LONG)) {p->vulong=vulong;return;} |
| 3665 | if(t==(UNSIGNED|LLONG)) {p->vullong=vullong;return;} |
| 3666 | if(t==(UNSIGNED|MAXINT)) {p->vumax=vumax;return;} |
| 3667 | if(t==FLOAT) {p->vfloat=vfloat;return;} |
| 3668 | if(t==DOUBLE) {p->vdouble=vdouble;return;} |
| 3669 | if(t==LDOUBLE) {p->vldouble=vldouble;return;} |
| 3670 | if(t==NPOINTER) {p->vuint=vuint;return;} |
| 3671 | if(t==FPOINTER||t==HPOINTER) {p->vulong=vulong;return;} |
| 3672 | } |
| 3673 | void eval_const(union atyps *p,int t) |
| 3674 | /* Weist bestimmten globalen Variablen Wert einer CEXPR zu. */ |
| 3675 | { |
| 3676 | int f=t&NQ; |
| 3677 | if(!p) ierror(0); |
| 3678 | if(f==MAXINT||(f>=BIT&&f<=LLONG)){ |
| 3679 | if(!(t&UNSIGNED)){ |
| 3680 | if(f==BIT){ |
| 3681 | if(zmeqto(zc2zm(p->vchar),l2zm(0L))) vmax=l2zm(0L); else vmax=l2zm(1L); |
| 3682 | }else if(f==CHAR) vmax=zc2zm(p->vchar); |
| 3683 | else if(f==SHORT)vmax=zs2zm(p->vshort); |
| 3684 | else if(f==INT) vmax=zi2zm(p->vint); |
| 3685 | else if(f==LONG) vmax=zl2zm(p->vlong); |
| 3686 | else if(f==LLONG) vmax=zll2zm(p->vllong); |
| 3687 | else if(f==MAXINT) vmax=p->vmax; |
| 3688 | else ierror(0); |
| 3689 | vumax=zm2zum(vmax); |
| 3690 | vldouble=zm2zld(vmax); |
| 3691 | }else{ |
| 3692 | if(f==BIT){ |
| 3693 | if(zumeqto(zuc2zum(p->vuchar),ul2zum(0UL))) vumax=ul2zum(0UL); else vumax=ul2zum(1UL); |
| 3694 | }else if(f==CHAR) vumax=zuc2zum(p->vuchar); |
| 3695 | else if(f==SHORT)vumax=zus2zum(p->vushort); |
| 3696 | else if(f==INT) vumax=zui2zum(p->vuint); |
| 3697 | else if(f==LONG) vumax=zul2zum(p->vulong); |
| 3698 | else if(f==LLONG) vumax=zull2zum(p->vullong); |
| 3699 | else if(f==MAXINT) vumax=p->vumax; |
| 3700 | else ierror(0); |
| 3701 | vmax=zum2zm(vumax); |
| 3702 | vldouble=zum2zld(vumax); |
| 3703 | } |
| 3704 | }else{ |
| 3705 | if(ISPOINTER(f)){ |
| 3706 | if(f==NPOINTER) |
| 3707 | vumax=zui2zum(p->vuint); |
| 3708 | else |
| 3709 | vumax=zul2zum(p->vulong); |
| 3710 | vmax=zum2zm(vumax);vldouble=zum2zld(vumax); |
| 3711 | }else{ |
| 3712 | if(f==FLOAT) vldouble=zf2zld(p->vfloat); |
| 3713 | else if(f==DOUBLE) vldouble=zd2zld(p->vdouble); |
| 3714 | else vldouble=p->vldouble; |
| 3715 | vmax=zld2zm(vldouble); |
| 3716 | vumax=zld2zum(vldouble); |
| 3717 | } |
| 3718 | } |
| 3719 | vfloat=zld2zf(vldouble); |
| 3720 | vdouble=zld2zd(vldouble); |
| 3721 | vuchar=zum2zuc(vumax); |
| 3722 | vushort=zum2zus(vumax); |
| 3723 | vuint=zum2zui(vumax); |
| 3724 | vulong=zum2zul(vumax); |
| 3725 | vullong=zum2zull(vumax); |
| 3726 | vchar=zm2zc(vmax); |
| 3727 | vshort=zm2zs(vmax); |
| 3728 | vint=zm2zi(vmax); |
| 3729 | vlong=zm2zl(vmax); |
| 3730 | vllong=zm2zll(vmax); |
| 3731 | } |
| 3732 | void printval(FILE *f,union atyps *p,int t) |
| 3733 | /* Gibt atyps aus. */ |
| 3734 | { |
| 3735 | t&=NU; |
| 3736 | if(t==BIT){vmax=zc2zm(p->vchar);fprintf(f,"B%d",!zmeqto(vmax,l2zm(0L)));} |
| 3737 | if(t==(UNSIGNED|BIT)){vumax=zuc2zum(p->vuchar);fprintf(f,"UB%d",!zumeqto(vmax,ul2zum(0UL)));} |
| 3738 | if(t==CHAR){vmax=zc2zm(p->vchar);printzm(f,vmax);} |
| 3739 | if(t==(UNSIGNED|CHAR)){fprintf(f,"UC");vumax=zuc2zum(p->vuchar);printzum(f,vumax);} |
| 3740 | if(t==SHORT){fprintf(f,"S");vmax=zs2zm(p->vshort);printzm(f,vmax);} |
| 3741 | if(t==(UNSIGNED|SHORT)){fprintf(f,"US");vumax=zus2zum(p->vushort);printzum(f,vumax);} |
| 3742 | if(t==FLOAT){fprintf(f,"F");vldouble=zf2zld(p->vfloat);printzld(f,vldouble);} |
| 3743 | if(t==DOUBLE){fprintf(f,"D");vldouble=zd2zld(p->vdouble);printzld(f,vldouble);} |
| 3744 | if(t==LDOUBLE){fprintf(f,"LD");printzld(f,p->vldouble);} |
| 3745 | if(t==INT){fprintf(f,"I");vmax=zi2zm(p->vint);printzm(f,vmax);} |
| 3746 | if(t==(UNSIGNED|INT)||t==NPOINTER){fprintf(f,"UI");vumax=zui2zum(p->vuint);printzum(f,vumax);} |
| 3747 | if(t==LONG){fprintf(f,"L");vmax=zl2zm(p->vlong);printzm(f,vmax);} |
| 3748 | if(t==(UNSIGNED|LONG)||t==FPOINTER||t==HPOINTER){fprintf(f,"UL");vumax=zul2zum(p->vulong);printzum(f,vumax);} |
| 3749 | if(t==LLONG){fprintf(f,"LL");vmax=zll2zm(p->vllong);printzm(f,vmax);} |
| 3750 | if(t==(UNSIGNED|LLONG)){fprintf(f,"ULL");vumax=zull2zum(p->vullong);printzum(f,vumax);} |
| 3751 | if(t==MAXINT) printzm(f,p->vmax); |
| 3752 | if(t==(UNSIGNED|MAXINT)) printzum(f,p->vumax); |
| 3753 | } |
| 3754 | void emitval(FILE *f,union atyps *p,int t) |
| 3755 | { |
| 3756 | t&=NU; |
| 3757 | if((t&NQ)==NPOINTER) t=(UNSIGNED|INT); |
| 3758 | if(t==BIT){vmax=zc2zm(p->vchar);emit(f,"%d",!zmeqto(vmax,l2zm(0L)));} |
| 3759 | if(t==(UNSIGNED|BIT)){vumax=zuc2zum(p->vuchar);emit(f,"%d",!zumeqto(vmax,ul2zum(0UL)));} |
| 3760 | if(t==CHAR){vmax=zc2zm(p->vchar);emitzm(f,vmax);} |
| 3761 | if(t==(UNSIGNED|CHAR)){vumax=zuc2zum(p->vuchar);emitzum(f,vumax);} |
| 3762 | if(t==SHORT){vmax=zs2zm(p->vshort);emitzm(f,vmax);} |
| 3763 | if(t==(UNSIGNED|SHORT)){vumax=zus2zum(p->vushort);emitzum(f,vumax);} |
| 3764 | if(t==FLOAT){vldouble=zf2zld(p->vfloat);emitzld(f,vldouble);} |
| 3765 | if(t==DOUBLE){vldouble=zd2zld(p->vdouble);emitzld(f,vldouble);} |
| 3766 | if(t==LDOUBLE){emitzld(f,p->vldouble);} |
| 3767 | if(t==INT){vmax=zi2zm(p->vint);emitzm(f,vmax);} |
| 3768 | if(t==(UNSIGNED|INT)||t==NPOINTER){vumax=zui2zum(p->vuint);emitzum(f,vumax);} |
| 3769 | if(t==LONG){vmax=zl2zm(p->vlong);emitzm(f,vmax);} |
| 3770 | if(t==(UNSIGNED|LONG)||t==FPOINTER||t==HPOINTER){vumax=zul2zum(p->vulong);emitzum(f,vumax);} |
| 3771 | if(t==LLONG){vmax=zll2zm(p->vllong);emitzm(f,vmax);} |
| 3772 | if(t==(UNSIGNED|LLONG)){vumax=zull2zum(p->vullong);emitzum(f,vumax);} |
| 3773 | if(t==MAXINT) emitzm(f,p->vmax); |
| 3774 | if(t==(UNSIGNED|MAXINT)) emitzum(f,p->vumax); |
| 3775 | } |
| 3776 | |
| 3777 | void conv_typ(struct Typ *p) |
| 3778 | /* Erzeugt extended types in einem Typ. */ |
| 3779 | { |
| 3780 | char *attr; |
| 3781 | while(p){ |
| 3782 | if(ISPOINTER(p->flags)){ |
| 3783 | p->flags=((p->flags&~NU)|POINTER_TYPE(p->next)); |
| 3784 | if(attr=p->next->attr){ |
| 3785 | if(strstr(attr,STR_NEAR)) |
| 3786 | p->flags=((p->flags&~NU)|NPOINTER); |
| 3787 | if(strstr(attr,STR_FAR)) |
| 3788 | p->flags=((p->flags&~NU)|FPOINTER); |
| 3789 | if(strstr(attr,STR_HUGE)) |
| 3790 | p->flags=((p->flags&~NU)|HPOINTER); |
| 3791 | } |
| 3792 | } |
| 3793 | if(ISINT(p->flags)&&(attr=p->attr)&&strstr(attr,"bit")) |
| 3794 | p->flags=((p->flags&~NU)|BIT); |
| 3795 | p=p->next; |
| 3796 | } |
| 3797 | } |
| 3798 | |
| 3799 | void init_db(FILE *f) |
| 3800 | { |
| 3801 | dwarf2_setup(sizetab[HPOINTER],".byte",".2byte",".4byte",".4byte",labprefix,idprefix,".section"); |
| 3802 | dwarf2_print_comp_unit_header(f); |
| 3803 | } |
| 3804 | void cleanup_db(FILE *f) |
| 3805 | { |
| 3806 | dwarf2_cleanup(f); |
| 3807 | if(f) section=-1; |
| 3808 | } |