home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / tools / developer-tools / c-tools / vbcc / machine.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-22  |  86.9 KB  |  2,067 lines

  1. /*  $VER: vbcc (machine.c amiga68k) V0.3    */
  2.  
  3. /*  File, das maschinenabhaengige Daten und Routinen fuer Codeerzeugung */
  4. /*  fuer Motorola 680x0-CPUs enthaelt (z.Z. auf 020+881 ausgerichtet).  */
  5.  
  6. #include "vbc.h"
  7.  
  8. /*  ab hier public Data, die vorhanden sein MUSS    */
  9.  
  10. char *ename[]={"strange","sequence","move","set+","set-","set*","set/","set%",
  11.                "set&","set^","set|","set<<","set>>","?:","lor","land","or",
  12.                "eor","and","equal","unequal","lt","le","gt","ge","lsl",
  13.                "lsr","add","sub","mul","div","mod","negate",
  14.                "not","preinc","postinc","predec","postdec","neg",
  15.                "dref-pointer","address-of","cast","call","index",
  16.                "dref-struct-pointer","dref-struct","identifier","constant",
  17.                "string","member",
  18.                 "convert-char","convert-short","convert-int","convert-long",
  19.                 "convert-float","convert-double","convert-void","convert-pointer",
  20.                 "convert-uchar","convert-ushort","convert-uint","convert-ulong",
  21.                 "address-of-array","first-element-of-array","pmult",
  22.                 "allocreg","freereg","pconstant","test","label","beq","bne",
  23.                 "blt","bge","ble","bgt","bra","compare","push","pop",
  24.                 "address-of-struct","add-int-to-pointer","sub-int-from-pointer",
  25.                 "sub-pointer-from-pointer","push-reg","pop-reg","pop-args",
  26.                 "save-regs","restore-regs","identifier-label","dc","align",
  27.                 "colon","get-return","set-return","move-from-reg","move-to-reg"};
  28.  
  29.  
  30. /*  Codegenerator-Flags                                 */
  31. int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0,0,0,0,0,0,0,0};
  32. char *g_flags_name[MAXGF]={"cpu","fpu","d2scratch","noa4","sc","sd","prof","const-in-data","use-framepointer","no-addressing-modes","no-delayed-popping"};
  33. union ppi g_flags_val[MAXGF];
  34.  
  35. /* Tabelle fuer alignment requirements, maschinenabhaengig */
  36. int align[]={1,1,2,2,2,2,2,2,2,2,2,2,2,2,2};
  37. int maxalign=2;
  38.  
  39. /*  Tabelle fuer die Groesse der einzelnen Typen    */
  40. int sizetab[]={0,1,2,4,4,4,8,0,4,0,0,0,4,0};
  41.  
  42. /*  Tabelle fuer minimale und maximale Werte der Integer-Typen  */
  43. zlong t_min[32];
  44. zulong t_max[32];
  45.  
  46. /*  Namen der Register              */
  47. char *regnames[MAXR+1]={"noreg","a0","a1","a2","a3","a4","a5","a6","a7",
  48.                                "d0","d1","d2","d3","d4","d5","d6","d7",
  49.                         "fp0","fp1","fp2","fp3","fp4","fp5","fp6","fp7"};
  50.  
  51. /*  Groessen der Register in Bytes  */
  52. int regsize[MAXR+1]={0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,12,12};
  53.  
  54. /*  Anfangswerte fuer die Register  */
  55. int regsa[MAXR+1]={0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  56.  
  57. /*  Werden Register von Funktionen evtl. zerstoert? */
  58. int regscratch[MAXR+1]={0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0};
  59.  
  60. /*  Speicher fuer die Register      */
  61. int regs[MAXR+1];
  62.  
  63. /*  Merker, ob Register benutzt wurden  */
  64. int regused[MAXR+1];
  65.  
  66. /*  Variablen, die in Register liegen   */
  67. struct Var *regsv[MAXR+1];
  68.  
  69. /*  Variablen, in die Register gespeichert werden   */
  70. struct Var *regsbuf[MAXR+1];
  71.  
  72. /*  Merker, in welcher Blocktiefe diese gespeichert wurden  */
  73. int regbnesting[MAXR+1];
  74.  
  75. extern int float_used;
  76.  
  77. /*  Ab hier private Data, speziell fuer einen Codegenerator */
  78.  
  79. char reglist[200];
  80.  
  81.  
  82. #define DATA 0
  83. #define BSS 1
  84. #define CODE 2
  85.  
  86. int reglabel,freglabel,section=-1;
  87. char *codename,*bssname,*dataname;
  88.  
  89. struct IC *do_refs(FILE *,struct IC *);
  90. void pr(FILE *,struct IC *);
  91. int get_reg(FILE *,int,struct IC *);
  92. long pof2(zulong);
  93. void function_top(FILE *,struct Var *,int);
  94. void function_bottom(FILE *f,struct Var *,int);
  95.  
  96. void saveregs(FILE *,struct IC *),restoreregsa(FILE *,struct IC *),restoreregsd(FILE *,struct IC *);
  97.  
  98. void assign(FILE *,struct IC *,struct obj *,struct obj *,int,int,int);
  99.  
  100. int is_const(struct Typ *t);
  101.  
  102. char x_s[]={'0','b','w','3','l'};
  103. char x_t[]={'?','b','w','l','l','s','d','v','l','a','s','u','e','f','?','?'};
  104.  
  105. char *quick[2]={"","q"};
  106. char *strshort[2]={"l","w"};
  107.  
  108. char *ubranch[]={"beq","bne","blo","bhs","bls","bhi"};
  109.  
  110. int pushedreg,stored_cc; /* pushedreg&2: aregsaved; 4: dreg; 8: freg */
  111.                          /* 16: durch RESTOREREGS gepushed           */
  112. int pushlabel,pushflag;
  113.  
  114. #define D16OFF 1024
  115.  
  116. int newobj=0;   /*  um zu erkennen, ob neue section erlaubt ist */
  117.  
  118. int init_cg(void)
  119. /*  Initialisiert evtl. maschinenspezifische Sachen, liefert 0, */
  120. /*  wenn etwas schiefgegangen ist                               */
  121. {
  122.     /*  default CPU ist 68000   */
  123.     if(!(g_flags[0]&USEDFLAG)) g_flags_val[0].l=68000;
  124.     /*  keine FPU per default   */
  125.     if(!(g_flags[1]&USEDFLAG)) g_flags_val[1].l=0;
  126.     if(g_flags_val[1].l<68000) {x_t[FLOAT]='l';}
  127.     /*  d2 als Scratchregister markeiren, wenn cclib benutzt wird   */
  128.     if(g_flags[2]&USEDFLAG) regscratch[11]=1;
  129.     /*  a4 als Scratchregister markeiren, wenn sclib benutzt wird   */
  130.     if(g_flags[3]&USEDFLAG) regsa[5]=1;
  131.     codename="\tsection\t\"CODE\",code\n";
  132.     /*  SmallData-Vorbereitungen    */
  133.     if(g_flags[5]&USEDFLAG){
  134.         regsa[5]=1;
  135.         bssname= "\tsection\t\"__MERGED\",bss\n";
  136.         dataname="\tsection\t\"__MERGED\",data\n";
  137.     }else{
  138.         bssname= "\tsection\t\"BSS\",bss\n";
  139.         dataname="\tsection\t\"DATA\",data\n";
  140.     }
  141.     /*  a5 zur Nutzung freigeben, wenn kein Framepointer benutzt wird   */
  142.     if(!(g_flags[8]&USEDFLAG)) regsa[6]=0;
  143.     if(DEBUG&1) printf("CPU=%ld FPU=%ld\n",g_flags_val[0].l,g_flags_val[1].l);
  144.     vlong=l2zl(0L);
  145.     t_min[UNSIGNED|CHAR]=t_min[UNSIGNED|SHORT]=t_min[UNSIGNED|INT]=t_min[UNSIGNED|LONG]=vlong;
  146.     vlong=l2zl((long)SCHAR_MIN); t_min[CHAR]=vlong;
  147.     vlong=l2zl((long)SHRT_MIN ); t_min[SHORT]=vlong;
  148.     vlong=l2zl((long)INT_MIN  ); t_min[INT]=vlong;
  149.     vlong=l2zl((long)LONG_MIN ); t_min[LONG]=vlong;
  150.     vulong=ul2zul((unsigned long)SCHAR_MAX); t_max[CHAR]=vulong;
  151.     vulong=ul2zul((unsigned long)SHRT_MAX ); t_max[SHORT]=vulong;
  152.     vulong=ul2zul((unsigned long)INT_MAX  ); t_max[INT]=vulong;
  153.     vulong=ul2zul((unsigned long)LONG_MAX ); t_max[LONG]=vulong;
  154.     vulong=ul2zul((unsigned long)UCHAR_MAX); t_max[UNSIGNED|CHAR]=vulong;
  155.     vulong=ul2zul((unsigned long)USHRT_MAX); t_max[UNSIGNED|SHORT]=vulong;
  156.     vulong=ul2zul((unsigned long)UINT_MAX ); t_max[UNSIGNED|INT]=vulong;
  157.     vulong=ul2zul((unsigned long)ULONG_MAX); t_max[UNSIGNED|LONG]=vulong;
  158.     return(1);
  159. }
  160.  
  161. int freturn(struct Typ *t)
  162. /*  Liefert Register zurueck, in dem Typ t von Funktionen zurueckgegeben    */
  163. /*  wird. Liefert Null, wenn Wert auf Stack zurueckgegeben wird.            */
  164. /*  Achtung! t kann pointer sein, aber trotzdem t->next==0!!                */
  165. /*  maschinenabhaengig                                                      */
  166. {
  167.     if((t->flags&15)==FLOAT)
  168.         {if(g_flags_val[1].l>=68000) return(17); else return(9);}
  169.     if((t->flags&15)==DOUBLE)
  170.         {if(g_flags_val[1].l>=68000) return(17); else return(0);}
  171.     if((t->flags&15)==STRUCT||(t->flags&15)==UNION) return(0);
  172.     if(szof(t)<=4) return(9); else return(0);
  173. }
  174.  
  175.  
  176. int regok(int r,int t,int mode)
  177. /*  Testet, ob Register r den Typ t verkraftet          */
  178. /*  mode!=0: mit Typ mode dereferenzierbar              */
  179. /*  natuerlich maschinenabhaengig                       */
  180. /*  Reg 1-8=a0-a7 9-16=d0-d7 und 17-24=FP0-FP7          */
  181. /*  dn nur Integers, an nur Pointer und FPn nur FK      */
  182. {
  183.     if(r==0) return(0);
  184.     t&=15;
  185.     if(t==FLOAT||t==DOUBLE){
  186.         if(g_flags_val[1].l>=68000){
  187.             if(r>=17&&r<=24) return(1); else return(0);
  188.         }else{
  189.             if(t==FLOAT&&r>=9&&r<=16) return(1); else return(0);
  190.         }
  191.     }
  192.     if(t==POINTER&&mode==0&&r>=9&&r<=16) return(1);
  193.     if(t==POINTER&&r>=1&&r<=8) return(1);
  194.     if(t>=CHAR&&t<=LONG&&r>=9&&r<=16) return(1);
  195.     return(0);
  196. }
  197.  
  198. int isquickkonst(union atyps *,int),isquickkonst2(union atyps *,int),regavailable(int);
  199. void move(FILE *,struct obj *,int,struct obj *,int,int);
  200. void add(FILE *,struct obj *,int,struct obj *,int,int);
  201. void sub(FILE *,struct obj *,int,struct obj *,int,int);
  202. void mult(FILE *,struct obj *,int,struct obj *,int,int,int,struct IC *);
  203.  
  204. long pof2(zulong x)
  205. /*  gibt log2(x)+1 oder 0 zurueck */
  206. {
  207.     zulong p;int ln=1;
  208.     p=ul2zul(1L);
  209.     while(zulleq(p,x)){
  210.         if(zuleqto(x,p)) return(ln);
  211.         ln++;p=zuladd(p,p);
  212.     }
  213.     return(0);
  214. }
  215.  
  216. #define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
  217.  
  218. #define PEA 1000
  219.  
  220. int addressing(void);
  221. long notpopped,stackoffset,loff;
  222. int offlabel,regoffset;
  223. /*  Merken, wofuer ConditionCodes gesetzt sind  */
  224. struct obj *cc_set,*cc_set_tst;
  225. int cc_typ,cc_typ_tst;
  226.  
  227.  
  228. void gen_code(FILE *f,struct IC *p,struct Var *v,int offset)
  229. /*  Eigentliche gen_code()-Routine                          */
  230. {
  231.     int c,t,comptyp;char fp[2]="\0\0";
  232.     if(DEBUG&1) printf("gen_code()\n");
  233.     for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
  234.     if(!(g_flags[9]&USEDFLAG)){
  235.     /*  Adressierungsarten benutzen */
  236.         if(!addressing()) offset=0;
  237.     }
  238.     reglabel=++label;freglabel=++label;
  239.     function_top(f,v,offset);
  240.     if(p!=first_ic) ierror(0);
  241.     cc_set=cc_set_tst=0;
  242.     stackoffset=notpopped=0;
  243.     for(;p;pr(f,p),p=p->next){
  244.         c=p->code;t=p->typf;
  245.         if(c==NOP) continue;
  246.         cc_set_tst=cc_set;
  247.         cc_typ_tst=cc_typ;
  248.         if(cc_set_tst&&(DEBUG&512)){fprintf(f,"; cc_set_tst=");probj(f,cc_set_tst,t,0);fprintf(f,"\n");}
  249.         if(cc_set&&(DEBUG&512)){fprintf(f,"; cc_set=");probj(f,cc_set,t,0);fprintf(f,"\n");}
  250.         pushedreg&=16;if(c==RESTOREREGS) pushedreg=0;
  251.         if(DEBUG&256){fprintf(f,"; "); pric2(f,p);}
  252.         if(DEBUG&512) fprintf(f,"; stackoffset=%ld, notpopped=%ld, pushedreg=%d\n",stackoffset,notpopped,pushedreg);
  253.         /*  muessen wir Argumente poppen?   */
  254.         if(notpopped){
  255.             int flag=0;
  256.             if(c==LABEL||c==COMPARE||c==TEST||c==BRA) flag=1;
  257.             /*  wenn demnaechst TEST kommt, gleich poppen, um evtl. ein */
  258.             /*  tst einzusparen                                         */
  259.             if(!flag&&c!=CALL&&c!=GETRETURN){
  260.                 struct IC *np=p->next;
  261.                 while(np&&np->code==FREEREG) np=np->next;
  262.                 if(np&&np->code==TEST) flag=1;
  263.             }
  264.             if(flag){
  265.                 fprintf(f,"\tadd%s.%s\t#%ld,a7\n",quick[notpopped<=8],strshort[notpopped<32768],notpopped);
  266.                 stackoffset+=notpopped;notpopped=0;/*cc_set_tst=cc_set=0;*/
  267.             }
  268.         }
  269.         /*  na, ob das hier ok ist..?   */
  270.         if(c==SUBPFP) c=SUB;
  271.         if(c==PMULT) c=MULT;
  272.         if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
  273.         if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
  274.         if(c==LABEL) {fprintf(f,"l%d\n",t);cc_set=0;continue;}
  275.         if(c==BRA){fprintf(f,"\tbra\tl%d\n",t);continue;}
  276.         if(c>=BEQ&&c<BRA){
  277.             if(stored_cc){fprintf(f,"\tbne\tl%d\n",t);stored_cc=0;continue;}
  278.             if((comptyp&UNSIGNED)||(comptyp&15)==POINTER){
  279.                 fprintf(f,"\t%s\tl%d\n",ubranch[c-BEQ],t);
  280.             }else{
  281.                 fprintf(f,"\t%s%s\tl%d\n",fp,ename[c],t);
  282.             }
  283.             continue;
  284.         }
  285.         if(p->q1.am){
  286.             if(!regs[p->q1.am->basereg]){pric2(stdout,p);printf("%s\n",regnames[p->q1.am->basereg]); ierror(0);}
  287.             if(p->q1.am->dreg&&!regs[p->q1.am->dreg&127]) {printf("Register %s:\n",regnames[p->q1.am->dreg&127]);ierror(0);}
  288.         }
  289.         if(p->q2.am){
  290.             if(!regs[p->q2.am->basereg]) ierror(0);
  291.             if(p->q2.am->dreg&&!regs[p->q2.am->dreg&127]) {printf("Register %s:\n",regnames[p->q2.am->dreg&127]);ierror(0);}
  292.         }
  293.         if(p->z.am){
  294.             if(!regs[p->z.am->basereg]) ierror(0);
  295.             if(p->z.am->dreg&&!regs[p->z.am->dreg&127]) {printf("Register %s:\n",regnames[p->z.am->dreg&127]);ierror(0);}
  296.         }
  297.         if((p->q1.flags®)&&!regs[p->q1.reg]){printf("Register %s:\n",regnames[p->q1.reg]);ierror(0);}
  298.         if((p->q2.flags®)&&!regs[p->q2.reg]){printf("Register %s:\n",regnames[p->q2.reg]);ierror(0);}
  299.         if((p->z.flags®)&&!regs[p->z.reg]){printf("Register %s:\n",regnames[p->z.reg]);ierror(0);}
  300.         if((p->q2.flags®)&&(p->z.flags®)&&p->q2.reg==p->z.reg){pric2(stdout,p);ierror(0);}
  301.         if((p->q2.flags&VAR)&&(p->z.flags&VAR)&&p->q2.v==p->z.v){pric2(stdout,p);ierror(0);}
  302.         /*  COMPARE #0 durch TEST ersetzen (erlaubt, da tst alle Flags setzt)   */
  303.         if(c==COMPARE&&(p->q2.flags&KONST)){
  304.             eval_const(&p->q2.val,t);
  305.             if(zleq(vlong)&&zuleq(vulong)&&zdeq(vdouble)){
  306.                 c=p->code=TEST;p->q2.flags=0;
  307.             }
  308.         }
  309.         if(c==COMPARE&&(p->q1.flags&KONST)){
  310.             eval_const(&p->q1.val,t);
  311.             if(zleq(vlong)&&zuleq(vulong)&&zdeq(vdouble)){
  312.                 struct IC *bp=p->next;int bc;
  313.                 c=p->code=TEST;p->q1=p->q2;p->q2.flags=0;p->q2.am=0;
  314.                 /*  Nachfolgenden Branch umdrehen   */
  315.                 while(bp&&bp->code==FREEREG) bp=bp->next;
  316.                 bc=bp->code;
  317.                 if(!bp||bc<BEQ||bc>BGT) ierror(0);
  318.                 if(bc==BLT) bp->code=BGT;
  319.                 if(bc==BGT) bp->code=BLT;
  320.                 if(bc==BLE) bp->code=BGE;
  321.                 if(bc==BGE) bp->code=BLE;
  322.             }
  323.         }
  324.         /*  gesetzte ConditionCodes merken  */
  325.         if(p->z.flags&&(!isreg(z)||p->z.reg>=9)&&c!=CONVFLOAT&&c!=CONVDOUBLE&&(((t&15)!=FLOAT&&(t&15)!=DOUBLE)||g_flags_val[1].l>68000)){
  326.              cc_set=&p->z;cc_typ=p->typf;
  327.         }else{
  328.             cc_set=0;
  329.         }
  330.         if(c==PEA){
  331.             fprintf(f,"\tpea\t");probj(f,&p->q1,t,0);fprintf(f,"\n");
  332.             stackoffset-=p->q2.reg;
  333.             continue;
  334.         }
  335.         if(c==PUSHREG){
  336.             if(p->q1.reg<17) {fprintf(f,"\tmove.l\t%s,-(a7)\n",regnames[p->q1.reg]);stackoffset-=4;}
  337.              else {fprintf(f,"\tfmove.x\t%s,-(a7)\n",regnames[p->q1.reg]);stackoffset-=12;}
  338.             continue;
  339.         }
  340.         if(c==MOVEFROMREG){
  341.             if(p->q1.reg<17) fprintf(f,"\tmove.l\t%s,",regnames[p->q1.reg]);
  342.                 else         fprintf(f,"\tfmove.x\t%s,",regnames[p->q1.reg]);
  343.             probj(f,&p->z,t,0);fprintf(f,"\n");
  344.             continue;
  345.         }
  346.         if(c==MOVETOREG){
  347.             if(p->z.reg<17) fprintf(f,"\tmove.l\t");
  348.                 else        fprintf(f,"\tfmove.x\t");
  349.             probj(f,&p->q1,t,0);fprintf(f,",%s\n",regnames[p->z.reg]);
  350.             continue;
  351.         }
  352.         if(c==POPREG){
  353.             if(p->z.reg<17) {fprintf(f,"\tmove.l\t(a7)+,%s\n",regnames[p->z.reg]);stackoffset+=4;}
  354.              else {fprintf(f,"\tfmove.x\t(a7)+,%s\n",regnames[p->z.reg]);stackoffset+=12;}
  355.             continue;
  356.         }
  357.         if(c==SAVEREGS||c==RESTOREREGS){
  358.             ierror(0);
  359.             continue;
  360.         }
  361.         if(g_flags[9]&USEDFLAG)
  362.             if(p->q1.am||p->q2.am||p->z.am){
  363.                 ierror(0);
  364.                 p->q1.am=p->q2.am=p->z.am=0;
  365.             }
  366.         p=do_refs(f,p);
  367.         if(g_flags[9]&USEDFLAG)
  368.             if(p->q1.am||p->q2.am||p->z.am){
  369.                 ierror(0);
  370.                 p->q1.am=p->q2.am=p->z.am=0;
  371.             }
  372.         if(c>=CONVCHAR&&c<=CONVULONG){
  373.             int to;
  374.             if(c==CONVCHAR) to=CHAR;
  375.             if(c==CONVUCHAR) to=UNSIGNED|CHAR;
  376.             if(c==CONVSHORT) to=SHORT;
  377.             if(c==CONVUSHORT) to=UNSIGNED|SHORT;
  378.             if(c==CONVINT) to=LONG;
  379.             if(c==CONVUINT) to=UNSIGNED|LONG;
  380.             if(c==CONVLONG) to=LONG;
  381.             if(c==CONVULONG) to=UNSIGNED|LONG;
  382.             if(c==CONVFLOAT) to=FLOAT;
  383.             if(c==CONVDOUBLE) to=DOUBLE;
  384.             if(c==CONVPOINTER) to=UNSIGNED|LONG;
  385.             if(c==CONVVOID){ierror(0);continue;}
  386.             if(t==FLOAT||t==DOUBLE||to==FLOAT||to==DOUBLE){
  387.                 if(g_flags_val[1].l>=68000){
  388.                     int zreg=0;
  389.                     if((t==FLOAT||t==DOUBLE)&&(to==FLOAT||to==DOUBLE)){
  390.                         if(isreg(q1)&&isreg(z)){
  391.                             if(p->q1.reg!=p->z.reg)
  392.                                 fprintf(f,"\tfmove.x\t%s,%s\n",regnames[p->q1.reg],regnames[p->z.reg]);
  393.                             continue;
  394.                         }
  395.                     }
  396.                     if(isreg(z)&&p->z.reg>=17)
  397.                         zreg=p->z.reg;
  398.                     if(isreg(q1)&&p->q1.reg>=17){
  399.                         if(!zreg) zreg=p->q1.reg; else zreg=get_reg(f,2,p);}
  400.                     if(!zreg) zreg=get_reg(f,2,p);
  401.                     if((to&UNSIGNED)&&x_t[to&15]!='l'){
  402.                         int dreg=get_reg(f,1,p);
  403.                         fprintf(f,"\tmoveq\t#0,%s\n",regnames[dreg]);
  404.                         move(f,&p->q1,0,0,dreg,to);
  405.                         move(f,0,dreg,0,zreg,LONG);
  406.                     }else{
  407.                         if(!isreg(q1)||p->q1.reg!=zreg)
  408.                             move(f,&p->q1,0,0,zreg,to);
  409.                     }
  410.                     if(t!=FLOAT&&t!=DOUBLE){
  411.                     /*  nach integer, d.h. Kommastellen abschneiden */
  412.                         if(g_flags_val[1].l==68040/*||g_flags_val[1].l==68060*/){
  413.                         /*  bei 040 emuliert    */
  414.                             int dreg1=get_reg(f,1,p),dreg2=get_reg(f,1,p);
  415.                             fprintf(f,"\tfmove.l\tfpcr,%s\n",regnames[dreg2]);
  416.                             fprintf(f,"\tmoveq\t#16,%s\n",regnames[dreg1]);
  417.                             fprintf(f,"\tor.l\t%s,%s\n",regnames[dreg2],regnames[dreg1]);
  418.                             fprintf(f,"\tand.w\t#-33,%s\n",regnames[dreg1]);
  419.                             fprintf(f,"\tfmove.l\t%s,fpcr\n",regnames[dreg1]);
  420.                             fprintf(f,"\tfmove.%c\t%s,",x_t[t&15],regnames[zreg]);
  421.                             probj(f,&p->z,t,0);fprintf(f,"\n");
  422.                             fprintf(f,"\tfmove.l\t%s,fpcr\n",regnames[dreg2]);
  423.                             continue;
  424.                         }else{
  425.                             if(!isreg(q1)||p->q1.reg!=zreg){
  426.                                 fprintf(f,"\tfintrz\t%s\n",regnames[zreg]);
  427.                             }else{
  428.                                 int nreg=get_reg(f,2,p);
  429.                                 fprintf(f,"\tfintrz\t%s,%s\n",regnames[zreg],regnames[nreg]);
  430.                                 zreg=nreg;
  431.                             }
  432.                         }
  433.                     }
  434.                     if(to&UNSIGNED&&x_t[to&15]=='l'){
  435.                         int nlabel;
  436.                         fprintf(f,"\ttst.%c\t",x_t[to&15]);
  437.                         probj(f,&p->q1,to,0);fprintf(f,"\n");
  438.                         nlabel=++label;
  439.                         fprintf(f,"\tbge\tl%d\n",nlabel);
  440.                         fprintf(f,"\tfadd.d\t#4294967296,%s\n",regnames[zreg]);
  441.                         fprintf(f,"l%d\n",nlabel);
  442.                     }
  443.                     if(!(p->z.reg)||p->z.reg!=zreg){
  444.                         move(f,0,zreg,&p->z,0,t);
  445.                     }
  446.                 }else{
  447.                     cc_set=0;
  448.                     if(to==t){
  449.                         assign(f,p,&p->q1,&p->z,ASSIGN,p->q2.reg,t);
  450.                         continue;
  451.                     }
  452.                     if(to==FLOAT&&t==DOUBLE){
  453.                         saveregs(f,p);
  454.                         assign(f,p,&p->q1,0,PUSH,sizetab[FLOAT],FLOAT);
  455.                         fprintf(f,"\tpublic\t__ieees2d\n\tjsr\t__ieees2d\n\taddq.w\t#4,a7\n");
  456.                         stackoffset+=4;
  457.                         restoreregsa(f,p);
  458.                         fprintf(f,"\tmovem.l\td0/d1,");
  459.                         probj(f,&p->z,t,0);fprintf(f,"\n");
  460.                         restoreregsd(f,p);
  461.                         continue;
  462.                     }
  463.                     if(to==DOUBLE&&t==FLOAT){
  464.                         saveregs(f,p);
  465.                         assign(f,p,&p->q1,0,PUSH,sizetab[DOUBLE],DOUBLE);
  466.                         fprintf(f,"\tpublic\t__ieeed2s\n\tjsr\t__ieeed2s\n\taddq.w\t#8,a7\n");
  467.                         stackoffset+=8;
  468.                         restoreregsa(f,p);
  469.                         move(f,0,9,&p->z,0,t);
  470.                         restoreregsd(f,p);
  471.                         continue;
  472.                     }
  473.                     if(to==FLOAT||to==DOUBLE){
  474.                         int uns;
  475.                         saveregs(f,p);
  476.                         if(t&UNSIGNED) uns='u'; else uns='s';
  477.                         assign(f,p,&p->q1,0,PUSH,sizetab[to&15],to);
  478.                         fprintf(f,"\tpublic\t__ieeefix%c%c\n\tjsr\t__ieeefix%c%c\n\taddq.w\t#%d,a7\n",x_t[to&15],uns,x_t[to&15],uns,sizetab[to&15]);
  479.                         stackoffset+=sizetab[to&15];
  480.                         restoreregsa(f,p);
  481.                         move(f,0,9,&p->z,0,t);
  482.                         restoreregsd(f,p);
  483.                         continue;
  484.                     }else{
  485.                         int uns,xt=x_t[to&15];
  486.                         saveregs(f,p);
  487.                         if(to&UNSIGNED) uns='u'; else uns='s';
  488.                         if(xt!='l') {fprintf(f,"\tsubq.w\t#4,a7\n");stackoffset-=4;}
  489.                         fprintf(f,"\tmove.%c\t",xt);
  490.                         probj(f,&p->q1,to,0);
  491.                         if(xt!='l') fprintf(f,",(a7)\n"); else {fprintf(f,",-(a7)\n");stackoffset-=4;}
  492.                         fprintf(f,"\tpublic\t__ieeeflt%c%c%c\n\tjsr\t__ieeeflt%c%c%c\n\taddq.w\t#4,a7\n",uns,xt,x_t[t&15],uns,xt,x_t[t&15]);
  493.                         stackoffset+=4;
  494.                         restoreregsa(f,p);
  495.                         if(t==DOUBLE){
  496.                             fprintf(f,"\tmovem.l\td0/d1,");
  497.                             probj(f,&p->z,t,0);fprintf(f,"\n");
  498.                         }else move(f,0,9,&p->z,0,t);
  499.                         restoreregsd(f,p);
  500.                         continue;
  501.                     }
  502.                 }
  503.                 continue;
  504.             }
  505.             if((to&15)<(t&15)){
  506.                 int zreg;
  507.                 if(isreg(z)&&p->z.reg>=9&&p->z.reg<=16)
  508.                     zreg=p->z.reg; else zreg=get_reg(f,1,p);
  509.                 /*  aufpassen, falls unsigned und Quelle==Ziel  */
  510.                 if((to&UNSIGNED)&&isreg(q1)&&zreg==p->q1.reg){
  511.                     unsigned long l;
  512.                     if((to&15)==CHAR) l=0xff; else l=0xffff;
  513.                     fprintf(f,"\tand.%c\t#%lu,%s\n",x_t[t&15],l,regnames[zreg]);
  514.                     continue;
  515.                 }
  516.                 if(to&UNSIGNED) fprintf(f,"\tmoveq\t#0,%s\n",regnames[zreg]);
  517.                 move(f,&p->q1,0,0,zreg,to);
  518.                 if(!(to&UNSIGNED)){
  519.                     if((to&15)==CHAR&&(t&15)==SHORT) fprintf(f,"\text.w\t%s\n",regnames[zreg]);
  520.                     if((to&15)==SHORT&&sizetab[t&15]==4) fprintf(f,"\text.l\t%s\n",regnames[zreg]);
  521.                     if((to&15)==CHAR&&sizetab[t&15]==4){
  522.                         if(g_flags_val[0].l>=68020)
  523.                             fprintf(f,"\textb.l\t%s\n",regnames[zreg]);
  524.                         else
  525.                             fprintf(f,"\text.w\t%s\n\text.l\t%s\n",regnames[zreg],regnames[zreg]);
  526.                     }
  527.                 }
  528.                 if(!isreg(z)||p->z.reg!=zreg){
  529.                     move(f,0,zreg,&p->z,0,t);
  530.                 }
  531.             }else{
  532.                 long diff;int m;
  533.                 m=0;
  534.                 if(p->q1.flags®){
  535.                     p->q1.val.vlong=l2zl(0L);
  536.                     p->q1.flags|=D16OFF;m=1;
  537.                 }
  538.                 diff=sizetab[to&15]-sizetab[t&15];
  539.                 vlong=l2zl(diff);
  540.                 p->q1.val.vlong=zladd(p->q1.val.vlong,vlong);
  541.                 move(f,&p->q1,0,&p->z,0,t);
  542.                 vlong=l2zl(diff);
  543.                 p->q1.val.vlong=zlsub(p->q1.val.vlong,vlong);
  544.                 if(m) p->q1.flags&=~D16OFF;
  545.             }
  546.             continue;
  547.         }
  548.         if((t==FLOAT||t==DOUBLE)&&g_flags_val[1].l>=68000) *fp='f'; else *fp=0;
  549.         if(c==MINUS||c==KOMPLEMENT){
  550.             int zreg;
  551.             if(t==FLOAT||t==DOUBLE){
  552.                 if(g_flags_val[1].l>=68000){
  553.                     if(isreg(z)) zreg=p->z.reg; else zreg=get_reg(f,2,p);
  554.                     fprintf(f,"\tfneg.%c\t",x_t[t&15]);probj(f,&p->q1,t,0);
  555.                     fprintf(f,",%s\n",regnames[zreg]);
  556.                     if(!isreg(z)||p->z.reg!=zreg){
  557.                         move(f,0,zreg,&p->z,0,t);
  558.                     }
  559.                     continue;
  560.                 }else{
  561.                     saveregs(f,p);
  562.                     assign(f,p,&p->q1,0,PUSH,sizetab[t&15],t);
  563.                     fprintf(f,"\tpublic\t__ieeeneg%c\n\tjsr\t__ieeeneg%c\n\taddq.w\t#%d,a7\n",x_t[t&15],x_t[t&15],sizetab[t&15]);
  564.                     stackoffset+=sizetab[t&15];
  565.                     restoreregsa(f,p);
  566.                     if(t==DOUBLE){
  567.                         fprintf(f,"\tmovem.l\td0/d1,");
  568.                         probj(f,&p->z,t,0);fprintf(f,"\n");
  569.                     }else move(f,0,9,&p->z,0,t);
  570.                     restoreregsd(f,p);
  571.                     continue;
  572.                 }
  573.             }
  574.             if(compare_objects(&p->q1,&p->z)){
  575.                 fprintf(f,"\t%s.%c\t",ename[c],x_t[t&15]);
  576.                 probj(f,&p->q1,t,0);fprintf(f,"\n");
  577.                 continue;
  578.             }
  579.             if(isreg(z)&&p->z.reg>=9/*&&p->z.reg<=16*/)
  580.                 zreg=p->z.reg; else zreg=get_reg(f,1,p);
  581.             if(!isreg(q1)||p->q1.reg!=zreg){
  582.                 move(f,&p->q1,0,0,zreg,t);
  583.             }
  584.             fprintf(f,"\t%s.%c\t%s\n",ename[c],x_t[t&15],regnames[zreg]);
  585.             if(!isreg(z)||p->z.reg!=zreg){
  586.                 move(f,0,zreg,&p->z,0,t);
  587.             }
  588.             continue;
  589.         }
  590.         if(c==SETRETURN){
  591.         /*  Returnwert setzen - q2.reg==size, z.reg==Returnregister */
  592.         /*  Wenn Returnwert ueber Zeiger gesetzt wird, nichts noetig    */
  593.             if(p->z.reg) move(f,&p->q1,0,0,p->z.reg,p->typf);
  594.             continue;
  595.         }
  596.         if(c==GETRETURN){
  597.         /*  Returnwert holen - q2.reg==size, q1.reg==Returnregister     */
  598.         /*  Wenn Returnwert ueber Zeiger gesetzt wird, nichts noetig    */
  599.             cc_set=0;
  600.             if(p->q1.reg){
  601.                 move(f,0,p->q1.reg,&p->z,0,p->typf);
  602.                 if(!(p->z.flags®)||(p->z.reg!=p->q1.reg&&p->z.reg>=9)){ cc_set=&p->z;cc_typ=p->typf;}
  603.             }
  604.             continue;
  605.         }
  606.         if(c==CALL){
  607.             fprintf(f,"\tjsr\t");probj(f,&p->q1,t,0);
  608.             fprintf(f,"\n");
  609.             if(p->q2.reg){
  610.                 notpopped+=p->q2.reg;
  611.                 if(!(g_flags[10]&USEDFLAG)&&!(pushedreg&30)&&stackoffset==-notpopped){
  612.                 /*  Entfernen der Parameter verzoegern  */
  613.                 }else{
  614.                     fprintf(f,"\tadd%s.%s\t#%d,a7\n",quick[p->q2.reg<=8],strshort[p->q2.reg<32768],p->q2.reg);
  615.                     stackoffset+=p->q2.reg;
  616.                     notpopped-=p->q2.reg;
  617.                 }
  618.             }
  619.             continue;
  620.         }
  621.         if(c==TEST){
  622.             /*  ConditionCodes schon gesetzt?   */
  623.             cc_set=&p->q1;cc_typ=t;
  624.             comptyp=t;
  625.             if(cc_set_tst&&t==cc_typ_tst){
  626.                 struct IC *branch;
  627.                 if(t&UNSIGNED){
  628.                     branch=p->next;
  629.                     while(branch&&(branch->code<BEQ||branch->code>BGT))
  630.                         branch=branch->next;
  631.                     if(!branch) ierror(0);
  632.                     if(branch->code==BLE) branch->code=BEQ;
  633.                     if(branch->code==BGT) branch->code=BNE;
  634.                     if(branch->code==BGE) {branch->code=BRA;continue;}
  635.                     if(branch->code==BLT) {branch->code=NOP;continue;}
  636.                 }
  637.                 if(compare_objects(&p->q1,cc_set_tst)&&p->q1.am==cc_set_tst->am&&zleqto(p->q1.val.vlong,cc_set_tst->val.vlong)){
  638.                     if(DEBUG&512){fprintf(f,"; tst eliminated: cc=");probj(f,cc_set_tst,t,0);
  639.                                   fprintf(f,", q1=");probj(f,&p->q1,t,0);fprintf(f,"\n");}
  640.                     continue;
  641.                 }
  642.             }
  643.             if(g_flags_val[0].l<68020&&isreg(q1)&&p->q1.reg>=1&&p->q1.reg<=8){
  644.             /*  tst ax gibt es nicht bei <68000 :-( */
  645.                 if(regavailable(1)){
  646.                     fprintf(f,"\tmove.%c\t%s,%s\n",x_t[t&15],regnames[p->q1.reg],regnames[get_reg(f,1,p)]);
  647.                 }else{
  648.                     fprintf(f,"\tcmp.w\t#0,%s\n",regnames[p->q1.reg]);
  649.                 }
  650.                 continue;
  651.             }
  652.             if((t==DOUBLE||t==FLOAT)&&g_flags_val[1].l<68000){
  653.             /*  nicht sehr schoen   */
  654.                 int result=get_reg(f,1,p);
  655.                 saveregs(f,p);
  656.                 assign(f,p,&p->q1,0,PUSH,sizetab[t&15],t);
  657.                 fprintf(f,"\tpublic\t__ieeetst%c\n\tjsr\t__ieeetst%c\n\taddq.w\t#%d,a7\n",x_t[t&15],x_t[t&15],sizetab[t&15]);
  658.                 stackoffset+=sizetab[t&15];
  659.                 restoreregsa(f,p);
  660.                 if(result!=9) fprintf(f,"\tmove.l\td0,%s\n",regnames[result]);
  661.                 fprintf(f,"\ttst.l\t%s\n",regnames[result]);
  662.                 restoreregsd(f,p);
  663.                 continue;
  664.             }
  665.             fprintf(f,"\t%stst.%c\t",fp,x_t[t&15]);probj(f,&p->q1,t,0);
  666.             fprintf(f,"\n");
  667.             continue;
  668.         }
  669.         if(c==ASSIGN||c==PUSH||c==POP){
  670.             if(c==ASSIGN&&compare_objects(&p->q1,&p->z)) cc_set=0;
  671.             assign(f,p,&p->q1,&p->z,c,p->q2.reg,t);
  672.             continue;
  673.         }
  674.         if(c==ADDRESS){
  675.             int zreg;
  676.             if(isreg(z)&&p->z.reg>=1&&p->z.reg<=8)
  677.                 zreg=p->z.reg; else zreg=get_reg(f,0,p);
  678.             fprintf(f,"\tlea\t");probj(f,&p->q1,t,0);
  679.             fprintf(f,",%s\n",regnames[zreg]);
  680.             if(!isreg(z)||p->z.reg!=zreg){
  681.                 move(f,0,zreg,&p->z,0,POINTER);
  682.             }
  683.             continue;
  684.         }
  685.         if(c==COMPARE){
  686.             int zreg;
  687.             comptyp=t;
  688.             if((p->q1.flags&KONST)||isreg(q2)){
  689.             /*  evtl. Argumente von cmp und nachfolgendes bcc umdrehen  */
  690.                 struct IC *n;struct obj m;
  691.                 n=p->next;
  692.                 while(n){
  693.                     if(n->code>=BEQ&&n->code<BRA){
  694.                         if(!p->z.flags){
  695.                             if(DEBUG&1) printf("arguments of cmp exchanged\n");
  696.                             m=p->q1;p->q1=p->q2;p->q2=m;
  697.                             p->z.flags=1;
  698.                         }
  699.                         /*  nachfolgenden Branch umdrehen   */
  700.                         switch(n->code){
  701.                             case BGT: n->code=BLT;break;
  702.                             case BLT: n->code=BGT;break;
  703.                             case BGE: n->code=BLE;break;
  704.                             case BLE: n->code=BGE;break;
  705.                         }
  706.                         break;
  707.                     }
  708.                     if(n->code==FREEREG) n=n->next; else break; /*  compare ohne branch => leerer Block o.ae.   */
  709.                 }
  710.             }
  711.             if(t==FLOAT||t==DOUBLE){
  712.                 if(g_flags_val[1].l>=68000){
  713.                     if(isreg(q1)&&p->q1.reg>=17){
  714.                         zreg=p->q1.reg;
  715.                     }else{
  716.                         zreg=get_reg(f,2,p);
  717.                         move(f,&p->q1,0,0,zreg,t);
  718.                     }
  719.                     fprintf(f,"\tfcmp.%c\t",x_t[t&15]);probj(f,&p->q2,t,0);
  720.                     fprintf(f,",%s\n",regnames[zreg]);
  721.                     continue;
  722.                 }else{
  723.                 /*  nicht sehr schoen   */
  724.                     int result=get_reg(f,1,p);
  725.                     saveregs(f,p);
  726.                     assign(f,p,&p->q1,0,PUSH,sizetab[t&15],t);
  727.                     assign(f,p,&p->q2,0,PUSH,sizetab[t&15],t);
  728.                     fprintf(f,"\tpublic\t__ieeecmp%c\n\tjsr\t__ieeecmp%c\n\tadd.w\t#%d,a7\n",x_t[t&15],x_t[t&15],2*sizetab[t&15]);
  729.                     stackoffset+=2*sizetab[t&15];
  730.                     restoreregsa(f,p);
  731.                     if(result!=9) fprintf(f,"\tmove.l\td0,%s\n",regnames[result]);
  732.                     fprintf(f,"\ttst.l\t%s\n",regnames[result]);
  733.                     restoreregsd(f,p);
  734.                     continue;
  735.                 }
  736.             }
  737.             if(p->q2.flags&KONST){
  738.                 fprintf(f,"\tcmp.%c\t",x_t[t&15]);probj(f,&p->q2,t,0);
  739.                 fprintf(f,",");probj(f,&p->q1,t,0);fprintf(f,"\n");
  740.                 continue;
  741.             }
  742.             if(isreg(q1)){
  743.                 zreg=p->q1.reg;
  744.             }else{
  745.                 zreg=get_reg(f,1,p);    /* hier evtl. auch Adressregister nehmen */
  746.                 move(f,&p->q1,0,0,zreg,t);
  747.             }
  748.             fprintf(f,"\tcmp.%c\t",x_t[t&15]);probj(f,&p->q2,t,0);
  749.             fprintf(f,",%s\n",regnames[zreg]);
  750.             continue;
  751.         }
  752.         if(c==ADDI2P||c==SUBIFP){
  753.             int zreg;
  754.             if(compare_objects(&p->q1,&p->z)){
  755.                 int r;
  756.                 if(p->q2.flags&KONST){
  757.                     if(c==ADDI2P)
  758.                         fprintf(f,"\tadd%s.l\t",quick[isquickkonst2(&p->q2.val,t)]);
  759.                     else
  760.                         fprintf(f,"\tsub%s.l\t",quick[isquickkonst2(&p->q2.val,t)]);
  761.                     probj(f,&p->q2,t,0);fprintf(f,",");
  762.                     probj(f,&p->z,POINTER,0);fprintf(f,"\n");
  763.                     continue;
  764.                 }
  765.                 if(isreg(q1)&&(x_t[t&15]=='l'||p->q1.reg<=8)){
  766.                     if(c==ADDI2P)
  767.                         fprintf(f,"\tadd.%c\t",x_t[t&15]);
  768.                     else
  769.                         fprintf(f,"\tsub.%c\t",x_t[t&15]);
  770.                     probj(f,&p->q2,t,0);fprintf(f,",%s\n",regnames[p->z.reg]);
  771.                     continue;
  772.                 }
  773.                 if(isreg(q2)&&p->q2.reg>=1){
  774.                     r=p->q2.reg;
  775.                 }else{
  776.                     r=get_reg(f,1,p);
  777.                     move(f,&p->q2,0,0,r,t);
  778.                 }
  779.                 if(x_t[t&15]!='l'&&(!isreg(z)||p->z.reg<1||p->z.reg>8)){
  780.                 /*  wenn Ziel kein Adressregister, muss short erst auf long */
  781.                 /*  char darf hier nicht auftreteten und long passt schon   */
  782.                     if(t&UNSIGNED) fprintf(f,"\tswap\t%s\n\tclr.w\t%s\n\tswap\t%s\n",regnames[r],regnames[r],regnames[r]);
  783.                      else          fprintf(f,"\text.l\t%s\n",regnames[r]);
  784.                     t=POINTER;
  785.                 }
  786. /*                if(c==ADDI2P)
  787.                     fprintf(f,"\tadd.%c\t%s,",x_t[t&15],regnames[r]);
  788.                 else
  789.                     fprintf(f,"\tsub.%c\t%s,",x_t[t&15],regnames[r]);
  790.                 probj(f,&p->z,t,0);fprintf(f,"\n");*/
  791.                 if(c==ADDI2P) add(f,0,r,&p->z,0,t);
  792.                  else         sub(f,0,r,&p->z,0,t);
  793.                 continue;
  794.             }
  795.             if(isreg(z)&&p->z.reg>=1&&p->z.reg<=16)
  796.                 zreg=p->z.reg; else zreg=get_reg(f,0,p);
  797.             /*  Spezialfall, falls Ziel Datenregister und short */
  798.             /*  nicht schoen, aber auf die Schnelle...          */
  799.             if(x_t[t&15]!='l'&&zreg>8){
  800.                 move(f,&p->q2,0,0,zreg,t);
  801.                 if(t&UNSIGNED) fprintf(f,"\tswap\t%s\n\tclr.w\t%s\n\tswap\t%s\n",regnames[zreg],regnames[zreg],regnames[zreg]);
  802.                  else          fprintf(f,"\text.l\t%s\n",regnames[zreg]);
  803.                 if(c==SUBIFP) fprintf(f,"\tneg.l\t%s\n",regnames[zreg]);
  804.                 add(f,&p->q1,0,0,zreg,POINTER);
  805.                 if(!isreg(z)||p->z.reg!=zreg)
  806.                     move(f,0,zreg,&p->z,0,POINTER);
  807.                 continue;
  808.             }
  809.             if(!isreg(q1)||p->q1.reg!=zreg){
  810.                 move(f,&p->q1,0,0,zreg,POINTER);
  811.             }
  812.             if(c==ADDI2P) add(f,&p->q2,0,0,zreg,t);
  813.              else         sub(f,&p->q2,0,0,zreg,t);
  814.             if(!isreg(z)||p->z.reg!=zreg){
  815.                 move(f,0,zreg,&p->z,0,POINTER);
  816.             }
  817.             continue;
  818.         }
  819.         if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD)){
  820.             int zreg,q1reg,q2reg,divflag=0;
  821.             if((p->q2.flags&KONST)&&
  822.                (!(p->q1.flags®)||!(p->z.flags®)||p->q1.reg!=p->z.reg)&&
  823.                (!(p->q1.flags&VAR)||!(p->z.flags&VAR)||p->q1.v!=p->z.v)&&
  824.                ((c>=OR&&c<=AND)||c==ADD||c==MULT)){
  825.                 struct obj o;
  826.                 if(c==MULT){
  827.                     eval_const(&p->q2.val,t);
  828.                     if(zlleq(l2zl(0L),vlong)&&zulleq(ul2zul(0UL),vulong)&&!pof2(vulong)){
  829.                         o=p->q1;p->q1=p->q2;p->q2=o;
  830.                     }
  831.                 }else{
  832.                     o=p->q1;p->q1=p->q2;p->q2=o;
  833.                 }
  834.             }
  835.             if(t==FLOAT||t==DOUBLE){
  836.                 if(g_flags_val[1].l>=68000){
  837.                     if(isreg(z)&&p->z.reg>=17) zreg=p->z.reg;
  838.                         else zreg=get_reg(f,2,p);
  839.                     if(!isreg(q1)||p->q1.reg!=p->z.reg)
  840.                         move(f,&p->q1,0,0,zreg,t);
  841.                     fprintf(f,"\tf%s.%c\t",ename[c],x_t[t&15]);probj(f,&p->q2,t,0);
  842.                     fprintf(f,",%s\n",regnames[zreg]);
  843.                     if(!isreg(z)||p->z.reg!=zreg){
  844.                         move(f,0,zreg,&p->z,0,t);
  845.                     }
  846.                     continue;
  847.                 }else{
  848.                     saveregs(f,p);
  849.                     assign(f,p,&p->q1,0,PUSH,sizetab[t&15],t);
  850.                     assign(f,p,&p->q2,0,PUSH,sizetab[t&15],t);
  851.                     fprintf(f,"\tpublic\t__ieee%s%c\n\tjsr\t__ieee%s%c\n\tadd.w\t#%d,a7\n",ename[c],x_t[t&15],ename[c],x_t[t&15],2*sizetab[t&15]);
  852.                     stackoffset+=2*sizetab[t&15];
  853.                     restoreregsa(f,p);
  854.                     if(t==DOUBLE){
  855.                         fprintf(f,"\tmovem.l\td0/d1,");
  856.                         probj(f,&p->z,0,t);fprintf(f,"\n");
  857.                     }else move(f,0,9,&p->z,0,t);
  858.                     restoreregsd(f,p);
  859.                     continue;
  860.                 }
  861.             }
  862.             if((c==MULT||c==DIV||(c==MOD&&(p->typf&UNSIGNED)))&&(p->q2.flags&KONST)){
  863.             /*  ersetzt mul etc. mit Zweierpotenzen     */
  864.             /*  hier evtl. noch Fehler                  */
  865.                 long ln;
  866.                 eval_const(&p->q2.val,t);
  867.                 if(zlleq(l2zl(0L),vlong)&&zulleq(ul2zul(0UL),vulong)){
  868.                     if(ln=pof2(vulong)){
  869.                         if(c==MOD){
  870.                             vlong=zlsub(vlong,l2zl(1L));
  871.                             p->code=AND;
  872.                         }else{
  873.                             vlong=l2zl(ln-1);
  874.                             if(c==DIV) {divflag=1;p->code=RSHIFT;} else p->code=LSHIFT;
  875.                         }
  876.                         c=p->code;
  877.                         if((t&31)==CHAR) p->q2.val.vchar=zl2zc(vlong);
  878.                         if((t&31)==SHORT) p->q2.val.vshort=zl2zs(vlong);
  879.                         if((t&31)==INT) p->q2.val.vint=zl2zi(vlong);
  880.                         if((t&31)==LONG) p->q2.val.vlong=vlong;
  881.                         vulong=zl2zul(vlong);
  882.                         if((t&31)==(UNSIGNED|CHAR)) p->q2.val.vuchar=zul2zuc(vulong);
  883.                         if((t&31)==(UNSIGNED|SHORT)) p->q2.val.vushort=zul2zus(vulong);
  884.                         if((t&31)==(UNSIGNED|INT))  p->q2.val.vuint=zul2zui(vulong);
  885.                         if((t&31)==(UNSIGNED|LONG)) p->q2.val.vulong=vulong;
  886.                     }
  887.                 }
  888.             }
  889.             if(c==DIV||c==MOD){
  890.                 if(x_t[t&15]=='l'&&g_flags_val[0].l<68020){
  891.                 /*  das hier ist auch nicht allzu schoen  */
  892.                     char *fname;
  893.                     cc_set=0;   /*  Library-Funktionen setzen cc nicht immer */
  894.                     saveregs(f,p);
  895.                     fprintf(f,"\tmove.l\t"); probj(f,&p->q2,t,0);
  896.                     fprintf(f,",-(a7)\n");
  897.                     stackoffset-=4;
  898.                     fprintf(f,"\tmove.l\t"); probj(f,&p->q1,t,0);
  899.                     fprintf(f,",-(a7)\n");
  900.                     stackoffset-=4;
  901.                     if(c==DIV){
  902.                         if(t&UNSIGNED) fname="divu"; else fname="divs";
  903.                     }else{
  904.                         if(t&UNSIGNED) fname="modu"; else fname="mods";
  905.                     }
  906.                     fprintf(f,"\tpublic\t__l%s\n",fname);
  907.                     fprintf(f,"\tjsr\t__l%s\n",fname);
  908.                     fprintf(f,"\taddq.w\t#8,a7\n");
  909.                     stackoffset+=8;
  910.                     restoreregsa(f,p);
  911.                     move(f,0,9,&p->z,0,t);
  912.                     restoreregsd(f,p);
  913.                     continue;
  914.                 }
  915.  
  916.             }
  917.             /*  hier die zweite Alternative mit isreg() schreiben?  */
  918.             if(compare_objects(&p->q2,&p->z)){
  919.                 struct obj m;
  920.                 if((c>=OR&&c<=AND)||c==ADD||c==SUB){
  921.                     if(c!=SUB){
  922.                         m=p->q1;p->q1=p->q2;p->q2=m;
  923.                     }else{
  924.                         if(isreg(q2)&&p->q2.reg>=9&&p->q2.reg<=16){
  925.                             m=p->q1;p->q1=p->q2;p->q2=m;
  926.                             c=ADD;
  927.                             fprintf(f,"\tneg.%c\t",x_t[t&15]);
  928.                             probj(f,&p->q1,t,0);fprintf(f,"\n");
  929.                         }
  930.                     }
  931.                 }
  932.             }
  933.             if(compare_objects(&p->q1,&p->z)){
  934.                 if((c>=OR&&c<=AND)||c==ADD||c==SUB){
  935.                     int r;
  936.                     if(p->q2.flags&KONST){
  937.                         if(c==ADD) {add(f,&p->q2,0,&p->z,0,t);continue;}
  938.                         if(c==SUB) {sub(f,&p->q2,0,&p->z,0,t);continue;}
  939.                         fprintf(f,"\t%s.%c\t",ename[c],x_t[t&15]);
  940.                         probj(f,&p->q2,t,0);fprintf(f,",");
  941.                         probj(f,&p->z,t,0);fprintf(f,"\n");
  942.                         continue;
  943.                     }
  944.                     if(!isreg(z)){
  945.                         if(isreg(q2)&&p->q2.reg>=9&&p->q2.reg<=16)
  946.                             r=p->q2.reg; else r=get_reg(f,1,p);
  947.                         if(!isreg(q2)||p->q2.reg!=r){
  948.                             move(f,&p->q2,0,0,r,t);
  949.                         }
  950.                         fprintf(f,"\t%s.%c\t%s,",ename[c],x_t[t&15],regnames[r]);
  951.                         probj(f,&p->z,t,0);fprintf(f,"\n");
  952.                         continue;
  953.                     }
  954.                 }
  955.             }
  956.             /*  bei xor oder asl (ausser 0<=const<=8) muss q2 in Register   */
  957.             if(isreg(q2)&&p->q2.reg>=9&&p->q2.reg<=16){
  958.                 q2reg=p->q2.reg;
  959.             }else{
  960.                 if(c==LSHIFT||c==RSHIFT||c==XOR){
  961.                     eval_const(&p->q2.val,t);
  962.                     if(c==XOR||!(p->q2.flags&KONST)||!isquickkonst2(&p->q2.val,t)){
  963.                         q2reg=get_reg(f,1,p);
  964.                         move(f,&p->q2,0,0,q2reg,t);
  965.                     }else q2reg=0;
  966.                 }else{
  967.                     q2reg=0;
  968.                 }
  969.             }
  970.             if(c==MOD){
  971.                 int modreg;
  972.                 modreg=get_reg(f,1,p);
  973.                 if(isreg(z)&&p->z.reg>=9&&p->z.reg<=16&&p->z.reg!=q2reg)
  974.                     zreg=p->z.reg; else zreg=get_reg(f,1,p);
  975.                 move(f,&p->q1,0,0,modreg,t);
  976.                 if(0 /*g_flags_val[0].l==68060*/){
  977.                 /*  div?l.l wird da emuliert?   */
  978.                     fprintf(f,"\tsmi\t%s\n\textb.l\t%s\n",regnames[zreg],regnames[zreg]);
  979.                     if(t&UNSIGNED) fprintf(f,"\tdivu.%c\t",x_t[t&15]); else fprintf(f,"\tdivs.%c\t",x_t[t&15]);
  980.                 }else{
  981.                     if(t&UNSIGNED) fprintf(f,"\tdivul.%c\t",x_t[t&15]); else fprintf(f,"\tdivsl.%c\t",x_t[t&15]);
  982.                 }
  983.                 probj(f,&p->q2,t,0);
  984.                 fprintf(f,",%s:%s\n",regnames[zreg],regnames[modreg]);
  985.                 move(f,0,zreg,&p->z,0,t);
  986.                 cc_set=0;
  987.                 continue;
  988.             }
  989.             if(isreg(z)&&p->z.reg>=9&&p->z.reg<=16&&p->z.reg!=q2reg)
  990.                 zreg=p->z.reg; else zreg=get_reg(f,1,p);
  991.             if(isreg(q1)&&p->q1.reg>=9&&p->q1.reg<=16)
  992.                 q1reg=p->q1.reg; else q1reg=0;
  993.             if(q1reg!=zreg){
  994.                 move(f,&p->q1,0,0,zreg,t);
  995.             }
  996.             if(c!=MULT&&c!=DIV&&c!=MOD&&c!=ADD&&c!=SUB){
  997.                 if(c==RSHIFT&&divflag&&!(t&UNSIGNED)) fprintf(f,"\tasr.%c\t",x_t[t&15]);
  998.                  else fprintf(f,"\t%s.%c\t",ename[c],x_t[t&15]);
  999.                 if(q2reg) fprintf(f,"%s",regnames[q2reg]); else probj(f,&p->q2,t,0);
  1000.                 fprintf(f,",%s\n",regnames[zreg]);
  1001.             }else{
  1002.                 if(c==ADD) add(f,&p->q2,q2reg,0,zreg,t);
  1003.                 if(c==SUB) sub(f,&p->q2,q2reg,0,zreg,t);
  1004.                 if(c==MULT||c==DIV||c==MOD) mult(f,&p->q2,q2reg,0,zreg,t,c,p);
  1005.             }
  1006.             if((!isreg(z)||p->z.reg!=zreg)){
  1007.                 move(f,0,zreg,&p->z,0,t);
  1008.             }
  1009.             continue;
  1010.         }
  1011.         ierror(0);
  1012.     }
  1013.     if(notpopped){
  1014.         fprintf(f,"\tadd%s.%s\t#%ld,a7\n",quick[notpopped<=8],strshort[notpopped<32768],notpopped);
  1015.         stackoffset+=notpopped;notpopped=0;
  1016.     }
  1017.     function_bottom(f,v,offset);
  1018.     if(pushflag){   /*  Speicher fuer pushlabel generieren - leider im cseg */
  1019.         fprintf(f,"\tcnop\t0,4\nl%d\n\tds.b\t4\n",pushlabel);
  1020.         pushflag=0;
  1021.     }
  1022. }
  1023. int pget_reg(FILE *f,int flag,struct IC *p)
  1024. /*  wie get_reg, fuer den Fall, dass waehrend PUSH etwas auf den Stack muss */
  1025. {
  1026.     int i;
  1027.     flag=1+flag*8;
  1028.     for(i=flag;i<flag+8;i++){
  1029.         if(regs[i]==1&&(!p||(i!=p->q1.reg&&i!=p->q2.reg&&i!=p->z.reg))){
  1030.             if(p){
  1031.                 if((p->q1.am&&(p->q1.am->dreg==i||p->q1.am->basereg==i))
  1032.                  ||(p->q2.am&&(p->q2.am->dreg==i||p->q2.am->basereg==i))
  1033.                  ||(p->z.am&&(p->z.am->dreg==i||p->z.am->basereg==i))){
  1034.                     continue;
  1035.                 }
  1036.             }
  1037.             regs[i]+=8;if(!pushlabel) {pushlabel=++label;pushflag=1;}
  1038.             fprintf(f,"\tmove.l\t%s,l%d\n",regnames[i],pushlabel);
  1039.             if(i<9) pushedreg|=2;
  1040.             else if (i<17) pushedreg|=4;
  1041.             else pushedreg|=8;
  1042.             return(i);
  1043.         }
  1044.     }
  1045.     ierror(0);
  1046. }
  1047. int get_reg(FILE *f,int flag,struct IC *p)
  1048. /*  Besorgt Register flag=0=areg, 1=dreg, 2=fpreg           */
  1049. {
  1050.     int i;
  1051.     flag=1+flag*8;
  1052.     for(i=flag;i<flag+8;i++){
  1053.         if(regs[i]==0){
  1054.             if(p){
  1055.                 if((p->q1.am&&(p->q1.am->dreg==i||p->q1.am->basereg==i))
  1056.                  ||(p->q2.am&&(p->q2.am->dreg==i||p->q2.am->basereg==i))
  1057.                  ||(p->z.am&&(p->z.am->dreg==i||p->z.am->basereg==i))){
  1058. /*                    iwarning("%s used in get_reg(1)",regnames[i]);*/
  1059.                     continue;
  1060.                 }
  1061.             }
  1062.             regs[i]=2;pushedreg|=1;
  1063.             if(!regused[i]&&!regscratch[i]){regused[i]=1; }
  1064.             return(i);
  1065.         }
  1066.     }
  1067.     for(i=flag;i<flag+8;i++){
  1068.         if(regs[i]==1&&(!p||(i!=p->q1.reg&&i!=p->q2.reg&&i!=p->z.reg))){
  1069.             if(p){
  1070.                 if((p->q1.am&&(p->q1.am->dreg==i||p->q1.am->basereg==i))
  1071.                  ||(p->q2.am&&(p->q2.am->dreg==i||p->q2.am->basereg==i))
  1072.                  ||(p->z.am&&(p->z.am->dreg==i||p->z.am->basereg==i))){
  1073. /*                    iwarning("%s used in get_reg(2)",regnames[i]);*/
  1074.                     continue;
  1075.                 }
  1076.             }
  1077.             regs[i]+=4;
  1078.             if(i<17) {fprintf(f,"\tmove.l\t%s,-(a7)\n",regnames[i]);stackoffset-=4;}
  1079.              else {fprintf(f,"\tfmove.x\t%s,-(a7)\n",regnames[i]);stackoffset-=12;}
  1080. /*            if(p->code==COMPARE) ierror("corrupt code for compare generated - sorry");*/
  1081.             if(i<9) pushedreg|=2;
  1082.             else if (i<17) pushedreg|=4;
  1083.             else pushedreg|=8;
  1084.             return(i);
  1085.         }
  1086.     }
  1087.     ierror(0);
  1088. }
  1089.  
  1090. int isquickkonst(union atyps *p,int t)
  1091. /*  liefert 1, wenn p auf Konstante zwischen -128 und 127 ist   */
  1092. {
  1093.     zlong zl;zulong zul;
  1094.     eval_const(p,t);
  1095.     if(t&UNSIGNED){
  1096.         zul=ul2zul(127UL);
  1097.         return(zulleq(vulong,zul));
  1098.     }else{
  1099.         zl=l2zl(-129L);
  1100.         if(zlleq(vlong,zl)) return(0);
  1101.         zl=l2zl(127L);
  1102.         return(zlleq(vlong,zl));
  1103.     }
  1104. }
  1105. int isquickkonst2(union atyps *p,int t)
  1106. /*  liefert 1, wenn p auf Konstante zwischen 0 und 8 ist   */
  1107. {
  1108.     zlong zl;zulong zul;
  1109.     eval_const(p,t);
  1110.     if(t&UNSIGNED){
  1111.         if(zuleq(vulong)) return(0);
  1112.         zul=ul2zul(8UL);
  1113.         return(zulleq(vulong,zul));
  1114.     }else{
  1115.         if(zleq(vlong)) return(0);
  1116.         zl=l2zl(-1L);
  1117.         if(zlleq(vlong,zl)) return(0);
  1118.         zl=l2zl(8L);
  1119.         return(zlleq(vlong,zl));
  1120.     }
  1121. }
  1122. int regavailable(int art)
  1123. /*  liefert true, wenn Register mit art frei ist, sonst 0       */
  1124. {
  1125.     int i;
  1126.     art=1+art*8;
  1127.     for(i=art+1;i<art+8;i++)
  1128.         if(regs[i]==0) return(1);
  1129.     return(0);
  1130. }
  1131.  
  1132. int compare_objects(struct obj *o1,struct obj *o2)
  1133. /*  Vergleicht, ob die beiden Objekte fuer d0_refs gleich sind  */
  1134. {
  1135.     if(o1->flags==o2->flags){
  1136.         if(!(o1->flags&VAR)||(o1->v==o2->v&&zleqto(o1->val.vlong,o2->val.vlong))){
  1137.             if(!(o1->flags®)||o1->reg==o2->reg){
  1138.                 return(1);
  1139.             }
  1140.         }
  1141.     }
  1142.     return(0);
  1143. }
  1144.  
  1145. struct IC *do_refs(FILE *f,struct IC *p)
  1146. /*  Kopiert DREFOBJs in Adressregister, wenn noetig         */
  1147. /*  und kleine Konstanten in Datenregister                  */
  1148. /*  zerstoert die ICs dabei so, dass kein zweiter Pass      */
  1149. /*  moeglich ist (was aber durch reg/freg garantiert ist).  */
  1150. {
  1151.     int reg,c=p->code,t=p->typf,equal;
  1152.     if((p->q1.flags&DREFOBJ)&&(!(p->q1.flags®)||p->q1.reg<1||p->q1.reg>8)){
  1153.         equal=0;
  1154.         if(compare_objects(&p->q1,&p->q2)) equal|=1;
  1155.         if(compare_objects(&p->q1,&p->z)) equal|=2;
  1156.         reg=get_reg(f,0,p);
  1157.         p->q1.flags&=~DREFOBJ;
  1158.         fprintf(f,"\tmove.l\t");probj(f,&p->q1,t,0);
  1159.         p->q1.flags=REG|SCRATCH|DREFOBJ;
  1160.         p->q1.reg=reg;
  1161.         fprintf(f,",%s\n",regnames[p->q1.reg]);
  1162.         if(equal&1) p->q2=p->q1;
  1163.         if(equal&2) p->z=p->q1;
  1164.     }
  1165.     if((p->q2.flags&DREFOBJ)&&(!(p->q2.flags®)||p->q2.reg<1||p->q2.reg>8)){
  1166.         if(compare_objects(&p->q2,&p->z)) equal=1; else equal=0;
  1167.         reg=get_reg(f,0,p);
  1168.         p->q2.flags&=~DREFOBJ;
  1169.         fprintf(f,"\tmove.l\t");probj(f,&p->q2,t,0);
  1170.         p->q2.flags=REG|SCRATCH|DREFOBJ;
  1171.         p->q2.reg=reg;
  1172.         fprintf(f,",%s\n",regnames[p->q2.reg]);
  1173.         if(equal) p->z=p->q2;
  1174.     }
  1175.     if((p->z.flags&DREFOBJ)&&(!(p->z.flags®)||p->z.reg<1||p->z.reg>8)){
  1176.         reg=get_reg(f,0,p);
  1177.         p->z.flags&=~DREFOBJ;
  1178.         fprintf(f,"\tmove.l\t");probj(f,&p->z,t,0);
  1179.         p->z.flags=REG|SCRATCH|DREFOBJ;
  1180.         p->z.reg=reg;
  1181.         fprintf(f,",%s\n",regnames[p->z.reg]);
  1182.     }
  1183.     if(g_flags_val[0].l<68040){
  1184.     /*  bei 040/060 ist das langsamer, also lassen wir es   */
  1185.         if(x_t[t&15]=='l'&&(t&15)!=FLOAT&&(c!=ASSIGN||!isreg(z))&&
  1186.            c!=MULT&&c!=DIV&&c!=MOD&&c!=LSHIFT&&c!=RSHIFT&&c!=SETRETURN&&c!=PUSH&&
  1187.            (!(p->z.flags®)||p->z.reg<9||p->z.reg>16)){
  1188.         /*  Konstanten evtl. in Register, noch nicht getestet   */
  1189.             if((p->q1.flags&KONST)&&isquickkonst(&p->q1.val,t)&&((c!=ADD&&c!=SUB&&c!=ADDI2P&&c!=SUBIFP)||!isquickkonst2(&p->q1.val,t))){
  1190.                 if(regavailable(1)){
  1191.                     reg=get_reg(f,1,p);
  1192.                     move(f,&p->q1,0,0,reg,t);
  1193.                     p->q1.flags=REG|SCRATCH;p->q1.reg=reg;
  1194.                     p->q1.val.vlong=l2zl(0L);
  1195.                 }
  1196.             }
  1197.             if((p->q2.flags&KONST)&&isquickkonst(&p->q2.val,t)&&((c!=ADD&&c!=SUB&&c!=ADDI2P&&c!=SUBIFP)||!isquickkonst2(&p->q2.val,t))){
  1198.                 if(regavailable(1)){
  1199.                     reg=get_reg(f,1,p);
  1200.                     move(f,&p->q2,0,0,reg,t);
  1201.                     p->q2.flags=REG|SCRATCH;p->q2.reg=reg;
  1202.                     p->q2.val.vlong=l2zl(0L);
  1203.                 }
  1204.             }
  1205.         }
  1206.     }
  1207.     return(p);
  1208. }
  1209. void pr(FILE *f,struct IC *p)
  1210. /*  Gibt Register frei, holt sie vom Stack                  */
  1211. {
  1212.     int i,size=0;
  1213.     /*  Haufen Gefummel um condition codes zu merken    */
  1214.     if((pushedreg&12)&&(p->code==TEST||p->code==COMPARE)){
  1215.         char *fp;struct IC *branch;
  1216.         if(g_flags_val[1].l>=68000&&((p->typf&15)==FLOAT||(p->typf&15)==DOUBLE)) fp="f"; else fp="";
  1217.         branch=p;
  1218.         while(branch->code<BEQ||branch->code>=BRA) branch=branch->next;
  1219.         if((p->typf&UNSIGNED)||(p->typf&15)==POINTER){
  1220.             fprintf(f,"\ts%s\t-2(a7)\n",ubranch[branch->code-BEQ]+1);
  1221.         }else{
  1222.             fprintf(f,"\t%ss%s\t-2(a7)\n",fp,ename[branch->code]+1);
  1223.         }
  1224.         stored_cc=1;
  1225.     }
  1226.     for(i=MAXR;i>0;i--){
  1227.         if(regs[i]==2) regs[i]=0;
  1228.         if(regs[i]&8){
  1229.             regs[i]&=~8;
  1230.             fprintf(f,"\tmove.l\tl%d,%s\n",pushlabel,regnames[i]);
  1231.             if(i>=9) cc_set=0;
  1232.         }
  1233.         if(regs[i]&4){
  1234.             regs[i]&=~4;
  1235.             if(i<17) {fprintf(f,"\tmove.l\t(a7)+,%s\n",regnames[i]);stackoffset+=4;size+=4;}
  1236.              else {fprintf(f,"\tfmove.x\t(a7)+,%s\n",regnames[i]);stackoffset+=12;size+=12;}
  1237.             if(i>=9) cc_set=0;
  1238.         }
  1239.     }
  1240.     if((pushedreg&12)&&(p->code==TEST||p->code==COMPARE))
  1241.         fprintf(f,"\ttst.b\t-%d(a7)\n",size+2);
  1242. }
  1243.  
  1244. void probj(FILE *f,struct obj *p,int t,int verbose)
  1245. /*  Gibt Objekt auf Bildschirm aus                      */
  1246. {
  1247.     if(p->am){
  1248.     /*  Ausgabe der erweiterten Adressierungsarten  */
  1249.         if(g_flags[9]&USEDFLAG) {ierror(0);p->am=0;return;}
  1250.         if(p->am->skal>=0){
  1251.             long l=0;
  1252.             if(p->flags&D16OFF) l=zl2l(p->val.vlong);
  1253.             fprintf(f,"(%ld,%s",p->am->dist+l,regnames[p->am->basereg]);
  1254.             if(p->am->dreg){
  1255.                 fprintf(f,",%s",regnames[p->am->dreg&127]);
  1256.                 if(p->am->dreg&128) fprintf(f,".w"); else fprintf(f,".l");
  1257.                 if(p->am->skal) fprintf(f,"*%d",p->am->skal);
  1258.             }
  1259.             fprintf(f,")");
  1260.             return;
  1261.         }
  1262.         if((p->flags&D16OFF)&&!zleq(p->val.vlong)) ierror(0);
  1263.         if(p->am->skal==-1){
  1264.             fprintf(f,"(%s)+",regnames[p->am->basereg]);
  1265.             return;
  1266.         }
  1267.         if(p->am->skal==-2){    /*  Noch nicht implementiert    */
  1268.             fprintf(f,"-(%s)",regnames[p->am->basereg]);
  1269.             return;
  1270.         }
  1271.     }
  1272.     if(p->flags&DREFOBJ){
  1273.         fprintf(f,"(");
  1274.         if((p->flags&D16OFF)&&!zleq(p->val.vlong))
  1275.             {printval(f,&p->val,LONG,0);fprintf(f,",");}
  1276.     }
  1277.     if((p->flags&VARADR)&&!(verbose&2)) fprintf(f,"#");
  1278.     if(p->flags&VAR) {
  1279.         if(verbose&1){
  1280.             printval(f,&p->val,LONG,1);
  1281.             if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
  1282.                 if(p->flags®)
  1283.                     fprintf(f,"+%s",regnames[p->reg]);
  1284.                 else
  1285.                     fprintf(f,"+%d(FP)", p->v->offset);
  1286.             }else{
  1287.                 if(p->v->storage_class==STATIC&&p->v->nesting>0){
  1288.                     fprintf(f,"+L%d",p->v->offset);
  1289.                 }else{
  1290.                     fprintf(f,"+_%s",p->v->identifier);
  1291.                 }
  1292.             }
  1293.             fprintf(f,"(%s)",p->v->identifier);
  1294.         }else{
  1295.             if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
  1296.                 if(p->flags®){
  1297.                     fprintf(f,"%s",regnames[p->reg]);
  1298.                 }else{
  1299.                     long os;
  1300.                     os=zl2l(p->val.vlong);
  1301.                     if(!(g_flags[8]&USEDFLAG)){
  1302.                         if(p->v->offset<0) os=os+loff-p->v->offset;
  1303.                          else              os=os+p->v->offset;
  1304.                         fprintf(f,"(%ld+l%d,a7)",os-stackoffset,offlabel);
  1305.                     }else{
  1306.                         if(p->v->offset<0) os=os-p->v->offset+4;
  1307.                          else              os=os-(p->v->offset+szof(p->v->vtyp));
  1308.                         fprintf(f,"(%ld,a5)",os);
  1309.                     }
  1310.                 }
  1311.             }else{
  1312.                 if(!zleq(p->val.vlong)){printval(f,&p->val,LONG,0);fprintf(f,"+");}
  1313.                 if(p->v->storage_class==STATIC&&(p->v->vtyp->flags&15)!=FUNKT){
  1314.                     fprintf(f,"l%d",p->v->offset);
  1315.                 }else{
  1316.                     fprintf(f,"_%s",p->v->identifier);
  1317.                 }
  1318.                 if((g_flags[5]&USEDFLAG)&&!(p->flags&VARADR)&&(p->v->vtyp->flags&15)!=FUNKT&&((g_flags[7]&USEDFLAG)||!is_const(p->v->vtyp)) )
  1319.                     fprintf(f,"(a4)");
  1320.             }
  1321.         }
  1322.     }
  1323.     if((p->flags®)&&!(p->flags&VAR)) fprintf(f,"%s",regnames[p->reg]);
  1324.     if(p->flags&KONST){
  1325.         /*  Das hier setzt voraus, dass Compiler Datentypen im  */
  1326.         /*  IEEE-Format nachbildet                              */
  1327.         if(t==FLOAT||t==DOUBLE){
  1328.             char str[10];int i;
  1329.             int *ip=(int *)&p->val.vfloat; /*   nicht schoen, aber...   */
  1330.             fprintf(f,"#$");sprintf(str,"%8x",*ip);
  1331.             for(i=0;i<8;i++) if(str[i]==' ') str[i]='0';
  1332.             fprintf(f,"%s",str);
  1333.             if(t==DOUBLE){
  1334.                 if(DEBUG&1) printf("doubleconst=%f\n",p->val.vdouble);
  1335.                 ip++;sprintf(str,"%8x",*ip);
  1336.                 for(i=0;i<10;i++) if(str[i]==' ') str[i]='0';
  1337.                 fprintf(f,"%s",str);
  1338.             }
  1339.         }else {fprintf(f,"#");printval(f,&p->val,t&31,verbose);}
  1340.     }
  1341.     if(p->flags&STACK) fprintf(f,"Stack");
  1342.     if(p->flags&DREFOBJ) fprintf(f,")");
  1343. }
  1344. char tsh[]={'w','l'};
  1345. int proflabel;
  1346. void function_top(FILE *f,struct Var *v,int offset)
  1347. /*  erzeugt Funktionskopf                       */
  1348. {
  1349.     if(g_flags_val[0].l!=68000) fprintf(f,"\tmachine\t%ld\n",g_flags_val[0].l);
  1350.     if(g_flags_val[1].l>68000) fprintf(f,"\tfpu\t1\n");
  1351.     if(g_flags[4]&USEDFLAG) fprintf(f,"\tnear\tcode\n");
  1352.     if(g_flags[5]&USEDFLAG) fprintf(f,"\tnear\ta4,-2\n");
  1353.     if(section!=CODE){fprintf(f,codename);section=CODE;}
  1354.     if(g_flags[6]&USEDFLAG){
  1355.         proflabel=++label;
  1356.         fprintf(f,"l%d\n\tdc.b\t\"%s\",0\n",proflabel,v->identifier);
  1357.     }
  1358.     if(v->storage_class==EXTERN) fprintf(f,"\tpublic\t_%s\n",v->identifier);
  1359.     fprintf(f,"\tcnop\t0,4\n_%s\n",v->identifier);
  1360.     if(g_flags[6]&USEDFLAG)
  1361.         fprintf(f,"\tpea\tl%d\n\tpublic\t__startprof\n\tjsr\t__startprof\n\taddq.w\t#4,a7\n",proflabel);
  1362.     offset=-((offset+4-1)/4)*4;
  1363.     loff=-offset;offlabel=++label;
  1364.     if(!(g_flags[8]&USEDFLAG)){
  1365.         if(offset<0) fprintf(f,"\tsub%s.%s\t#%d,a7\n",quick[offset>=-8],strshort[offset>=-32768],-offset);
  1366.     }else{
  1367.         if(offset>=-32768||g_flags_val[0].l>=68020){
  1368.             fprintf(f,"\tlink.%c\ta5,#%d\n",tsh[offset<-32768],offset);
  1369.         }else{
  1370.             fprintf(f,"\tlink.w\ta5,#-32768\n");offset+=32768;
  1371.             fprintf(f,"\tsub.%c\t#%d,a5\n",tsh[offset<-32768],offset);
  1372.         }
  1373.     }
  1374.     if(g_flags_val[1].l>68000&&float_used) fprintf(f,"\tfmovem.x\tl%d,-(a7)\n",freglabel);
  1375.     fprintf(f,"\tmovem.l\tl%d,-(a7)\n",reglabel);
  1376.     /*  Was mach ich hier mit stackoffset?  */
  1377. }
  1378. void function_bottom(FILE *f,struct Var *v,int offset)
  1379. /*  erzeugt Funktionsende                       */
  1380. {
  1381.     int i,size=0;
  1382.     *reglist=0;
  1383.     for(i=1;i<=16;i++){
  1384.         if(regused[i]&&!regscratch[i]&&!regsa[i]){
  1385.             if(*reglist) strcat(reglist,"/");
  1386.             strcat(reglist,regnames[i]);size+=4;
  1387.         }
  1388.     }
  1389.     if(*reglist) fprintf(f,"l%d\treg\t%s\n\tmovem.l\t(a7)+,l%d\n",reglabel,reglist,reglabel);
  1390.         else fprintf(f,"l%d\treg\n",reglabel);
  1391.     *reglist=0;
  1392.     for(i=17;i<=MAXR;i++){
  1393.         if(regused[i]&&!regscratch[i]&&!regsa[i]){
  1394.             if(*reglist) strcat(reglist,"/");
  1395.             strcat(reglist,regnames[i]);size+=12;
  1396.         }
  1397.     }
  1398.     if(g_flags_val[1].l>68000&&float_used){
  1399.         if(*reglist) fprintf(f,"l%d\tfreg\t%s\n\tfmovem.x\t(a7)+,l%d\n",freglabel,reglist,freglabel);
  1400.             else fprintf(f,"l%d\tfreg\n",freglabel);
  1401.     }
  1402.     if(!(g_flags[8]&USEDFLAG)){
  1403.         if(loff) fprintf(f,"\tadd%s.%s\t#%ld,a7\n",quick[loff<=8],strshort[loff<32768],loff);
  1404.         fprintf(f,"l%d\tEQU\t%d\n",offlabel,size);
  1405.     }else fprintf(f,"\tunlk\ta5\n");
  1406.     if(g_flags[6]&USEDFLAG)
  1407.         fprintf(f,"\tpea\tl%d\n\tpublic\t__endprof\n\tjsr\t__endprof\n\taddq.w\t#4,a7\n",proflabel);
  1408.     fprintf(f,"\trts\n");
  1409. }
  1410. void gen_ds(FILE *f,int size,struct Typ *t)
  1411. /*  generiert Speicher fuer size Bytes mit Null initialisiert.  */
  1412. /*  Aufpassen, dass kein BSS in einem teilweise initialisierten */
  1413. /*  Array erzeugt wird.                                         */
  1414. /*  t darf 0 sein, dann sind es nur Fuellbytes                  */
  1415. {
  1416.     if(section!=BSS&&newobj){fprintf(f,bssname);section=BSS;}
  1417.     fprintf(f,"\tds.b\t%d\n",size);newobj=0;
  1418. }
  1419. void gen_align(FILE *f,int align)
  1420. /*  generiert alignment auf align Bytes (oder aehnlich)         */
  1421. {
  1422.     if(align>1) fprintf(f,"\tcnop\t0,4\n");
  1423. }
  1424. int is_const(struct Typ *t)
  1425. /*  tested, ob ein Typ konstant (und damit evtl. in der Code-Section) ist   */
  1426. {
  1427.     if(!(t->flags&(CONST|STRINGCONST))){
  1428.         do{
  1429.             if(t->flags&(CONST|STRINGCONST)) return(1);
  1430.             if((t->flags&15)!=ARRAY) return(0);
  1431.             t=t->next;
  1432.         }while(1);
  1433.     }else return(1);
  1434. }
  1435.  
  1436. void gen_var_head(FILE *f,struct Var *v)
  1437. /*  generiert Kopf fuer eine Variable                           */
  1438. {
  1439.     int constflag;
  1440.     if(v->clist) constflag=is_const(v->vtyp);
  1441.     if(v->storage_class==STATIC){
  1442.         if((v->vtyp->flags&15)==FUNKT) return;
  1443.         if(v->clist&&(!constflag||(g_flags[7]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  1444.         if(v->clist&&constflag&&!(g_flags[7]&USEDFLAG)&§ion!=CODE){fprintf(f,codename);section=CODE;}
  1445.         if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  1446.         fprintf(f,"\tcnop\t0,4\nl%d\n",v->offset);
  1447.         newobj=1;
  1448.     }
  1449.     if(v->storage_class==EXTERN){
  1450.         fprintf(f,"\tpublic\t_%s\n",v->identifier);
  1451.         if(v->flags&(DEFINED|TENTATIVE)){
  1452.             if(v->clist&&(!constflag||(g_flags[7]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  1453.             if(v->clist&&constflag&&!(g_flags[7]&USEDFLAG)&§ion!=CODE){fprintf(f,codename);section=CODE;}
  1454.             if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  1455.             fprintf(f,"\tcnop\t0,4\n_%s\n",v->identifier);
  1456.             newobj=1;
  1457.         }
  1458.     }
  1459. }
  1460. void gen_dc(FILE *f,int t,struct const_list *p)
  1461. /*  generiert Konstanten fuer Typ t aus clist p                 */
  1462. {
  1463.     char s;
  1464.     if(!p){ierror(0);return;}
  1465. /*    if(section!=DATA){fprintf(f,dataname);section=DATA;}*/
  1466.     if((t&15)==FLOAT||(t&15)==DOUBLE) s='l'; else s=x_t[t&15];
  1467.     fprintf(f,"\tdc.%c\t",s);
  1468.     if(!p->tree){
  1469.         if((t&15)==FLOAT||(t&15)==DOUBLE){
  1470.         /*  auch wieder nicht sehr schoen und IEEE noetig   */
  1471.             int *ip;
  1472.             ip=(int *)&p->val.vdouble;
  1473.             fprintf(f,"$%x",*ip);
  1474.             if((t&15)==DOUBLE) fprintf(f,",$%x",*(++ip));
  1475.         }else{
  1476.             printval(f,&p->val,t&31,0);
  1477.         }
  1478.     }else{
  1479.         p->tree->o.am=0;
  1480.         probj(f,&p->tree->o,t&31,2);
  1481.     }
  1482.     fprintf(f,"\n");newobj=0;
  1483. }
  1484.  
  1485. void move(FILE *f,struct obj *q,int qreg,struct obj *z,int zreg,int t)
  1486. /*  erzeugt eine move Anweisung...Da sollen mal Optimierungen rein  */
  1487. {
  1488.     if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
  1489.     if(!qreg&&(q->flags&(REG|DREFOBJ))==REG) qreg=q->reg;
  1490.     if(zreg==qreg&&zreg) return;
  1491.     if(q&&(q->flags&VARADR)&&zreg>=1&&zreg<=8){
  1492.         fprintf(f,"\tlea\t");
  1493.         q->flags&=~VARADR;probj(f,q,t,0);q->flags|=VARADR;
  1494.         fprintf(f,",%s\n",regnames[zreg]);
  1495.         return;
  1496.     }
  1497.     if(zreg>=9&&zreg<=16&&q&&(q->flags&KONST)&&isquickkonst(&q->val,t)){
  1498.         fprintf(f,"\tmoveq\t");
  1499.     }else{
  1500.         if(zreg>=17||qreg>=17){
  1501.             if(qreg>=17&&zreg>=17) fprintf(f,"\tfmove.x\t");
  1502.              else fprintf(f,"\tfmove.%c\t",x_t[t&15]);
  1503.         }else{
  1504.             fprintf(f,"\tmove.%c\t",x_s[sizetab[t&15]]);
  1505.         }
  1506.     }
  1507.     if(qreg) fprintf(f,"%s",regnames[qreg]); else probj(f,q,t,0);
  1508.     fprintf(f,",");
  1509.     if(zreg) fprintf(f,"%s",regnames[zreg]); else probj(f,z,t,0);
  1510.     fprintf(f,"\n");
  1511. }
  1512. void add(FILE *f,struct obj *q,int qreg,struct obj *z,int zreg,int t)
  1513. /*  erzeugt eine add Anweisung...Da sollen mal Optimierungen rein   */
  1514. {
  1515.     if(!qreg&&!q) ierror(0);
  1516.     if(!zreg&&!z) ierror(0);
  1517.     if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
  1518.     if(!qreg&&(q->flags&KONST)&&isquickkonst2(&q->val,t)){
  1519.         fprintf(f,"\taddq.%c\t",x_t[t&15]);
  1520.     }else{
  1521.         /*  hier noch Abfrage, ob #c.w,ax   */
  1522.         fprintf(f,"\tadd.%c\t",x_t[t&15]);
  1523.     }
  1524.     if(qreg) fprintf(f,"%s",regnames[qreg]); else probj(f,q,t,0);
  1525.     fprintf(f,",");
  1526.     if(zreg) fprintf(f,"%s",regnames[zreg]); else probj(f,z,t,0);
  1527.     fprintf(f,"\n");
  1528. }
  1529. void sub(FILE *f,struct obj *q,int qreg,struct obj *z,int zreg,int t)
  1530. /*  erzeugt eine sub Anweisung...Da sollen mal Optimierungen rein   */
  1531. {
  1532.     if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
  1533.     if(q&&(q->flags&KONST)&&isquickkonst2(&q->val,t)){
  1534.         fprintf(f,"\tsubq.%c\t",x_t[t&15]);
  1535.     }else{
  1536.         /*  hier noch Abfrage, ob #c.w,ax   */
  1537.         fprintf(f,"\tsub.%c\t",x_t[t&15]);
  1538.     }
  1539.     if(qreg) fprintf(f,"%s",regnames[qreg]); else probj(f,q,t,0);
  1540.     fprintf(f,",");
  1541.     if(zreg) fprintf(f,"%s",regnames[zreg]); else probj(f,z,t,0);
  1542.     fprintf(f,"\n");
  1543. }
  1544. void mult(FILE *f,struct obj *q,int qreg,struct obj *z,int zreg, int t,int c,struct IC *p)
  1545. /*  erzeugt eine mult Anweisung...Da sollen mal Optimierungen rein  */
  1546. /*  erzeugt auch div/mod etc.                                       */
  1547. {
  1548.     int modreg;
  1549.     if(!qreg&&(q->flags&(REG|DREFOBJ))==REG) qreg=q->reg;
  1550.     if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
  1551.     if((c==MULT||c==DIV||c==MOD)&&g_flags_val[0].l<68020&&sizetab[t&15]==4){
  1552.         if(c==MULT){
  1553.         /*  ist das mit get_reg(.,.,0) ok? nochmal ueberdenken...   */
  1554.         /*  ...die ganze Routine am besten...                       */
  1555.         /*  ...es war nicht, deshalb ist es jetzt geaendert         */
  1556.             int dx,dy,t1,t2;
  1557.             if(zreg>=9&&zreg<=16){
  1558.                 dx=zreg;
  1559.             }else{
  1560.                 dx=get_reg(f,1,p);
  1561.                 move(f,z,0,0,dx,t);
  1562.             }
  1563.             if(qreg>=9&&qreg<=16&&qreg!=dx){
  1564.                 dy=qreg;
  1565.             }else{
  1566.                 dy=get_reg(f,1,p);
  1567.                 move(f,q,0,0,dy,t);
  1568.             }
  1569.             t1=get_reg(f,1,p);t2=get_reg(f,1,p);
  1570.             if(t1==dx||t2==dx||t1==dy||t2==dy) ierror(0);
  1571.             fprintf(f,"\tmove.l\t%s,%s\n",regnames[dx],regnames[t1]);
  1572.             fprintf(f,"\tmove.l\t%s,%s\n",regnames[dy],regnames[t2]);
  1573.             fprintf(f,"\tswap\t%s\n",regnames[t1]);
  1574.             fprintf(f,"\tswap\t%s\n",regnames[t2]);
  1575.             fprintf(f,"\tmulu.w\t%s,%s\n",regnames[dy],regnames[t1]);
  1576.             fprintf(f,"\tmulu.w\t%s,%s\n",regnames[dx],regnames[t2]);
  1577.             fprintf(f,"\tmulu.w\t%s,%s\n",regnames[dy],regnames[dx]);
  1578.             fprintf(f,"\tadd.w\t%s,%s\n",regnames[t2],regnames[t1]);
  1579.             fprintf(f,"\tswap\t%s\n",regnames[t1]);
  1580.             fprintf(f,"\tclr.w\t%s\n",regnames[t1]);
  1581.             fprintf(f,"\tadd.l\t%s,%s\n",regnames[t1],regnames[dx]);
  1582.             if(zreg!=dx) move(f,0,t1,z,0,t);
  1583.         }else ierror(0);
  1584.         return;
  1585.     }
  1586.     if(c==MULT){
  1587.         /*  das duerfte nur der Aesthetik dienen... */
  1588.         if(t&UNSIGNED) fprintf(f,"\tmulu.%c\t",x_t[t&15]); else fprintf(f,"\tmuls.%c\t",x_t[t&15]);
  1589.     }
  1590.     if(c==DIV){
  1591.         if(t&UNSIGNED) fprintf(f,"\tdivu.%c\t",x_t[t&15]); else fprintf(f,"\tdivs.%c\t",x_t[t&15]);
  1592.     }
  1593.     if(qreg) fprintf(f,"%s",regnames[qreg]); else probj(f,q,t,0);
  1594.     fprintf(f,",");
  1595.     /*  eigentlich muss zreg!=0 sein...     */
  1596.     if(zreg) fprintf(f,"%s",regnames[zreg]); else probj(f,z,t,0);
  1597.     fprintf(f,"\n");
  1598. }
  1599.  
  1600. struct IC *am_freedreg[9],*am_shiftdreg[9];
  1601. struct IC *am_dist_ic[9],*am_dreg_ic[9],*am_use[9];
  1602. /*  am_dist_ic und am_dreg_ic werden auch fuer (ax)+ benutzt    */
  1603. long am_dist[9],am_dreg[9],am_base[9],am_inc[9],am_skal[9],am_dbase[9];
  1604. #define AMS sizeof(struct AddressingMode)
  1605.  
  1606. void clear_am(int reg)
  1607. /*  loescht Werte fuer erweiterte Adressierungsarten fuer Register reg  */
  1608. {
  1609.     if(reg<0||reg>16) ierror(0);
  1610.     if(DEBUG&32) printf("clear_am(%s)\n",regnames[reg]);
  1611.     if(reg<=8){
  1612.         am_dist_ic[reg]=am_dreg_ic[reg]=am_use[reg]=0;
  1613.         am_dist[reg]=am_dreg[reg]=am_base[reg]=am_inc[reg]=0;
  1614.     }else{
  1615.         reg-=8;
  1616.         am_freedreg[reg]=am_shiftdreg[reg]=0;
  1617.         am_skal[reg]=am_dbase[reg]=0;
  1618.     }
  1619. }
  1620. int addressing(void)
  1621. /*  Untersucht ICs auf erweiterte Addresierungsarten    */
  1622. {
  1623.     struct IC *p;int count,localused=0;
  1624.     if(DEBUG&32) printf("addressing() started\n");
  1625.     for(count=1;count<=16;count++) clear_am(count);
  1626.     for(count=0,p=first_ic;p;p=p->next){
  1627.         int c=p->code,q1reg,q2reg,zreg;
  1628.         if(p->q1.flags®) q1reg=p->q1.reg; else q1reg=0;
  1629.         if(p->q2.flags®) q2reg=p->q2.reg; else q2reg=0;
  1630.         if(p->z.flags®) zreg=p->z.reg; else zreg=0;
  1631.         if(c==ADDI2P) c=ADD;
  1632.         if(c==SUBIFP) c=SUB;
  1633.         if(DEBUG&32) pric2(stdout,p);
  1634.         if(!localused){
  1635.             if((p->q1.flags&(VAR|REG))==VAR&&(p->q1.v->storage_class==AUTO||p->q1.v->storage_class==REGISTER)&&p->q1.v->offset>=0)
  1636.                 localused=1;
  1637.             if((p->q2.flags&(VAR|REG))==VAR&&(p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER)&&p->q2.v->offset>=0)
  1638.                 localused=1;
  1639.             if((p->z.flags&(VAR|REG))==VAR&&(p->z.v->storage_class==AUTO||p->z.v->storage_class==REGISTER)&&p->z.v->offset>=0)
  1640.                 localused=1;
  1641.             if(DEBUG&32&&localused==1) printf("localused=1\n");
  1642.         }
  1643.         if(c==ASSIGN&&isreg(q1)&&isreg(z)&&q1reg>=1&&q1reg<=8&&zreg>=1&&zreg<=8){
  1644.         /*  fuer (ax)+  */
  1645.             int i;
  1646.             for(i=1;i<=8;i++)
  1647.                 if(am_base[i]==zreg||am_base[i]==q1reg) clear_am(i);
  1648.             clear_am(zreg);am_base[zreg]=q1reg;am_dreg_ic[zreg]=p;
  1649.             if(DEBUG&32) printf("move %s,%s found\n",regnames[q1reg],regnames[zreg]);
  1650.             continue;
  1651.         }
  1652.         if(c==MULT&&g_flags_val[0].l>=68020&&(p->q2.flags&KONST)&&isreg(z)&&zreg>=9&&zreg<=16){
  1653.         /*  dx=a*const, fuer Skalierung    */
  1654.             int dreg=zreg-8;
  1655.             if(dreg<1||dreg>8) ierror(0);
  1656.             if(DEBUG&32) printf("mult x,const->dreg found\n");
  1657.             if(am_skal[dreg]) {clear_am(zreg);continue;}
  1658.             eval_const(&p->q2.val,p->typf);
  1659.             am_skal[dreg]=zl2l(vlong);
  1660.             if(am_skal[dreg]!=2&&am_skal[dreg]!=4&&am_skal[dreg]!=8)
  1661.                 {clear_am(zreg);continue;}
  1662.             am_shiftdreg[dreg]=p;
  1663.             if(isreg(q1)&&q1reg>=9&&q1reg<=16) am_dbase[dreg]=q1reg; else am_dbase[dreg]=zreg;
  1664.             if(DEBUG&32) printf("is usable\n");
  1665.             continue;
  1666.         }
  1667.         if((c==ADD||c==SUB)&&(p->q2.flags&KONST)&&zreg>=1&&zreg<=8&&isreg(z)){
  1668.         /*  add ax,#const,ax->az Test auf d8/16 fehlt noch (nicht mehr) */
  1669.             long l;
  1670.             if(zreg<1||zreg>8) ierror(0);
  1671.             if(am_dist[zreg]||am_inc[zreg]) {clear_am(zreg);continue;} /* nur ein Offset */
  1672.             eval_const(&p->q2.val,p->typf);
  1673.             l=zl2l(vlong);
  1674.             if(c==SUB) l=-l;
  1675.             if(isreg(q1)&&q1reg==zreg&&(l==1||l==2||l==4)){
  1676.             /*  ax+=const, fuer (ax)+   */
  1677.                 int i,f;
  1678.                 for(f=0,i=1;i<=8;i++){
  1679.                     if(am_base[i]==zreg&&!am_dreg[i]&&!am_dist[i]){
  1680.                         if(f) ierror(0);
  1681.                         am_inc[i]=l;am_dist_ic[i]=p;f=i;
  1682.                         if(DEBUG&32) printf("inc %s found\n",regnames[i]);
  1683.                     }
  1684.                 }
  1685.                 if(f) continue;
  1686.             }
  1687.             am_dist[zreg]=l;
  1688.             if(DEBUG&32) printf("dist=%ld\n",am_dist[zreg]);
  1689.             if(g_flags_val[0].l<68020){
  1690.             /*  bei <68020 darf der Offset nur 16bit oder 8bit bei dreg sein */
  1691.                 if((am_dreg[zreg]&&(am_dist[zreg]<-128||am_dist[zreg]>127))||am_dist[zreg]<-32768||am_dist[zreg]>32767)
  1692.                     {clear_am(zreg);continue;}
  1693.             }
  1694.             am_dist_ic[zreg]=p;
  1695.             if(am_base[zreg]){
  1696.                 if(q1reg!=zreg||!isreg(q1)) {clear_am(zreg);continue;}
  1697.             }else{
  1698.                 if(q1reg>=1&&q1reg<=8&&isreg(q1)) am_base[zreg]=q1reg; else am_base[zreg]=zreg;
  1699.                 if(DEBUG&32) printf("%s potential base for %s\n",regnames[am_base[zreg]],regnames[zreg]);
  1700.             }
  1701.             if(DEBUG&32) printf("add #const,%s found\n",regnames[zreg]);
  1702.             continue;
  1703.         }
  1704.         if(c==ADD&&q2reg>=9&&q2reg<=16&&isreg(q2)&&zreg>=1&&zreg<=8&&isreg(z)&&(p->q1.flags&(REG|DREFOBJ))!=(REG|DREFOBJ)){
  1705.         /*  add ax,dy->az   */
  1706.             int i;
  1707.             if(zreg<1||zreg>8) ierror(0);
  1708.             for(i=1;i<=8;i++)
  1709.                 if(am_dreg[i]==q2reg){ clear_am(q2reg);clear_am(i);}
  1710.             if(am_dreg[zreg]||am_inc[zreg]) {clear_am(zreg);continue;} /* nur ein Regoffset */
  1711.             if(g_flags_val[0].l<68020&&(am_dist[zreg]<-128||am_dist[zreg]>127))
  1712.                 {clear_am(zreg);continue;} /* bei <68020 nur 8bit Offset */
  1713.             am_dreg[zreg]=q2reg;
  1714.             if((p->typf&15)==SHORT) am_dreg[zreg]|=128; /* dx.w statt dx.l */
  1715.             am_dreg_ic[zreg]=p;
  1716.             if(am_base[zreg]){
  1717.                 if(q1reg!=zreg||!isreg(q1)) {clear_am(zreg);continue;}
  1718.             }else{
  1719.                 if(q1reg>=1&&q1reg<=8&&isreg(q1)) am_base[zreg]=q1reg; else am_base[zreg]=zreg;
  1720.             }
  1721.             if(DEBUG&32) printf("add %s,%s found\n",regnames[q2reg],regnames[zreg]);
  1722.             continue;
  1723.         }
  1724.         if(c==FREEREG){
  1725.         /*  wir koennen den Modus tatsaechlich benutzen */
  1726.             struct AddressingMode *am;struct IC *p1,*p2;int dreg;
  1727.             if(DEBUG&32) printf("freereg found, code=%d\n",p->code);
  1728.             if(q1reg>=9&&q1reg<=16) {am_freedreg[q1reg-8]=p;if(DEBUG&32) printf("freedreg[%d]=%lx\n",q1reg-8,(long)p);}
  1729.             if(q1reg>8||!am_use[q1reg]) continue;
  1730.             p1=am_dist_ic[q1reg];p2=am_dreg_ic[q1reg];
  1731.             if(DEBUG&32){
  1732.                 printf("could really use %s\n",regnames[q1reg]);
  1733.                 if(p1) pric2(stdout,p1);
  1734.                 if(p2) pric2(stdout,p2);
  1735.             }
  1736.             if(am_base[q1reg]==q1reg){
  1737.                 if(p1) {p1->q2.flags=0;p1->code=ASSIGN;p1->q2.reg=4;p1->typf=POINTER;}
  1738.                 if(p2) {p2->q2.flags=0;p2->code=ASSIGN;p2->q2.reg=4;p2->typf=POINTER;}
  1739.             }else{
  1740.                 if(p1) remove_IC(p1);
  1741.                 if(p2) remove_IC(p2);
  1742.             }
  1743.             dreg=(am_dreg[q1reg]&127)-8;
  1744.             am=(struct AddressingMode *)mymalloc(AMS);
  1745.             am->skal=0;
  1746.             am->basereg=am_base[q1reg];
  1747.             am->dist=am_dist[q1reg];
  1748.             am->dreg=am_dreg[q1reg];
  1749.             if(am_inc[q1reg]) am->skal=-1;
  1750.             if(dreg>0){
  1751.                 /*  bei (d,ax,dy) das freereg dy nach hinten verschieben    */
  1752.                 if(dreg<1||dreg>8) ierror(0);
  1753.                 if(p1=am_freedreg[dreg]){
  1754.                     if(DEBUG&32){
  1755.                         printf("freereg %s moved from %p to %p\n",regnames[dreg+8],p1,p);
  1756.                         pric2(stdout,p1);
  1757.                     }
  1758.                     if(p1->code!=FREEREG){ierror(0);printf("freereg[%d]=%p\n",dreg,p1);continue;}
  1759.                     if(!p1->next) {ierror(0);continue;}
  1760.                     if(!p1->prev) {ierror(0);continue;}
  1761.                     p1->prev->next=p1->next;
  1762.                     p1->next->prev=p1->prev;
  1763.                     p1->next=p->next;
  1764.                     p1->prev=p;
  1765.                     if(p->next) p->next->prev=p1;
  1766.                     p->next=p1;
  1767.                 }
  1768.                 if(am_skal[dreg]){
  1769.                 /*  Skalierung bearbeiten   */
  1770.                     if(p1){
  1771.                         am->skal=am_skal[dreg];
  1772.                         am->dreg=am_dbase[dreg];
  1773.                         p1=am_shiftdreg[dreg];
  1774.                         if(DEBUG&32) pric2(stdout,p1);
  1775.                         if(am_dbase[dreg]==dreg+8){
  1776.                             p1->code=ASSIGN;p1->q2.flags=0;p1->q2.reg=sizetab[p1->typf&15];
  1777.                         }else remove_IC(p1);
  1778.                     }
  1779.                     clear_am(dreg+8);
  1780.                 }
  1781.             }
  1782.             /*  das hier duerfte unnoetig sein, da die Adressierungsart in  */
  1783.             /*  einem IC eigentlich hoechstens einmal vorkommen darf        */
  1784.             if(q1reg<0||q1reg>8) ierror(0);
  1785.             p1=am_use[q1reg];
  1786.             if(DEBUG&32) pric2(stdout,p1);
  1787.             if(p1->code==PUSH&&p1->q1.reg==q1reg&&((p1->q1.flags&(DREFOBJ|REG))==(REG))){
  1788.                 p1->q1.am=(struct AddressingMode *)mymalloc(AMS);
  1789.                 memcpy(p1->q1.am,am,AMS);
  1790.                 p1->code=PEA;
  1791.                 if(DEBUG&32) printf("q1 patched\n");
  1792.             }
  1793.             if(p1->q1.reg==q1reg&&((p1->q1.flags&(DREFOBJ|REG))==(DREFOBJ|REG))){
  1794.                 p1->q1.am=(struct AddressingMode *)mymalloc(AMS);
  1795.                 memcpy(p1->q1.am,am,AMS);
  1796.                 if(DEBUG&32) printf("q1 patched\n");
  1797.             }
  1798.             if(p1->q2.reg==q1reg&&((p1->q2.flags&(DREFOBJ|REG))==(DREFOBJ|REG))){
  1799.                 p1->q2.am=(struct AddressingMode *)mymalloc(AMS);
  1800.                 memcpy(p1->q2.am,am,AMS);
  1801.                 if(DEBUG&32) printf("q2 patched\n");
  1802.             }
  1803.             if(p1->z.reg==q1reg&&((p1->z.flags&(DREFOBJ|REG))==(DREFOBJ|REG))){
  1804.                 p1->z.am=(struct AddressingMode *)mymalloc(AMS);
  1805.                 memcpy(p1->z.am,am,AMS);
  1806.                 if(DEBUG&32) printf("z patched\n");
  1807.             }
  1808.             free(am);count++;
  1809.             clear_am(q1reg);
  1810.             continue;
  1811.         }
  1812.         if(c==LABEL){
  1813.             int i;      /*  ueber Labels hinweg ist das zu unsicher */
  1814.             for(i=1;i<=16;i++) clear_am(i);
  1815.             continue;
  1816.         }
  1817.         /*  Wenn Libraryaufrufe noetig sind (floating point ohne FPU oder   */
  1818.         /*  32bit mul/div/mod ohne 020+) keine Addressierungsarten nutzen   */
  1819.         if(g_flags_val[1].l<68000&&(p->typf==FLOAT||p->typf==DOUBLE||c==CONVFLOAT||c==CONVDOUBLE)){
  1820.             int i;
  1821.             for(i=1;i<=16;i++) clear_am(i);
  1822.             continue;
  1823.         }
  1824.         if(g_flags_val[0].l<68020&&(c==DIV||c==MOD)){
  1825.             int i;
  1826.             for(i=1;i<=16;i++) clear_am(i);
  1827.             continue;
  1828.         }
  1829.         if(c==PUSH&&((p->q1.flags&(DREFOBJ|REG))==REG&&q1reg<=8&&(am_inc[q1reg]||am_dist[q1reg]||am_dreg[q1reg]))){
  1830.             if(q1reg<1||q1reg>8) ierror(0);
  1831.             if(am_inc[q1reg]&&am_inc[q1reg]!=sizetab[p->typf&15]) clear_am(q1reg);
  1832.             if(DEBUG&32) printf("use of %s found\n",regnames[q1reg]);
  1833.         }
  1834.         if(((p->q1.flags&(DREFOBJ|REG))==(DREFOBJ|REG)&&q1reg<=8&&(am_inc[q1reg]||am_dist[q1reg]||am_dreg[q1reg]))){
  1835.             if(q1reg<1||q1reg>8) ierror(0);
  1836.             if(am_use[q1reg]&&(am_use[q1reg]!=p||am_inc[q1reg])) clear_am(q1reg); else am_use[q1reg]=p;
  1837.             if(am_inc[q1reg]&&am_inc[q1reg]!=sizetab[p->typf&15]) clear_am(q1reg);
  1838.             if(DEBUG&32) printf("use of %s found\n",regnames[q1reg]);
  1839.         }
  1840.         if(((p->q2.flags&(DREFOBJ|REG))==(DREFOBJ|REG)&&q2reg<=8&&(am_inc[q2reg]||am_dist[q2reg]||am_dreg[q2reg]))){
  1841.             if(q2reg<1||q2reg>8) ierror(0);
  1842.             if(am_use[q2reg]&&(am_use[q2reg]!=p||am_inc[q2reg])) clear_am(q2reg); else am_use[q2reg]=p;
  1843.             if(am_inc[q2reg]&&am_inc[q2reg]!=sizetab[p->typf&15]) clear_am(q2reg);
  1844.             if(DEBUG&32) printf("use of %s found\n",regnames[q2reg]);
  1845.         }
  1846.         if(((p->z.flags&(DREFOBJ|REG))==(DREFOBJ|REG)&&zreg<=8&&(am_inc[zreg]||am_dist[zreg]||am_dreg[zreg]))){
  1847.             if(zreg<1||zreg>8) ierror(0);
  1848.             if(am_use[zreg]&&(am_use[zreg]!=p||am_inc[zreg])) clear_am(zreg); else am_use[zreg]=p;
  1849.             if(am_inc[zreg]&&am_inc[zreg]!=sizetab[p->typf&15]) clear_am(zreg);
  1850.             if(DEBUG&32) printf("use of %s found\n",regnames[zreg]);
  1851.         }
  1852.         if(c==ALLOCREG){
  1853.         /*  allocreg zaehlt als zerstoerung von reg */
  1854.             p->z.flags=REG;
  1855.             p->z.reg=zreg=q1reg;
  1856.         }
  1857.         if(q1reg>=1&&q1reg<=16&&isreg(q1)&&(q1reg>8||am_use[q1reg]!=p)) clear_am(q1reg);
  1858.         if(q2reg>=1&&q2reg<=16&&isreg(q2)&&(q2reg>8||am_use[q2reg]!=p)) clear_am(q2reg);
  1859.         if(zreg>=1&&zreg<=16&&isreg(z)) clear_am(zreg);
  1860.         if(isreg(z)&&zreg<=16){
  1861.         /*  schauen, ob eines der Register ueberschrieben wird  */
  1862.         /*  wohl noch sehr langsam                              */
  1863.             int i;
  1864.             for(i=1;i<=8;i++)
  1865.                 if(!am_use[i]&&(am_base[i]==zreg||(am_dreg[i]&127)==zreg)) clear_am(i);
  1866.         }
  1867.         if(c==ALLOCREG) p->z.flags=0;
  1868.     }
  1869.     if(DEBUG&1) printf("%d addressingmodes used, localused=%d\n",count,localused);
  1870.     return(localused);
  1871. }
  1872. int alignment(struct obj *o)
  1873. /*  versucht rauszufinden, wie ein Objekt alignet ist   */
  1874. {
  1875.     /*  wenn es keine Variable ist, kann man nichts aussagen    */
  1876.     long os;
  1877.     if((o->flags&(DREFOBJ|VAR))!=VAR||o->am) return(0);
  1878.     if(!o->v) ierror(0);
  1879.     os=zl2l(o->val.vlong);
  1880.     if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
  1881.         if(!(g_flags[8]&USEDFLAG)){
  1882.             if(o->v->offset<0) os=os+loff-o->v->offset;
  1883.              else              os=os+o->v->offset;
  1884.         }else{
  1885.             if(o->v->offset<0) os=os-o->v->offset+4;
  1886.              else              os=os-(o->v->offset+szof(o->v->vtyp));
  1887.         }
  1888.     }
  1889.     return(os&3);
  1890. }
  1891. void assign(FILE *f,struct IC *p,struct obj *q,struct obj *z,int c,int size,int t)
  1892. /*  Generiert Code fuer Zuweisungen und PUSH/POP; hier noch einiges zu tun  */
  1893. {
  1894.     /*  auch noch sehr fpu-spezifisch   */
  1895.     if(t==FLOAT||t==DOUBLE){
  1896.         if(q&&(q->flags&KONST)){
  1897.             if(z&&(z->flags&(DREFOBJ|REG))==REG){
  1898.             /*  FP-Konstante->Register (muss immer reinpassen)  */
  1899.                 if(z->reg>=17) fprintf(f,"\tfmove"); else fprintf(f,"\tmove");
  1900.                 fprintf(f,".%c\t",x_t[t&15]);probj(f,q,t,0);
  1901.                 fprintf(f,",%s\n",regnames[z->reg]);
  1902.             }else{
  1903.             /*  FP-Konstante->Speicher (evtl. auf zweimal)  */
  1904.                 int m,*ip=(int *)&q->val.vfloat; /* nicht sehr schoen  */
  1905.                 if(c==PUSH&&t==DOUBLE) {fprintf(f,"\tmove.l\t#$%x,-(a7)\n",ip[1]);stackoffset-=4;}
  1906.                 fprintf(f,"\tmove.l\t#$%x,",*ip);
  1907.                 if(c==ASSIGN) probj(f,z,t,0); else {fprintf(f,"-(a7)");stackoffset-=4;}
  1908.                 fprintf(f,"\n");
  1909.                 if(t!=DOUBLE||c==PUSH) return;
  1910.                 ip++;m=0;
  1911.                 if(z&&z->flags®){
  1912.                     m=1;z->flags|=D16OFF;
  1913.                     z->val.vlong=l2zl(0L);
  1914.                 }
  1915.                 vlong=l2zl(4L);
  1916.                 z->val.vlong=zladd(z->val.vlong,vlong);
  1917.                 fprintf(f,"\tmove.l\t#$%x,",*ip);probj(f,z,t,0);
  1918.                 fprintf(f,"\n");
  1919.                 if(m){
  1920.                     z->flags&=~D16OFF;vlong=l2zl(4L);
  1921.                     z->val.vlong=zlsub(z->val.vlong,vlong);
  1922.                 }
  1923.             }
  1924.             return;
  1925.         }
  1926.         if((q&&(q->flags®)&&q->reg>=17)||(z&&(z->flags®)&&z->reg>=17)){
  1927.             if(c==ASSIGN&&q->reg==z->reg) return;
  1928.             fprintf(f,"\tfmove.%c\t",x_t[t&15]);
  1929.             if(c==POP) {fprintf(f,"(a7)+");stackoffset+=size;} else probj(f,q,t,0);
  1930.             fprintf(f,",");
  1931.             if(c==PUSH) {fprintf(f,"-(a7)");stackoffset-=size;} else probj(f,z,t,0);
  1932.             fprintf(f,"\n");return;
  1933.         }
  1934.     }
  1935.     if(size<=4&&(t&15)!=ARRAY&&((t&15)!=CHAR||size==1)){
  1936.         if((t&15)==STRUCT||(t&15)==UNION){
  1937.             if(size==2) t=SHORT; else t=LONG;
  1938.         }
  1939.         if(c==ASSIGN){move(f,q,0,z,0,t);return;}
  1940.         /*  Sonderfall pea  */
  1941.         if((q->flags&VARADR)&&c==PUSH){
  1942.             fprintf(f,"\tpea\t");
  1943.             q->flags&=~VARADR; probj(f,q,t,0); q->flags|=VARADR;
  1944.             fprintf(f,"\n"); stackoffset-=4;return;
  1945.         }
  1946.         fprintf(f,"\tmove.%c\t",x_s[size]);
  1947.         if(c==POP) {fprintf(f,"(a7)+");stackoffset+=size;} else probj(f,q,t,0);
  1948.         fprintf(f,",");
  1949.         if(c==PUSH) {fprintf(f,"-(a7)");stackoffset-=size;} else probj(f,z,t,0);
  1950.         fprintf(f,"\n");return;
  1951.     }else{
  1952.         int a1,a2,qreg,zreg,dreg,s=size,loops;char *cpstr;
  1953.         if(c==PUSH) cpstr="\tmove.%c\t-(%s),-(%s)\n"; else cpstr="\tmove.%c\t(%s)+,(%s)+\n";
  1954.         if(c==POP){
  1955.             qreg=8;
  1956.         }else{
  1957.             if(q->flags==(SCRATCH|REG|DREFOBJ)&&q->reg>=1&&q->reg<=8&&!q->am){
  1958.                 qreg=q->reg;
  1959.             }else{
  1960.                 if(c!=ASSIGN&&!regavailable(0)) qreg=pget_reg(f,0,p);
  1961.                     else qreg=get_reg(f,0,p);
  1962.                 fprintf(f,"\tlea\t");probj(f,q,POINTER,0);
  1963.                 fprintf(f,",%s\n",regnames[qreg]);
  1964.             }
  1965.         }
  1966.         if(c==PUSH){
  1967.             zreg=8;
  1968.             fprintf(f,"\tadd%s.%s\t#%d,%s\n",quick[s<=8],strshort[s<=32767],s,regnames[qreg]);
  1969.         }else{
  1970.             zreg=get_reg(f,0,p);
  1971.             fprintf(f,"\tlea\t");probj(f,z,POINTER,0);
  1972.             fprintf(f,",%s\n",regnames[zreg]);
  1973.         }
  1974.         if(c!=POP) a1=alignment(q); else a1=0;
  1975.         if(c!=PUSH)  a2=alignment(z); else a2=0;
  1976.         /*  wenn Typ==CHAR, dann ist das ein inline_memcpy und wir nehmen   */
  1977.         /*  das unguenstigste Alignment an                                  */
  1978.         if((t&15)==CHAR){ a1=1;a2=2;}
  1979.  
  1980.         if((a1&1)&&(a2&1)){fprintf(f,cpstr,'b',regnames[qreg],regnames[zreg]);s--;a1&=~1;a2&=~1;}
  1981.         if((a1&2)&&(a2&2)){fprintf(f,cpstr,'w',regnames[qreg],regnames[zreg]);s-=2;a1&=~2;a2&=~2;}
  1982.         if(!(a1&1)&&!(a2&1)) loops=s/16-1; else loops=s/4-1;
  1983.         if(loops>0){
  1984.             if(c!=ASSIGN&&!regavailable(1)) dreg=pget_reg(f,0,p);
  1985.                 else dreg=get_reg(f,1,p);
  1986.             fprintf(f,"\tmove%s.l\t#%d,%s\nl%d\n",quick[loops>=-128&&loops<=127],loops,regnames[dreg],++label);
  1987.         }
  1988.         if(loops>=0){
  1989.             int t;
  1990.             if(!(a1&1)&&!(a2&1)) t='l'; else t='b';
  1991.             fprintf(f,cpstr,t,regnames[qreg],regnames[zreg]);
  1992.             fprintf(f,cpstr,t,regnames[qreg],regnames[zreg]);
  1993.             fprintf(f,cpstr,t,regnames[qreg],regnames[zreg]);
  1994.             fprintf(f,cpstr,t,regnames[qreg],regnames[zreg]);
  1995.         }
  1996.         if(loops>0){
  1997.             if(loops<=32767&&loops>=-32768){
  1998.                 fprintf(f,"\tdbra\t%s,l%d\n",regnames[dreg],label);
  1999.             }else{
  2000.                 fprintf(f,"\tsubq.l\t#1,%s\n\tbge\tl%d\n",regnames[dreg],label);
  2001.             }
  2002.         }
  2003.         if(!(a1&1)&&!(a2&1)){
  2004.             if(s&8){
  2005.                 fprintf(f,cpstr,'l',regnames[qreg],regnames[zreg]);
  2006.                 fprintf(f,cpstr,'l',regnames[qreg],regnames[zreg]);
  2007.             }
  2008.             if(s&4) fprintf(f,cpstr,'l',regnames[qreg],regnames[zreg]);
  2009.             if(s&2) fprintf(f,cpstr,'w',regnames[qreg],regnames[zreg]);
  2010.             if(s&1) fprintf(f,cpstr,'b',regnames[qreg],regnames[zreg]);
  2011.         }else{
  2012.             s&=3;
  2013.             while(s){fprintf(f,cpstr,'b',regnames[qreg],regnames[zreg]);s--;}
  2014.         }
  2015.         if(c==PUSH) stackoffset-=size;
  2016.         if(c==POP)  stackoffset+=size;
  2017.     }
  2018.     return;
  2019. }
  2020.  
  2021. int must_convert(np p,int t)
  2022. /*  liefert 1, wenn fuer Umwandlung von p->o nach Typ t tatsaechlich    */
  2023. /*  Code erzeugt werden muss, sonst 0                                   */
  2024. {
  2025.     int o=p->ntyp->flags,op=o&15,tp=t&15;
  2026.     /*  Zeiger sind gleich  */
  2027.     if(tp==POINTER&&op==POINTER) return(0);
  2028.     /*  Pointer und int/long auch   */
  2029. /*    if(tp==POINTER&&(op==INT||op==LONG)) return(0);
  2030.     if(op==POINTER&&(tp==INT||tp==LONG)) return(0);*/
  2031.     /*  signed und unsigned integers der selben Groesse sind gleich */
  2032.     if((t&UNSIGNED)&&(o&UNSIGNED)&&(sizetab[tp]==sizetab[op])) return(0);
  2033.     /*  int==long   */
  2034.     if((tp==INT&&op==LONG)||(tp==LONG&&op==INT)) return(0);
  2035.     /*  float und double gibt es in fp-Registern nicht  */
  2036.     if((tp==FLOAT||tp==DOUBLE)&&(op==FLOAT||op==DOUBLE)&&(p->o.flags®)&&p->o.reg>=17&&p->o.reg<=24)
  2037.         return(0);
  2038.  
  2039.     return(1);
  2040. }
  2041.  
  2042. int store_saveregs;
  2043.  
  2044. void saveregs(FILE *f,struct IC *p)
  2045. {
  2046.     int dontsave;
  2047.     store_saveregs=0;
  2048.     if((p->z.flags&(REG|DREFOBJ))==REG) dontsave=p->z.reg; else dontsave=0;
  2049.     if(dontsave!= 9&®s[ 9]) {fprintf(f,"\tmove.l\td0,-(a7)\n");stackoffset-=4;store_saveregs|=1;}
  2050.     if(dontsave!=10&®s[10]) {fprintf(f,"\tmove.l\td1,-(a7)\n");stackoffset-=4;store_saveregs|=2;}
  2051.     if(dontsave!= 1&®s[ 1]) {fprintf(f,"\tmove.l\ta0,-(a7)\n");stackoffset-=4;store_saveregs|=4;}
  2052.     if(dontsave!= 2&®s[ 2]) {fprintf(f,"\tmove.l\ta1,-(a7)\n");stackoffset-=4;store_saveregs|=8;}
  2053. }
  2054. void restoreregsa(FILE *f,struct IC *p)
  2055. {
  2056.     if(store_saveregs&8) {fprintf(f,"\tmove.l\t(a7)+,a1\n");stackoffset+=4;}
  2057.     if(store_saveregs&4) {fprintf(f,"\tmove.l\t(a7)+,a0\n");stackoffset+=4;}
  2058. }
  2059. void restoreregsd(FILE *f,struct IC *p)
  2060. {
  2061.     int dontsave;
  2062.     if((p->z.flags&(REG|DREFOBJ))==REG) dontsave=p->z.reg; else dontsave=0;
  2063.     if(dontsave!=10&&(store_saveregs&2)) {fprintf(f,"\tmovem.l\t(a7)+,d1\n");stackoffset+=4;}
  2064.     if(dontsave!=9 &&(store_saveregs&1)) {fprintf(f,"\tmovem.l\t(a7)+,d0\n");stackoffset+=4;}
  2065. }
  2066.  
  2067.