changeset 133:7d436c08e949

separate float / double flow
author kono
date Fri, 02 May 2003 14:26:54 +0900
parents 07eb1249f07a
children 7a55819b0482
files .gdbinit Changes mc-code-ia32.c mc-code-mips.c mc-code-powerpc.c mc-code.h mc-codegen.c mc-codegen.h mc-parse.c mc.h
diffstat 10 files changed, 293 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/.gdbinit	Fri Apr 11 14:04:40 2003 +0900
+++ b/.gdbinit	Fri May 02 14:26:54 2003 +0900
@@ -1,5 +1,5 @@
 tb main
-r -s test/arg.c
+r -s test/basic.c
 define regs 
 printf "pc =%08x lr =%08x r0 =%08x r1 =%08x r3= %08x r4= %08x\n",$pc,$lr,$r0,$r1,$r3,$r4
 printf "r10=%08x r11=%08x r12=%08x r13=%08x r14=%08x r15=%08x\n",$r10,$r11,$r12,$r13,$r14,$r15
--- a/Changes	Fri Apr 11 14:04:40 2003 +0900
+++ b/Changes	Fri May 02 14:26:54 2003 +0900
@@ -2796,3 +2796,74 @@
 ない? dpsub とかを呼び出すのっておかしくない? (まぁ、
 いいんだけどさ)
 
+Fri Apr 11 14:36:33 JST 2003
+
+(二日酔だ...)
+
+要するに、
+     浮動小数点レジスタは single float しか使えない
+     double は、すべて、汎用レジスタに置き、計算はすべて、 subroutine 
+ってことだよね。(あ〜、やだやだ)
+
+single float だけでの演算を導入するためには、DSUBの他にFSUB 
+などを導入する必要がある。これは「うざい」。不可能じゃないけ
+ど、かなりめんどくさいね。浮動小数点誤差の問題もあるし。全部
+double に変換してから計算すれば問題ないかと言うと、そんなこ
+とはないわけだが。せめて、浮動小数点レジスタ上での演算をおこ
+なうsubroutineはないの? (あるかも知れない) 
+
+まぁなぁ。FCOMPとかやればいいだけなんだけど。
+
+Sat Apr 12 13:30:07 JST 2003
+
+jal dpadd は、やっぱり、かなり複雑な浮動小数点演算だというが
+わかった。IEEEの形式と合わないとかとかでそうなったんじゃなか
+ろうか? もっとも、PlayStation に合わせてあるのかも知れないけ
+ど。
+
+ということで、single float 計算を入れないと、もとのgcc との
+差が大きすぎるだろうと思う。ってことは、fmachineop とか FSUB
+を入れないとだめってことか。まぁ、やれば、いいだけなんだけど、
+他のCPUとの調節がなぁ... 
+
+今は、float の演算もpipeline上では1clockなんだろうから、
+できればdouble でやって欲しいけどね。とはいえ、double/float
+の変換が不要になるので、float base だとMIPSの方が速い
+ってことにはなるかも知れない。
+
+gdb のdisass を見ると、jal bpadd とかは特定レジスタ
+を使った間接代入になっているらしい。また、disass の
+レジスタ表示が、
+
+    $a0 $a2 $a3 $at $f0 $gp $ra $s0 $s1 $sp $t9 $zero $v1 $f12 $at
+
+とかなので、よくわからん。こまったものだ。これも、
+ちょっと時間かかるのかな?
+
+
+まぁ、なぁ... ANSI-C に従おうと思うと、このあたりのfloat/double
+はうっとうしいよね。でも、とりあえず動けば良い?
+
+expr の引数として「output type」を入れるか? 基本的には assign
+で決まるtypeを要求する。やっぱり、C の規格書がいるんだろうなぁ。
+(それは嫌だな...) CbC として、そういうものを入れるのが本当に
+正しいの? (さぁねぇ...)
+    float  = float op float
+は良いんだけど、
+    double = float op float
+の時に、必要な精度を確保できない。cast すれば良いんだけど、それは
+ANSI-C とは異なる挙動になってしまう。ま、いいか。
+
+MIPSはdouble=float ということにするっていう手もあるね。
+その方がきれいか。でも、どうせ、他のCPUもあることを考えると、
+fbinop するんじゃないの? lbinop も出さないとだめだろうし。
+short とかunsigned char の扱いもね。(sigh...)
+
+まぁ、時間の問題だから、やれば良いだけなんだけど。めんどい!
+
+(せめてdoubleのルーチンが浮動小数点レジスタを使ってくれれば
+楽だったのに〜)
+
+Mon Apr 14 23:29:37 JST 2003
+
+やっぱり、ちょっと変更大きいなぁ。
--- a/mc-code-ia32.c	Fri Apr 11 14:04:40 2003 +0900
+++ b/mc-code-ia32.c	Fri May 02 14:26:54 2003 +0900
@@ -1683,14 +1683,23 @@
     printf("\tfldl _%d\n",lb);
 }
 
+void code_fconst(int e2,int freg)
+{
+    code_dconst(e2,freg);
+}
+
 void code_dneg(int freg)
 { 
     printf("\tfchs\n");
 }
 
+void code_fneg(int freg)
+{
+    code_dneg(freg);
+}
+
 void code_d2i(int freg,int creg)
 { 
-    /* fuck you! */
     printf("\tlea -%d(%%esp),%%esp\n",size_of_int*2);
     printf("\tfnstcw  (%%esp)\n");
     printf("\tmovl    (%%esp), %s\n",register_name(creg,0));
@@ -1733,6 +1742,13 @@
     printf("\tlea %d(%%esp),%%esp\n",size_of_int*2);
 }
 
+void code_d2f(int freg) { }
+void code_f2d(int freg) { }
+void code_f2i(int freg,int creg) { code_d2i(freg,creg); }
+void code_f2u(int freg,int creg) { code_d2u(freg,creg); }
+void code_i2f(int creg,int freg) { code_i2d(creg,freg); }
+void code_u2f(int creg,int freg) { code_u2d(creg,freg); }
+
 void code_drgvar(int e2,int d,int freg)
 { 
     printf("\t%s %s\n",fload(d),((NMTBL*)cadr(e2))->nm);
@@ -1757,10 +1773,15 @@
 void dtosop(int op,int e1)
 {
     switch(op) {
+    case FADD:
     case DADD: printf("\tfaddp %%st,%%st(1)\n"); break;
+    case FSUB:
     case DSUB: printf("\tfsubp %%st,%%st(1)\n"); break;
+    case FDIV:
     case DDIV: printf("\tfdivp %%st,%%st(1)\n"); break;
+    case FMUL:
     case DMUL: printf("\tfmulp %%st,%%st(1)\n"); break;
+    case FCMP:
     case DCMP: 
 	printf("\tfucompp\n");
 	printf("\tfnstsw\t%%ax\n");
@@ -1809,19 +1830,23 @@
     g_expr(list3(DCMP,e1,e2));
     switch(op) {
 	case DOP+GE:
+	case FOP+GE:
 	    printf("\ttestb\t$5,%%ah\n");
 	    printf("\tjne\t_%d\n",l1);
 	    break;
 	case DOP+GT:
+	case FOP+GT:
 	    printf("\ttestb\t$69,%%ah\n");
 	    printf("\tjne\t_%d\n",l1);
 	    break;
 	case DOP+EQ:
+	case FOP+EQ:
 	    printf("\tandb\t$69,%%ah\n");
 	    printf("\txorb\t$64,%%ah\n");
 	    printf("\tjne\t_%d\n",l1);
 	    break;
 	case DOP+NEQ:
+	case FOP+NEQ:
 	    printf("\tandb\t$69,%%ah\n");
 	    printf("\txorb\t$64,%%ah\n");
 	    printf("\tje\t_%d\n",l1);
@@ -1868,7 +1893,7 @@
 { 
 }
 
-void emit_dpush()
+void emit_dpush(int type)
 { 
     if (freg_sp>=MAX_FPU_STACK) code_save_fstacks();
     if (freg_sp>MAX_MAX) error(-1);
--- a/mc-code-mips.c	Fri Apr 11 14:04:40 2003 +0900
+++ b/mc-code-mips.c	Fri May 02 14:26:54 2003 +0900
@@ -2268,7 +2268,7 @@
     free_fregister(e1);
 }
 
-void emit_dpush()
+void emit_dpush(int d)
 { 
     int new_reg;
     if (freg_sp>MAX_MAX) error(-1);
--- a/mc-code-powerpc.c	Fri Apr 11 14:04:40 2003 +0900
+++ b/mc-code-powerpc.c	Fri May 02 14:26:54 2003 +0900
@@ -2294,7 +2294,16 @@
     return (i[1] == 0x3ff00000)?j[1]:j[0];
 }
 
-void code_dconst(int e2,int freg)
+int
+code_f(double d)
+{
+    float f = d;
+    int *j = (int *)&f;
+    return *j;
+}
+
+static
+void code_dconst1(int e2,int freg,int db)
 { 
     int lb;
     double d = dcadr(e2);
@@ -2319,7 +2328,11 @@
     printf(" \t.data\n\t.align 3\n");
     lb=fwdlabel();
     printf("L_%d:\n",lb);
-    printf("\t.long\t0x%x,0x%x\n",code_d2(d),code_d1(d));
+    if (db) {
+	printf("\t.long\t0x%x,0x%x\n",code_d2(d),code_d1(d));
+    } else {
+	printf("\t.long\t0x%x\n",code_f(d));
+    }
     if (output_mode==TEXT_EMIT_MODE) {
 	printf(".text\n");
     } else {
@@ -2327,17 +2340,37 @@
     }
     printf("\taddis %s,r31,ha16(L_%d-L_%d)\n",rrn,lb,code_base);
     printf("\tla %s,lo16(L_%d-L_%d)(%s)\n",rrn,lb,code_base,rrn);
-    printf("\tlfd %s,0(%s)\n",frn,rrn);
+    if (db) {
+	printf("\tlfd %s,0(%s)\n",frn,rrn);
+    } else {
+	printf("\tlfs %s,0(%s)\n",frn,rrn);
+    }
     free_register(r);
     fregv[freg]=1;
 }
 
+void code_fconst(int e2,int freg)
+{
+    code_dconst1(e2,freg,0);
+}
+
+void code_dconst(int e2,int freg)
+{
+    code_dconst1(e2,freg,1);
+}
+
+
 void code_dneg(int freg)
 { 
     char *frn = fregister_name(freg);
     printf("\tfneg %s,%s\n",frn,frn);
 }
 
+void code_fneg(int freg)
+{
+    code_dneg(freg);
+}
+
 void code_d2i(int freg,int creg)
 { 
     char *frn = fregister_name(freg);
@@ -2485,6 +2518,13 @@
     regs[creg]=0;
 }
 
+void code_d2f(int freg) { }
+void code_f2d(int freg) { }
+void code_f2i(int freg,int creg) { code_d2i(freg,creg); }
+void code_f2u(int freg,int creg) { code_d2u(freg,creg); }
+void code_i2f(int creg,int freg) { code_i2d(creg,freg); }
+void code_u2f(int creg,int freg) { code_u2d(creg,freg); }
+
 void code_drgvar(int e2,int d,int freg)
 { 
     int r;
@@ -2534,18 +2574,26 @@
     char *grn=fregister_name(e1);
     fregv[freg]=1;
     switch(op) {
+    case FADD:
     case DADD: opn="fadd"; break;
+    case FSUB:
     case DSUB: opn="fsub"; break;
+    case FDIV:
     case DDIV: opn="fdiv"; break;
+    case FMUL:
     case DMUL: opn="fmul"; break;
+    case FCMP:
     case DCMP: 
 	printf("\tfcmpu cr0,%s,%s\n",frn,grn);
 	free_fregister(e1);
 	return;
+    case FCMPGE: 
     case DCMPGE: 
 	printf("\tfcmpu cr7,%s,%s\n",frn,grn);
 	free_fregister(e1);
 	return;
+    default:
+	error(-1); return;
     }
     printf("\t%s %s,%s,%s\n",opn,frn,frn,grn);
     free_fregister(e1);
@@ -2628,16 +2676,20 @@
     g_expr(list3(((op==DOP+GE)?DCMPGE:DCMP),e1,e2));
     switch(op) {
 	case DOP+GE:
+	case FOP+GE:
 	    printf("\tcror 2,29,30\n");
 	    printf("\tbne\tcr0,L_%d\n",l1);
 	    break;
 	case DOP+GT:
+	case FOP+GT:
 	    printf("\tble\tcr0,L_%d\n",l1);
 	    break;
 	case DOP+EQ:
+	case FOP+EQ:
 	    printf("\tbne\tcr0,L_%d\n",l1);
 	    break;
 	case DOP+NEQ:
+	case FOP+NEQ:
 	    printf("\tbeq\tcr0,L_%d\n",l1);
 	    break;
     }
@@ -2661,7 +2713,7 @@
     free_fregister(e1);
 }
 
-void emit_dpush()
+void emit_dpush(int type)
 { 
     int new_reg;
     if (freg_sp>MAX_MAX) error(-1);
--- a/mc-code.h	Fri Apr 11 14:04:40 2003 +0900
+++ b/mc-code.h	Fri May 02 14:26:54 2003 +0900
@@ -102,16 +102,25 @@
 extern void code_dassign_lvar(int,int,int);
 extern void code_dassign_fregister(int e2,int d,int reg);
 extern void code_dconst(int,int);
+extern void code_fconst(int,int);
 extern void code_dneg(int);
+extern void code_fneg(int);
 extern void code_drgvar(int,int,int);
 extern void code_drlvar(int,int,int);
 extern void dtosop(int,int);
 extern void emit_dpop_free(int);
-extern void emit_dpush();
+extern void emit_dpush(int);
 extern void code_i2d(int,int);
 extern void code_d2i(int,int);
 extern void code_u2d(int,int);
 extern void code_d2u(int,int);
+extern void code_d2f(int freg);
+extern void code_f2d(int freg);
+extern void code_f2i(int freg,int creg);
+extern void code_f2u(int freg,int creg);
+extern void code_i2f(int creg,int freg);
+extern void code_u2f(int creg,int freg);
+
 
 extern void code_dpreinc(int e1,int e2,int d,int reg);
 extern void code_dpostinc(int e1,int e2,int d,int reg);
--- a/mc-codegen.c	Fri Apr 11 14:04:40 2003 +0900
+++ b/mc-codegen.c	Fri May 02 14:26:54 2003 +0900
@@ -80,7 +80,7 @@
 int
 g_expr0(int e1)
 {
-    int e2,e3,t;
+    int e2,e3,t,d;
     NMTBL *n;
 
     e2 = cadr(e1);
@@ -130,6 +130,9 @@
     case DCONST:
 	code_dconst(e1,freg);
 	return DOUBLE;
+    case FCONST:
+	code_fconst(e1,freg);
+	return FLOAT;
     case STRING:
 	code_string(e1,creg);
 	return ADDRESS;
@@ -155,21 +158,22 @@
     case DMINUS: 
 	g_expr0(e2); code_dneg(freg);
 	return DOUBLE;
+    case FMINUS: 
+	g_expr0(e2); code_fneg(freg);
+	return FLOAT;
     case CONV: 
 	g_expr0(e2); 
 	switch(caddr(e1)) {
-	case I2D: 
-	    code_i2d(creg,freg);
-	    return DOUBLE;
-	case D2I: 
-	    code_d2i(freg,creg);
-	    return INT;
-	case U2D: 
-	    code_u2d(creg,freg);
-	    return DOUBLE;
-	case D2U: 
-	    code_d2u(freg,creg);
-	    return UNSIGNED;
+	case I2D: code_i2d(creg,freg); return DOUBLE;
+	case D2I: code_d2i(freg,creg); return INT;
+	case U2D: code_u2d(creg,freg); return DOUBLE;
+	case F2U: code_f2u(freg,creg); return UNSIGNED;
+	case I2F: code_i2f(creg,freg); return FLOAT;
+	case F2I: code_f2i(freg,creg); return INT;
+	case U2F: code_u2f(creg,freg); return FLOAT;
+	case D2U: code_d2u(freg,creg); return UNSIGNED;
+	case D2F: code_d2f(freg); return FLOAT;
+	case F2D: code_f2d(freg); return DOUBLE;
 	default:
 	    error(-1); return INT;
 	}
@@ -220,8 +224,13 @@
     case DMUL: case DDIV:
     case DADD: case DSUB:
     case DCMP: case DCMPGE:
-	dmachinop(e1);
+	dmachinop(e1,1);
 	return DOUBLE;
+    case FMUL: case FDIV:
+    case FADD: case FSUB:
+    case FCMP: case FCMPGE:
+	dmachinop(e1,0);
+	return FLOAT;
     case COND:
 	e2=fwdlabel();
 	b_expr(cadr(e1),0,e2,0);
@@ -236,14 +245,16 @@
 	fwddef(e3);
 	return t;
     case DCOND:
+    case FCOND:
+	d = car(e1)==DCOND?DOUBLE:FLOAT;
 	e2=fwdlabel();
 	b_expr(cadr(e1),0,e2,0);
-	code_set_fixed_creg(0,DOUBLE);
+	code_set_fixed_creg(0,d);
 	t = g_expr0(caddr(e1));
 	code_set_fixed_creg(1,t);
 	jmp(e3=fwdlabel());
 	fwddef(e2);
-	code_set_fixed_creg(0,DOUBLE);
+	code_set_fixed_creg(0,d);
 	t = g_expr0(cadddr(e1));
 	code_set_fixed_creg(1,t);
 	fwddef(e3);
@@ -877,7 +888,7 @@
 }
 
 void
-dmachinop(int e1)
+dmachinop(int e1,int d)
 {
     int e2,e3,op;
 
@@ -885,15 +896,14 @@
     op = car(e1);
     e3 = caddr(e1);
     g_expr(e3);
-    emit_dpush();
+    emit_dpush(d);
     g_expr(e2);
-    dtosop(car(e1),(e2=emit_dpop(1)));
+    dtosop(car(e1),(e2=emit_dpop(d)));
     emit_dpop_free(e2);
     fregv[freg]=1;
     return;
 }
 
-
 void
 sassign(int e1)
 {
@@ -1051,7 +1061,8 @@
     d = (car(e1)==LASS)?2:(car(e1)==DASS)?1:0;
     if (!use && (
 	    (e5==DREGISTER) ||
-	    (car(e2)==DREGISTER&&(e5==DRGVAR||e5==DRLVAR||e5==DCONST))
+	    (car(e2)==DREGISTER&&(e5==DRGVAR||e5==DRLVAR||e5==DCONST))||
+	    (car(e2)==DREGISTER&&(e5==FRGVAR||e5==FRLVAR||e5==FCONST))
 	)) {
 	dassign_opt(e5,e2,e4,d);
 	return;
@@ -1118,7 +1129,7 @@
     op = cadddr(e1);
 
     g_expr(e3);
-    emit_dpush();
+    emit_dpush(d);
     g_expr(e2);
     code_dassop(op,d);
     regv[creg]=1;
@@ -1240,13 +1251,14 @@
 	case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT:
 	case ADD: case SUB: case BAND: case EOR: case BOR: case CMP:
 	case DMUL: case DDIV: case DADD: case DSUB: case DCMP: case DCMPGE:
+	case FMUL: case FDIV: case FADD: case FSUB: case FCMP: case FCMPGE:
 	case SASS: case ASS: case CASS: case FASS: case DASS: case LASS: 
 	case ASSOP: case CASSOP: case DASSOP: case FASSOP: case COMMA:
 	    if (contains(cadr(e),type)) return 1;
 	    e = caddr(e);
 	    continue;
         /* tarary operators */
-	case COND:
+	case COND: case DCOND: case FCOND:
 	    if (contains(cadr(e), type)) return 1;
 	    if (contains(caddr(e),type)) return 1;
 	    e = cadddr(e);
--- a/mc-codegen.h	Fri Apr 11 14:04:40 2003 +0900
+++ b/mc-codegen.h	Fri May 02 14:26:54 2003 +0900
@@ -81,7 +81,7 @@
 /* floating point */
 
 extern void dassop(int e1);
-extern void dmachinop(int e1);
+extern void dmachinop(int e1,int d);
 extern void dassign(int e1);
 
 /* end */
--- a/mc-parse.c	Fri Apr 11 14:04:40 2003 +0900
+++ b/mc-parse.c	Fri May 02 14:26:54 2003 +0900
@@ -1720,10 +1720,22 @@
 }
 
 int
+double_value(int e2,int type)
+{
+    if (car(e2)==CONST)  return dlist2(DCONST,(double)cadr(e2));
+    if(type==DOUBLE) return e2;
+    if(type==FLOAT) return list3(CONV,rvalue_t(e2,type),F2D);
+    if(type==UNSIGNED) return list3(CONV,rvalue_t(e2,type),U2D);
+    if(integral(type)) return list3(CONV,rvalue_t(e2,type),I2D);
+    error(TYERR); return dlist2(DCONST,1.0);
+}
+
+int
 float_value(int e2,int type)
 {
-    if (car(e2)==CONST)  return dlist2(DCONST,(double)cadr(e2));
-    if(type==FLOAT||type==DOUBLE) return e2;
+    if (car(e2)==CONST)  return dlist2(FCONST,(double)cadr(e2));
+    if(type==FLOAT) return e2;
+    if(type==DOUBLE) return list3(CONV,rvalue_t(e2,type),D2F);
     if(type==UNSIGNED) return list3(CONV,rvalue_t(e2,type),U2D);
     if(integral(type)) return list3(CONV,rvalue_t(e2,type),I2D);
     error(TYERR); return dlist2(DCONST,1.0);
@@ -1768,7 +1780,7 @@
 	if (!integral(type)) error(TYERR);
 	type= INT;return(list3(CASS,e1,e2));
     } else if(t==DOUBLE) {
-	e2=float_value(e2,type);
+	e2=double_value(e2,type);
 	type= t;return(list3(DASS,e1,e2));
     } else if(t==FLOAT) {
 	e2=float_value(e2,type);
@@ -1841,7 +1853,7 @@
 	    return(list4(FASSOP,e1,e2,op+DOP));
 	}
 	if (t==DOUBLE) {
-	    e2=float_value(e2,type); type=t;
+	    e2=double_value(e2,type); type=t;
 	    return(list4(DASSOP,e1,e2,op+DOP));
 	}
 	if(!integral(type)) error(TYERR);
@@ -1887,11 +1899,17 @@
 	    } else
 		return e3;
 	}
-	if(type==FLOAT||type==DOUBLE||t==FLOAT||t==DOUBLE) {
+	if(type==DOUBLE||t==DOUBLE) {
+	    e2=double_value(e2,t);
+	    e3=double_value(e3,type);
+	    t=type=DOUBLE;
+	    return(list4(DCOND,e1,e2,e3));
+	}
+	if(type==FLOAT||t==FLOAT) {
 	    e2=float_value(e2,t);
 	    e3=float_value(e3,type);
-	    t=type=DOUBLE;
-	    return(list4(DCOND,e1,e2,e3));
+	    t=type=FLOAT;
+	    return(list4(FCOND,e1,e2,e3));
 	}
 	if(type==INT||(t!=INT&&type==UNSIGNED))
 	    type=t;
@@ -2334,8 +2352,10 @@
 	    if (integral(t)) {
 		if(t==UNSIGNED) e1=unsigned_value(e1,type);
 		else e1=int_value(e1,type);
-	    } else if(t==FLOAT||t==DOUBLE) {
-		if(integral(type)) e1=float_value(e1,type);
+	    } else if(t==FLOAT) {
+		e1=float_value(e1,type);
+	    } else if(t==DOUBLE) {
+		e1=double_value(e1,type);
 	    }
 	    type=t;
 	    return e1;
@@ -2525,16 +2545,24 @@
     return e;
 }
 
+#define DTYPE(dop) (dop==DOP?DOUBLE:FLOAT)
+
 static int
-dbinop(int op, int e1, int e2, int t1, int t2)
+fdbinop(int op, int e1, int e2, int t1, int t2, int dop)
 {
     double d1,d2,d;
     int b=0;
 
-    type= DOUBLE;
-    if (integral(t1)) { e1=float_value(e1,t1); t1=DOUBLE; }
-    if (integral(t2)) { e2=float_value(e2,t2); t2=DOUBLE; }
-    if(car(e1)==DCONST&&car(e2)==DCONST) {
+    type= DTYPE(dop);
+    if (dop==DOP) {
+	e1=double_value(e1,t1);
+	e2=double_value(e2,t2);
+    } else {
+	e1=float_value(e1,t1);
+	e2=float_value(e2,t2);
+    }
+    t1=t2=DTYPE(dop);
+    if(car(e1)==dop+CONST&&car(e2)==dop+CONST) {
 	d1=dcadr(e1);
 	d2=dcadr(e2);
 	switch(op) {
@@ -2556,18 +2584,18 @@
 	    type = INT;
 	    return list2(CONST,b);
 	}
-	return dlist2(DCONST,d);
+	return dlist2(dop+CONST,d);
     }
-    if(car(e1)==DCONST) {
+    if(car(e1)==dop+CONST) {
 	if ((op==SUB||op==ADD)&&dcadr(e1)==0.0) {
 	    return e2;
 	} else if (op==MUL&&dcadr(e1)==1.0) {
 	    return e2;
 	} else if (op==MUL&&-dcadr(e1)==1.0) {
-	    return list2(DMINUS,e2);
+	    return list2(dop+MINUS,e2);
 	}
     }
-    if(car(e2)==DCONST) {
+    if(car(e2)==dop+CONST) {
 	if ((op==SUB||op==ADD)&&dcadr(e2)==0.0) {
 	    return e1;
 	}
@@ -2584,14 +2612,14 @@
 	    op=MUL; dcadr(e2)=1/dcadr(e2);
 	}
     }
-    if (car(e1)==DCONST && (op==ADD||op==MUL)) {
-	return(list3(op+DOP,e2,e1));
+    if (car(e1)==dop+CONST && (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(op==ADD||op==SUB||op==MUL||op==DIV)
-	return(list3(op+DOP,e1,e2));
+	return(list3(op+dop,e1,e2));
     else {
 	error(-1);
 	return e1;
@@ -2599,12 +2627,26 @@
 }
 
 static int
+dbinop(int op, int e1, int e2, int t1, int t2)
+{
+    return fdbinop(op, e1, e2, t1, t2,DOP);
+}
+
+static int
+fbinop(int op, int e1, int e2, int t1, int t2)
+{
+    return fdbinop(op, e1, e2, t1, t2,FOP);
+}
+
+static int
 binop(int op, int e1, int e2, int t1, int t2)
 {
     int e=0;
 
-    if(t1==DOUBLE||t2==DOUBLE||t1==FLOAT||t2==FLOAT)
+    if(t1==DOUBLE||t2==DOUBLE)
 	return dbinop(op,e1,e2,t1,t2);
+    if(t1==FLOAT||t2==FLOAT)
+	return fbinop(op,e1,e2,t1,t2);
     if(car(e1)==CONST&&car(e2)==CONST) {
 	e1=cadr(e1);
 	e2=cadr(e2);
@@ -2742,7 +2784,8 @@
     if (t==DOTS) return e;
     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 (t==FLOAT)     e = float_value(e,type);
+    else if (t==DOUBLE)    e = double_value(e,type);
     else if ((t1=car(t))==STRUCT||t1==UNION) {
 	if(size(t)!=size(type)) error(TYERR);
     }
--- a/mc.h	Fri Apr 11 14:04:40 2003 +0900
+++ b/mc.h	Fri May 02 14:26:54 2003 +0900
@@ -151,7 +151,6 @@
 #define SASS	69
 #define RSTRUCT	70
 
-#define FASSOP	71
 #define DASSOP	(DOP+ASSOP)
 #define DCMP	(DOP+CMP)
 #define DMINUS	(DOP+MINUS)
@@ -159,7 +158,16 @@
 #define DDIV	(DOP+DIV)
 #define DADD	(DOP+ADD)
 #define DSUB	(DOP+SUB)
-#define DCMPGE	72
+#define FASSOP	(FOP+ASSOP)
+#define FCMP	(FOP+CMP)
+#define FMINUS	(FOP+MINUS)
+#define FMUL	(FOP+MUL)
+#define FDIV	(FOP+DIV)
+#define FADD	(FOP+ADD)
+#define FSUB	(FOP+SUB)
+#define CMPGE	72
+#define DCMPGE	(DOP+CMPGE)
+#define FCMPGE	(FOP+CMPGE)
 #define LMUL	73
 #define LDIV	74
 #define LADD	75
@@ -174,8 +182,8 @@
 #define LRGVAR	88
 #define LRLVAR	89
 #define LRINDIRECT	90
-#define DCONST	91
-#define FCONST	92
+#define DCONST	(DOP+CONST)
+#define FCONST	(FOP+CONST)
 #define LCONST	93
 #define DASS	94
 #define FASS	95
@@ -186,16 +194,24 @@
 #define D2I	99
 #define U2D	100
 #define D2U	101
-#define FPOSTINC	102
-#define DPOSTINC	103
-#define FPREINC	104
-#define DPREINC	105
-#define DCOND	106
+#define F2D	108
+#define D2F	109
+#define I2F	110
+#define F2I	111
+#define U2F	112
+#define F2U	113
+#define FPOSTINC	(FOP+POSTINC)
+#define DPOSTINC	(DOP+POSTINC)
+#define FPREINC	(FOP+PREINC)
+#define DPREINC	(DOP+PREINC)
+#define DCOND	(DOP+COND)
+#define FCOND	(FOP+COND)
 #define CONV	107
 
 #define US	1
 #define AS	200
 #define DOP	400
+#define FOP	600
 
 #define FILERR	1
 #define DCERR	2