changeset 237:1933266f1efa

long long ia32 (imcomplete)
author kono
date Fri, 30 Apr 2004 11:47:51 +0900
parents 7353a818858c
children d64e9a6a66bd
files mc-code-ia32.c mc-code-powerpc.c mc.h test/code-gen.c
diffstat 4 files changed, 338 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/mc-code-ia32.c	Thu Apr 29 23:53:31 2004 +0900
+++ b/mc-code-ia32.c	Fri Apr 30 11:47:51 2004 +0900
@@ -150,7 +150,7 @@
 static void shift(char *op, int reg,int creg);
 static void ld_indexx(int byte, int n, int xreg,int reg,int sign);
 static void data_mode(char *name);
-static int edx_setup();
+static int edx_setup(int rreg);
 static void edx_cleanup();
 static void local_table(void);
 #if FLOAT_CODE
@@ -1026,6 +1026,9 @@
 
 #ifdef SAVE_STACKS
     code_save_stacks();
+#if FLOAT_CODE
+    code_save_fstacks();
+#endif
 #endif
     if (free_register_count(0)<1) {
         for(save = 0;save==dreg||save==creg;save++);
@@ -1044,6 +1047,9 @@
 	if(scalar(t)) {
 	    g_expr(e4);
 	    printf("\tpushl %s\n",register_name(creg,0));
+	} else if (t==LONGLONG||t==ULONGLONG) {
+	    g_expr(e4);
+	    printf("\tpushl %%edx\n\tpushl %%eax\n");
 	} else if (t==DOUBLE) {
 	    g_expr(e4);
 	    printf("\tleal\t-8(%%esp),%%esp\n\tfstpl\t(%%esp)\n");
@@ -1095,6 +1101,8 @@
     regv[save]=0;
     if (ret_type==DOUBLE||ret_type==FLOAT) {
 	fregv[freg]=1; regv[creg]=0;
+    } else if (ret_type==LONGLONG||ret_tpye==ULONGLONG) {
+	fregv[freg]=0; regv[creg]=0;
     } else if (ret_type==VOID) {
 	fregv[freg]=0; regv[creg]=0;
     } else {
@@ -1177,9 +1185,27 @@
 #endif
 
 #if LONGLONG_CODE
+
+static void
+lload(int creg,int offset)
+{
+    char *crn = register_name(creg,0);
+    if(rname[creg]==REG_EAX) {
+	printf("\tmovl %d(%s),%%edx\n",op,offset+size_of_int,crn);
+	printf("\tmovl %d(%s),%%eax\n",op,offset,crn);
+    } else {
+	printf("\tmovl %d(%s),%%eax\n",op,offset,crn);
+	printf("\tmovl %d(%s),%%edx\n",op,offset+size_of_int,crn);
+    }
+}
+
 int
 code_lrindirect(int e1, int reg, int offset, int us)
 {
+    char *crn;
+    g_expr(e1);
+    use_longlong(reg);
+    lload(creg,offset);
     return LONGLONG;
 }
 #endif
@@ -1235,7 +1261,7 @@
 code_assop(int op,int reg,int byte,int sign) {
     char *xrn;
     int xreg;
-    int edx = edx_setup();
+    int edx = edx_setup(-1);
     use_int(reg);
     xrn = register_name(xreg = emit_pop(0),0);       /* pop e3 value */
     regv[xreg]=regs[xreg]=1;
@@ -1308,7 +1334,7 @@
     case DIV:
     case UDIV:
 	use_register(creg,REG_EAX,1);
-	edx_setup();
+	edx_setup(REG_EDX);
 	orn = register_name(oreg,0);
 	if (op==DIV)
 	    printf("\tcltd\n\tidivl %s\n",orn);
@@ -1319,7 +1345,7 @@
     case MOD:
     case UMOD:
 	use_register(creg,REG_EAX,1);
-	edx_setup();
+	edx_setup(REG_EDX);
 	orn = register_name(oreg,0);
 	if (op==MOD)
 	    printf("\tcltd\n\tidivl %s\n",orn);
@@ -1392,7 +1418,7 @@
 static int edx_stack=0;
 
 int
-edx_setup()
+edx_setup(int rreg)
 {
     int edx_save;
     /* make real EDX register empty */
@@ -1405,7 +1431,8 @@
         edx_stack = list3(edx_save,edx_stack,1);
     }
     regv[edx_save]=0;
-    use_register(edx_save,REG_EDX,0);
+    if (rreg!=-1)
+	use_register(edx_save,rreg,0);
     return edx_save;
 }
 
@@ -2154,9 +2181,6 @@
 	    creg=screg;
 	}
     }
-#if FLOAT_CODE
-    code_save_fstacks();
-#endif
 }
 
 #if FLOAT_CODE
@@ -2184,102 +2208,340 @@
 
 /* 64bit int part */
 
-void lrexpr(int e1, int e2,int l1, int op,int cond)
+static void
+pcond(char *s,int l1)
 {
+    printf("\tj%s\t_%d\n",s,l1);
 }
 
-int lpop_register()
+void lrexpr(int e1, int e2,int l1, int op,int cond)
 {
-	return 0;
+    int reg;
+    int e3;
+    g_expr(e1);
+    emit_lpush();
+    g_expr(e2);
+    e3 = emit_lpop();
+    reg = lreg;
+
+    printf("\tsubl %edx,4(%%esp)\n");
+    switch(op) {
+    case LOP+GT:
+        pcond(code_gt(cond),l1); break;
+    case LOP+GE:
+        pcond(code_ge(cond),l1); break;
+    case LOP+EQ:
+        pcond(code_eq(cond),l1); break;
+    case LOP+NEQ:
+        pcond(code_eq(!cond),l1); break;
+    case LOP+LT:
+        pcond(code_ge(!cond),l1); break;
+    case LOP+LE:
+        pcond(code_gt(!cond),l1); break;
+    case LOP+UGT:
+        pcond(code_ugt(cond),l1); break;
+    case LOP+UGE:
+        pcond(code_uge(cond),l1); break;
+    default:
+        error(-1);
+    }
+    printf("\tsubl %eax,(%%esp)\n");
+    switch(op) {
+    case LOP+GT:
+        pcond(code_gt(cond),l1); break;
+    case LOP+GE:
+        pcond(code_ge(cond),l1); break;
+    case LOP+EQ:
+        pcond(code_eq(cond),l1); break;
+    case LOP+NEQ:
+        pcond(code_eq(!cond),l1); break;
+    case LOP+LT:
+        pcond(code_ge(!cond),l1); break;
+    case LOP+LE:
+        pcond(code_gt(!cond),l1); break;
+    case LOP+UGT:
+        pcond(code_ugt(cond),l1); break;
+    case LOP+UGE:
+        pcond(code_uge(cond),l1); break;
+    default:
+        error(-1);
+    }
+    emit_lpop_free(e3);
 }
 
 int emit_lpop()
 {
-	return 0;
+    return 0;
 }
 
 void code_lregister(int e2,int reg)
 {
-
+    error(-1);
 }
 
 void code_cmp_lregister(int reg)
 {
-
+    error(-1);
 }
 
 void code_cmp_lrgvar(int e1,int e2)
 {
-
+    char *n,*crn;
+    n = ((NMTBL*)cadr(e1))->nm;
+    use_int(e2);
+    crn = register_name(e2,0);
+    printf("\tmovl %s,%s\n",n,crn);
+    printf("\torl  %s+4,%s\n",n,crn);
+    printf("\ttestl %s,%s\n",crn);
 }
 
 void code_cmp_lrlvar(int e1,int e2)
 {
-
+    char *crn;
+    use_int(e2);
+    crn = register_name(e2,0);
+    printf("\tmovl %s,%d(%%dbp)\n",crn,lvar(e1));
+    printf("\trol  %s,%d(%%dbp)\n",crn,lvar(e1)+4);
+    printf("\ttestl %s,%s\n",crn);
 }
 
 void code_lassign(int e1,int e2)
 {
-
+    char *rn;
+    // e1 = e2
+    use_longlong(e2);
+    rn = register_name(e1);
+    printf("\tmovl %%eax,(%s)\n",rn);
+    printf("\tmovl %%edx,4(%s)\n",rn);
 }
 
 void code_lassign_gvar(int e1,int e2)
 {
-
+    char *n,*crn;
+    n = ((NMTBL*)cadr(e1))->nm;
+    use_longlong(e2);
+    printf("\tmovl %%eax,%s\n",n);
+    printf("\tmovl %%edx,%s+4\n",n);
 }
 
 void code_lassign_lvar(int e1,int e2)
 {
-
+    use_longlong(e2);
+    printf("\tmovl %%eax,%d(%%dbp)\n",lvar(e1));
+    printf("\tmovl %%edx,%d(%%dbp)\n",lvar(e1)+4);
 }
 
 void code_lassign_lregister(int e2,int reg)
 {
+    error(-1);
+}
 
+static int 
+code_l1(long long d)
+{
+    int *i = (int *)&ll0; int *j = (int *)&d;
+    return (i[1] == 1)?j[1]:j[0];
 }
 
-void code_lconst(int e1,int e2)
+static int 
+code_l2(long long d)
 {
+    int *i = (int *)&ll0; int *j = (int *)&d;
+    return (i[1] == 1)?j[0]:j[1];
+}
 
+void
+code_lconst(int e1,int creg)
+{
+    use_longlong(creg);
+    code_const(code_l1(lcadr(e1)),virtual(REG_EAX));
+    code_const(code_l2(lcadr(e1)),virtual(REG_EDX));
 }
 
 void code_lneg(int e1)
 {
-
+    // use_longlong(creg);
+    printf("\tnegl %%eax\n");
+    printf("\tadcl $0,%%edx\n");
+    printf("\tnegl %%edx\n");
 }
 
 void code_lrgvar(int e1,int e2)
 {
-
+    char *n,*crn;
+    n = ((NMTBL*)cadr(e1))->nm;
+    use_longlong(e2);
+    printf("\tmovl %s,%%eax\n",n);
+    printf("\tmovl %s+4,%%edx\n",n);
 }
 
 void code_lrlvar(int e1,int e2)
 {
-
+    use_longlong(e2);
+    printf("\tmovl %d(%%dbp),%%eax\n",lvar(e1));
+    printf("\tmovl %d(%%dbp),%%edx\n",lvar(e1)+4);
 }
 
 void ltosop(int e1,int reg,int e2)
 {
+    char *opl,*oph,*call;
+    int lb;
 
+    use_longlong(reg);
+    opl = 0; call=0;
+
+    switch(op) {
+    case LLSHIFT:
+    case LULSHIFT:
+	printf("\tmovl %%ecx,4(%%esp)\n";);
+	printf("\tpopl %%ecx\n";);
+        printf("\tshldl %%eax,%%edx\n");
+        printf("\tsall %%cl,%%eax\n");
+        printf("\ttestb $32,%%cl\n");
+	printf("\tje\t_%d\n",(lb=fwdlabel()));
+        printf("\tmovl %%eax,%%edx\n");
+        printf("\txorl %%eax,%%eax\n");
+	fwddef(lb);
+	printf("\tpopl %%ecx\n");
+	return;
+    case LRSHIFT:
+	printf("\tmovl %%ecx,4(%%esp)\n";);
+	printf("\tpopl %%ecx\n";);
+        printf("\tshrdl %%eax,%%edx\n");
+        printf("\tsarl %%cl,%%eax\n");
+        printf("\ttestb $32,%%cl\n");
+	printf("\tje\t_%d\n",(lb=fwdlabel()));
+        printf("\tmovl %%edx,%%eax\n");
+        printf("\tsarl $31,%%edx\n");
+	fwddef(lb);
+	printf("\tpopl %%ecx\n");
+	return;
+    case LURSHIFT:
+	printf("\tmovl %%ecx,4(%%esp)\n";);
+	printf("\tpopl %%ecx\n";);
+        printf("\tshrdl %%eax,%%edx\n");
+        printf("\tshrl %%cl,%%eax\n");
+        printf("\ttestb $32,%%cl\n");
+	printf("\tje\t_%d\n",(lb=fwdlabel()));
+        printf("\tmovl %%edx,%%eax\n");
+        printf("\txorl %%edx,%%edx\n");
+	fwddef(lb);
+	printf("\tpopl %%ecx\n");
+	return;
+    }
+    switch(op) {
+    case LADD: opl="addl";oph="adcl"; break;
+    case LSUB: opl="subl";oph="bbl"; break;
+    case LBAND: opl=oph="andl"; break;
+    case LEOR:  opl=oph="xorl"; break;
+    case LBOR:  opl=oph="orl"; break;
+    case LMUL:
+    case LUMUL:
+	printf("\tpushl %%edx\n";);
+	printf("\tpushl %%eax\n";);
+	printf("\tpushl %%ecx\n";);
+	//       4   c_l
+	//       8   c_h
+	//      12   o_l
+	//      16   o_h
+        printf("\tmull 12(%%esp)\n");          //  c_l*o_l -> %edx,%eax
+        printf("\tmovl 4(%%esp),%%ecx\n");     //  c_l->%ecx
+        printf("\timull 16(%%esp),%%ecx\n");   //  c_l*o_h->%ecx
+        printf("\taddl %%ecx,%%edx\n",h);      //  %edx+%ecx->%edx
+        printf("\tmovl 8(%%esp),%%ecx\n");     //  c_h->%ecx
+        printf("\timull 12(%%esp),%%ecx\n");   //  c_h*o_l->%ecx
+        printf("\taddl %%ecx,%%edx\n",h);      //  %edx+%ecx->%edx
+	printf("\tpopl %%ecx\n");
+	printf("\tladd $16,%%esp\n");
+	return;
+    case LDIV:  call="__divdi3"; break;
+    case LUDIV: call="__udivdi3"; break;
+    case LMOD:  call="__moddi3"; break;
+    case LUMOD: call="__umoddi3"; break;
+    default: error(-1);
+    }
+    if (opl) {
+	printf("\t%s (%%esp),%%eax\n\t%s 4(%%esp),%%edx\n",opl,oph);
+	emit_lpop_free(e2);
+    } eles if (call) {
+	printf("\tcall %s\n",call);
+	printf("\tladd $16,%esp\n");
+    }
 }
 
-int code_lconst_op_p(int op,int e) {return 0;}
-void loprtc(int op,int reg,int e) {}
+int code_lconst_op_p(int op,int e) {
+    long long l = lcadr(e);
+    switch(op) {
+    case LLSHIFT:
+    case LULSHIFT:
+    case LRSHIFT:
+    case LURSHIFT:
+	return (0<=l&&l<=32);
+    case LADD:
+    case LSUB:
+    case LBAND
+    case LEOR:
+    case LBOR:
+	return 1;
+    default:
+	return 0;
+    }
+}
+
+void loprtc(int op,int reg,int e) {
+    char *opl,*oph;
+    int lb;
+    int vl = code_l1(lcadr(e));
+    int vh = code_l2(lcadr(e));
+
+    use_longlong(reg);
+    opl = 0;
+
+    switch(op) {
+    case LLSHIFT:
+    case LULSHIFT:
+        printf("\tshldl $%d,%%eax,%%edx\n",vl);
+        printf("\tsall $%d,%%eax\n",vl);
+	return;
+    case LRSHIFT:
+        printf("\tshrdl $%d,%%eax,%%edx\n",vl);
+        printf("\tsarl $%d,%%eax\n",vl);
+	return;
+    case LURSHIFT:
+        printf("\tshrdl $%d,%%eax,%%edx\n",vl);
+        printf("\tshrl $%d,%%eax\n",vl);
+	return;
+    }
+    switch(op) {
+    case LADD: opl="addl";oph="adcl"; break;
+    case LSUB: opl="subl";oph="bbl"; break;
+    case LBAND: opl=oph="andl"; break;
+    case LEOR:  opl=oph="xorl"; break;
+    case LBOR:  opl=oph="orl"; break;
+    default: error(-1);
+    }
+    if (opl) {
+	printf("\t%s $%d,%%eax\n\t%s $%d,%%edx\n",opl,vl,oph,vh);
+    }
+}
 
 void emit_lpop_free(int e1)
 {
-
+    printf("\taddl $8,%%esp\n");
 }
 
 void emit_lpush()
 {
-
+    printf("\tpush %edx\n\tpushl %eax\n");
 }
 
 void code_i2ll()
 {
-    use_int0();
-
+    int reg = USE_CREG;
+    if (virtual(REG_EAX)!=creg)
+	printf("\tmovl %s,%%eax\n",register_name(creg,0));
+    use_longlong0();
+    printf("\tcltd\n");
 }
 
 void code_i2ull()
@@ -2289,7 +2551,11 @@
 
 void code_u2ll()
 {
-
+    int reg = USE_CREG;
+    if (virtual(REG_EAX)!=creg)
+	printf("\tmovl %s,%%eax\n",register_name(creg,0));
+    use_longlong0();
+    printf("\txorl %%edx,%%edx\n");
 }
 
 void code_u2ull()
@@ -2299,73 +2565,89 @@
 
 void code_ll2i()
 {
-
+    int reg = USE_CREG;
+    reg = use_int0();
+    if (virtual(REG_EAX)!=reg)
+	printf("\tmovl %%eax,%s\n",register_name(creg,0));
 }
 
 void code_ll2u()
 {
-
+    code_ll2i();
 }
 
 void code_ull2i()
 {
-
+    code_ll2i();
 }
 
 void code_ull2u()
 {
-
+    code_ll2i();
 }
 
 #if FLOAT_CODE
 void code_d2ll()
 {
-
+    use_longlong0();
+        printf("\tsubl $40,%%esp\n");
+        printf("\tfnstcw 2(%%esp)\n");
+        printf("\tmovw 2(%%esp),%%ax\n");
+        printf("\torw $3072,%%ax\n");
+        printf("\tmovw %%ax,0(%%esp)\n");
+        printf("\tfldcw 0(%%esp)\n");
+        printf("\tfistpll 12(%%esp)\n");
+        printf("\tfldcw 2(%%esp)\n");
+        printf("\tmovl 12(%esp),%%eax\n");
+        printf("\tmovl 16(%esp),%%edx\n");
+        printf("\taddl $40,%%esp\n");
 }
 
 void code_d2ull()
 {
-
+    use_longlong0();
+        printf("\tsubl $16,%%esp\n");
+        printf("\tfstpl (%%esp)\n");
+        printf("\tcall __fixunsdfdi\n");
+        printf("\taddl $16,%%esp\n");
 }
 
 void code_f2ll()
 {
-
+    code_d2ll();
 }
 
 void code_f2ull()
 {
-
+    use_longlong0();
+        printf("\tsubl $16,%%esp\n");
+        printf("\tfstpl (%%esp)\n");
+        printf("\tcall __fixunssfdi\n");
+        printf("\taddl $16,%%esp\n");
 }
 
 void code_ll2d()
 {
-
+        printf("\tsubl $8,%%esp\n");
+        printf("\tmovl %%eax,(%%esp)\n");
+        printf("\tmovl %%edx,4(%%esp)\n");
+        printf("\tfildll (%%esp)\n");
+        printf("\taddl $8,%%esp\n");
 }
 
 void code_ll2f()
 {
-
+    code_ll2d();
 }
 
 void code_ull2d()
 {
-
+    code_ll2d();
 }
 
 void code_ull2f()
 {
-
-}
-
-void code_ull2ll()
-{
-
-}
-
-void code_ull2ull()
-{
-
+    code_ll2d();
 }
 
 #endif
--- a/mc-code-powerpc.c	Thu Apr 29 23:53:31 2004 +0900
+++ b/mc-code-powerpc.c	Fri Apr 30 11:47:51 2004 +0900
@@ -3409,16 +3409,10 @@
 }
 
 int
-lpop_register()
-{
-    return lreg_stack[--lreg_sp];
-}
-
-int
 emit_lpop()
 {
     int xreg,reg;
-    xreg=lpop_register();
+    xreg=lreg_stack[--lreg_sp];
     if (xreg<= -REG_LVAR_OFFSET) {
         reg = get_lregister();
         code_lrlvar(REG_LVAR_OFFSET+xreg,reg);
--- a/mc.h	Thu Apr 29 23:53:31 2004 +0900
+++ b/mc.h	Fri Apr 30 11:47:51 2004 +0900
@@ -11,7 +11,7 @@
 #endif
 
 #define FLOAT_CODE 1
-#define LONGLONG_CODE 0
+#define LONGLONG_CODE 1
 
 #define SIZE_INT   4
 
--- a/test/code-gen.c	Thu Apr 29 23:53:31 2004 +0900
+++ b/test/code-gen.c	Fri Apr 30 11:47:51 2004 +0900
@@ -2,7 +2,7 @@
 /* $Id$ */
 
 #define FLOAT_CODE 1
-#define LONGLONG_CODE 0
+#define LONGLONG_CODE 1
 
 // code_lvar(int e2,int creg)