home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / compiler / vbcc / machines / i386 / machine.c next >
Encoding:
C/C++ Source or Header  |  1997-02-07  |  43.1 KB  |  1,196 lines

  1. /*  Code generator for Intel 80386 or higher.                   */
  2.  
  3. #include "vbc.h"
  4.  
  5. static char FILE_[]=__FILE__;
  6.  
  7. /*  Public data that MUST be there.                             */
  8.  
  9. /*  Commandline-flags the code-generator accepts                */
  10. int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0,
  11.                     0};
  12. char *g_flags_name[MAXGF]={"cpu","fpu","no-delayed-popping","const-in-data",
  13.                            "merge-constants","elf"};
  14. union ppi g_flags_val[MAXGF];
  15.  
  16. /*  Alignment-requirements for all types in bytes.              */
  17. zlong align[16];
  18.  
  19. /*  Alignment that is sufficient for every object.              */
  20. zlong maxalign;
  21.  
  22. /*  CHAR_BIT of the target machine.                             */
  23. zlong char_bit;
  24.  
  25. /*  Sizes of all elementary types in bytes.                     */
  26. zlong sizetab[16];
  27.  
  28. /*  Minimum and Maximum values each type can have.              */
  29. /*  Must be initialized in init_cg().                           */
  30. zlong t_min[32];
  31. zulong t_max[32];
  32.  
  33. /*  Names of all registers.                                     */
  34. char *regnames[MAXR+1]={"noreg","%eax","%ecx","%edx","%ebx",
  35.                                 "%esi","%edi","%ebp","%esp",
  36.                                 "%st(0)","%st(1)","%st(2)","%st(3)",
  37.                                 "%st(4)","%st(5)","%st(6)","%st(7)"};
  38.  
  39. /*  The Size of each register in bytes.                         */
  40. zlong regsize[MAXR+1];
  41.  
  42. /*  regsa[reg]!=0 if a certain register is allocated and should */
  43. /*  not be used by the compiler pass.                           */
  44. int regsa[MAXR+1];
  45.  
  46. /*  Specifies which registers may be scratched by functions.    */
  47. int regscratch[MAXR+1]={0,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1};
  48.  
  49.  
  50. /****************************************/
  51. /*  Some private data and functions.    */
  52. /****************************************/
  53.  
  54. static long malign[16]={1,1,2,2,2,2,2,2,2,2,2,2,2,2,2};
  55. static long msizetab[16]={0,1,2,4,4,4,8,0,4,0,0,0,4,0};
  56.  
  57.  
  58. #define DATA 0
  59. #define BSS 1
  60. #define CODE 2
  61.  
  62. static int section=-1,newobj;
  63. static char *codename="\t.text\n",*dataname="\t.data\n",*bssname="";
  64. static int is_const(struct Typ *);
  65. static const int ax=1,cx=2,dx=3,bx=4,si=5,di=6,bp=7,sp=8;
  66. static char x_t[]={'?','b','w','l','l','s','l','v','l','a','s','u','e','f','?','?'};
  67. static int is_const(struct Typ *);
  68. static void pr(FILE *,struct IC *);
  69. static void function_top(FILE *,struct Var *,long);
  70. static void function_bottom(FILE *f,struct Var *,long);
  71.  
  72. #define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
  73.  
  74. static long loff,stackoffset,notpopped,dontpop;
  75.  
  76. static char *ccs[]={"z","nz","l","ge","le","g","mp"};
  77. static char *ccu[]={"z","nz","b","ae","be","a","mp"};
  78. static char *logicals[]={"or","xor","and"};
  79. static char *arithmetics[]={"sal","sar","add","sub","imul","div","mod"};
  80. static char *farithmetics[]={"f?","f?","fadd","fsub","fmul","fdiv","fsubr","fdivr"};
  81. static char *dct[]={"","byte","short","long","long","long","long","long","long"};
  82. static pushedsize,pushorder=2;
  83. static int fst[8];
  84. static int cxl,dil,sil;
  85. static char *idprefix="",*labprefix="";
  86.  
  87. static struct fpconstlist {
  88.     struct fpconstlist *next;
  89.     int label,typ;
  90.     union atyps val;
  91. } *firstfpc;
  92.  
  93. static int addfpconst(struct obj *o,int t)
  94. {
  95.     struct fpconstlist *p=firstfpc;
  96.     t&=15;
  97.     if(g_flags[4]&USEDFLAG){
  98.         for(p=firstfpc;p;p=p->next){
  99.             if(t==p->typ){
  100.                 eval_const(&p->val,t);
  101.                 if(t==FLOAT&&zdeqto(vdouble,zf2zd(o->val.vfloat))) return(p->label);
  102.                 if(t==DOUBLE&&zdeqto(vdouble,o->val.vdouble)) return(p->label);
  103.             }
  104.         }
  105.     }
  106.     p=mymalloc(sizeof(struct fpconstlist));
  107.     p->next=firstfpc;
  108.     p->label=++label;
  109.     p->typ=t;
  110.     p->val=o->val;
  111.     firstfpc=p;
  112.     return(p->label);
  113. }
  114. static void probj2(FILE *f,struct obj *p,int t)
  115. /*  Gibt Objekt auf Bildschirm aus                      */
  116. {
  117.     if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) fprintf(f,"(");
  118.     if(p->flags&VARADR) fprintf(f,"$");
  119.     if((p->flags&VAR)&&!(p->flags®)) {
  120.         if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
  121.             if(p->v->offset<0) fprintf(f,"%ld(%%esp)",(long)(loff-zl2l(p->v->offset)+zl2l(p->val.vlong))-stackoffset+pushedsize);
  122.                 else           fprintf(f,"%ld(%%esp)",(long)(zl2l(p->v->offset)+zl2l(p->val.vlong)-stackoffset));
  123.         }else{
  124.             if(!zleqto(l2zl(0L),p->val.vlong)){printval(f,&p->val,LONG,0);fprintf(f,"+");}
  125.             if(p->v->storage_class==STATIC&&(p->v->vtyp->flags&15)!=FUNKT){
  126.                 fprintf(f,"%sl%ld",labprefix,zl2l(p->v->offset));
  127.             }else{
  128.                 fprintf(f,"%s%s",idprefix,p->v->identifier);
  129.             }
  130.         }
  131.     }
  132.     if(p->flags®){
  133.         if(p->reg>8){
  134.             int i;
  135.             for(i=0;i<8;i++){
  136.                 if(fst[i]==p->reg)
  137.                     fprintf(f,"%s",regnames[i+9]);
  138.             }
  139.         }else{
  140.             fprintf(f,"%s",regnames[p->reg]);
  141.         }
  142.     }
  143.     if(p->flags&KONST){
  144.         if((t&15)==FLOAT||(t&15)==DOUBLE){
  145.             fprintf(f,"%sl%d",labprefix,addfpconst(p,t));
  146.         }else{
  147.             fprintf(f,"$");printval(f,&p->val,t&31,0);
  148.         }
  149.     }
  150.     if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) fprintf(f,")");
  151. }
  152. static void fxch(FILE *f,int i)
  153. {
  154.     int m;
  155.     fprintf(f,"\tfxch\t%s\n",regnames[i+9]);
  156.     m=fst[0];fst[0]=fst[i];fst[i]=m;
  157. }
  158. static int freest(void)
  159. {
  160.     int i;
  161.     for(i=0;i<8;i++){
  162.         if(fst[i]<0) return(i);
  163.     }
  164.     ierror(0);
  165. }
  166. static void fpush(FILE *f)
  167. {
  168.     int i;
  169.     if(fst[7]>0){
  170.         i=freest();
  171.         fxch(f,i);fxch(f,7);
  172.     }
  173.     for(i=7;i>0;i--)
  174.         fst[i]=fst[i-1];
  175.     fst[0]=-1;
  176. }
  177. static void fpop(void)
  178. {
  179.     int i;
  180. /*    if(fst[0]>0&®s[fst[0]]) ierror(0);*/
  181.     for(i=0;i<7;i++)
  182.         fst[i]=fst[i+1];
  183.     fst[7]=-1;
  184. }
  185. static void fload(FILE *f,struct obj *o,int t)
  186. {
  187.     fprintf(f,"\tfld");
  188.     if((o->flags&(REG|DREFOBJ))==REG) fprintf(f,"\t");
  189.         else fprintf(f,"%c\t",x_t[t&15]);
  190.     probj2(f,o,t);fprintf(f,"\n");
  191.     fpush(f);
  192. }
  193. static void fstore(FILE *f,struct obj *o,int t)
  194. {
  195.     int i;
  196.     if((o->flags&(REG|DREFOBJ))==REG){
  197.         for(i=0;i<8;i++)
  198.             if(fst[i]==o->reg) fst[i]=-1;
  199.         fst[0]=o->reg;
  200.     }else{
  201.         fprintf(f,"\tfstp%c\t",x_t[t&15]);probj2(f,o,t);
  202.         fpop();fprintf(f,"\n");
  203.     }
  204. }
  205. static void prfst(FILE *f,char *s)
  206. {
  207.     int i;
  208.     if(DEBUG==0) return;
  209.     fprintf(f,"*\t%s\t",s);
  210.     for(i=0;i<8;i++){
  211.         if(fst[i]>=0)
  212.             fprintf(f,"%s ",regnames[fst[i]]+3);
  213.         else
  214.             fprintf(f,"--- ");
  215.     }
  216.     fprintf(f,"\n");
  217. }
  218. static void finit(void)
  219. {
  220.     int i;
  221.     for(i=0;i<8;i++){
  222.         if(regs[i+9])
  223.             fst[i]=i+9;
  224.         else
  225.             fst[i]=-1;
  226.     }
  227. }
  228. static void forder(FILE *f)
  229. {
  230.     int i,m,unordered;
  231.     prfst(f,"forder");
  232. oloop:
  233.     unordered=0;
  234.     for(i=0;i<8;i++){
  235.         if(fst[i]>=0&&fst[i]!=i+9&®s[fst[i]]){unordered=1;break;}
  236.     }
  237.     if(!unordered) return;
  238.     if(fst[0]>=0&®s[fst[0]]){
  239.         if(fst[0]!=9){
  240.             fxch(f,fst[0]-9);
  241.             goto oloop;
  242.         }else{
  243.             fxch(f,freest());
  244.         }
  245.     }
  246.     for(i=1;i<8;i++){
  247.         if(fst[i]>=0&&fst[i]!=i+9&®s[fst[i]]&&fst[i]!=9){
  248.             fxch(f,i);
  249.             goto oloop;
  250.         }
  251.     }
  252.     if(regs[9]){
  253.         for(i=1;i<8;i++){
  254.             if(fst[i]==9){ fxch(f,i);return;}
  255.         }
  256.     }
  257. }
  258. static void pr(FILE *f,struct IC *p)
  259. {
  260.     int i;
  261.     for(;pushorder>2;pushorder>>=1){
  262.         for(i=1;i<=8;i++){
  263.             if(regs[i]&pushorder){
  264.                 fprintf(f,"\tpopl\t%s\n",regnames[i]);
  265.                 stackoffset+=4;regs[i]&=~pushorder;
  266.             }
  267.         }
  268.     }
  269.     for(i=1;i<=8;i++)
  270.         if(regs[i]&2) regs[i]&=~2;
  271. }
  272. static void function_top(FILE *f,struct Var *v,long offset)
  273. /*  erzeugt Funktionskopf                       */
  274. {
  275.     int i;
  276.     if(section!=CODE){fprintf(f,codename);section=CODE;}
  277.     if(v->storage_class==EXTERN) fprintf(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
  278.     fprintf(f,"%s%s:\n",idprefix,v->identifier);
  279.     for(pushedsize=0,i=1;i<sp;i++){
  280.         if(regused[i]&&!regscratch[i]){
  281.             fprintf(f,"\tpushl\t%s\n",regnames[i]);
  282.             pushedsize+=4;
  283.         }
  284.     }
  285.     if(offset) fprintf(f,"\tsubl\t$%ld,%%esp\n",offset);
  286. }
  287. static void function_bottom(FILE *f,struct Var *v,long offset)
  288. /*  erzeugt Funktionsende                       */
  289. {
  290.     int i;
  291.     if(offset) fprintf(f,"\taddl\t$%ld,%%esp\n",offset);
  292.     for(i=sp-1;i>0;i--){
  293.         if(regused[i]&&!regscratch[i]){
  294.             fprintf(f,"\tpopl\t%s\n",regnames[i]);
  295.         }
  296.     }
  297.     fprintf(f,"\tret\n");
  298. }
  299. static int is_const(struct Typ *t)
  300. /*  Tests if a type can be placed in the code-section.  */
  301. {
  302.     if(!(t->flags&(CONST|STRINGCONST))){
  303.         do{
  304.             if(t->flags&(CONST|STRINGCONST)) return(1);
  305.             if((t->flags&15)!=ARRAY) return(0);
  306.             t=t->next;
  307.         }while(1);
  308.     }else return(1);
  309. }
  310. static int compare_objects(struct obj *o1,struct obj *o2)
  311. {
  312.     if(o1->flags==o2->flags&&o1->am==o2->am){
  313.         if(!(o1->flags&VAR)||(o1->v==o2->v&&zleqto(o1->val.vlong,o2->val.vlong))){
  314.             if(!(o1->flags®)||o1->reg==o2->reg){
  315.                 return(1);
  316.             }
  317.         }
  318.     }
  319.     return(0);
  320. }
  321. static int get_reg(FILE *f,struct IC *p)
  322. {
  323.     int i;
  324.     /*  If we can use a register which was already used by the compiler */
  325.     /*  or it is a sratch register then we can use it without problems. */
  326.     for(i=1;i<=8;i++){
  327.         if(!regs[i]&&(regused[i]||regscratch[i])){
  328.             regs[i]=2;
  329.             return(i);
  330.         }
  331.     }
  332.     /*  Otherwise we have to save this register.                        */
  333.     /*  We may not use a register which is used in this IC.             */
  334.     for(i=1;i<=8;i++){
  335.         if(regs[i]<2
  336.             &&(!(p->q1.flags®)||p->q1.reg!=i)
  337.             &&(!(p->q2.flags®)||p->q2.reg!=i)
  338.             &&(!(p->z.flags®)||p->z.reg!=i) ){
  339.  
  340.             fprintf(f,"\tpushl\t%s\n",regnames[i]);
  341.             /*  Mark register as pushed (taking care of the order). */
  342.             pushorder<<=1; regs[i]|=pushorder;
  343.             stackoffset-=4;
  344.             return(i);
  345.         }
  346.     }
  347.     ierror(0);
  348. }
  349. static void move(FILE *f,struct obj *q,int qr,struct obj *z,int zr,int t)
  350. /*  Generates code to move object q (or register qr) into object z (or  */
  351. /*  register zr).                                                       */
  352. {
  353.     if(q&&(q->flags&(REG|DREFOBJ))==REG) qr=q->reg;
  354.     if(z&&(z->flags&(REG|DREFOBJ))==REG) zr=z->reg;
  355.     if(qr&&zr){
  356.         if(qr!=zr)
  357.             fprintf(f,"\tmovl\t%s,%s\n",regnames[qr],regnames[zr]);
  358.         return;
  359.     }
  360.     if(zr&&(q->flags&KONST)){
  361.         eval_const(&q->val,t);
  362.         if(zleqto(vlong,l2zl(0L))&&zuleqto(vulong,ul2zul(0UL))&&zdeqto(vdouble,d2zd(0.0))){
  363.             fprintf(f,"\txorl\t%s,%s\n",regnames[zr],regnames[zr]);
  364.             return;
  365.         }
  366.     }
  367.     fprintf(f,"\tmov%c\t",x_t[t&15]);
  368.     if(qr) fprintf(f,"%s",regnames[qr]); else probj2(f,q,t);
  369.     fprintf(f,",");
  370.     if(zr) fprintf(f,"%s",regnames[zr]); else probj2(f,z,t);
  371.     fprintf(f,"\n");
  372. }
  373. static long pof2(zulong x)
  374. /*  Yields log2(x)+1 oder 0. */
  375. {
  376.     zulong p;int ln=1;
  377.     p=ul2zul(1L);
  378.     while(zulleq(p,x)){
  379.         if(zuleqto(x,p)) return(ln);
  380.         ln++;p=zuladd(p,p);
  381.     }
  382.     return(0);
  383. }
  384.  
  385. /****************************************/
  386. /*  End of private fata and functions.  */
  387. /****************************************/
  388.  
  389.  
  390. int init_cg(void)
  391. /*  Does necessary initializations for the code-generator. Gets called  */
  392. /*  once at the beginning and should return 0 in case of problems.      */
  393. {
  394.     int i;
  395.     /*  Initialize some values which cannot be statically initialized   */
  396.     /*  because they are stored in the target's arithmetic.             */
  397.     maxalign=l2zl(4L);
  398.     char_bit=l2zl(8L);
  399.     for(i=0;i<16;i++){
  400.         sizetab[i]=l2zl(msizetab[i]);
  401.         align[i]=l2zl(malign[i]);
  402.     }
  403.     for(i=1;i<= 8;i++) regsize[i]=l2zl(4L);
  404.     for(i=9;i<=16;i++) regsize[i]=l2zl(8L);
  405.  
  406.     /*  Initialize the min/max-settings. Note that the types of the     */
  407.     /*  host system may be different from the target system and you may */
  408.     /*  only use the smallest maximum values ANSI guarantees if you     */
  409.     /*  want to be portable.                                            */
  410.     /*  That's the reason for the subtraction in t_min[INT]. Long could */
  411.     /*  be unable to represent -2147483648 on the host system.          */
  412.     t_min[UNSIGNED|CHAR]=t_min[UNSIGNED|SHORT]=t_min[UNSIGNED|INT]=t_min[UNSIGNED|LONG]=l2zl(0L);
  413.     t_min[CHAR]=l2zl(-128L);
  414.     t_min[SHORT]=l2zl(-32768L);
  415.     t_min[LONG]=zlsub(l2zl(-2147483647L),l2zl(1L));
  416.     t_min[INT]=t_min[LONG];
  417.     t_max[CHAR]=ul2zul(128UL);
  418.     t_max[SHORT]=ul2zul(32767UL);
  419.     t_max[LONG]=ul2zul(2147483647UL);
  420.     t_max[INT]=t_max[LONG];
  421.     t_max[UNSIGNED|CHAR]=ul2zul(255UL);
  422.     t_max[UNSIGNED|SHORT]=ul2zul(65535UL);
  423.     t_max[UNSIGNED|LONG]=ul2zul(4294967295UL);
  424.     t_max[UNSIGNED|INT]=t_max[UNSIGNED|LONG];
  425.     /*  Reserve a few registers for use by the code-generator.      */
  426.     /*  We only reserve the stack-pointer here.                     */
  427.     regsa[sp]=1;
  428.     /*  We need at least one free slot in the flaoting point stack  */
  429.     regsa[16]=1;regscratch[16]=0;
  430.     /*  Use l%d as labels and _%s as identifiers by default. If     */
  431.     /*  -elf is specified we use .l%d and %s instead.               */
  432.     if(g_flags[5]&USEDFLAG) labprefix="."; else idprefix="_";
  433.     return(1);
  434. }
  435.  
  436. int freturn(struct Typ *t)
  437. /*  Returns the register in which variables of type t are returned. */
  438. /*  If the value cannot be returned in a register returns 0.        */
  439. {
  440.     if((t->flags&15)==FLOAT||(t->flags&15)==DOUBLE) return 9;
  441.     if((t->flags&15)<=POINTER) return 1;
  442.     return 0;
  443. }
  444.  
  445. int regok(int r,int t,int mode)
  446. /*  Returns 0 if register r cannot store variables of   */
  447. /*  type t. If t==POINTER and mode!=0 then it returns   */
  448. /*  non-zero only if the register can store a pointer   */
  449. /*  and dereference a pointer to mode.                  */
  450. {
  451.     if(r==0) return(0);
  452.     t&=15;
  453.     if(r>8){
  454.         if(t==FLOAT||t==DOUBLE) return(1);
  455.             else                return(0);
  456.     }
  457.     if(t==CHAR&&(r==si||r==di||r==bp)) return(0);
  458.     if(t<=LONG) return(1);
  459.     if(t==POINTER) return(1);
  460.     return(0);
  461. }
  462.  
  463. int dangerous_IC(struct IC *p)
  464. /*  Returns zero if the IC p can be safely executed     */
  465. /*  without danger of exceptions or similar things.     */
  466. /*  vbcc may generate code in which non-dangerous ICs   */
  467. /*  are sometimes executed although control-flow may    */
  468. /*  never reach them (mainly when moving computations   */
  469. /*  out of loops).                                      */
  470. /*  Typical ICs that generate exceptions on some        */
  471. /*  machines are:                                       */
  472. /*      - accesses via pointers                         */
  473. /*      - division/modulo                               */
  474. /*      - overflow on signed integer/floats             */
  475. {
  476.     int c=p->code;
  477.     if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
  478.         return(0);
  479.     if((c==DIV||c==MOD)&&!(p->q2.flags&KONST))
  480.         return(1);
  481.     return(0);
  482. }
  483.  
  484. int must_convert(np p,int t)
  485. /*  Returns zero if code for converting np to type t    */
  486. /*  can be omitted.                                     */
  487. /*  In this generic 32bit RISC cpu pointers and 32bit   */
  488. /*  integers have the same representation and can use   */
  489. /*  the same registers.                                 */
  490. {
  491.     int o=p->ntyp->flags,op=o&15,tp=t&15;
  492.     if(tp==POINTER&&op==POINTER) return(0);
  493.     if((t&UNSIGNED)&&(o&UNSIGNED)&&zleqto(sizetab[tp],sizetab[op])) return(0);
  494.     if((tp==INT&&op==LONG)||(tp==LONG&&op==INT)) return(0);
  495.  
  496.     return(1);
  497. }
  498.  
  499. void gen_ds(FILE *f,zlong size,struct Typ *t)
  500. /*  This function has to create <size> bytes of storage */
  501. /*  initialized with zero.                              */
  502. {
  503.     if(newobj) fprintf(f,"%ld\n",zl2l(size));
  504.         else   fprintf(f,"\t.space\t%ld\n",zl2l(size));
  505.     newobj=0;
  506. }
  507.  
  508. void gen_align(FILE *f,zlong align)
  509. /*  This function has to make sure the next data is     */
  510. /*  aligned to multiples of <align> bytes.              */
  511. {
  512.     if(!zlleq(align,l2zl(1L))) fprintf(f,"\t.align\t2\n");
  513. }
  514.  
  515. void gen_var_head(FILE *f,struct Var *v)
  516. /*  This function has to create the head of a variable  */
  517. /*  definition, i.e. the label and information for      */
  518. /*  linkage etc.                                        */
  519. {
  520.     int constflag;
  521.     if(v->clist) constflag=is_const(v->vtyp);
  522.     if(v->storage_class==STATIC){
  523.         if((v->vtyp->flags&15)==FUNKT) return;
  524.         if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  525.         if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&§ion!=CODE){fprintf(f,codename);section=CODE;}
  526.         if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  527.         if(section!=BSS) fprintf(f,"\t.align\t2\n%sl%ld:\n",labprefix,zl2l(v->offset));
  528.             else fprintf(f,"\t.lcomm\t%sl%ld,",labprefix,zl2l(v->offset));
  529.         newobj=1;
  530.     }
  531.     if(v->storage_class==EXTERN){
  532.         fprintf(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
  533.         if(v->flags&(DEFINED|TENTATIVE)){
  534.             if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  535.             if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&§ion!=CODE){fprintf(f,codename);section=CODE;}
  536.             if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  537.             if(section!=BSS) fprintf(f,"\t.align\t2\n%s%s:\n",idprefix,v->identifier);
  538.                 else fprintf(f,"\t.comm\t%s%s,",idprefix,v->identifier);
  539.             newobj=1;
  540.         }
  541.     }
  542. }
  543.  
  544. void gen_dc(FILE *f,int t,struct const_list *p)
  545. /*  This function has to create static storage          */
  546. /*  initialized with const-list p.                      */
  547. {
  548.     fprintf(f,"\t.%s\t",dct[t&15]);
  549.     if(!p->tree){
  550.         if((t&15)==FLOAT||(t&15)==DOUBLE){
  551.         /*  auch wieder nicht sehr schoen und IEEE noetig   */
  552.             unsigned char *ip;
  553.             ip=(unsigned char *)&p->val.vdouble;
  554.             fprintf(f,"0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]);
  555.             if((t&15)==DOUBLE){
  556.                 fprintf(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
  557.             }
  558.         }else{
  559.             printval(f,&p->val,t&31,0);
  560.         }
  561.     }else{
  562.         int m=p->tree->o.flags;
  563.         p->tree->o.flags&=~VARADR;
  564.         probj2(f,&p->tree->o,t&31);
  565.         p->tree->o.flags=m;
  566.     }
  567.     fprintf(f,"\n");newobj=0;
  568. }
  569.  
  570. /*  The main code-generation routine.                   */
  571. /*  f is the stream the code should be written to.      */
  572. /*  p is a pointer to a doubly linked list of ICs       */
  573. /*  containing the function body to generate code for.  */
  574. /*  v is a pointer to the function.                     */
  575. /*  offset is the size of the stackframe the function   */
  576. /*  needs for local variables.                          */
  577. void gen_code(FILE *f,struct IC *p,struct Var *v,zlong offset)
  578. {
  579.     int c,t,lastcomp=0,reg;
  580.     if(DEBUG&1) printf("gen_code()\n");
  581.     for(c=1;c<=15;c++) regs[c]=regsa[c];
  582.     regs[16]=0;
  583.     loff=((zl2l(offset)+1)/2)*2;
  584.     function_top(f,v,loff);
  585.     stackoffset=notpopped=dontpop=0;
  586.     finit();
  587.     for(;p;pr(f,p),p=p->next){
  588.         c=p->code;t=p->typf;
  589.         if(c==NOP) continue;
  590.         if(c==SUBPFP) c=SUB;
  591.         if(c==SUBIFP) c=SUB;
  592.         if(c==ADDI2P) c=ADD;
  593.         if(c==ALLOCREG){
  594.             regs[p->q1.reg]=1;
  595.             continue;
  596.         }
  597.         if(c==FREEREG){
  598.             if(p->q1.reg>9){
  599.                 for(c=0;c<8;c++)
  600.                     if(fst[c]==p->q1.reg) fst[c]=-1;
  601.             }
  602.             regs[p->q1.reg]=0;
  603.             continue;
  604.         }
  605.         if(notpopped&&!dontpop){
  606.             int flag=0;
  607.             if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
  608.                 fprintf(f,"\taddl\t$%ld,%%esp\n",notpopped);
  609.                 stackoffset+=notpopped;notpopped=0;
  610.             }
  611.         }
  612.         if(c==LABEL) {forder(f);fprintf(f,"%sl%d:\n",labprefix,t);continue;}
  613.         if(c>=BEQ&&c<=BRA){
  614.             forder(f);
  615.             if(lastcomp&UNSIGNED) fprintf(f,"\tj%s\t%sl%d\n",ccu[c-BEQ],labprefix,t);
  616.                 else              fprintf(f,"\tj%s\t%sl%d\n",ccs[c-BEQ],labprefix,t);
  617.             continue;
  618.         }
  619.         if(c==MOVETOREG){
  620.             if(p->z.reg>8){
  621.                 for(c=0;c<8;c++){
  622.                     if(fst[c]==p->z.reg) fst[c]=0;
  623.                 }
  624.                 fload(f,&p->q1,DOUBLE);
  625.                 fst[0]=p->z.reg;
  626.                 continue;
  627.             }
  628.             move(f,&p->q1,0,0,p->z.reg,LONG);
  629.             continue;
  630.         }
  631.         if(c==MOVEFROMREG){
  632.             if(p->q1.reg>8){
  633.                 if(fst[0]!=p->q1.reg){
  634.                     for(c=0,reg=-1;c<8;c++){
  635.                         if(fst[c]==p->q1.reg) reg=c;
  636.                     }
  637.                     if(reg<0) ierror(0);
  638.                     fxch(f,reg);
  639.                 }
  640.                 fprintf(f,"\tfstpl\t");probj2(f,&p->z,DOUBLE);
  641.                 fprintf(f,"\n");fpop();
  642.                 continue;
  643.             }
  644.             move(f,0,p->q1.reg,&p->z,0,LONG);
  645.             continue;
  646.         }
  647.         if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ){
  648.             reg=get_reg(f,p);
  649.             move(f,&p->q1,0,0,reg,LONG);
  650.             p->q1.flags|=REG;p->q1.reg=reg;
  651.         }
  652.         if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ){
  653.             reg=get_reg(f,p);
  654.             move(f,&p->q2,0,0,reg,LONG);
  655.             p->q2.flags|=REG;p->q2.reg=reg;
  656.         }
  657.         if((p->z.flags&(DREFOBJ|REG))==DREFOBJ){
  658.             reg=get_reg(f,p);
  659.             move(f,&p->z,0,0,reg,LONG);
  660.             p->z.flags|=REG;p->z.reg=reg;
  661.         }
  662.         if(c>=CONVCHAR&&c<=CONVULONG){
  663.             int to;
  664.             if(c==CONVCHAR) to=CHAR;
  665.             if(c==CONVUCHAR) to=(UNSIGNED|CHAR);
  666.             if(c==CONVSHORT) to=SHORT;
  667.             if(c==CONVUSHORT) to=(UNSIGNED|SHORT);
  668.             if(c==CONVINT) to=INT;
  669.             if(c==CONVUINT) to=(UNSIGNED|INT);
  670.             if(c==CONVLONG) to=INT;
  671.             if(c==CONVULONG) to=(UNSIGNED|INT);
  672.             if(c==CONVFLOAT) to=FLOAT;
  673.             if(c==CONVDOUBLE) to=DOUBLE;
  674.             if(c==CONVPOINTER) to=(UNSIGNED|INT);
  675.             if((t&31)==LONG) t=INT;
  676.             if((t&31)==(UNSIGNED|LONG)||(t&31)==POINTER) t=(UNSIGNED|INT);
  677.             if((to&15)<=INT&&(t&15)<=INT){
  678.                 if(isreg(z)) reg=p->z.reg;
  679.                 else if(isreg(q1)) reg=p->q1.reg;
  680.                 else reg=get_reg(f,p);
  681.                 if((to&15)<=SHORT){
  682.                     fprintf(f,"\tmov%c%cl\t",(to&UNSIGNED)?'z':'s',x_t[to&15]);
  683.                     if(isreg(q1)){
  684.                         if((to&15)==SHORT){
  685.                             fprintf(f,"%%%s",regnames[p->q1.reg]+2);
  686.                         }else{
  687.                             fprintf(f,"%%%cl",regnames[p->q1.reg][2]);
  688.                         }
  689.                     }else probj2(f,&p->q1,to);
  690.                     fprintf(f,",%s\n",regnames[reg]);
  691.                 }else{
  692.                     move(f,&p->q1,0,0,reg,to);
  693.                 }
  694.                 move(f,0,reg,&p->z,0,t);
  695.                 continue;
  696.             }
  697.             if((t&15)==FLOAT||(t&15)==DOUBLE){
  698.                 if((to&15)==FLOAT||(to&15)==DOUBLE){
  699.                     if(isreg(q1)&&fst[0]==p->q1.reg){
  700.                         if(isreg(z)){
  701.                             if(p->z.reg==fst[0]) continue;
  702.                             for(reg=0,c=7;c>=0;c--){
  703.                                 if(fst[c]==p->z.reg){reg=c;break;}
  704.                                 if(fst[c]<0) reg=c;
  705.                             }
  706.                             fst[reg]=p->z.reg;
  707.                         }
  708.                         fprintf(f,"\tfst%c\t",x_t[t&15]);
  709.                         probj2(f,&p->z,t);fprintf(f,"\n");
  710.                         continue;
  711.                     }
  712.                     fload(f,&p->q1,to);
  713.                     fstore(f,&p->z,t);
  714.                     continue;
  715.                 }
  716.                 if((to&15)<=SHORT){
  717.                     if(isreg(q1)){
  718.                         reg=p->q1.reg;
  719.                         if(to&UNSIGNED){
  720.                             fprintf(f,"\tandl\t$%ld,%s\n",(to&15)==CHAR?255L:65535L,regnames[reg]);
  721.                         }else{
  722. /*                            fprintf(f,"\tc%ctl\t%s\n",x_t[to&15],regnames[reg]);*/
  723.                             if((to&15)==SHORT){
  724.                                 fprintf(f,"\tmovswl\t%%%s,%s\n",regnames[reg]+2,regnames[reg]);
  725.                             }else{
  726.                                 fprintf(f,"\tmovsbl\t%%%cl,%s\n",regnames[reg][2],regnames[reg]);
  727.                             }
  728.                         }
  729.                     }else{
  730.                         reg=get_reg(f,p);
  731.                         if(to&UNSIGNED){
  732.                             fprintf(f,"\tmovz%cl\t",x_t[to&15]);
  733.                         }else{
  734.                             fprintf(f,"\tmovs%cl\t",x_t[to&15]);
  735.                         }
  736.                         probj2(f,&p->q1,to);fprintf(f,",%s\n",regnames[reg]);
  737.                     }
  738.                     fprintf(f,"\tmovl\t%s,-4(%s)\n",regnames[reg],regnames[sp]);
  739.                     fprintf(f,"\tfildl\t-4(%s)\n",regnames[sp]);
  740.                 }else{
  741.                     if(to&UNSIGNED){
  742.                         fprintf(f,"\tpushl\t$0\n\tpushl\t");stackoffset-=4;
  743.                         probj2(f,&p->q1,to);
  744.                         fprintf(f,"\n\tfildq\t(%s)\n\taddl\t$8,%s\n",regnames[sp],regnames[sp]);
  745.                         stackoffset+=4;
  746.                     }else{
  747.                         if(isreg(q1)){
  748.                             fprintf(f,"\tmovl\t%s,-4(%s)\n\tfildl\t-4(%s)\n",regnames[p->q1.reg],regnames[sp],regnames[sp]);
  749.                         }else{
  750.                             fprintf(f,"\tfildl\t");probj2(f,&p->q1,t);
  751.                             fprintf(f,"\n");
  752.                         }
  753.                     }
  754.                 }
  755.                 fpush(f);
  756.                 fstore(f,&p->z,t);
  757.                 continue;
  758.             }
  759.             if((to&15)==FLOAT||(to&15)==DOUBLE){
  760.                 if(isreg(q1)&&fst[0]==p->q1.reg){
  761.                     if((t&15)==CHAR){
  762.                         if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p);
  763.                         fprintf(f,"\tfistl\t-4(%s)\n\tmovsbl\t-4(%s),%s\n",regnames[sp],regnames[sp],regnames[reg]);
  764.                         move(f,0,reg,&p->z,0,t);
  765.                     }else{
  766.                         if(isreg(z))
  767.                             fprintf(f,"\tfistl\t-4(%s)\n\tmov%c\t-4(%s),",regnames[sp],x_t[t&15],regnames[sp]);
  768.                         else
  769.                             fprintf(f,"\tfist%c\t",x_t[t&15]);
  770.                         probj2(f,&p->z,t);fprintf(f,"\n");
  771.                     }
  772.                 }else{
  773.                     fload(f,&p->q1,to);
  774.                     if((t&15)==CHAR){
  775.                         if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p);
  776.                         fprintf(f,"\tfistpl\t-4(%s)\n\tmovsbl\t-4(%s),%s\n",regnames[sp],regnames[sp],regnames[reg]);
  777.                         fpop(); move(f,0,reg,&p->z,0,t);
  778.                     }else{
  779.                         if(isreg(z))
  780.                             fprintf(f,"\tfistpl\t-4(%s)\n\tmov%c\t-4(%s),",regnames[sp],x_t[t&15],regnames[sp]);
  781.                         else
  782.                             fprintf(f,"\tfistp%c\t",x_t[t&15]);
  783.                         probj2(f,&p->z,t);fprintf(f,"\n");fpop();
  784.                     }
  785.                 }
  786.                 continue;
  787.             }
  788.             ierror(0);
  789.         }
  790.         if(c==MINUS||c==KOMPLEMENT){
  791.             char *s;
  792.             if((t&15)==FLOAT||(t&15)==DOUBLE){
  793.                 if(isreg(z)&&p->z.reg==9&&isreg(q1)&&p->q1.reg==9){
  794.                     fprintf(f,"\tfchs\n");
  795.                     continue;
  796.                 }
  797.                 fload(f,&p->q1,t);
  798.                 fprintf(f,"\tfchs\n");
  799.                 fprintf(f,"\tfstp%c\t",x_t[t&15]);
  800.                 probj2(f,&p->z,t);fprintf(f,"\n");
  801.                 fpop();
  802.                 continue;
  803.             }
  804.             if(c==MINUS) s="neg"; else s="not";
  805.             if(compare_objects(&p->q1,&p->q2)){
  806.                 fprintf(f,"\t%s%c\t",s,x_t[t&15]);
  807.                 probj2(f,&p->z,t);fprintf(f,"\n");
  808.                 continue;
  809.             }
  810.             if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p);
  811.             move(f,&p->q1,0,0,reg,t);
  812.             fprintf(f,"\t%s%c\t%s\n",s,x_t[t&15],regnames[reg]);
  813.             move(f,0,reg,&p->z,0,t);
  814.             continue;
  815.         }
  816.         if(c==SETRETURN){
  817.             if(p->z.reg){
  818.                 if(p->z.reg==9){
  819.                     if(!isreg(q1)||fst[0]!=p->q1.reg)
  820.                         fload(f,&p->q1,t);
  821.                 }else{
  822.                     move(f,&p->q1,0,0,p->z.reg,t);
  823.                 }
  824.             }
  825.             continue;
  826.         }
  827.         if(c==GETRETURN){
  828.             if(p->q1.reg){
  829.                 if(p->q1.reg==9){
  830.                     if(!isreg(z)||fst[0]!=p->z.reg)
  831.                         fstore(f,&p->z,t);
  832.                 }else{
  833.                     move(f,0,p->q1.reg,&p->z,0,t);
  834.                 }
  835.             }
  836.             continue;
  837.         }
  838.         if(c==CALL){
  839.             int reg;
  840.             if(p->q1.flags&DREFOBJ){
  841.                 if(!(p->q1.flags®)) ierror(0);
  842.                 fprintf(f,"\tcall\t*%s\n",regnames[p->q1.reg]);
  843.             }else{
  844.                 fprintf(f,"\tcall\t");probj2(f,&p->q1,t);
  845.                 fprintf(f,"\n");
  846.             }
  847.             if(!zleqto(l2zl(0L),p->q2.val.vlong)){
  848.                 notpopped+=zl2l(p->q2.val.vlong);
  849.                 dontpop-=zl2l(p->q2.val.vlong);
  850.                 if(!(g_flags[2]&USEDFLAG)&&stackoffset==-notpopped){
  851.                 /*  Entfernen der Parameter verzoegern  */
  852.                 }else{
  853.                     fprintf(f,"\taddl\t$%ld,%%esp\n",zl2l(p->q2.val.vlong));
  854.                     stackoffset+=zl2l(p->q2.val.vlong);
  855.                     notpopped-=zl2l(p->q2.val.vlong);
  856.                 }
  857.             }
  858.             continue;
  859.         }
  860.         if(c==ASSIGN||c==PUSH){
  861.             if(c==PUSH) dontpop+=zl2l(p->q2.val.vlong);
  862.             if((t&15)==FLOAT||(t&15)==DOUBLE){
  863.                 if(c==ASSIGN){
  864.                     prfst(f,"fassign");
  865.                     fload(f,&p->q1,t);
  866.                     fstore(f,&p->z,t);
  867.                     continue;
  868.                 }else if(isreg(q1)){
  869.                     prfst(f,"fpush");
  870.                     fprintf(f,"\tsubl\t$%ld,%s\n",zl2l(sizetab[t&15]),regnames[sp]);
  871.                     stackoffset-=zl2l(sizetab[t&15]);
  872.                     if(fst[0]==p->q1.reg){
  873.                         fprintf(f,"\tfst%c\t(%s)\n",x_t[t&15],regnames[sp]);
  874.                     }else{
  875.                         fload(f,&p->q1,t);
  876.                         fprintf(f,"\tfstp%c\t(%s)\n",x_t[t&15],regnames[sp]);
  877.                         fpop();
  878.                     }
  879.                     continue;
  880.                 }
  881.             }
  882.             if((t&15)>POINTER||!zleqto(p->q2.val.vlong,sizetab[t&15])||!zlleq(p->q2.val.vlong,l2zl(4L))){
  883.                 int mdi=di,msi=si,m=0;long l;
  884.                 l=zl2l(p->q2.val.vlong);
  885.                 if(regs[cx]){m|=1;if(!cxl)cxl=++label;fprintf(f,"\tmovl\t%s,%sl%d\n",regnames[cx],labprefix,cxl);}
  886.                 if(regs[msi]||!regused[msi]){m|=2;if(!sil)sil=++label;fprintf(f,"\tmovl\t%s,%sl%d\n",regnames[msi],labprefix,sil);}
  887.                 if(regs[mdi]||!regused[mdi]){m|=4;if(!dil)dil=++label;fprintf(f,"\tmovl\t%s,%sl%d\n",regnames[mdi],labprefix,dil);}
  888.                 if((p->z.flags®)&&p->z.reg==msi&&(p->q1.flags®)&&p->q1.reg==mdi){
  889.                     msi=di;mdi=si;
  890.                     m|=8;
  891.                 }
  892.                 if(!(p->z.flags®)||p->z.reg!=msi){
  893.                     fprintf(f,"\tleal\t");probj2(f,&p->q1,t);
  894.                     fprintf(f,",%s\n",regnames[msi]);
  895.                 }
  896.                 if(c==PUSH){
  897.                     fprintf(f,"\tsubl\t$%ld,%s\n\tmovl\t%s,%s\n",l,regnames[sp],regnames[sp],regnames[mdi]);
  898.                     stackoffset-=l;
  899.                 }else{
  900.                     fprintf(f,"\tleal\t");probj2(f,&p->z,t);
  901.                     fprintf(f,",%s\n",regnames[mdi]);
  902.                 }
  903.                 if((p->z.flags®)&&p->z.reg==msi){
  904.                     fprintf(f,"\tleal\t");probj2(f,&p->q1,t);
  905.                     fprintf(f,",%s\n",regnames[msi]);
  906.                 }
  907.                 if(m&8){
  908.                     msi=si;mdi=di;
  909.                     fprintf(f,"\txch\t%s,%s\n",regnames[msi],regnames[mdi]);
  910.                 }
  911.                 if((t&15)==ARRAY||(t&15)==CHAR||l<4){
  912.                     fprintf(f,"\tmovl\t$%ld,%s\n\trep\n\tmovsb\n",l,regnames[cx]);
  913.                 }else{
  914.                     if(l>=8)
  915.                         fprintf(f,"\tmovl\t$%ld,%s\n\trep\n",l/4,regnames[cx]);
  916.                     fprintf(f,"\tmovsl\n");
  917.                     if(l%2) fprintf(f,"\tmovsw\n");
  918.                     if(l%1) fprintf(f,"\tmovsb\n");
  919.                 }
  920.                 if(m&4) fprintf(f,"\tmovl\t%sl%d,%s\n",labprefix,dil,regnames[mdi]);
  921.                 if(m&2) fprintf(f,"\tmovl\t%sl%d,%s\n",labprefix,sil,regnames[msi]);
  922.                 if(m&1) fprintf(f,"\tmovl\t%sl%d,%s\n",labprefix,cxl,regnames[cx]);
  923.                 continue;
  924.             }
  925.             if(t==FLOAT) t=LONG;
  926.             if(c==PUSH){
  927.                 fprintf(f,"\tpush%c\t",x_t[t&15]);
  928.                 probj2(f,&p->q1,t);fprintf(f,"\n");
  929.                 stackoffset-=zl2l(p->q2.val.vlong);
  930.                 continue;
  931.             }
  932.             if(c==ASSIGN){
  933.                 if(p->q1.flags&KONST){
  934.                     move(f,&p->q1,0,&p->z,0,t);
  935.                     continue;
  936.                 }
  937.                 if(isreg(z)) reg=p->z.reg;
  938.                 else if(isreg(q1)) reg=p->q1.reg;
  939.                 else reg=get_reg(f,p);
  940.                 move(f,&p->q1,0,0,reg,t);
  941.                 move(f,0,reg,&p->z,0,t);
  942.                 continue;
  943.             }
  944.             ierror(0);
  945.         }
  946.         if(c==ADDRESS){
  947.             if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p);
  948.             fprintf(f,"\tleal\t");probj2(f,&p->q1,t);
  949.             fprintf(f,",%s\n",regnames[reg]);
  950.             move(f,0,reg,&p->z,0,POINTER);
  951.             continue;
  952.         }
  953.         if(c==TEST){
  954.             lastcomp=t;
  955.             if((t&15)==FLOAT||(t&15)==DOUBLE){
  956.                 if(isreg(q1)&&fst[0]==p->q1.reg){
  957.                     fprintf(f,"\tftst\n");lastcomp|=UNSIGNED;
  958.                     continue;
  959.                 }else{
  960.                     p->code=c=COMPARE;
  961.                     p->q2.flags=KONST;
  962.                     p->q2.val.vdouble=d2zd(0.0);
  963.                     if((t&15)==FLOAT) p->q2.val.vfloat=zd2zf(p->q2.val.vdouble);
  964.                     /*  fall through to COMPARE */
  965.                 }
  966.             }else{
  967.                 fprintf(f,"\tcmp%c\t$0,",x_t[t&15]);
  968.                 probj2(f,&p->q1,t);fprintf(f,"\n");
  969.                 continue;
  970.             }
  971.         }
  972.         if(c==COMPARE){
  973.             lastcomp=t;
  974.             if(isreg(q2)||(p->q1.flags&KONST)){
  975.                 struct IC *b=p->next;
  976.                 struct obj o;
  977.                 o=p->q1;p->q1=p->q2;p->q2=o;
  978.                 while(b&&b->code==FREEREG) b=b->next;
  979.                 if(!b) ierror(0);
  980.                 if(b->code==BLT) b->code=BGT;
  981.                 else if(b->code==BLE) b->code=BGE;
  982.                 else if(b->code==BGT) b->code=BLT;
  983.                 else if(b->code==BGE) b->code=BLE;
  984.             }
  985.             if((t&15)==FLOAT||(t&15)==DOUBLE){
  986.                 prfst(f,"fcomp");
  987.                 if(isreg(q1)&&p->q1.reg==fst[0]){
  988.                     fprintf(f,"\tfcom%c\t",x_t[t&15]);
  989.                     probj2(f,&p->q2,t);fprintf(f,"\n");
  990.                 }else{
  991.                     fload(f,&p->q1,t);
  992.                     fprintf(f,"\tfcomp%c\t",x_t[t&15]);
  993.                     probj2(f,&p->q2,t);fprintf(f,"\n");
  994.                     fpop();
  995.                 }
  996.                 fprintf(f,"\tfstsw\n\tsahf\n");
  997.                 lastcomp|=UNSIGNED;
  998.                 continue;
  999.             }
  1000.             if(!isreg(q1)){
  1001.                 if(!isreg(q2)){
  1002.                     reg=get_reg(f,p);
  1003.                     move(f,&p->q1,0,0,reg,t);
  1004.                     p->q1.flags=REG;
  1005.                     p->q1.reg=reg;
  1006.                 }
  1007.             }
  1008.             fprintf(f,"\tcmp%c\t",x_t[t&15]);
  1009.             probj2(f,&p->q2,t);fprintf(f,",");
  1010.             probj2(f,&p->q1,t);fprintf(f,"\n");
  1011.             continue;
  1012.         }
  1013.         if((t&15)==FLOAT||(t&15)==DOUBLE){
  1014.             char s[2];
  1015.             prfst(f,"fmath");
  1016.             if(isreg(q2)) s[0]=0; else {s[0]=x_t[t&15];s[1]=0;}
  1017.             if(isreg(z)&&isreg(q1)&&p->q1.reg==fst[0]&&p->z.reg==fst[0]){
  1018.                 fprintf(f,"\t%s%s\t",farithmetics[c-LSHIFT],s);
  1019.                 probj2(f,&p->q2,t); fprintf(f,"\n");continue;
  1020.             }
  1021.             fload(f,&p->q1,t);
  1022.             fprintf(f,"\t%s%s\t",farithmetics[c-LSHIFT],s);
  1023.             probj2(f,&p->q2,t); fprintf(f,"\n");
  1024.             fstore(f,&p->z,t); continue;
  1025.         }
  1026.         if((c==MULT||c==DIV||(c==MOD&&(p->typf&UNSIGNED)))&&(p->q2.flags&KONST)){
  1027.             long ln;
  1028.             eval_const(&p->q2.val,t);
  1029.             if(zlleq(l2zl(0L),vlong)&&zulleq(ul2zul(0UL),vulong)){
  1030.                 if(ln=pof2(vulong)){
  1031.                     if(c==MOD){
  1032.                         vlong=zlsub(vlong,l2zl(1L));
  1033.                         p->code=AND;
  1034.                     }else{
  1035.                         vlong=l2zl(ln-1);
  1036.                         if(c==DIV) p->code=RSHIFT; else p->code=LSHIFT;
  1037.                     }
  1038.                     c=p->code;
  1039.                     if((t&31)==CHAR) p->q2.val.vchar=zl2zc(vlong);
  1040.                     if((t&31)==SHORT) p->q2.val.vshort=zl2zs(vlong);
  1041.                     if((t&31)==INT) p->q2.val.vint=zl2zi(vlong);
  1042.                     if((t&31)==LONG) p->q2.val.vlong=vlong;
  1043.                     vulong=zl2zul(vlong);
  1044.                     if((t&31)==(UNSIGNED|CHAR)) p->q2.val.vuchar=zul2zuc(vulong);
  1045.                     if((t&31)==(UNSIGNED|SHORT)) p->q2.val.vushort=zul2zus(vulong);
  1046.                     if((t&31)==(UNSIGNED|INT))  p->q2.val.vuint=zul2zui(vulong);
  1047.                     if((t&31)==(UNSIGNED|LONG)) p->q2.val.vulong=vulong;
  1048.                 }
  1049.             }
  1050.         }
  1051.         if(c==MOD||c==DIV){
  1052.             int m=0;
  1053.             if(regs[ax]&&(!isreg(z)||p->z.reg!=ax)){
  1054.                 fprintf(f,"\tpushl\t%s\n",regnames[ax]);
  1055.                 stackoffset-=4;m|=1;
  1056.             }
  1057.             if(regs[dx]&&(!isreg(z)||p->z.reg!=dx)){
  1058.                 fprintf(f,"\tpushl\t%s\n",regnames[dx]);
  1059.                 stackoffset-=4;m|=2;
  1060.             }
  1061.             move(f,&p->q1,0,0,ax,t);
  1062.             if(p->q2.flags&KONST){
  1063.                 fprintf(f,"\tpush%c\t",x_t[t&15]);probj2(f,&p->q2,t);
  1064.                 fprintf(f,"\n");m|=4;stackoffset-=4;
  1065.             }
  1066.             if(t&UNSIGNED) fprintf(f,"\txorl\t%s,%s\n\tdivl\t",regnames[dx],regnames[dx]);
  1067.                 else       fprintf(f,"\tcltd\n\tidivl\t");
  1068.             if((m&4)||(isreg(q2)&&p->q2.reg==dx)){
  1069.                 fprintf(f,"(%s)",regnames[sp]);
  1070.             }else{
  1071.                 probj2(f,&p->q2,t);
  1072.             }
  1073.             fprintf(f,"\n");
  1074.             if(c==DIV) move(f,0,ax,&p->z,0,t);
  1075.                 else   move(f,0,dx,&p->z,0,t);
  1076.             if(m&4){ fprintf(f,"\taddl\t$%ld,%s\n",zl2l(sizetab[t&15]),regnames[sp]);stackoffset+=4;}
  1077.             if(m&2){ fprintf(f,"\tpopl\t%s\n",regnames[dx]);stackoffset+=4;}
  1078.             if(m&1){ fprintf(f,"\tpopl\t%s\n",regnames[ax]);stackoffset+=4;}
  1079.             continue;
  1080.         }
  1081.         if(!(p->q2.flags&KONST)&&(c==LSHIFT||c==RSHIFT)){
  1082.             char *s=arithmetics[c-LSHIFT];
  1083.             int fl=0;
  1084.             if(c==RSHIFT&&(t&UNSIGNED)) s="shr";
  1085.             if(((p->q1.flags®)&&p->q1.reg==cx)||((p->z.flags®)&&p->z.reg==cx)
  1086.                ||(!compare_objects(&p->q1,&p->z)&&!isreg(q1))){
  1087.                 reg=get_reg(f,p);
  1088.                 move(f,&p->q1,0,0,reg,t);
  1089.                 move(f,&p->q2,0,0,cx,t);
  1090.                 fprintf(f,"\t%s%c\t%%cl,%s\n",s,x_t[t&15],regnames[reg]);
  1091.                 move(f,0,reg,&p->z,0,t);
  1092.                 continue;
  1093.             }else{
  1094.                 if(!isreg(q2)||p->q2.reg!=cx){
  1095.                     if(regs[cx]){fprintf(f,"\tpushl\t%s\n",regnames[cx]);fl=1;}
  1096.                     move(f,&p->q2,0,0,cx,t);
  1097.                 }
  1098.                 if(compare_objects(&p->q1,&p->z)){
  1099.                     fprintf(f,"\t%s%c\t%%cl,",s,x_t[t&15]);
  1100.                     probj2(f,&p->z,t);fprintf(f,"\n");
  1101.                 }else{
  1102.                     move(f,0,p->q1.reg,&p->z,0,t);
  1103.                     fprintf(f,"\t%s%c\t%%cl,",s,x_t[t&15]);
  1104.                     probj2(f,&p->z,t);fprintf(f,"\n");
  1105.                 }
  1106.                 if(fl) fprintf(f,"\tpopl\t%s\n",regnames[cx]);
  1107.                 continue;
  1108.             }
  1109.         }
  1110.         if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)){
  1111.             char *s;
  1112.             if(c>=OR&&c<=AND) s=logicals[c-OR];
  1113.                 else s=arithmetics[c-LSHIFT];
  1114.             if(c==RSHIFT&&(t&UNSIGNED)) s="shr";
  1115.             if(c!=MULT&&compare_objects(&p->q1,&p->z)){
  1116.                 if(isreg(z)||isreg(q1)||(p->q2.flags&KONST)){
  1117.                     if((p->q2.flags&KONST)&&(c==ADD||c==SUB)){
  1118.                         eval_const(&p->q2.val,t);
  1119.                         if(zleqto(vlong,l2zl(1L))&&zuleqto(vulong,ul2zul(1UL))&&zdeqto(vdouble,d2zd(1.0))){
  1120.                             if(c==ADD) s="inc"; else s="dec";
  1121.                             fprintf(f,"\t%s%c\t",s,x_t[t&15]);
  1122.                             probj2(f,&p->z,t);fprintf(f,"\n");
  1123.                             continue;
  1124.                         }
  1125.                     }
  1126.                     fprintf(f,"\t%s%c\t",s,x_t[t&15]);
  1127.                     probj2(f,&p->q2,t);fprintf(f,",");
  1128.                     probj2(f,&p->z,t);fprintf(f,"\n");
  1129.                     continue;
  1130.                 }else{
  1131.                     if(isreg(q2)) reg=p->q2.reg; else reg=get_reg(f,p);
  1132.                     move(f,&p->q2,0,0,reg,t);
  1133.                     fprintf(f,"\t%s%c\t%s",s,x_t[t&15],regnames[reg]);
  1134.                     fprintf(f,","); probj2(f,&p->z,t);fprintf(f,"\n");
  1135.                     continue;
  1136.                 }
  1137.             }
  1138.             if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p);
  1139.             move(f,&p->q1,0,0,reg,t);
  1140.             if((p->q2.flags&KONST)&&(c==ADD||c==SUB)){
  1141.                 eval_const(&p->q2.val,t);
  1142.                 if(zleqto(vlong,l2zl(1L))&&zuleqto(vulong,ul2zul(1UL))&&zdeqto(vdouble,d2zd(1.0))){
  1143.                     if(c==ADD) s="inc"; else s="dec";
  1144.                     fprintf(f,"\t%s%c\t%s\n",s,x_t[t&15],regnames[reg]);
  1145.                 }else{
  1146.                     fprintf(f,"\t%s%c\t",s,x_t[t&15]);
  1147.                     probj2(f,&p->q2,t);fprintf(f,",%s\n",regnames[reg]);
  1148.                 }
  1149.             }else{
  1150.                 fprintf(f,"\t%s%c\t",s,x_t[t&15]);
  1151.                 probj2(f,&p->q2,t);fprintf(f,",%s\n",regnames[reg]);
  1152.             }
  1153.             move(f,0,reg,&p->z,0,t);
  1154.             continue;
  1155.         }
  1156.         ierror(0);
  1157.     }
  1158.     if(notpopped){
  1159.         fprintf(f,"\taddl\t$%ld,%%esp\n",notpopped);
  1160.         stackoffset+=notpopped;notpopped=0;
  1161.     }
  1162.     function_bottom(f,v,loff);
  1163. }
  1164.  
  1165. int shortcut(int code,int typ)
  1166. {
  1167.     return(0);
  1168. }
  1169.  
  1170. void cleanup_cg(FILE *f)
  1171. {
  1172.     struct fpconstlist *p;
  1173.     unsigned char *ip;
  1174.     while(p=firstfpc){
  1175.         if(f){
  1176.             if(section!=CODE){fprintf(f,codename);section=CODE;}
  1177.             fprintf(f,"%sl%d:\n\t.long\t",labprefix,p->label);
  1178.             ip=(unsigned char *)&p->val.vdouble;
  1179.             fprintf(f,"0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]);
  1180.             if((p->typ&15)==DOUBLE){
  1181.                 fprintf(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
  1182.             }
  1183.             fprintf(f,"\n");
  1184.         }
  1185.         firstfpc=p->next;
  1186.         free(p);
  1187.     }
  1188.     if(f){
  1189.         if(section!=BSS){fprintf(f,bssname);section=BSS;}
  1190.         if(cxl) fprintf(f,"\t.lcomm\t%sl%d,4\n",labprefix,cxl);
  1191.         if(sil) fprintf(f,"\t.lcomm\t%sl%d,4\n",labprefix,sil);
  1192.         if(dil) fprintf(f,"\t.lcomm\t%sl%d,4\n",labprefix,dil);
  1193.     }
  1194. }
  1195.  
  1196.