changeset 318:9fe0b32a7d57

asm continue...
author kono
date Fri, 18 Jun 2004 18:34:42 +0900
parents 3dfac70ef7e1
children 88cf6512fa1b
files Changes mc-code-powerpc.c mc-parse.c mc.h
diffstat 4 files changed, 238 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/Changes	Wed Jun 16 21:13:56 2004 +0900
+++ b/Changes	Fri Jun 18 18:34:42 2004 +0900
@@ -4968,3 +4968,28 @@
 
 association list を使って、unwind すれば良いんだけどね。
 それは、全体的に手直しした方が良い。後回し。
+
+cheap の扱いで boundary を見てないのがいつくあるね。
+
+Thu Jun 17 17:10:21 JST 2004
+
+えーと、
+    "m" とかは、メモリの変更なので見なくてよろしい
+    "r" はレジスタを割り当てる
+    "=" は出力のマークなので無視して良い
+    "+", "&" は出力のマークなので無視して良い
+で、
+    "0"   0番目のoperand
+とかなんだけど... こいつは input (先にコンパイルする方)
+に現れる。だから、output operand を先に処理する。out
+put operand は単純な代入文だから、それでOk。
+
+Fri Jun 18 13:33:19 JST 2004
+
+なんか、%0,%1 とかって、同じレジスタに割り振られることも
+あるみたいね。さらに、連続してでて来るとも限らないみたい。
+
+ってことは?
+
+なんか、間違えた。%0...%8 は、パラメターの順序を
+さしているのね。そうだよな。
--- a/mc-code-powerpc.c	Wed Jun 16 21:13:56 2004 +0900
+++ b/mc-code-powerpc.c	Fri Jun 18 18:34:42 2004 +0900
@@ -4934,13 +4934,198 @@
 
 #if ASM_CODE
 
+/*
+        __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (a
+ddr));
+   asm string : output constraint parameter : input constraint parameter : opt
+
+     1: asm string     %1,%2 will be replaced by register or value
+     2: constraint     gcc constraint sting
+        prefix
+           =    overwrite by this asm for output
+           &    overwrite by this asm and can't be used as input register
+           ignored in this compiler
+        constraints
+           m    value expression is modified (no coresponding register)
+                        information for compiler
+           r    register for input or output 
+			input register, output register can be shared
+           0-9  same operands as outout register in input constraints
+      3: opt     "cc", "memory"
+           ignored in this compiler
+ */
+
+
+#define MAX_ASM_REG 30
+
+static void
+print_asm_reg(int rstr)
+{
+    if (car(rstr)==REGISTER) {
+	printf("%s",register_name(cadr(rstr)));
+    } else if (car(rstr)==CONST) {
+	printf("%d",cadr(rstr));
+    } else if (car(rstr)==STRING) {
+	printf("%s",(char*)cadr(rstr));
+    } else {
+	error(-1);
+    }
+}
+
+static void
+replase_asm_string(char *asm_str,int repl)
+{
+    int c,i,rstr,val,path;
+    char *p;
+    int reg[MAX_ASM_REG];
+
+    c = *asm_str;
+    if (c!='\t'&&c!=' ') printf("\t");
+    for(i=0;i<MAX_ASM_REG;i++) {
+	reg[i] = 0;
+    }
+    // asm parameters %0,%1 may be not contiguous nor starting from 0.
+    // two path execution is necessary. 
+    for(path=1;path<=2;path++) {
+	p = asm_str;
+	if (path==2) {
+	    for(i=0;repl && i<MAX_ASM_REG;i++) {
+		if (reg[i]) {
+		    reg[i] = car(repl);
+		    repl = cadr(repl);
+		}
+	    }
+	}
+	while((c = *p++)) {
+	    if (c=='%') {
+		c = *p++;
+		if (!c) { break;
+		} else if (c=='%') {
+		    if (path==2) printf("%%"); continue;
+		} else if (!digit(c)) {
+		    if (path==2) printf("%%%c",c); continue;
+		}
+		val = 0;
+		do { val = val*10 + c-'0'; } while (digit(c=*asm_str++)) ;
+		asm_str--;
+		if (val>MAX_ASM_REG) error(-1); // too large register
+		if (path==1) {
+		    reg[val] = 1;
+		} else  {
+		    rstr = reg[val];
+		    print_asm_reg(rstr);
+		}
+	    } else {
+		if (path==2) printf("%c",c);
+	    }
+	}
+	if (path==2) printf("\n");
+    }
+}
+
+#define ASM_INPUT  1
+#define ASM_OUTPUT 2
+#define ASM_USED   3
+
+static int
+asm_operand(char *p,int e1,int mode,int repl,int n,int repl0)
+{
+    int r;
+    int c;
+    int val;
+    int clobber = 0;
+
+    printf("# constraint %s\n",p);
+    if (*p=='=') {
+	// output register
+	p++;
+    }
+    if (*p=='&') {
+	// earlyclobber
+	p++;
+	clobber = 1;
+    }
+    c = *p;
+    if (c=='r') {
+	if (mode==ASM_INPUT) {
+	    for(;repl0;repl0 = cadr(repl0)) {
+		if (car(car(repl0))==REGISTER && caddr(repl0)==0) {
+		    r = cadr(car(repl0));
+		    caddr(repl0) = ASM_USED;
+		    break;
+		}
+            }  
+	    r = get_register();
+	} else {
+	    r = get_register();
+	}
+	repl = list3(list2(REGISTER,r),repl,clobber);
+    } else if (c=='m') {
+    } else if (c=='i') {
+	if (car(e1)==GVAR||car(e1)==FNAME) {
+	    e1=list3(STRING,(int)(((NMTBL *)cadr(e1))->nm),0);
+	}
+	if (car(e1)!=CONST && car(e1)!=STRING) error(-1);
+	repl = list3(e1,repl,clobber);
+    } else if (digit(c)) {
+	val = 0;
+	do { val = val*10 + c-'0'; } while (digit(c=*p++));
+	if (val>MAX_ASM_REG) error(-1); // too large register
+	if (n-val<0) error(-1);
+	repl = list3(car(nth(n-val-1,repl0)),repl,clobber);
+    } else error(-1);
+    return repl;
+}
+
+static void
+free_asm_operand(int repl)
+{
+    for(;repl;repl=cadr(repl)) {
+	if (car(car(repl))==REGISTER)
+	    free_register(cadr(car(repl)));
+    }
+}
+
 void
 code_asm(int asm0,int in,int out,int opt,int e)
 {
+    int i,e1,n;
+    int repl = 0;
+    int repl0;
+    int assign = 0;
+    char *p;
+
+    printf("# asm\n");
+    in = reverse0(in);
+    out = reverse0(out);
+    e = reverse0(e);
+    for(i=out;i;i=cadr(i)) {
+	p = (char*)cadr(car(i));
+	e1 = car(e); e = cadr(e);
+	repl = asm_operand(p,e1,ASM_OUTPUT,repl,0,0);
+	if (car(car(repl))==REGISTER) {
+	    assign = list2(assign_expr0(e1,car(repl),INT,INT),assign);
+	}
+    }
+    repl0 = repl;
+    n = length(repl0);
+    for(i=in;i;i=cadr(i)) {
+	p = (char*)cadr(car(i));
+	e1 = car(e); e = cadr(e);
+	repl = asm_operand(p,e1,ASM_INPUT,repl,n,repl0);
+	if (car(car(repl))==REGISTER) {
+	    g_expr_u(assign_expr0(car(repl),e1,INT,INT));
+	}
+    }
+    replase_asm_string((char*)cadr(asm0),repl);
+    for(i=assign;i;i=cadr(i)) {
+	g_expr_u(car(i));
+    }
+    free_asm_operand(repl);
+    // no check for opt 
 }
 
 #endif
 
 
 /* end */
-
--- a/mc-parse.c	Wed Jun 16 21:13:56 2004 +0900
+++ b/mc-parse.c	Fri Jun 18 18:34:42 2004 +0900
@@ -12,12 +12,10 @@
 static NMTBL *msearch(char *name);
 static NMTBL *msearch0(char *name);
 static char * mappend(int lists);
-static int alpha(char c);
 static int append3(int p,int a1,int a2);
 static int binop(int op, int e1, int e2, int t1, int t2);
 static int cexpr(int e);
 static int decl_data(int t, NMTBL *n,int offset,int skip);
-static int digit(char c);
 static int expr(int);
 static int expr0(void);
 static int expr1(void);
@@ -4261,14 +4259,14 @@
     return sym=s1;
 }
 
-static int
-alpha(char c)
+int
+alpha(int c)
 {
     return(('a'<=c&&c<='z')||('A'<=c&&c<='Z')||c=='_');
 }
 
-static int
-digit(char c)
+int
+digit(int c)
 {
     return('0'<=c&&c<='9');
 }
@@ -5271,6 +5269,25 @@
 }
 
 int
+length(int list)
+{
+    int n=0;
+    for(;list;n++) {
+	list = cadr(list);
+    }
+    return n;
+}
+
+int
+nth(int n, int list)
+{
+    while(n-->0) {
+	list = cadr(list);
+    }
+    return list;
+}
+
+int
 insert_ascend(int p,int e,int eq())
 {
     int p1,p2,dup;
--- a/mc.h	Wed Jun 16 21:13:56 2004 +0900
+++ b/mc.h	Fri Jun 18 18:34:42 2004 +0900
@@ -480,6 +480,8 @@
 extern int list2(int e1, int e2);
 extern int list3(int e1, int e2, int e3);
 extern int list4(int e1, int e2, int e3,int e4);
+extern int length(int e1);
+extern int nth(int n,int e1);
 extern int reverse0(int t1);
 extern int assign_data(int e, int t, NMTBL *n,int offset);
 extern int assign_expr0(int e1,int e2,int t,int type) ;
@@ -531,6 +533,8 @@
 EXTERN int list3(int e1, int e2, int e3);
 EXTERN int list4(int e1, int e2, int e3, int e4);
 EXTERN int reverse0(int t1);
+EXTERN int digit(int c);
+EXTERN int alpha(int c);
 /*
 EXTERN int rplacad(int e, int n);
 EXTERN int rplacadd(int e, int n);