changeset 94:1ad7045741a7 dbinop

float dbinop fix
author kono
date Wed, 12 Mar 2003 15:28:44 +0900
parents 8f5d61239b93
children 185d2cc6a3a9
files Changes Makefile mc-code-ia32.c mc-code.h mc-codegen.c mc-codegen.h mc-parse.c mc.h test/call.c test/float.c
diffstat 10 files changed, 577 insertions(+), 362 deletions(-) [+]
line wrap: on
line diff
--- a/Changes	Sun Mar 09 18:31:00 2003 +0900
+++ b/Changes	Wed Mar 12 15:28:44 2003 +0900
@@ -2066,3 +2066,51 @@
 でも、結局、引数は関数呼び出しの前にセーブするのね。だったら、
 そんなことしないで、セーブすれば良いのか。
 
+Mon Mar 10 11:42:40 JST 2003
+
+で、レジスタのセーブなんだけど、mc-codegen.c を変更しない
+とすれば、引数のリストを使って変更していくのが良い。
+関数呼び出しは基本的には並列代入になる。並列代入でき
+てもできなくても、セーブする必要はある。今の並列代入
+ルーチンのできは良くないので、「同じかどうか」だけ
+判断するのが良いのではないか?
+
+関数呼び出しの前に式用にレジスタに積まれた値はセーブした
+方が良い。セーブした後はlvarとしてアクセスすることになる。
+スタックでもいいけど。
+そうすると、stack 配列には、
+
+     レジスタ   レジスタ番号 (>0)
+     スタック   -1
+     lvar       lvar番号
+
+の三種類が入ることになる。それに合わせてtosop/assopを書き直
+す必要がある。emit_pop だけでいいかも。スタックを止めちまう
+のも手ではあるが、ia32の方で効率が悪い。やっぱり三種類サポー
+トするのが良いだろう。
+
+(けっこういろいろあるなぁ... どこから手を付けるか...) 
+
+Tue Mar 11 14:23:57 JST 2003
+
+save_stacks すると、レジスタはほとんど使われなくなって
+しまう。が、コードの見通しは良くなる。
+
+定数を右辺に持って行くとsave_stacksでsaveする量が減る。が以
+外にめんどくさいね。反射律が成り立たない演算子に関しては。tosop
+の定数版とか作ることになるので... あとスタックに積む順序が逆
+になってしまう。まぁ、もとの版では行われていたことだが... 
+CMPではrexpr で反転して論理を逆転させる方が簡単か。SUBでは、
+ADD + (-CONST) にする方が良いね。
+
+      je _xxx
+したあと、current register のregv[]が残ってしまう。これは、
+変だよね。gexpr_init で regv が残るのは、case 文の比較だけ。
+あとは全部0にして良い。(まぁ、害は無いんだけど)
+
+(case 文のjumpは、switch 文が終る時に処理すれば、index jump
+にすることができるね)
+
+Wed Mar 12 12:58:47 JST 2003
+
+比較で入れ換えるとの否定は若干違うよね。
--- a/Makefile	Sun Mar 09 18:31:00 2003 +0900
+++ b/Makefile	Wed Mar 12 15:28:44 2003 +0900
@@ -7,15 +7,20 @@
 PRINTF= # printf.c
 CONVERTER=conv/c.o conv/null.o
 # conv/c2cbc.o conv/cbc2c.o
-
+COMPLIB = mc-parse.o mc-codegen.o mc-tree.o
 # CODE=mc-code-ia32.o
 CODE=mc-code-powerpc.o
 
-all: mc 
+all: mc mc-ia32 mc-powerpc
+
+mc:  mc-powerpc
+	cp mc-powerpc mc
 
-mc : mc-parse.o mc-codegen.o $(CODE) mc-tree.o $(CONVERTER)
-	$(CC) -g mc-parse.o mc-codegen.o $(CODE) \
-		mc-tree.o $(CONVERTER) -o $@
+mc-powerpc : mc-code-powerpc.o $(COMPLIB) $(CONVERTER)
+	$(CC) -g mc-code-powerpc.o $(COMPLIB) $(CONVERTER) -o $@
+
+mc-ia32 : mc-code-ia32.o $(COMPLIB) $(CONVERTER)
+	$(CC) -g mc-code-ia32.o $(COMPLIB) $(CONVERTER) -o $@
 
 conv/conv.h: conv_func.tbl conv_func.pl
 	perl conv_func.pl
@@ -36,14 +41,14 @@
                 mc-code-powerpc.c
 
 clean :
-	-rm -f *.bak *.s *.o *.cc mc mc1 a.out *~ core* */*.o *.bak test/*.s test/*.cc test/*.o test/*.bak test/*~ conv/*.s conv/*.cc conv/*.o conv/*.bak conv/*~
+	-rm -f mc mc-ia32 mc-powerpc *.bak *.s *.o *.cc mc mc1 a.out *~ core* */*.o *.bak test/*.s test/*.cc test/*.o test/*.bak test/*~ conv/*.s conv/*.cc conv/*.o conv/*.bak conv/*~
 
 mc1 : b00.s b01.s mc-codegen.o mc-tree.o $(CONVERTER)
 	$(CC) -g -o $@ $(PRINTF) b00.s b01.s mc-codegen.o mc-tree.o $(CONVERTER)
-b00.s : mc-parse.c mc
-	./mc -s -ob00.s mc-parse.c
-b01.s : mc-code-ia32.c mc
-	./mc -s -ob01.s mc-code-ia32.c 
+b00.s : mc-parse.c $(MC)
+	./$(MC) -s -ob00.s mc-parse.c
+b01.s : mc-code-ia32.c $(MC)
+	./$(MC) -s -ob01.s mc-code-ia32.c 
 b10.s : mc-parse.c mc1
 	./mc1 -s -ob10.s mc-parse.c
 b11.s : mc-code-ia32.c $(PRINTF) mc1
--- a/mc-code-ia32.c	Sun Mar 09 18:31:00 2003 +0900
+++ b/mc-code-ia32.c	Wed Mar 12 15:28:44 2003 +0900
@@ -6,6 +6,8 @@
 #include "mc-codegen.h"
 #include "mc-code.h"
 
+#define SAVE_STACKS 1
+
 #define TEXT_EMIT_MODE 0
 #define DATA_EMIT_MODE 1
 #define RODATA_EMIT_MODE 2
@@ -80,6 +82,7 @@
 static char * fload(int d);
 static int code_d1(double d);
 static int code_d2(double d);
+static void code_save_stacks();
 
 void
 code_init(void)
@@ -130,6 +133,7 @@
 void
 gexpr_code_init(void){
     use_register(creg,REG_EAX,0);
+    regv[creg]=0;
     regv[dreg]=0;
 }
 
@@ -199,10 +203,6 @@
 }
 
 void
-set_register_var() {
-}
-
-void
 code_arg_register(int args)
 {
     NMTBL *n;
@@ -241,6 +241,7 @@
 	    printf(" %s",register_name(reg_stack[i],0));
     }
 #endif
+    printf(" f:%d",freg_sp);
     printf("\n");
 }
 
@@ -248,8 +249,10 @@
 gexpr_init(void)
 {
     while(reg_sp > 0) {
-	free_register(reg_stack[--reg_sp]);
+	if (reg_stack[--reg_sp]>=0)
+	    free_register(reg_stack[reg_sp]);
     }
+    freg_sp = 0;
     text_mode();
     gexpr_code_init();
     register_usage("gexpr_init");
@@ -263,6 +266,7 @@
     for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; regv[i]=0;rname[i]=i;}
     free_all_register();
     reg_sp = 0;
+    freg_sp = 0;
     text_mode();
 }
 
@@ -286,11 +290,6 @@
     return reg_stack[--reg_sp];
 }
 
-int
-stack_used(void) {
-    return reg_stack[--reg_sp]<0;
-}
-
 void
 emit_pop_free(int xreg)
 {
@@ -393,11 +392,16 @@
 	    use_data_reg(dreg,0);
 if (regv[dreg]) {
     printf("# emit_pop dreg conflict\n");
+    error(-1);
 }
 	printf("\tpopl %s\n",register_name(dreg,0));
-	xreg = dreg;
-	regv[xreg]=1;
-    } 
+	regv[dreg]=1;
+	return dreg;
+    } else if (xreg<= -REG_LVAR_OFFSET) {
+	code_rlvar(lvar(xreg+REG_LVAR_OFFSET),dreg);
+	regv[dreg]=1;
+	return dreg;
+    }
     return xreg;
 }
 
@@ -437,14 +441,14 @@
 
 
 void
-code_rlvar(int e2) {
-    printf("\tmovl %d(%%ebp),%s\n",e2,register_name(creg,0));
+code_rlvar(int e2,int reg) {
+    printf("\tmovl %d(%%ebp),%s\n",e2,register_name(reg,0));
 }
 
 
 void
-code_crlvar(int e2) {
-    printf("\tmovsbl %d(%%ebp),%s\n",e2,register_name(creg,0));
+code_crlvar(int e2,int reg) {
+    printf("\tmovsbl %d(%%ebp),%s\n",e2,register_name(reg,0));
 }
 
 
@@ -838,12 +842,15 @@
     return length/size_of_int;
 }
 
-void
+int
 function(int e1)
 {
     int e2,e3,e4,e5,nargs,t;
     NMTBL *n;
     int save,saved;
+#ifdef SAVE_STACKS
+    code_save_stacks();
+#endif
     if (free_register_count()<1) {
         for(save = 0;save==dreg||save==creg;save++);
 	printf("\tpushl %s\n",register_name(save,0));
@@ -910,8 +917,14 @@
         free_register(save);
     }
     regv[save]=0;
-    regv[creg]=1;
-    fregv[freg]=1; /* return type はどこ? fnptr にはあるけど... */
+    if (fnptr->ty==DOUBLE||fnptr->ty==FLOAT) {
+	fregv[freg]=1; regv[creg]=0;
+    } else if (fnptr->ty==VOID) {
+	fregv[freg]=0; regv[creg]=0;
+    } else {
+	fregv[freg]=0; regv[creg]=1;
+    }
+    return fnptr->ty;
 }
 
 void
@@ -937,21 +950,24 @@
     printf("\tjmp *%s\n",register_name(e2,0));
 }
 
-void
+int
 rindirect(int e1)   /* *(p +5 ) */
 {
     char *op;
-    int e2,e3,byte;
+    int e2,e3,byte,t;
     e3 = cadr(e2 = cadr(e1));
     g_expr(e2);
     switch (car(e1)) {
     case FRINDIRECT: case DRINDIRECT:
     printf("\t%s (%s)\n",fload(car(e1)==DRINDIRECT),register_name(creg,0));
+    t=DOUBLE;
     break;
     case CRINDIRECT: case RINDIRECT:
     op = ((byte = (car(e1) == CRINDIRECT)) ? "movsbl" : "movl");
     printf("\t%s (%s),%s\n",op,register_name(creg,0),register_name(creg,0));
+    t=byte?CHAR:INT;
     }
+    return t;
 }
 
 char *
@@ -1033,6 +1049,10 @@
         printf("\tpopl %s\n",register_name(dreg,0));
 	oreg = dreg;
 	regv[dreg]=1;
+    } else if (oreg<= -REG_LVAR_OFFSET) {
+	code_rlvar(lvar(oreg+REG_LVAR_OFFSET),dreg);
+	oreg = dreg;
+	regv[dreg]=1;
     }
     regv[oreg]=1; regs[oreg]=1;
     orn = register_name(oreg,0);
@@ -1087,6 +1107,7 @@
     }
     if (oreg!=dreg&&oreg>=0)
 	free_register(oreg);
+    else if (oreg==dreg) regv[dreg]=0;
 }
 
 static int edx_stack=0;
@@ -1613,7 +1634,7 @@
 }
 
 void dtosop(int op,int e1)
-{ 
+{
     switch(op) {
     case DADD: printf("\tfaddp %%st,%%st(1)\n"); break;
     case DSUB: printf("\tfsubp %%st,%%st(1)\n"); break;
@@ -1686,22 +1707,80 @@
     }
 }
 
-int dpop_register()
-{ 
-    return 1;
+void 
+code_dregister(int e2)
+{
+    error(-1);
+}
+
+void 
+code_cmp_dregister(int r)
+{
+    error(-1);
 }
 
-int emit_dpop(int e1)
+int dpop_register()
 { 
-    return 1;
+    if (freg_sp<0) { error(-1); return -1;}
+    printf("# fpop: %d\n",freg_sp-1);
+    return freg_stack[--freg_sp];
 }
 
+int
+emit_dpop(int type)
+{
+    int xreg;
+    if ((xreg=dpop_register())==-1) {
+    } else if (xreg<= -REG_LVAR_OFFSET) {
+	code_drlvar(lvar(REG_LVAR_OFFSET+xreg),1);
+	/* pushed order is reversed.   We don't need this for comutable 
+	    operator, but it is ok to do this.  */
+        printf("\tfxch\t%%st(1)\n");
+    } 
+    return xreg;
+}
+
+
 void emit_dpop_free(int e1)
 { 
 }
 
 void emit_dpush()
 { 
+    if (freg_sp>MAX_MAX) error(-1);
+    else
+	freg_stack[freg_sp++]=-1;
+    printf("# fpush:%d\n",freg_sp);
+}
+
+void
+code_save_stacks()
+{
+    /* temporal registers or stacks in fpu are saved in local variable */
+    int xreg,sp,screg;
+    sp=reg_sp;
+    while(sp-->0) {
+	if ((xreg=reg_stack[sp])>=0) {
+	    screg=creg;
+	    if(creg!=xreg) {
+		if (xreg!=dreg) free_register(xreg); 
+		creg = xreg;
+	    }
+	    code_assign_lvar(
+		lvar(reg_stack[sp]=new_lvar(size_of_int)),0); 
+	    reg_stack[sp]= reg_stack[sp]-REG_LVAR_OFFSET;
+	    regv[xreg]=0;
+	    creg=screg;
+	}
+    }
+    sp=freg_sp;
+    while(sp-->0) {
+	if ((xreg=freg_stack[sp])==-1) {
+	    code_dassign_lvar(
+		lvar(freg_stack[sp]=new_lvar(size_of_double)),1); 
+	    freg_stack[sp]= freg_stack[sp]-REG_LVAR_OFFSET;
+	}
+    }
 }
 
 /* end */
--- a/mc-code.h	Sun Mar 09 18:31:00 2003 +0900
+++ b/mc-code.h	Wed Mar 12 15:28:44 2003 +0900
@@ -10,6 +10,7 @@
 extern int MAX_REGISTER; 
 extern int MAX_REGISTGER_VAR;
 extern int MAX_FREGISTER;
+#define REG_LVAR_OFFSET 2
 
 extern char *register_name(int i,int byte);
 extern void gexpr_code_init(void);
@@ -25,8 +26,8 @@
 extern void code_crgvar(int e1);
 extern void code_lvar(int e2);
 extern void code_register(int e2);
-extern void code_rlvar(int e2);
-extern void code_crlvar(int e2);
+extern void code_rlvar(int e2,int reg);
+extern void code_crlvar(int e2,int reg);
 extern void code_fname(char *e2);
 extern void code_const(int e2);
 extern void code_neg();
@@ -53,12 +54,12 @@
 extern void code_cmp_register(int e2);
 extern void string(int e1);
 extern void emit_copy(int from,int  to,int length,int offset,int value,int det);
-extern void function(int e1);
+extern int function(int e1);
 extern void code_frame_pointer(int e3);
 extern void code_fix_frame_pointer(int disp_offset);
 extern void code_jmp(char *s);
 extern void code_indirect_jmp(int e2);
-extern void rindirect(int e1);
+extern int rindirect(int e1);
 extern void code_assign_gvar(int e2,int byte);
 extern void code_assign_lvar(int e2,int byte);
 extern void code_assign_register(int e2,int byte);
@@ -83,6 +84,8 @@
 
 extern int dpop_register();
 extern int emit_dpop(int);
+extern void code_dregister(int e2);
+extern void code_cmp_dregister(int);
 extern void code_cmp_drgvar(int);
 extern void code_cmp_drlvar(int);
 extern void code_dassign(int,int);
--- a/mc-codegen.c	Sun Mar 09 18:31:00 2003 +0900
+++ b/mc-codegen.c	Wed Mar 12 15:28:44 2003 +0900
@@ -52,21 +52,20 @@
 void sassign(int e1);
 void assign(int e1);
 void assop(int e1);
-void g_expr0(int e1);
+int g_expr0(int e1);
 
-void
+int
 gexpr(int e1,int use0)
 {
-    if (chk) return;
+    if (chk) return INT;
     gexpr_init();
     use = use0;
 #if 0
     if(lineno==2862) {
-        g_expr0(e1); /*break here*/
-        return;
+        return g_expr0(e1); /*break here*/
     } 
 #endif
-    g_expr0(e1);
+    return g_expr0(e1);
 }
 
 int
@@ -75,26 +74,30 @@
     return rname[creg]; /* for switch value */
 }
 
-void
+int
 g_expr_u(int e1)
 {
+    int t;
     int suse = use; use=0;
-    g_expr0(e1);
+    t=g_expr0(e1);
     use=suse;
+    return t;
 }
 
-void
+int
 g_expr(int e1)
 {
+    int t;
     int suse = use; use=1;
-    g_expr0(e1);
+    t=g_expr0(e1);
     use=suse;
+    return t;
 }
 
-void
+int
 g_expr0(int e1)
 {
-    int e2,e3;
+    int e2,e3,t;
     NMTBL *n;
 
     e2 = cadr(e1);
@@ -102,150 +105,154 @@
     case GVAR:   
 	code_gvar(e1);
 	regv[creg]=1;
-	return;
+	return ADDRESS;
     case RGVAR:
 	code_rgvar(e1);
 	regv[creg]=1;
-	return;
+	return INT;
     case CRGVAR:
 	code_crgvar(e1);
 	regv[creg]=1;
-	return;
+	return CHAR;
     case LVAR:
 	code_lvar(lvar(e2));
 	regv[creg]=1;
-	return;
+	return ADDRESS;
     case REGISTER:
 	/* this is of course redundant... */
 	/* we can use rname for this? */
 	/* or why not creg=e2? */
 	code_register(e2);
 	regv[creg]=1;
-	return;
+	return INT;
+    case DREGISTER:
+	/* this is of course redundant... */
+	/* we can use rname for this? */
+	/* or why not creg=e2? */
+	code_dregister(e2);
+	fregv[freg]=1;
+	return DOUBLE;
     case RLVAR:
-	code_rlvar(lvar(e2));
+	code_rlvar(lvar(e2),creg);
 	regv[creg]=1;
-	return;
+	return INT;
     case CRLVAR:
-	code_crlvar(lvar(e2));
+	code_crlvar(lvar(e2),creg);
 	regv[creg]=1;
-	return;
+	return CHAR;
     case FRLVAR:
 	code_drlvar(lvar(e2),0);
 	fregv[freg]=1;
-	return;
+	return FLOAT;
     case FRGVAR:
 	code_drgvar(e1,0);
 	fregv[freg]=1;
-	return;
+	return FLOAT;
     case DRLVAR:
 	code_drlvar(lvar(e2),1);
 	fregv[freg]=1;
-	return;
+	return DOUBLE;
     case DRGVAR:
 	code_drgvar(e1,1);
 	fregv[freg]=1;
-	return;
+	return DOUBLE;
     case FNAME:
 	code_fname(((NMTBL *)(e2))->nm);
 	regv[creg]=1;
-	return;
+	return ADDRESS;
     case CONST:  /* 代入する値が0でも特別な処理はしない */
 	code_const(e2);
 	regv[creg]=1;
-	return;
+	return INT;
     case DCONST:
 	code_dconst(e1);
 	fregv[freg]=1;
-	return;
+	return DOUBLE;
     case STRING:
 	string(e1);
 	regv[creg]=1;
-	return;
+	return ADDRESS;
     case FUNCTION:
-	function(e1);
+	t = function(e1);
 	regv[creg]=1;
-	return;
+	return t;
     case CODE:
 	jump(e2,caddr(e1));
-	return;
+	return VOID;
     case INDIRECT:
-	g_expr0(e2);
-	return;
+	return g_expr0(e2);
     case RINDIRECT:  case CRINDIRECT:
     case DRINDIRECT: case FRINDIRECT:
-	rindirect(e1);
-	return;
+	return rindirect(e1);
     case ADDRESS:
-	g_expr0(e2);
-	return;
+	return g_expr0(e2);
     case MINUS:  /* レジスタに対し、neglを実行すれば実現可能 */
 	g_expr0(e2); code_neg();
-	return;
+	return INT;
     case DMINUS: 
 	g_expr0(e2); code_dneg();
-	return;
+	return DOUBLE;
     case I2D: 
 	g_expr0(e2); code_i2d();
-	return;
+	return DOUBLE;
     case D2I: 
 	g_expr0(e2); code_d2i();
-	return;
+	return INT;
     case U2D: 
 	g_expr0(e2); code_u2d();
-	return;
+	return DOUBLE;
     case D2U: 
 	g_expr0(e2); code_d2u();
-	return;
+	return UNSIGNED;
     case BNOT:   /* ~ */
 	g_expr0(e2); code_not();
-	return;
+	return INT;
     case LNOT:   /* !  */
 	g_expr0(e2); code_lnot();
-	return;
+	return INT;
     case PREINC:
 	code_preinc(e1,e2);
-	return;
+	return INT;
     case POSTINC:
 	code_postinc(e1,e2);
-	return;
+	return INT;
     case DPREINC:
 	code_dpreinc(e1,e2,1);
-	return;
+	return DOUBLE;
     case DPOSTINC:
 	code_dpostinc(e1,e2,1);
-	return;
+	return DOUBLE;
     case FPREINC:
 	code_dpreinc(e1,e2,0);
-	return;
+	return FLOAT;
     case FPOSTINC:
 	code_dpostinc(e1,e2,0);
-	return;
+	return FLOAT;
     case CPOSTINC:
 	/*   char *p; *p++ */
 	code_cpostinc(e1,e2);
-	return;
+	return CHAR;
     case CPREINC:
 	code_cpreinc(e1,e2);
-	return;
+	return CHAR;
     case CPOSTDEC:
 	code_cpostdec(e1,e2);
-	return;
+	return CHAR;
     case CPREDEC:
 	code_cpredec(e1,e2);
-	return;
+	return CHAR;
     case MUL: case UMUL:
     case DIV: case UDIV:	   
     case MOD: case UMOD:
     case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT:
-    case ADD: case SUB: case BAND: case EOR: case BOR:
+    case ADD: case SUB: case BAND: case EOR: case BOR: case CMP:
 	machinop(e1);
-	return;
+	return INT;
     case DMUL: case DDIV:
     case DADD: case DSUB:
     case DCMP: case DCMPGE:
 	dmachinop(e1);
-	return;
+	return DOUBLE;
     case COND:
 	e2=fwdlabel();
 	b_expr(cadr(e1),0,e2,0);
@@ -256,61 +263,89 @@
 	jmp(e3=fwdlabel());
 	fwddef(e2);
 	code_set_fixed_creg(0);
-	g_expr0(cadddr(e1));
+	t = g_expr0(cadddr(e1));
 	code_set_fixed_creg(1);
 	fwddef(e3);
-	return;
+	return t;
     case SASS: 
 	sassign(e1);
-	return;
+	return RSTRUCT;
     case ASS: case CASS: 
 	assign(e1);
-	return;
+	return INT;
     case FASS: case DASS: case LASS: 
 	dassign(e1);
-	return;
+	return DOUBLE;
     case ASSOP: case CASSOP:
 	assop(e1);
-	return;
+	return INT;
     case DASSOP: case FASSOP:
 	dassop(e1);
-	return;
+	return DOUBLE;
     case RSTRUCT:
 	g_expr0(e2);
-	return;
+	return RSTRUCT;
     case COMMA:
 	g_expr_u(e2);
-	g_expr0(caddr(e1));
-	return;
+	return g_expr0(caddr(e1));
     case RETURN:
 	n = (NMTBL *)e2;
 	if (retcont==0)
 	    retcont=fwdlabel();
 	code_return(creg);
 	regv[creg]=1;
-	return;
+	return VOID;
     case ENVIRONMENT:
 	code_environment(creg);
 	regv[creg]=1;
-	return;
+	return ADDRESS;
     default:
-	code_bool(e1);
+	code_bool(e1); /* type? */
 	regv[creg]=1;
+	return INT;
     }
 }
 
+#define dual_ops(op) \
+    (op==GT|| op==UGT|| op==GE|| op==UGE|| op==LT|| \
+	op==ULT|| op==LE|| op==ULE||  \
+	op==DOP+GT|| op==DOP+GE|| op==DOP+LT|| op==DOP+LE || \
+         op==EQ|| op==NEQ|| op==DOP+EQ|| op==DOP+NEQ)
+
+int
+rop_dual(op)
+{
+    if (op==GT) return LT;
+    if (op==UGT) return ULT;
+    if (op==GE) return LE;
+    if (op==UGE) return ULE;
+    if (op==LT) return GT;
+    if (op==ULT) return UGT;
+    if (op==LE) return GE;
+    if (op==ULE) return UGE;
+    if (op==DOP+GT) return DOP+LT;
+    if (op==DOP+GE) return DOP+LE;
+    if (op==DOP+LT) return DOP+GT;
+    if (op==DOP+LE) return DOP+GE;
+    return op;
+}
+
 void
 bexpr(int e1, char cond, int l1)
 {
+    int op = car(e1);
     if (chk) return;
     gexpr_init();
-    b_expr(e1,cond,l1,0);
+    if (dual_ops(op) && (car(caddr(e1))==CONST||(car(caddr(e1))==DCONST)))
+	b_expr(list3(rop_dual(op),caddr(e1),cadr(e1)),cond,l1,0);
+    else
+	b_expr(e1,cond,l1,0);
 }
 
 void
 b_expr(int e1, char cond, int l1,int err)
 {
-    int e2,l2;
+    int e2,l2,t;
     e2=cadr(e1);
     switch(car(e1)) {
     case LNOT:
@@ -404,6 +439,10 @@
 	code_cmp_register(e2);
 	jcond(l1,cond);
 	return;
+    case DREGISTER:
+	code_cmp_dregister(e2);
+	jcond(l1,cond);
+	return;
     case CONST:
 	if((cond&&e2)||(!cond&&!e2)) jmp(l1);
 	return;
@@ -413,9 +452,12 @@
     default:
 	if(err) {
 	    error(-1); return; /* recursive g_expr/b_expr */
-	} /* type ? */
-	g_expr(e1);
-	code_cmp_register(creg);
+	}
+	t=g_expr(e1);
+	if(t==FLOAT||t==DOUBLE)
+	    code_cmp_dregister(freg);
+	else
+	    code_cmp_register(creg);
 	jcond(l1,cond);
 	return;
     }
@@ -484,8 +526,7 @@
 	g_expr_u(assign_expr0(e1,s,ty,ty));
 	*target = append4(*target,t,ty,e1);
     } else {
-	disp-=sz;
-	g_expr_u(assign_expr0((e1=list2(LVAR,disp)),s,ty,ty));
+	g_expr_u(assign_expr0((e1=list2(LVAR,new_lvar(sz))),s,ty,ty));
 	*target = append4(*target,t,ty,e1);
     }
 }
@@ -660,8 +701,7 @@
 	    arg_size-=sz;
 	}
 	if (!is_simple(car(s0))) {
-	    disp-=sz;
-	    g_expr_u(assign_expr0((e4=list2(LVAR,disp)),s0,ty,ty));
+	    g_expr_u(assign_expr0((e4=list2(LVAR,new_lvar(sz))),s0,ty,ty));
 	    cadddr(e2)=e4;
 	    s0=e4;
         } else if (is_same_type(t0,s0)) {
@@ -752,7 +792,7 @@
     g_expr(e3);
     emit_dpush();
     g_expr(e2);
-    dtosop(car(e1),(e2=dpop_register()));
+    dtosop(car(e1),(e2=emit_dpop(1)));
     emit_dpop_free(e2);
     fregv[freg]=1;
     return;
--- a/mc-codegen.h	Sun Mar 09 18:31:00 2003 +0900
+++ b/mc-codegen.h	Wed Mar 12 15:28:44 2003 +0900
@@ -47,11 +47,11 @@
 extern void emit_init(void);
 extern void enter(char *name);
 extern void enter1();
-extern void g_expr(int e1);
+extern int g_expr(int e1);
 extern void gen_comment(char *s);
 extern void gen_gdecl(char *n, int gpc);
 extern void gen_source(char *s);
-extern void gexpr(int e1,int use);
+extern int gexpr(int e1,int use);
 extern void gexpr_init(void);
 extern void jcond(int l, char cond);
 extern void jmp(int l);
--- a/mc-parse.c	Sun Mar 09 18:31:00 2003 +0900
+++ b/mc-parse.c	Wed Mar 12 15:28:44 2003 +0900
@@ -137,7 +137,7 @@
     if (!chk && ccout)
 	if ( (freopen(ccout,"w",stdout)) == NULL ) error(FILERR);
     init();
-    while(1) {	
+    while(1) {
 	for (nptr = &ntable[GSYMS],i=LSYMS; i--;) {
 	    (nptr++)->sc = 0;
 	}
@@ -157,17 +157,17 @@
 error(int n)
 {
     if(n == EOFERR) {
-	if(filep!=filestack) {	
+	if(filep!=filestack) {
 	    fclose(filep->fcb);
 	    lineno=filep->ln;
 	    --filep;
 	    return;
-	} else if(ac2!=ac) {	
+	} else if(ac2!=ac) {
 	    fclose(filep->fcb);
 	    newfile();
 	    return;
-	} else if(mode == TOP) {	
-	    if (chk) { 
+	} else if(mode == TOP) {
+	    if (chk) {
 		fprintf(stderr, "Total internal labels : %u.\n",labelno-1);
 		fprintf(stderr, "Total global variables: %u bytes.\n",gpc);
 	    }
@@ -224,13 +224,13 @@
 {
     char *p;
 
-    if (sym != s) {	
+    if (sym != s) {
 	p=(s==RPAR) ? "')'": (s==RBRA) ? "']'": (s==SM) ? "';'":
 	  (s==LPAR) ? "'('": (s==WHILE) ? "'while'":
 	  (s==COLON) ? "':'": "Identifier";
 	fprintf(stderr,"%d:%s expected.\n",lineno,p);
 	errmsg();
-    } else 
+    } else
 	getsym();
 }
 
@@ -362,19 +362,19 @@
     if (mode==GDECL) { typedefed=0;  }
 
     if(sym==STATIC) {
-	if(mode==LDECL) {	
+	if(mode==LDECL) {
 		getsym();
 		conv->static_();
 		mode=STADECL;
 		stmode=LDECL;
-	} else if(mode==GDECL) {	
+	} else if(mode==GDECL) {
 		getsym();
 		conv->static_();
 		stmode=STATIC;
-	} else 
+	} else
 	    error(DCERR);
     } else if(sym==REGISTER) {
-	if(mode!=LDECL)  
+	if(mode!=LDECL)
 	    error(DCERR);
 	stmode=REGISTER;
 	getsym();
@@ -384,15 +384,15 @@
 	conv->extern_();
 	stmode=EXTRN;
     } else if(sym==TYPEDEF) {
-	if(mode==GDECL) {	
+	if(mode==GDECL) {
 		getsym();
 		conv->typedef_();
 		mode=GTDECL;
-	} else if(mode==LDECL) {	
+	} else if(mode==LDECL) {
 		getsym();
 		conv->typedef_();
 		mode=LTDECL;
-	} else 
+	} else
 		error(DCERR);
     }
     if((t=typespec())==0) return;
@@ -417,22 +417,22 @@
     }
     conv->return_type_(type,n,sd);
     def(n);
-    while(sym==COMMA) {	
+    while(sym==COMMA) {
 	conv->comma_();
 	getsym();
 	type=t;
 	n=decl0();
 	reverse(t);
-	if(n == &null_nptr) error(DCERR); 
+	if(n == &null_nptr) error(DCERR);
 	/* if(args) error(DCERR); */
 	conv->return_type_(type,n,1);
 	def(n);
     }
     if(sym!=SM) error(DCERR);
     conv->sm_();
-    if(mode==GTDECL) 
+    if(mode==GTDECL)
 	mode=GDECL;
-    if(mode==STADECL||mode==LTDECL) 
+    if(mode==STADECL||mode==LTDECL)
 	mode=LDECL;
 }
 
@@ -470,7 +470,7 @@
     case LONG:
 	t=INT;
 	getsym();
-	if(sym==LONG) { 
+	if(sym==LONG) {
 	    getsym();
 	    t=LONGLONG;
 	}
@@ -478,12 +478,12 @@
 	break;
     default:
 	if(sym==IDENT) {
-	    if(nptr->sc==TYPE) {	
+	    if(nptr->sc==TYPE) {
 		t=nptr->ty;
 		typedefed=glist2((int)nptr,typedefed);
 		getsym();
 		break;
-	    } else if(nptr->sc==EMPTY && gnptr->sc==TYPE) {	
+	    } else if(nptr->sc==EMPTY && gnptr->sc==TYPE) {
 		getsym();
 		break;
 	    }
@@ -504,7 +504,7 @@
 decl0(void)
 {
     NMTBL *n;
-    if(sym==MUL) {	
+    if(sym==MUL) {
 	getsym();
 	n=decl0();
 	type=list2(POINTER,type);
@@ -520,11 +520,11 @@
     NMTBL *n;
     int i,t;
 
-    if(sym==LPAR) {	
+    if(sym==LPAR) {
 	getsym();
 	n=decl0();
 	checksym(RPAR);
-    } else if (sym == IDENT) {	
+    } else if (sym == IDENT) {
 	n=nptr;
 	getsym();
     } else {
@@ -533,7 +533,7 @@
     }
     while(1) {
 	if(sym==LBRA) {
-	    if(getsym()==RBRA) {	
+	    if(getsym()==RBRA) {
 		getsym();
 		if(mode==ADECL) {
 		    type=list2(POINTER,type);
@@ -542,16 +542,16 @@
 		} else {
 		    error(DCERR);
 		}
-	    } else {	
+	    } else {
 		t=type;
 		i=cexpr(expr(1));
 		checksym(RBRA);
 		type=list3(ARRAY,t,i);
 	    }
-	} else if(sym==LPAR) {	
+	} else if(sym==LPAR) {
 	    if(mode==GDECL) {
 		mode=ADECL;getsym();mode=GDECL; /* ??? */
-	    } else 
+	    } else
 		getsym();
 	    n->dsp=0;
 	    if (type==CODE) {
@@ -577,9 +577,9 @@
             /* in GDECL mode dsp contains real parameter, if not,
                it contains arg type list. Real parameter list is compatible
                with arg type list. See def/ADECL  */
-	    if (mode!=GDECL) 
+	    if (mode!=GDECL)
 		n->dsp=t;
-	} else 
+	} else
 	    return n;
     }
     /* NOT REACHED */
@@ -606,7 +606,7 @@
     mode=ADECL;
     args = 0;
     n->dsp=0;
-    for(;;) {	
+    for(;;) {
 	if(sym==IDENT && nptr->sc!=TYPE) {
 	    type=INT;  /* naked argument, old K&R C */
 	    def(nptr);
@@ -617,7 +617,7 @@
 		argtypes=list2(DOTS,argtypes);
 		getsym();
 		break;
-	    } 
+	    }
 	    if((t=typespec())==0) {
 		error(DCERR);
 		break;
@@ -629,15 +629,15 @@
 		arg=decl0();
 		args = sargs;
 		reverse(t);
-		if (arg != &null_nptr) { 
-		    if (smode==GDECL) 
+		if (arg != &null_nptr) {
+		    if (smode==GDECL)
 			def(arg);
-		} 
+		}
 		argtypes=list2(type,argtypes);
 	    }
 	    if(sym==RPAR) break;
-	} 
-	if (sym!=COMMA) error(DCERR); 
+	}
+	if (sym!=COMMA) error(DCERR);
 	getsym();
     }
     argtypes=reverse0(argtypes);
@@ -651,13 +651,13 @@
     return argtypes;
 }
 
-static void 
+static void
 reverse(int t1)
 {
     int t2,t3;
     t2=t1;
 
-    while(type!=t1) {	
+    while(type!=t1) {
 	t3=cadr(type);
 	rplacad(type,t2);
 	t2=type;
@@ -666,13 +666,13 @@
     type = t2;
 }
 
-int 
+int
 reverse0(int t1)
 {
     int t2,t3;
 
     t2=0;
-    while(t1) {	
+    while(t1) {
 	t3=cadr(t1);
 	rplacad(t1,t2);
 	t2=t1;
@@ -691,21 +691,27 @@
     if(t==FLOAT) return size_of_float;
     if(t==DOUBLE) return size_of_double;
     if(t==LONGLONG) return size_of_longlong;
-    if(car(t)==STRUCT||car(t)==UNION) {	
+    if(car(t)==STRUCT||car(t)==UNION) {
 	if(cadr(t)==-1) error(DCERR);
 	return(cadr(t));
     }
-    if(car(t)==ARRAY) 
+    if(car(t)==ARRAY)
 	return(size(cadr(t))*caddr(t));
-    else if(car(t)==CODE) 
+    else if(car(t)==CODE)
 	return size_of_int;
-    else if(car(t)==FUNCTION) 
+    else if(car(t)==FUNCTION)
 	return size_of_int;
-    else 
+    else
 	error(DCERR);
     return 0;
 }
 
+int
+new_lvar(int sz)
+{
+    return disp -= sz;
+}
+
 static NMTBL *
 def(NMTBL *n)
 {
@@ -717,13 +723,13 @@
 	n->nm = "_";
     }
     nsc=ndsp=0;
-    if(car(type)==FUNCTION) {	
+    if(type>0&&(car(type)==FUNCTION || car(type)==CODE)) {
 	if (n->sc==EXTRN || (mode==GDECL)) {
 	    fcheck(n);
 	    return n;
 	}
     }
-    if (n->sc!=EMPTY && 
+    if (n->sc!=EMPTY &&
 	    !(n->sc==GVAR&&n->dsp==EXTRN) &&
 	    !(n->sc==FUNCTION&&n->dsp==EXTRN) &&
 	(mode!=ADECL || n->sc!=LVAR || n->ty!=INT) &&
@@ -753,12 +759,12 @@
 	    }
 	    *cheapp++ = 0;
 	}
-	if(sym==ASS) {	
+	if(sym==ASS) {
 	    conv->op_(sym);
 	    decl_data(type,n,0);
 	    emit_data_closing(n);
 	    /* gpc is incremented by emit_data */
-	} else 
+	} else
 	    gpc +=sz;
 	return n;
     case GSDECL:
@@ -792,7 +798,7 @@
 	if(type==CHAR) {
 	    if (n->dsp==0) {
 		n->dsp = args;
-		if (endian) 
+		if (endian)
 		    n->dsp += size_of_int-1;
 	    }
 	    args += size_of_int;
@@ -818,11 +824,11 @@
                error(-1);
 	} else {
 	    nsc = LVAR;
-	    ndsp = (disp -= sz);
+	    ndsp = new_lvar(sz);
 	}
 	n->sc = nsc;
 	n->dsp = ndsp;
-	if(sym==ASS) {	
+	if(sym==ASS) {
 	    conv->op_(sym);
 	    decl_data(type,n,0);
 	}
@@ -914,8 +920,8 @@
 	    for(i=0;;i++) {
 		if (sym!=RC)
 		    offset=decl_data(t1,n,offset); /* array of some thing */
-		if (sym==COMMA) { 
-		    conv->comma_(); 
+		if (sym==COMMA) {
+		    conv->comma_();
 		    continue;
 		} else if (sym==RC) {
 		    conv->decl_data_end_();
@@ -942,7 +948,7 @@
 	    } else if (caddr(t)!=size(type)) {  /* size match?           */
 		error(TYERR);
 	    }
-	} else 
+	} else
 	    error(DCERR);
     } else if (t1==STRUCT) {
 	if (sym==LC) {
@@ -956,10 +962,10 @@
 		if ( t1 && sym==COMMA) { conv->comma_(); continue; }
 		if (!t1 && sym!=RC) error(DCERR);
 	    }
-	    conv->decl_data_end_(); conv->rc_(); 
+	    conv->decl_data_end_(); conv->rc_();
 	    getsym();
 	    return offset;
-	} else 
+	} else
 	    error(DCERR);
     } else {
 	mode = mode_save;
@@ -978,16 +984,16 @@
     smode=mode;
     if (mode==GDECL || mode==GSDECL || mode==GUDECL || mode==GTDECL)
 	mode=(s==STRUCT?GSDECL:GUDECL);
-    else 
+    else
 	mode=(s==STRUCT?LSDECL:LUDECL);
     sdisp=disp;
     disp=0;
     if (sdecl_f) conv->sdecl_(s);
-    if (getsym() == IDENT) {	
+    if (getsym() == IDENT) {
 	nptr0 = nptr;
 	gnptr0 = gnptr;
 	if (sdecl_f) conv->id_(sym,nptr);
-	if (getsym() == LC) {	
+	if (getsym() == LC) {
 	    if (sdecl_f) conv->lc_();
 	    if (nptr0->sc != EMPTY) error(DCERR);
 	    nptr0->sc = TAG;
@@ -1002,7 +1008,7 @@
 	    tags=reverse0(tags);
 	    heap[nptr0->ty+2]=tags;
 	    rplacad(type0 = nptr0->ty,disp);
-	} else {	
+	} else {
 	    /* struct tag name */
 	    if(nptr0->sc == EMPTY) nptr0=gnptr0;
 	    if(nptr0->sc == EMPTY) error(UDERR);
@@ -1012,7 +1018,7 @@
 	    conv->comment_(' ');
 	}
 	type0 = list4(s,disp,tags,(int)nptr0);
-    } else if(sym==LC) {	
+    } else if(sym==LC) {
 	if (sdecl_f) conv->lc_();
 	tags = 0;
 	while(getsym() != RC) {
@@ -1041,7 +1047,7 @@
     fnptr=n;
     disp = -args;
     mode=ADECL;
-    if (sym!=LC) { 
+    if (sym!=LC) {
 	stmode=REGISTER;
 	reg_var=0;
 	args=0; fnptr->dsp=0;
@@ -1065,7 +1071,7 @@
     stmode=0;
     mode=STAT;
     init_vars=0;
-    while (typeid(getsym()) || sym==STATIC || sym==EXTRN || sym==TYPEDEF) {	
+    while (typeid(getsym()) || sym==STATIC || sym==EXTRN || sym==TYPEDEF) {
 	mode=LDECL;
 	decl();
 	mode=STAT;
@@ -1098,7 +1104,7 @@
     reg_var=0;
     fcheck(n);
     mode=ADECL;
-    if (sym!=LC) { 
+    if (sym!=LC) {
 	args=0; fnptr->dsp=0;
 	while (sym!=LC) { /* argument declaration !ANSI */
 	    stmode=0;
@@ -1114,8 +1120,8 @@
     init_vars=0;
     /* local variable declaration */
     mode=STAT;
-    while (typeid(getsym()) || sym==STATIC || sym==EXTRN 
-		|| sym==REGISTER || sym==TYPEDEF) {	
+    while (typeid(getsym()) || sym==STATIC || sym==EXTRN
+		|| sym==REGISTER || sym==TYPEDEF) {
 	mode=LDECL;
 	stmode=0;
 	decl();
@@ -1140,7 +1146,7 @@
 /*
     If function has structure return value, it has extra
     argument for where to write the structure. It have to be
-    a first argument. We add it here and we have to fix all arguments' 
+    a first argument. We add it here and we have to fix all arguments'
     offset. If it is the last value, we don't have to fix, but
     gcc has a first argument convention.
  */
@@ -1185,10 +1191,12 @@
 void
 fcheck(NMTBL *n)
 {
-    if(!(mode==GDECL||mode==ADECL)||car(type)!=FUNCTION) error(DCERR);
+    if(!(mode==GDECL||mode==ADECL)||
+             (car(type)!=FUNCTION&&car(type)!=CODE)) error(DCERR);
     if(n->sc==FUNCTION) compatible(n->ty,cadr(type));
+    else if(n->sc==CODE) compatible(n->ty,cadr(type));
     else {
-	if(n->sc!=EMPTY) 
+	if(n->sc!=EMPTY)
 	    error(DCERR);
 	else {
 	    n->sc=FUNCTION;
@@ -1200,10 +1208,10 @@
 static void
 compatible(int t1, int t2)
 {
-    if(integral(t1)) {	
+    if(integral(t1)) {
 	    if(t1!=t2) error(TYERR);
     }
-    else if(car(t1)!=car(t2)) 
+    else if(car(t1)!=car(t2))
 	    error(TYERR);
     else if((car(t1)==STRUCT || car(t1)==UNION) && cadr(t1)!=cadr(t2))
 	    error(TYERR);
@@ -1238,9 +1246,9 @@
 {
     int slfree;
 
-    if(sym==SM) { 
+    if(sym==SM) {
 	conv->sm_();
-	getsym(); return; 
+	getsym(); return;
     }
     checkret();
     switch(sym) {
@@ -1289,10 +1297,10 @@
 	dogoto();
 	return;
     default:
-	if(sym==IDENT&&skipspc()==':') {	
+	if(sym==IDENT&&skipspc()==':') {
 	    dolabel();
 	    statement();
-	} else {	
+	} else {
 	    slfree=lfree;
 	    gexpr(expr(0),0);
 	    lfree=slfree;
@@ -1316,9 +1324,9 @@
     checksym(RPAR);
     statement();
     checkret();
-    if(sym==ELSE) {	
+    if(sym==ELSE) {
 	conv->if_else_();
-	if ((l2 = control)) 
+	if ((l2 = control))
 	    jmp(l2=fwdlabel());
 	fwddef(l1);
 	getsym();
@@ -1346,12 +1354,12 @@
     e=expr(0);
     checksym(RPAR);
     conv->while_body_();
-    if(sym==SM) {	
+    if(sym==SM) {
 	bexpr(e,1,clabel);
 	lfree=slfree;
 	conv->sm_();
 	getsym();
-    } else {	
+    } else {
 	bexpr(e,0,blabel);
 	lfree=slfree;
 	statement();
@@ -1406,7 +1414,7 @@
     getsym();
     checksym(LPAR);
     slfree=lfree;
-    if(sym!=SM) {	
+    if(sym!=SM) {
 	gexpr(expr(0),0);
 	checksym(SM);
 	conv->for1_();
@@ -1416,7 +1424,7 @@
     }
     lfree=slfree;
     l=backdef();
-    if(sym!=SM) {	
+    if(sym!=SM) {
 	bexpr(expr(0),0,blabel);
 	checksym(SM);
 	conv->for2_();
@@ -1425,13 +1433,13 @@
 	getsym();
     }
     lfree=slfree;
-    if(sym==RPAR) {	
+    if(sym==RPAR) {
 	clabel=l;
 	conv->for_body_();
 	getsym();
 	statement();
 	checkret();
-    } else {	
+    } else {
 	clabel=fwdlabel();
 	e=expr(0);
 	conv->for_body_();
@@ -1500,7 +1508,7 @@
 
     c=0;
     slfree=lfree;
-    while(sym==CASE) {	
+    while(sym==CASE) {
 	conv->case_begin_(c,0);
 	getsym();
 	c=list2(cexpr(expr(1)),c);
@@ -1508,12 +1516,12 @@
 	checksym(COLON);
     }
     l=fwdlabel();
-    if (control) {	
+    if (control) {
 	control=0;
 	jmp(l);
     }
     if (cslabel) fwddef(cslabel);
-    while(cadr(c)) {	
+    while(cadr(c)) {
 	cmpdimm(car(c),csvalue1);
 	jcond(l,0);
 	c=cadr(c);
@@ -1540,7 +1548,7 @@
 {
     int slfree,e,e1;
 
-    if(getsym()==SM) {	
+    if(getsym()==SM) {
 	conv->return_();
 	conv->return_end_();
 	getsym();
@@ -1609,7 +1617,7 @@
 	checksym(SM);
 	conv->goto_label_(nptr0);
 	return;
-    } 
+    }
     if (t==COMMA) {
 	env = caddr(e1);
 	e1  = cadr(e1);
@@ -1620,7 +1628,7 @@
     if (t==FUNCTION) {
 	conv->jump_(env);
 	e2 = cadr(e1);
-	if (car(e2) == FNAME) {     
+	if (car(e2) == FNAME) {
 	    nptr0=(NMTBL *)cadr(e2);
 	    nptr0->sc = CODE;
 	}
@@ -1637,9 +1645,9 @@
 static void
 dolabel(void)
 {
-    if(nptr->sc == FLABEL) 
+    if(nptr->sc == FLABEL)
 	fwddef(nptr->dsp);
-    else if(nptr->sc != EMPTY) 
+    else if(nptr->sc != EMPTY)
 	error(TYERR);
     nptr->sc = BLABEL;
     nptr->dsp = backdef();
@@ -1653,8 +1661,8 @@
 {
     if (car(e2)==CONST)  return dlist2(DCONST,(double)cadr(e2));
     if(type==FLOAT||type==DOUBLE) return e2;
-    if(type==UNSIGNED) return list2(U2D,e2);
-    if(integral(type)) return list2(I2D,e2);
+    if(type==UNSIGNED) return list2(U2D,rvalue_t(e2,type));
+    if(integral(type)) return list2(I2D,rvalue_t(e2,type));
     error(TYERR); return dlist2(DCONST,1.0);
 }
 
@@ -1663,7 +1671,7 @@
 {
     if (car(e2)==DCONST||car(e2)==FCONST)  return list2(CONST,(int)dcadr(e2));
     if(scalar(type)||car(type)==ARRAY) return e2;
-    if(type==FLOAT||type==DOUBLE) return list2(D2I,e2);
+    if(type==FLOAT||type==DOUBLE) return list2(D2I,rvalue_t(e2,type));
     error(TYERR); return list2(CONST,1);
 }
 
@@ -1671,7 +1679,7 @@
 unsigned_value(int e2,int type)
 {
     if(scalar(type)) return e2;
-    if(type==FLOAT||type==DOUBLE) return list2(D2U,e2);
+    if(type==FLOAT||type==DOUBLE) return list2(D2U,rvalue_t(e2,type));
     error(TYERR); return e2;
 }
 
@@ -1774,7 +1782,7 @@
 	if((t==UNSIGNED||type==UNSIGNED)&&
 	    (op==MUL||op==DIV||op==MOD||op==RSHIFT||op==LSHIFT))
 	    op=op+US;
-	if(t==CHAR) {	
+	if(t==CHAR) {
 	    type= INT;
 	    return(list4(CASSOP,e1,e2,op));
 	}
@@ -1796,7 +1804,7 @@
     int e1,e2,e3,t;
 
     e1=expr3();
-    if(sym==COND) {	
+    if(sym==COND) {
 	conv->cond_();
 	e1=rvalue(e1);
 	getsym();
@@ -1810,10 +1818,10 @@
 	if(car(e1)==CONST) {
 	    if(cadr(e1)) {
 		type=t;return e2;
-	    } else 
+	    } else
 		return e3;
 	}
-	if(type==INT||(t!=INT&&type==UNSIGNED)) 
+	if(type==INT||(t!=INT&&type==UNSIGNED))
 	    type=t;
 	return(list4(COND,e1,e2,e3));
     }
@@ -1826,7 +1834,7 @@
     int e;
 
     e=expr4();
-    while(sym==LOR) {	
+    while(sym==LOR) {
 	    conv->op_(sym);
 	    e=rvalue(e);
 	    getsym();
@@ -1842,7 +1850,7 @@
     int e;
 
     e=expr5();
-    while(sym==LAND) {	
+    while(sym==LAND) {
 	conv->op_(sym);
 	e=rvalue(e);
 	getsym();
@@ -1858,7 +1866,7 @@
     int e1,e2,t;
 
     e1=expr6();
-    while(sym==BOR) {	
+    while(sym==BOR) {
 	conv->op_(sym);
 	e1=rvalue(e1);
 	t=type;
@@ -1875,7 +1883,7 @@
     int e1,e2,t;
 
     e1=expr7();
-    while(sym==EOR) {	
+    while(sym==EOR) {
 	conv->op_(sym);
 	e1=rvalue(e1);
 	t=type;
@@ -1892,7 +1900,7 @@
     int e1,e2,t;
 
     e1=expr8();
-    while(sym==BAND) {	
+    while(sym==BAND) {
 	conv->op_(sym);
 	e1=rvalue(e1);
 	t=type;
@@ -1909,7 +1917,7 @@
     int e1,e2,op,t;
 
     e1=expr9();
-    while((op=sym)==EQ||op==NEQ) {	
+    while((op=sym)==EQ||op==NEQ) {
 	conv->op_(sym);
 	e1=rvalue(e1);
 	t=type;
@@ -1927,19 +1935,19 @@
     int e1,e2,t,op;
 
     e1=expr10();
-    while((op=sym)==GT||op==GE||op==LT||op==LE) {	
+    while((op=sym)==GT||op==GE||op==LT||op==LE) {
 	conv->op_(sym);
 	e1=rvalue(e1);
 	t=type;
 	getsym();
 	e2=rvalue(expr10());
-	if(t==INT&&type==INT) 
+	if(t==INT&&type==INT)
 	    e1=binop(op,e1,e2,t,type);
 	else if(t==DOUBLE||type==DOUBLE||
-	          t==FLOAT||type==FLOAT) 
+	          t==FLOAT||type==FLOAT)
 	    /* binop will handle op+DOP */
 	    e1=binop(op,e1,e2,t,type);
-	else 
+	else
 	    e1=binop(op+US,e1,e2,t,type);
 	type= INT;
     }
@@ -1952,7 +1960,7 @@
     int e1,e2,t,op;
 
     e1=expr11();
-    while((op=sym)==RSHIFT||op==LSHIFT) {	
+    while((op=sym)==RSHIFT||op==LSHIFT) {
 	conv->op_(sym);
 	e1=rvalue(e1);
 	t=type;
@@ -1969,7 +1977,7 @@
     int e1,e2,t,op;
 
     e1=expr12();
-    while((op=sym)==ADD||op==SUB) {	
+    while((op=sym)==ADD||op==SUB) {
 	conv->op_(sym);
 	e1=rvalue(e1);
 	t=type;
@@ -1986,7 +1994,7 @@
     int e1,e2,t,op;
 
     e1=expr13();
-    while((op=sym)==MUL||op==DIV||op==MOD) {	
+    while((op=sym)==MUL||op==DIV||op==MOD) {
 	conv->op_(sym);
 	e1=rvalue(e1);
 	t=type;
@@ -2007,7 +2015,7 @@
 	conv->prefix_(sym);
 	getsym();
 	lcheck(e=expr13());
-	if(type==CHAR) {	
+	if(type==CHAR) {
 	    type= INT;
 	    return(list2(op==INC?CPREINC:CPREDEC,e));
 	}
@@ -2017,7 +2025,7 @@
 	    return(list3(FPREINC,e,op==INC?1:-1));
 	if(type==DOUBLE)
 	    return(list3(DPREINC,e,op==INC?1:-1));
-	if(car(type)!=POINTER) 
+	if(car(type)!=POINTER)
 	    error(TYERR);
 	return(list3(PREINC,e,
 	    op==INC?size(cadr(type)):-size(cadr(type)) ));
@@ -2047,59 +2055,59 @@
 	conv->prefix_(sym);
 	getsym();
 	e=rvalue(expr13());
-	if(type==FLOAT||type==DOUBLE) 
+	if(type==FLOAT||type==DOUBLE)
 	    return list2(DMINUS,e);
-	if(!integral(type)) 
+	if(!integral(type))
 	    error(TYERR);
 	return(car(e)==CONST?list2(CONST,-cadr(e)):list2(MINUS,e));
     case BNOT:
 	conv->prefix_(sym);
 	getsym();
 	e=rvalue(expr13());
-	if(!integral(type)) 
+	if(!integral(type))
 	    error(TYERR);
 	return(car(e)==CONST?list2(CONST,~cadr(e)):list2(BNOT,e));
     case LNOT:
 	conv->prefix_(sym);
 	getsym();
 	e=rvalue(expr13());
-	if(type==FLOAT||type==DOUBLE) 
+	if(type==FLOAT||type==DOUBLE)
 	    return(car(e)==DCONST?list2(CONST,!dcadr(e)):
 		list3(DOP+NEQ,list2(CONST,0),e));
-	if(!scalar(type)) 
+	if(!scalar(type))
 	    error(TYERR);
 	return(car(e)==CONST?list2(CONST,!cadr(e)):list2(LNOT,e));
     case SIZEOF:
 	conv->prefix_(sym);
 	if(getsym()==LPAR) {
-	    if(typeid(getsym())) {	
+	    if(typeid(getsym())) {
 		e=list2(CONST,size(typename()));
 		type=INT;
 		checksym(RPAR);
 		return e;
-	    } else {	
+	    } else {
 		e=expr0();
 		checksym(RPAR);
 		expr16(e);
-		if(sym==INC||sym==DEC) {	
+		if(sym==INC||sym==DEC) {
 		    getsym();
 		    if(type==CHAR) type=INT;
 		    else if(!scalar(type)&&type!=FLOAT&&type!=DOUBLE)
 			error(TYERR);
 		}
 	    }
-	} else 
+	} else
 	    expr13();
 	e=list2(CONST,size(type));
 	type=INT;
 	return e;
     }
     e=expr14();
-    if((op=sym)==INC||op==DEC) {	
+    if((op=sym)==INC||op==DEC) {
 	conv->postfix_(sym);
 	lcheck(e);
 	getsym();
-	if(type==CHAR) {	
+	if(type==CHAR) {
 	    type= INT;
 	    return(list2(op==INC?CPOSTINC:CPOSTDEC,e));
 	}
@@ -2109,7 +2117,7 @@
 	    return(list3(FPOSTINC,e,op==INC?1:-1));
 	if(type==DOUBLE)
 	    return(list3(DPOSTINC,e,op==INC?1:-1));
-	if(car(type)!=POINTER) 
+	if(car(type)!=POINTER)
 	    error(TYERR);
 	return (list3(POSTINC,e,
 	    op == INC ? size(cadr(type)): -size(cadr(type)) ));
@@ -2148,7 +2156,7 @@
 	    getsym();
 	    break;
 	case EMPTY:
-	    if(getsym()==LPAR) {	
+	    if(getsym()==LPAR) {
 		nptr->sc = FUNCTION;
 		nptr->ty= INT;
 		type= list3(FUNCTION,INT,0);
@@ -2181,7 +2189,7 @@
 	getsym();
 	break;
     case RETURN:
-	conv-> return_f_(); 
+	conv-> return_f_();
 	if (fnptr->sc != FUNCTION) {
 	    error(STERR);
 	}
@@ -2201,14 +2209,14 @@
 	checksym(RPAR);
 	break;
     case ENVIRONMENT:
-	conv-> environment_();      
+	conv-> environment_();
 	type=list2(POINTER,VOID);
 	e1=list2(ENVIRONMENT,0);
 	getsym();
 	break;
     case LPAR:
 	conv->lpar_();
-	if(typeid(getsym())) {	
+	if(typeid(getsym())) {
 	    t=typename();
 	    conv->return_type_(t,0,0);
 	    conv->rpar_();
@@ -2238,7 +2246,7 @@
     int e2,t;
 
     while(1) {
-	if(sym==LBRA) {	
+	if(sym==LBRA) {
 	    conv->lbra_(sym);
 	    e1=rvalue(e1);
 	    t=type;
@@ -2263,7 +2271,7 @@
 rvalue(int e)
 {
     int t;
-    if(type==CHAR) {	
+    if(type==CHAR) {
 	type= INT;
 	switch(car(e)) {
 	case GVAR:
@@ -2275,7 +2283,7 @@
 	default:return(e);
 	}
     }
-    if(type==FLOAT) {	
+    if(type==FLOAT) {
 	switch(car(e)) {
 	case GVAR:
 	    return(list3(FRGVAR,cadr(e),caddr(e)));
@@ -2286,7 +2294,7 @@
 	default:return(e);
 	}
     }
-    if(type==DOUBLE) {	
+    if(type==DOUBLE) {
 	switch(car(e)) {
 	case GVAR:
 	    return(list3(DRGVAR,cadr(e),caddr(e)));
@@ -2297,7 +2305,7 @@
 	default:return(e);
 	}
     }
-    if(type==LONGLONG) {	
+    if(type==LONGLONG) {
 	switch(car(e)) {
 	case GVAR:
 	    return(list3(LRGVAR,cadr(e),caddr(e)));
@@ -2311,11 +2319,11 @@
     if(!integral(type)&&type!=VOID) {
 	if(type==CODE) {
 	    return e;
-	} if((t=car(type))==ARRAY) {	
+	} if((t=car(type))==ARRAY) {
 	    type=list2(POINTER,cadr(type));
 	    if(car(e)==INDIRECT) return cadr(e);
 	    return list2(ADDRESS,e);
-	} else if(t==STRUCT || t==UNION) { 
+	} else if(t==STRUCT || t==UNION) {
 	    t = cadr(type); /* size */
 	    return list3(RSTRUCT,e,t);
 	} else if(t==FUNCTION) {
@@ -2364,9 +2372,9 @@
 	else if(car(type)==CODE || car(type)==FUNCTION)
 	    type=type;
 	else error(TYERR);
-    } else 
+    } else
 	type= CHAR;
-    if(car(e)==ADDRESS) 
+    if(car(e)==ADDRESS)
 	return(cadr(e));
     return(list2(INDIRECT,e));
 }
@@ -2384,7 +2392,7 @@
 	switch(car(e)) {
 	case GVAR:
 	    e=list2(INDIRECT,list3(ADD,e,list2(CONST,nptr->dsp)));
-	    break; 
+	    break;
 	case LVAR:
 	    e=list2(LVAR,cadr(e) + nptr->dsp);
 	    break;
@@ -2410,6 +2418,7 @@
 dbinop(int op, int e1, int e2, int t1, int t2)
 {
     double d1,d2,d;
+    int b;
 
     type= DOUBLE;
     if (integral(t1)) { e1=float_value(e1,t1); t1=DOUBLE; }
@@ -2423,23 +2432,36 @@
 	case MUL: d=d1*d2;break;
 	case DIV:
 	    if(!d2) error(EXERR);d=d1/d2;break;
-	case GT:
-	    d=(d1>d2);break;
-	case GE:
-	    d=(d1>=d2);break;
-	case LT:
-	    d=(d1<d2);break;
-	case LE:
-	    d=(d1<=d2);break;
-	case EQ:
-	    d=(d1==d2);break;
-	case NEQ:
-	    d=(d1!=d2);break;
+	default:
+	    switch(op) {
+		case GT: b=(d1>d2);break;
+		case GE: b=(d1>=d2);break;
+		case LT: b=(d1<d2);break;
+		case LE: b=(d1<=d2);break;
+		case EQ: b=(d1==d2);break;
+		case NEQ: b=(d1!=d2);break;
+		default: error(EXERR);
+	    }
+	    type = INT;
+	    return list2(CONST,b);
 	}
 	return dlist2(DCONST,d);
     }
-    if(op==GT||op==GE||op==LT||op==LE||op==EQ||op==NEQ||
-	    ADD||SUB||MUL||DIV)
+    if(car(e2)==DCONST) {
+	if (op==SUB) {
+	    op=ADD; dcadr(e2) = -dcadr(e2);
+	} else if(op==DIV) {
+	    if(dcadr(e2)==0.0) error(EXERR);
+	    op=MUL; dcadr(e2)=1/dcadr(e2);
+	}
+    }
+    if (car(e1)==DCONST && (op==ADD||op==MUL)) {
+	return(list3(op+DOP,e2,e1));
+    }
+    if(op==GT||op==GE||op==LT||op==LE||op==EQ||op==NEQ) {
+	type=INT;
+	return(list3(op+DOP,e1,e2));
+    } else if(ADD||SUB||MUL||DIV)
 	return(list3(op+DOP,e1,e2));
     else
 	error(-1);
@@ -2450,7 +2472,7 @@
 {
     int e;
 
-    if(t1==DOUBLE||t2==DOUBLE||t1==FLOAT||t2==FLOAT) 
+    if(t1==DOUBLE||t2==DOUBLE||t1==FLOAT||t2==FLOAT)
 	return dbinop(op,e1,e2,t1,t2);
     if(car(e1)==CONST&&car(e2)==CONST) {
 	e1=cadr(e1);
@@ -2464,15 +2486,15 @@
 	case BAND:
 	    e=e1&e2;break;
 	case ADD:
-	    if(integral(t1)) {	
+	    if(integral(t1)) {
 		if(integral(t2)) {
 			e=e1+e2;
-		} else {	
+		} else {
 			if(car(t2)!=POINTER) error(TYERR);
 			e=size(cadr(t2))*e1+e2;
 			type=t2;
 		}
-	    } else {	
+	    } else {
 		if(car(t1)!=POINTER) error(TYERR);
 		e=e1+size(cadr(t1))*e2;
 		type=t1;
@@ -2481,7 +2503,7 @@
 	case SUB:
 	    if(integral(t1)) {
 		e=e1-e2;
-	    } else {	
+	    } else {
 		if(car(t1)!=POINTER) error(TYERR);
 		e=e1-size(cadr(t1))*e2;
 		type=t1;
@@ -2525,14 +2547,15 @@
 	    op==EQ||op==NEQ
 	    )
 	return(list3(op,e1,e2));
+    if(op==SUB&&car(e2)==CONST) { op=ADD; cadr(e2)=-cadr(e2); }
     if((op==ADD||op==MUL||op==BOR||op==EOR||op==BAND)&&
 	(car(e1)==CONST||(car(e2)!=CONST&&
 	(car(e1)==RGVAR||car(e1)==RLVAR)))) {
 	e=e1;e1=e2;e2=e;e=t1;t1=t2;t2=e;
     }
-    if(op==ADD) {	
-	if(integral(t1)) {	
-	    if(integral(t2)) {	
+    if(op==ADD) {
+	if(integral(t1)) {
+	    if(integral(t2)) {
 		if(t1==INT) type=t2;else type=t1;
 		return(list3(ADD,e1,e2));
 	    }
@@ -2551,14 +2574,14 @@
 		cadr(cadr(e1))+cadr(e))));
 	return(list3(ADD,e1,e));
     }
-    if(op==SUB) {	
-	if(integral(t1)) {	
+    if(op==SUB) {
+	if(integral(t1)) {
 	    if(!integral(t2)) error(TYERR);
 	    if(t1==INT) type=t2;else type=t1;
 	    return(list3(SUB,e1,e2));
 	}
 	if(car(t1)!=POINTER) error(TYERR);
-	if(integral(t2)) {	
+	if(integral(t2)) {
 	    e=binop(MUL,e2,list2(CONST,size(cadr(t1))),t2,INT);
 	    type=t1;
 	    return(list3(SUB,e1,e));
@@ -2586,8 +2609,8 @@
     if (type==FLOAT && t==DOTS) { type=DOUBLE;}
     if (type==CHAR  && t==DOTS) { type=INT;}
     if (t==DOTS) return e;
-    if (t==UNSIGNED)                 e = unsigned_value(e,type); 
-    else if (integral(t))            e = int_value(e,type); 
+    if (t==UNSIGNED)                 e = unsigned_value(e,type);
+    else if (integral(t))            e = int_value(e,type);
     else if (t==FLOAT||t==DOUBLE)    e = float_value(e,type);
     else if ((t1=car(t))==STRUCT||t1==UNION) {
 	if(size(t)!=size(type)) error(TYERR);
@@ -2621,11 +2644,11 @@
     }
     t=type;
     arglist=0;
-    while(sym!=RPAR) {	
+    while(sym!=RPAR) {
 	e=rvalue(expr1());
 	if(argtypes==0) at=DOTS;
 	else if(car(argtypes)==DOTS) at=DOTS;
-        else { at=car(argtypes); argtypes=cadr(argtypes); } 
+        else { at=car(argtypes); argtypes=cadr(argtypes); }
 	e = function_args(e,at);
 	arglist=list3(e,arglist,type);
 	if(sym!=COMMA) break;
@@ -2634,7 +2657,7 @@
     }
     checksym(RPAR);
     conv->funcall_args_();
-    if(car(t)==CODE) 
+    if(car(t)==CODE)
 	return list3(FUNCTION,e1,arglist);
     type=cadr(t);
     if(type==CHAR) type=INT;
@@ -2669,7 +2692,7 @@
 static int
 typeid(int s)
 {
-    return (integral(s) || s==CODE || s==SHORT || 
+    return (integral(s) || s==CODE || s==SHORT ||
 	s==LONG || s==STRUCT || s==UNION ||
 	s==LONGLONG || s==FLOAT || s==DOUBLE ||
     (s==IDENT && nptr->sc==TYPE));
@@ -2689,7 +2712,7 @@
 static int
 ndecl0(void)
 {
-    if(sym==MUL) {	
+    if(sym==MUL) {
 	getsym();
 	return type=list2(POINTER,ndecl0());
     }
@@ -2704,23 +2727,23 @@
     if(sym==LPAR) {
 	if(getsym()==RPAR) {
 	    type=list3(FUNCTION,type,0); getsym();
-	} else {	
+	} else {
 	    ndecl0();
 	    checksym(RPAR);
 	}
     }
     while(1) {
-	if(sym==LBRA) {	
+	if(sym==LBRA) {
 	    getsym();
 	    t=type;
 	    i=cexpr(expr(1));
 	    checksym(RBRA);
 	    type=list3(ARRAY,t,i);
-	} else if(sym==LPAR) {	
+	} else if(sym==LPAR) {
 	    t = type;
 	    getsym();
 	    arglist=0;
-	    while(sym!=RPAR) {	
+	    while(sym!=RPAR) {
 		ndecl0();
 		arglist=list2(type,arglist);
 		if(sym!=COMMA) break;
@@ -2735,7 +2758,7 @@
 
 static int
 cexpr(int e)
-{       
+{
     conv->conv_();
     if (car(e) != CONST) error(CNERR);
     return (cadr(e));
@@ -2753,15 +2776,15 @@
     char *scheapp;
     char c;
 
-    if (alpha(skipspc())) {	
+    if (alpha(skipspc())) {
 	i = hash = 0;
 	name = namebuf;
-	while (alpha(ch) || digit(ch)) {	
-	    if (i < LBUFSIZE-1) 
+	while (alpha(ch) || digit(ch)) {
+	    if (i < LBUFSIZE-1)
 		hash=(7*hash ^ (name[i++]=ch));
 	    getch();
 	}
-	name[i++] = '\0'; 
+	name[i++] = '\0';
 
 	nptrm=msearch(name);
 	if (mode==MDECL) {
@@ -2769,7 +2792,7 @@
 	    return (sym==MACRO);
 	}
 	if (mode==IFDEF) {
-	    if (nptrm->sc == MACRO||nptrm->sc==FMACRO) {	
+	    if (nptrm->sc == MACRO||nptrm->sc==FMACRO) {
 		return (symval=1);
 	    } else {
 		return (symval=0);
@@ -2826,14 +2849,14 @@
 		if (ch=='.') {
 		    getch();
 		    return sym=DOTS;
-		} 
+		}
 		error(CHERR);
 		return getsym();
 	    } else if (!digit(ch))
 		return sym=PERIOD;
 	    d=1;
 	    *cheapp++ = '.'; /* .0 case */
-	} else if (ch == '0') {	
+	} else if (ch == '0') {
 	    if (getch() == 'x' || ch == 'X') {
 		while(1) {
 		    if(digit(getch()))
@@ -2874,13 +2897,13 @@
 	dsymval = strtod(scheapp,0);
 	cheapp=scheapp;
 	return sym=DCONST;
-    } else if(ch=='\'') {	
+    } else if(ch=='\'') {
 	getch();
 	symval=escape();
 	if(ch!='\'') error(CHERR);
 	getch();
 	return sym=CONST;
-    } else if(ch=='"') {	
+    } else if(ch=='"') {
 	getstring();
 	return sym= STRING;
     }
@@ -2941,7 +2964,7 @@
     case '/':
 	if(ch=='/') {
 	    in_comment = 1;
-	    conv->comment_('/'); conv->comment_('/'); 
+	    conv->comment_('/'); conv->comment_('/');
 	    while(ch!='\n') { getch(); conv->comment_(ch); }
 	    in_comment = 0;
 	    getch();
@@ -2949,7 +2972,7 @@
 	}
 	if(ch!='*') return postequ(DIV,DIV+AS);
 	in_comment = 1;
-	conv->comment_('/'); conv->comment_('*'); 
+	conv->comment_('/'); conv->comment_('*');
 	do {
 	    c=ch; getch(); conv->comment_(ch);
 	} while(!(c=='*'&&ch=='/'));
@@ -2993,8 +3016,8 @@
     NMTBL *nptr,*iptr;
 
     iptr=nptr= &ntable[hash % GSYMS];
-    while(nptr->sc!=0) {	
-	if (++nptr== &ntable[GSYMS]) 
+    while(nptr->sc!=0) {
+	if (++nptr== &ntable[GSYMS])
 	    nptr=ntable;
 	if (nptr==iptr) error(GSERR);
     }
@@ -3014,8 +3037,8 @@
     NMTBL *nptr,*iptr;
 
     iptr=nptr= &ntable[hash % GSYMS];
-    while(nptr->sc!=0 && neqname(nptr->nm,name)) {	
-	if (++nptr== &ntable[GSYMS]) 
+    while(nptr->sc!=0 && neqname(nptr->nm,name)) {
+	if (++nptr== &ntable[GSYMS])
 	    nptr=ntable;
 	if (nptr==iptr) error(GSERR);
     }
@@ -3032,8 +3055,8 @@
     NMTBL *nptr,*iptr;
 
     iptr=nptr= &ntable[hash%LSYMS+GSYMS];
-    while(nptr->sc!=0 && neqname(nptr->nm,name)) {	
-	if (++nptr== &ntable[LSYMS+GSYMS]) 
+    while(nptr->sc!=0 && neqname(nptr->nm,name)) {
+	if (++nptr== &ntable[LSYMS+GSYMS])
 	    nptr= &ntable[GSYMS];
 	if (nptr==iptr) error(LSERR);
     }
@@ -3051,8 +3074,8 @@
     NMTBL *nptr,*iptr;
 
     iptr=nptr= &mtable[hash%MSYMS];
-    while(nptr->sc!=0 && neqname(nptr->nm,name)) {	
-	if (++nptr== &mtable[MSYMS]) 
+    while(nptr->sc!=0 && neqname(nptr->nm,name)) {
+	if (++nptr== &mtable[MSYMS])
 	    nptr= &mtable[0];
 	if (nptr==iptr) error(MSERR);
     }
@@ -3077,7 +3100,7 @@
     }
     iptr=nptr= &mtable[hash%MSYMS];
     while(nptr->sc!=0 && neqname(nptr->nm,name)) {
-	if (++nptr== &mtable[MSYMS]) 
+	if (++nptr== &mtable[MSYMS])
 	    nptr= &mtable[0];
 	if (nptr==iptr) error(MSERR);
     }
@@ -3103,7 +3126,7 @@
 {
     if (!p)
 	return 0;
-    while(*p && *p!='.') 
+    while(*p && *p!='.')
 	    if(*p++ != *q++) return 1;
     return (*q!=0);
 }
@@ -3114,7 +3137,7 @@
     getch();
     symval = 0;
     sptr = cheapp;
-    while (ch != '"') {	
+    while (ch != '"') {
 	*cheapp++ = escape();
 	symval++;
 	if (cheapp >= cheap+CHEAPSIZE) error(STRERR);
@@ -3155,14 +3178,14 @@
     return getch();
 }
 
-char 
+char
 escape(void)
 {
     char c;
-    if ((c=ch) == '\\') {	
-	if (digit(c=getch())) {	
+    if ((c=ch) == '\\') {
+	if (digit(c=getch())) {
 	    c = ch-'0';
-	    if (digit(getch())) {	
+	    if (digit(getch())) {
 		c = c*8+ch-'0';
 		if (digit(getch())) {
 		    c=c*8+ch-'0';getch();
@@ -3231,14 +3254,14 @@
 	i=0;
 	while ((*chptr++ = c = getc(filep->fcb)) != '\n') {
 	    if (++i > LBUFSIZE-2) error(LNERR);
-	    if (c==EOF) {	
+	    if (c==EOF) {
 		    error(EOFERR);
 		    --chptr;
 	    }
 	}
 	*chptr = '\0';
 	if (lsrc && !asmf && !macro_if_skip) gen_comment(linebuf);
-	if (*(chptr = linebuf) == '#' && !in_comment) {	
+	if (*(chptr = linebuf) == '#' && !in_comment) {
 	    macro_processing();
 	}
     } while(macro_if_skip || linebuf[0] == '#');
@@ -3264,7 +3287,7 @@
 	    macro_if_skip = (!i)^c;
 	}
 	return;
-    } else if (macroeq("if")) {	
+    } else if (macroeq("if")) {
 	macro_if_current++;
 	if (!macro_if_skip) {
             for(c=0;chptr[c];c++);
@@ -3276,15 +3299,15 @@
 	    macro_if_skip = !i;
 	}
 	return;
-    } else if (macroeq("else")) {	
+    } else if (macroeq("else")) {
 	if (macro_if_current==0) {
 	    error(MCERR); /* extra #else */
 	    return;
 	}
-	if (macro_if_current == macro_if_depth) 
+	if (macro_if_current == macro_if_depth)
 	    macro_if_skip = !macro_if_skip;
 	return;
-    } else if (macroeq("endif")) {	
+    } else if (macroeq("endif")) {
 	if (macro_if_current == macro_if_depth) {
 	    macro_if_skip = 0;
 	    macro_if_depth = --macro_if_current;
@@ -3298,38 +3321,38 @@
 	return;
     }
     if (macro_if_skip) return;
-    if (macroeq("define")) {	
+    if (macroeq("define")) {
 	macro_define0();
 	*(chptr = linebuf) = '\0';
-    } else if (macroeq("undef")) {	
+    } else if (macroeq("undef")) {
 	i=mode;
 	mode=LDECL;
 	ch= *chptr;
-	if (getsym() == IDENT) {	
-	    if (nptr->sc == MACRO) {	
+	if (getsym() == IDENT) {
+	    if (nptr->sc == MACRO) {
 	        nptr->sc = EMPTY;
-	    } else if (nptr->sc == FMACRO) {	
+	    } else if (nptr->sc == FMACRO) {
 	        nptr->sc = EMPTY;
 		/* we cannot reclaim it's arg */
 	    } else error(MCERR);
 	}
 	mode=i;
-    } else if (macroeq("include")) {	
+    } else if (macroeq("include")) {
 	if(filep+1 >= filestack + FILES) error(FILERR);
 	if ( ((filep+1)->fcb=getfname()) == NULL) error(FILERR);
 	(filep+1)->ln=lineno;
 	lineno=0;
 	++filep;
 	*(chptr = linebuf) = '\0';
-    } else if (macroeq("asm")) {	
+    } else if (macroeq("asm")) {
 	if (asmf) error(MCERR);
 	asmf = 1;
 	getline();
-	while (asmf) {	
+	while (asmf) {
 	    gen_source(linebuf);
 	    getline();
 	}
-    } else if (macroeq("endasm")) {	
+    } else if (macroeq("endasm")) {
 	if (!asmf) error(MCERR);
 	asmf = 0;
     } else if (macroeq(" "))
@@ -3378,7 +3401,7 @@
 	args = macro_args(&cheapp,cheap+CHEAPSIZE,&chptr);
     } else {
 	nptr->sc = MACRO;
-	nptr->ty = -1; 
+	nptr->ty = -1;
     }
     nptr->dsp = list2((int)cheapp,args); /* macro body */
     while ((*cheapp++ = c = *chptr++)
@@ -3395,7 +3418,7 @@
     mode=i;
 }
 
-static int 
+static int
 macro_args(char **pcheapp,char *maxcheap,char **pchptr)
 {
     int c;
@@ -3514,9 +3537,9 @@
 {
     NMTBL *nptr0;
     nptr0 = msearch0(macro);
-    nptr0->ty=list3(nptr0->sc,nptr0->ty,nptr0->dsp); 
-    nptr0->sc=MACRO; 
-    nptr0->dsp=list2((int)value,0); 
+    nptr0->ty=list3(nptr0->sc,nptr0->ty,nptr0->dsp);
+    nptr0->sc=MACRO;
+    nptr0->dsp=list2((int)value,0);
 }
 
 static void
@@ -3526,9 +3549,9 @@
     int save;
     nptr0 = msearch0(macro);
     save = nptr0->ty;
-    nptr0->sc=car(save); 
-    nptr0->dsp=caddr(save); 
-    nptr0->ty=cadr(save); 
+    nptr0->sc=car(save);
+    nptr0->dsp=caddr(save);
+    nptr0->ty=cadr(save);
 }
 
 static int
@@ -3730,11 +3753,11 @@
 void
 display_ntable(NMTBL *n, char *s)
 {
-    fprintf(stderr,"\n%s %0x %0x ",s,(int)n,(int)ntable); 
-    fprintf(stderr,"nptr->sc %d ",n->sc); 
-    fprintf(stderr,"nptr->dsp %d ",n->dsp); 
-    fprintf(stderr,"nptr->ty %d ",n->ty); 
-    fprintf(stderr,"nptr->nm %s\n",n->nm); 
+    fprintf(stderr,"\n%s %0x %0x ",s,(int)n,(int)ntable);
+    fprintf(stderr,"nptr->sc %d ",n->sc);
+    fprintf(stderr,"nptr->dsp %d ",n->dsp);
+    fprintf(stderr,"nptr->ty %d ",n->ty);
+    fprintf(stderr,"nptr->nm %s\n",n->nm);
 }
 
 int c0(int d)  { fprintf(stderr,"heap[%d]=",d);return car(d); }
--- a/mc.h	Sun Mar 09 18:31:00 2003 +0900
+++ b/mc.h	Wed Mar 12 15:28:44 2003 +0900
@@ -60,7 +60,8 @@
 
 #define FLOAT	(-46)
 #define DOUBLE	(-47)
-#define LONGLONG	(-48)
+#define DREGISTER       (-48)
+#define LONGLONG	(-49)
 
 #define TOP	0
 #define GDECL	1
@@ -318,5 +319,7 @@
 EXTERN void display_ntable(NMTBL *n, char *s);
 EXTERN void exit(int l);
 EXTERN void fwddef(int l);
+EXTERN int new_lvar(int size);
+
 
 /* end */
--- a/test/call.c	Sun Mar 09 18:31:00 2003 +0900
+++ b/test/call.c	Wed Mar 12 15:28:44 2003 +0900
@@ -1,4 +1,6 @@
 
+int
+a0(int i);
 
 int (*conv)(int);
 
--- a/test/float.c	Sun Mar 09 18:31:00 2003 +0900
+++ b/test/float.c	Wed Mar 12 15:28:44 2003 +0900
@@ -1,11 +1,11 @@
 #include "stdio.h"
 
-void test2(double);
 void test1();
 void print(double d);
 
 extern double sin(double);
 // extern float fsin(float);
+double test2(double f,int i);
 
 float f = 0.3;
 double d = 0.3;
@@ -64,7 +64,7 @@
    i = f;
    f = i;
    printf("\n%d %g %f",i,d,f);
-   f = g = d = g = d = f;
+   f = g = d = d1 = d2 = f;
    printf(" %d %g %f %g\n",i,d,f,g);
 
    d = 4204967294.4234; f=4204967294.4234;
@@ -80,6 +80,7 @@
    print(1.234e-10);
 
    test1();
+   printf("nested call: %g\n",test2(test2(test2(test2(-0.333,3),5),6),7));
    return 0;
 }
 
@@ -298,3 +299,14 @@
 
     return;
 }
+
+double
+test2(double f,int i)
+{
+    double g,h;
+  
+    if (i<=0) return f;
+    g =  f*2;
+    h =  f-0.5;
+    return h/3-(3.0-(g+3)*test2(f*0.5,i-1)/(h-1));
+}