changeset 126:1d1612fe705a

*** empty log message ***
author kono
date Wed, 26 Mar 2003 16:50:12 +0900
parents e537da31dce3
children eb4d8975926c
files .gdbinit Changes Makefile mc-code-ia32.c mc-code-powerpc.c mc-code.h mc-codegen.c mc-parse.c
diffstat 8 files changed, 215 insertions(+), 169 deletions(-) [+]
line wrap: on
line diff
--- a/.gdbinit	Mon Mar 24 12:15:53 2003 +0900
+++ b/.gdbinit	Wed Mar 26 16:50:12 2003 +0900
@@ -1,5 +1,5 @@
 tb main
-r -s test/tmp7.c
+r -s test/fact-a.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	Mon Mar 24 12:15:53 2003 +0900
+++ b/Changes	Wed Mar 26 16:50:12 2003 +0900
@@ -2495,4 +2495,104 @@
 良かったかも。
 
 
-
+        stwu r1,lo16(-L_9)(r1)
+とかしているから、局所変数は64k以内ってことだね。haしてもいいんだけどさ。
+
+Mon Mar 24 17:07:59 JST 2003
+
+さて、ようやっと fact-a.c に取り掛かれるわけだけど、今のままだと、
+    input register -> メモリへのsave
+ってのがあるんだよね。これはいただけない。sub routine call すると、
+r0-r10 は破壊されちゃうし。ということは、code segment の引数は、
+r29-r20 が良いんじゃないか? 浮動小数点f31-f20を含めて。
+
+問題は、どこでinput register を指定するかだけど、get_input_register_var
+で code 用かどうかを指定するのが良いかな。fnptr ではダメなので明示した
+方が良いだろう。
+
+r31, r1 の設定があるのはやむを得まい。r1=r30であった方が良いのだろうか?
+その方がfunction calll の時の変更が少ないだろう。
+
+メモリとinput register (この場合はr29-r20,f21-f20だけど)の対応は
+どうする? 通常だと呼出側が確保するわけだけど、そうはいかないね。
+レジスタもsaveする必要が無いから、いろいろ簡単でよろしい。
+
+あとは、return/environment の扱いだけど。ia32 の方でもいろいろ
+動かなくなっているようだな。
+
+Mon Mar 24 21:56:47 JST 2003
+
+うーん、別にフレームを変えないで、そのままでいいか。
+その方が楽だよね。return しようと思うといちいち
+frame をうごかさないといけないけど、return は
+別処理するんだから、いらないか。
+
+Wed Mar 26 14:29:21 JST 2003
+
+で、フレームを変えないとすると、
+    
+                       <------r1_offset------------------------------>
+                      *               <------------lvar_offset------->
+ r+  +------------+---+---------------+----------+--------------+----+    -
+      callee arg   xx   register save ! local      caller arg     xx
+                          reg_save      disp       max_func_args*size_of_int
+        lvar>0                         lvar<0       lvar>0x1000 0000
+
+なので、r1/r30 を常に移動させる必要がある。前のcode segement/
+function がどこにr1/r30を持っていたかを知る手段はないので、
+jump する前に糢とに戻す必要がある。r30が固定ならばr1のみの
+修正で良く、前に戻す必要はない。
+
+でも、r1_offset 分を戻せば良いだけなんだから、r30を * に固定
+しても良いんじゃないか? ! でもいいんだけど。こっちの方が簡単
+かな? code の場合は register_save は 0 (つまり、マイナス)な
+わけだから。(まぁ、穴を開けておいても良いけど) 
+
+Intel の場合はどうして、こうしなかったのか? (でも、最後にチェック
+した時にはcore dumpしていたが...)
+
+                      ebp                        <-----esp----------->
+                       <------r1_offset------------------------------>
+                      *               <------------lvar_offset------->
+ r+  +------------+---+---------------+----------+--------------+----+    -
+      callee arg   xx   register save ! local      caller arg     xx
+                          reg_save      disp       max_func_args*size_of_int
+        lvar>0                         lvar<0       lvar>0x1000 0000
+
+というわけなので、* にそろえる方が intel 版とも一致する。
+ってことは、ebp の移動は intel でもやっていたってこと?
+いやfunctionではこうなっているんだけど、code では違う。
+
+
+     ebp                                         <-----esp----------->
+                       <------r1_offset------------------------------>
+                      *               <------------lvar_offset------->
+ r+  +------------+---+---------------+----------+--------------+----+    -
+      callee arg   xx   register save ! local      caller arg     xx
+                          reg_save      disp       max_func_args*size_of_int
+        lvar>0                         lvar<0       lvar>0x1000 0000
+
+ってわけか。とすると powerpc では、
+
+     r30               <------r1_offset------------------------------> r1
+     #                *               <------------lvar_offset------->
+ r+  +------------+---+---------------+----------+--------------+----+    -
+  xx  callee arg   zz   register save ! local      caller arg     zz
+                          reg_save      disp       max_func_args*size_of_int
+        lvar>0                         lvar<0       lvar>0x1000 0000
+
+の#にr30を固定してr1をずらすことになる。やっぱ、こっちだよね。
+zz はから。xx に、base  となる関数呼び出しが来る。から、
+calle arg は破壊される。
+
+どっちも可能だな。両方実装する? やっぱり後者からかな。gcc は
+前者の方が簡単だろう。
+
+入力変数をレジスタに割り振ってしまうと、その範囲では
+簡単に動いてしまう。(そりゃ、そうだ...)
+
+goto with environment で構造体を返すのには注意が必要。
+どこでコピーする? goto した場所? return-continuation?
+そうねぇ。return-continuation 側が普通でしょう。あぁ、
+でも返し先は元の関数呼び出しの引数上だから壊れちゃって
+いるかもね。だから、とっておく実装の方が良いわけね。
--- a/Makefile	Mon Mar 24 12:15:53 2003 +0900
+++ b/Makefile	Wed Mar 26 16:50:12 2003 +0900
@@ -3,18 +3,20 @@
 BASE=0
 STAGE=1
 MFLAGS=$(MFALGS) BASE=$(BASE) STAGE=$(STAGE)
-MC=mc
+ARCH=powerpc
+MC=mc-$(ARCH)
+# MLIB = -lm
 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.c
-CODE=mc-code-powerpc.c
+CODE=mc-code-$(ARCH).c
 
 all: mc mc-ia32 mc-powerpc
 
-mc:  mc-powerpc
-	cp mc-powerpc mc
+mc:  mc-$(ARCH)
+	cp mc-$(ARCH) mc
 
 mc-powerpc : mc-code-powerpc.o $(COMPLIB) $(CONVERTER)
 	$(CC) -g mc-code-powerpc.o $(COMPLIB) $(CONVERTER) -o $@
@@ -48,10 +50,10 @@
 	make check TARGET=test/tmp9
 
 check: $(MC)
-	-gcc $(TARGET).c -o b.out
+	-gcc $(TARGET).c -o b.out $(MLIB)
 	-./b.out > $(TARGET).gcc.out
 	-./$(MC) -s $(TARGET).c
-	-gcc $(TARGET).s
+	-gcc $(TARGET).s -$(MLIB)
 	-./a.out > $(TARGET).$(MC).out
 	-diff  $(TARGET).gcc.out $(TARGET).$(MC).out
 
@@ -86,62 +88,3 @@
 
 # DO NOT DELETE
 
-mc-code-ia32.o: mc.h /usr/include/stdio.h /usr/include/sys/types.h
-mc-code-ia32.o: /usr/include/sys/appleapiopts.h /usr/include/sys/cdefs.h
-mc-code-ia32.o: /usr/include/machine/types.h /usr/include/ppc/types.h
-mc-code-ia32.o: /usr/include/machine/ansi.h /usr/include/ppc/ansi.h
-mc-code-ia32.o: /usr/include/machine/endian.h /usr/include/ppc/endian.h
-mc-code-ia32.o: conv/conv.h mc-codegen.h
-mc-codegen.o: mc.h /usr/include/stdio.h /usr/include/sys/types.h
-mc-codegen.o: /usr/include/sys/appleapiopts.h /usr/include/sys/cdefs.h
-mc-codegen.o: /usr/include/machine/types.h /usr/include/ppc/types.h
-mc-codegen.o: /usr/include/machine/ansi.h /usr/include/ppc/ansi.h
-mc-codegen.o: /usr/include/machine/endian.h /usr/include/ppc/endian.h
-mc-codegen.o: conv/conv.h mc-codegen.h mc-code.h
-mc-parse.o: mc.h /usr/include/stdio.h /usr/include/sys/types.h
-mc-parse.o: /usr/include/sys/appleapiopts.h /usr/include/sys/cdefs.h
-mc-parse.o: /usr/include/machine/types.h /usr/include/ppc/types.h
-mc-parse.o: /usr/include/machine/ansi.h /usr/include/ppc/ansi.h
-mc-parse.o: /usr/include/machine/endian.h /usr/include/ppc/endian.h
-mc-parse.o: conv/conv.h mc-codegen.h
-mc-tree.o: mc.h /usr/include/stdio.h /usr/include/sys/types.h
-mc-tree.o: /usr/include/sys/appleapiopts.h /usr/include/sys/cdefs.h
-mc-tree.o: /usr/include/machine/types.h /usr/include/ppc/types.h
-mc-tree.o: /usr/include/machine/ansi.h /usr/include/ppc/ansi.h
-mc-tree.o: /usr/include/machine/endian.h /usr/include/ppc/endian.h
-mc-tree.o: conv/conv.h
-mc.o: /usr/include/stdio.h /usr/include/sys/types.h
-mc.o: /usr/include/sys/appleapiopts.h /usr/include/sys/cdefs.h
-mc.o: /usr/include/machine/types.h /usr/include/ppc/types.h
-mc.o: /usr/include/machine/ansi.h /usr/include/ppc/ansi.h
-mc.o: /usr/include/machine/endian.h /usr/include/ppc/endian.h conv/conv.h
-conv/c.o: mc.h /usr/include/stdio.h /usr/include/sys/types.h
-conv/c.o: /usr/include/sys/appleapiopts.h /usr/include/sys/cdefs.h
-conv/c.o: /usr/include/machine/types.h /usr/include/ppc/types.h
-conv/c.o: /usr/include/machine/ansi.h /usr/include/ppc/ansi.h
-conv/c.o: /usr/include/machine/endian.h /usr/include/ppc/endian.h conv/conv.h
-conv/c.o: conv/convdef.h conv/c.h
-conv/c2cbc.o: mc.h /usr/include/stdio.h /usr/include/sys/types.h
-conv/c2cbc.o: /usr/include/sys/appleapiopts.h /usr/include/sys/cdefs.h
-conv/c2cbc.o: /usr/include/machine/types.h /usr/include/ppc/types.h
-conv/c2cbc.o: /usr/include/machine/ansi.h /usr/include/ppc/ansi.h
-conv/c2cbc.o: /usr/include/machine/endian.h /usr/include/ppc/endian.h
-conv/c2cbc.o: conv/conv.h
-conv/cbc2c.o: mc.h /usr/include/stdio.h /usr/include/sys/types.h
-conv/cbc2c.o: /usr/include/sys/appleapiopts.h /usr/include/sys/cdefs.h
-conv/cbc2c.o: /usr/include/machine/types.h /usr/include/ppc/types.h
-conv/cbc2c.o: /usr/include/machine/ansi.h /usr/include/ppc/ansi.h
-conv/cbc2c.o: /usr/include/machine/endian.h /usr/include/ppc/endian.h
-conv/cbc2c.o: conv/conv.h
-conv/null.o: mc.h /usr/include/stdio.h /usr/include/sys/types.h
-conv/null.o: /usr/include/sys/appleapiopts.h /usr/include/sys/cdefs.h
-conv/null.o: /usr/include/machine/types.h /usr/include/ppc/types.h
-conv/null.o: /usr/include/machine/ansi.h /usr/include/ppc/ansi.h
-conv/null.o: /usr/include/machine/endian.h /usr/include/ppc/endian.h
-conv/null.o: conv/conv.h conv/convdef.h conv/null.h
-mc-code-powerpc.o: mc.h /usr/include/stdio.h /usr/include/sys/types.h
-mc-code-powerpc.o: /usr/include/sys/appleapiopts.h /usr/include/sys/cdefs.h
-mc-code-powerpc.o: /usr/include/machine/types.h /usr/include/ppc/types.h
-mc-code-powerpc.o: /usr/include/machine/ansi.h /usr/include/ppc/ansi.h
-mc-code-powerpc.o: /usr/include/machine/endian.h /usr/include/ppc/endian.h
-mc-code-powerpc.o: conv/conv.h mc-codegen.h
--- a/mc-code-ia32.c	Mon Mar 24 12:15:53 2003 +0900
+++ b/mc-code-ia32.c	Wed Mar 26 16:50:12 2003 +0900
@@ -213,18 +213,22 @@
 }
 
 int 
-get_input_register_var(int i,NMTBL *nptr)
+get_input_register_var(int i,NMTBL *nptr,int is_code)
 {
-    i =  virtual(i+REG_ESI);
-    regs[i]=regv[i]=1;
-    return list3(REGISTER,i,(int)nptr);
+    if (is_code) {
+	if (i>=MAX_CODE_INPUT_REGISTER_VAR) return 0;
+	i =  virtual(i+REG_ESI);
+	regs[i]=regv[i]=1;
+	return list3(REGISTER,i,(int)nptr);
+    } else {
+	return 0;
+    }
 }
 
 int 
-get_input_fregister_var(int i,NMTBL *nptr)
+get_input_fregister_var(int i,NMTBL *nptr,int is_code)
 {
-    error(-1);
-    return -1;
+    return 0;
 }
 
 int 
--- a/mc-code-powerpc.c	Mon Mar 24 12:15:53 2003 +0900
+++ b/mc-code-powerpc.c	Wed Mar 26 16:50:12 2003 +0900
@@ -116,25 +116,11 @@
 int my_func_args;
 #define ARG_LVAR_OFFSET 0x10000000
 
-/*
-                                           -16  -8 local2   <-- r30
-                                           -12  -4 local1
-                                            -8  8  arg3
-                                            -4  4  arg2
-                                             0  0  arg1
-         local2     -20 4                    0    (r5)
-         local1 <-- -16 0 local variable     0    (r4)
-                    -12  <- disp_offset          %ebp
-        r30 (sp)     -8
-                      0   <- r1
-        r1  (fp)      8   <- arg_offset
-          arg1        8 0
-          arg2       12 4
-            see enter/enter1/leave           see code_enter
+/*          
 
      r0    return value etc.
      r3-r10  input register
-     r22-r29 saved register variable
+     r22-r29 saved register variable (input register for code segement)
      r30   stack pointer
      r31   0
      r1    frame pointer
@@ -162,11 +148,14 @@
 void
 code_offset_set()
 {
+#if 0
     int l;
+#endif
     int lvar_offsetv = -disp+max_func_args*size_of_int+func_disp_offset;
     int r1_offsetv = -disp+max_func_args*size_of_int-reg_save+r1_offset;
     printf(".set L_%d,%d\n",lvar_offset_label,lvar_offsetv);
     printf(".set L_%d,%d\n",r1_offset_label,r1_offsetv);
+#if 0
 printf("# function %s\n",fnptr->nm);
     l = ARG_LVAR_OFFSET;
 printf("# offset call0\t%d\n",CALLER_ARG);
@@ -183,6 +172,7 @@
 printf("# offset carg0\t%d\n",CALLEE_ARG+r1_offsetv);
     l = my_func_args;
 printf("# offset cargn\t%d %d\n",CALLEE_ARG+r1_offsetv,my_func_args);
+#endif
 }
 
 
@@ -190,7 +180,7 @@
 lvar8(int l)
 {
     if (fnptr->sc==CODE) {
-	printf("lo16(%d+L_%d)(r30)\n",CODE_LVAR,lvar_offset_label);
+	printf("lo16(%d)(r30)\n",CODE_LVAR);
     } else if (l<0) {  /* local variable */
 	printf("lo16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label);
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
@@ -213,7 +203,7 @@
 lvar16ha(int l)
 {
     if (fnptr->sc==CODE) {
-	printf("la r0,ha16(%d+L_%d)(r30)\n",CODE_LVAR,lvar_offset_label);
+	printf("la r0,ha16(%d)(r30)\n",CODE_LVAR);
     } else if (l<0) {  /* local variable */
 	printf("la r0,ha16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label);
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
@@ -228,7 +218,7 @@
 lvar16lo(int l)
 {
     if (fnptr->sc==CODE) {
-	printf("lo16(%d+L_%d)(r0)\n",CODE_LVAR,lvar_offset_label);
+	printf("lo16(%d)(r0)\n",CODE_LVAR);
     } else if (l<0) {  /* local variable */
 	printf("lo16(%d+L_%d)(r0)\n",FUNC_LVAR,lvar_offset_label);
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
@@ -269,10 +259,10 @@
 void
 code_arg_register()
 {
-    code_save_input_registers();
+    if (is_function(fnptr))
+	code_save_input_registers();
 }
 
-
 int 
 get_register(void)
 {    /* 使われていないレジスタを調べる */
@@ -359,17 +349,30 @@
 }
 
 int
-get_input_fregister_var(int i,NMTBL *n)
+get_input_fregister_var(int i,NMTBL *n,int is_code)
 {
-    if (i<0||MAX_FREGISTER<i+MIN_TMP_FREG) error(-1);
-    return list3(DREGISTER,i+MIN_TMP_FREG,(int)n);
+    if (is_code) {
+	if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0;
+	i = REG_VAR_BASE-i;
+    } else {
+	if (i<0||MAX_FREGISTER<i+MIN_TMP_FREG) return 0;
+	return list3(DREGISTER,i+MIN_TMP_FREG,(int)n);
+	i = i+MIN_TMP_FREG;
+    }
+    return list3(DREGISTER,i,(int)n);
 }
 
 int
-get_input_register_var(int i,NMTBL *n)
+get_input_register_var(int i,NMTBL *n,int is_code)
 {
-    if (i<0||MAX_REGISTER<i+MIN_TMP_REG) error(-1);
-    return list3(REGISTER,i+MIN_TMP_REG,(int)n);
+    if (is_code) {
+	if(!(i<FREG_VAR_BASE-FREG_VAR_MIN)) return 0;
+	i = REG_VAR_BASE-i;
+    } else {
+	if (i<0||MAX_REGISTER<i+MIN_TMP_REG) return 0;
+	i = i+MIN_TMP_REG;
+    }
+    return list3(REGISTER,i,(int)n);
 }
 
 int
@@ -415,25 +418,20 @@
 void
 register_usage(char *s)
 {
+#if 0
     int i;
+#endif
     if (chk) return;
     if (!lsrc) return;
     printf("# %d: %s:",lineno,s);
-    printf(" creg=%s fgreg=%s\n# regs:",register_name(creg),fregister_name(freg));
+    printf(" creg=%s fgreg=%s",register_name(creg),fregister_name(freg));
 #if 0
-    for(i=0;i<MAX_REGISTER;i++) {
-	printf("%d",regv[i]);
-    }
+    printf("\n# regs:");
+    for(i=0;i<MAX_REGISTER;i++) { printf("%d",regv[i]); }
     printf(":");
-#endif
-    for(i=0;i<MAX_REGISTER;i++) {
-	printf("%d",regs[i]);
-    }
+    for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i]); }
     printf("\n# freg:");
-    for(i=0;i<MAX_FREGISTER;i++) {
-	printf("%d",fregs[i]);
-    }
-#if 0
+    for(i=0;i<MAX_FREGISTER;i++) { printf("%d",fregs[i]); }
     printf(" regs_stack",register_name(creg),register_name(dreg));
     for(i=reg_sp;i>=0;i--) {
 	if(reg_stack[i]>=0)
@@ -908,7 +906,8 @@
 
 void
 code_environment(int creg) {
-    printf("\tmr %s,r1\n",register_name(creg));
+    /* save frame pointer */
+    printf("\tmr %s,r30\n",register_name(creg));
 }
 
 
@@ -1328,10 +1327,10 @@
 	    } else if (!simple_args(e3) && cadr(e3)) {
 		arg = get_register_var(0); 
 		arg_assign = list2(
-		    assign_expr0(get_input_register_var(reg_arg,0),arg,t,t),
+		    assign_expr0(get_input_register_var(reg_arg,0,0),arg,t,t),
 		    arg_assign);
 	    } else {
-		arg = get_input_register_var(reg_arg,0); 
+		arg = get_input_register_var(reg_arg,0,0); 
 	    }
 	    use_var(arg); /* protect from input register free */
 	    reg_arg_list = list2(arg,reg_arg_list);
@@ -1354,8 +1353,8 @@
 		    e4 = list2(DREGISTER,freg);
 		    /* freg should not change until XXX */
 		}
-		r0=get_input_register_var(reg_arg,0);
-		r1=get_input_register_var(reg_arg+1,0);
+		r0=get_input_register_var(reg_arg,0,0);
+		r1=get_input_register_var(reg_arg+1,0,0);
 		use_var(r0); /* protect from input register free */
 		use_var(r1); /* protect from input register free */
 		reg_arg_list = list2(r0,reg_arg_list);
@@ -1373,7 +1372,7 @@
                  */
 		arg_assign = list2(
 		    assign_expr0(list2(LVAR,caller_arg_offset_v(nargs)),
-			    get_input_fregister_var(freg_arg,0),t,t),
+			    get_input_fregister_var(freg_arg,0,0),t,t),
 		    arg_assign);
 	    }
 	    if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
@@ -1381,10 +1380,10 @@
 	    } else if (!simple_args(e3)) {
 		arg = get_fregister_var(0); 
 		arg_assign = list2(
-		    assign_expr0(get_input_fregister_var(freg_arg,0),arg,t,t),
+		    assign_expr0(get_input_fregister_var(freg_arg,0,0),arg,t,t),
 		    arg_assign);
 	    } else {
-		arg = get_input_fregister_var(freg_arg,0); 
+		arg = get_input_fregister_var(freg_arg,0,0); 
 	    }
 	    use_var(arg); /* protect from input register free */
 	    reg_arg_list = list2(arg,reg_arg_list);
@@ -1433,7 +1432,7 @@
 
 void
 code_frame_pointer(int e3) {
-    printf("\tmr %s,r1\n",register_name(e3));
+    printf("\tmr r30,%s\n",register_name(e3));
 }
 
 
@@ -1725,8 +1724,6 @@
     printf("## %s",s);
 }
 
-static int code_begin;
-
 void
 code_enter(char *name)
 {
@@ -1736,12 +1733,15 @@
 	printf("\t.align 2\n");
     if (stmode!=STATIC)
 	printf(".globl _%s\n",name);
-/*
+#ifdef DOT_SIZE
     printf("\t.type\t%s,@function\n",name);
- */
+#endif
     printf("_%s:\n",name);
     code_disp_label=fwdlabel();
-    printf("\tla r30,L_%d(r30)\n",code_disp_label);
+    printf("\tstwu r1,lo16(L_%d)(r30)\n",code_disp_label);
+    printf("\tbcl 20,31,L_%d\n",code_base = fwdlabel());
+    fwddef(code_base);
+    printf("\tmflr r31\n");
     max_func_args = 0;
 }
 
@@ -1758,9 +1758,7 @@
 code_leave(char *name)
 {
     disp&= -size_of_int;
-    printf("\t.set L_%d,%d\n",code_disp_label,disp+code_disp_offset);
-    printf("L_%d:\n",labelno);
-    printf("\t.size\t_%s,L_%d-L_%d\n",name,labelno,code_begin);
+    printf(".set L_%d,%d\n",code_disp_label,disp+code_disp_offset);
     local_table();
     labelno++;
     free_all_register();
@@ -1815,7 +1813,16 @@
     if (control) {
 	code_set_return_register(1);
     }
-    if (retcont) fwddef(retcont);
+    if (retcont) { 
+	if (control) jmp(retlabel);
+	fwddef(retcont);
+	printf("\tmr r1,r30\n");
+	if (cadr(fnptr->ty)==FLOAT||cadr(fnptr->ty)==DOUBLE) {
+	    printf("\tfmr f1,f31\n");
+	} else if (cadr(fnptr->ty)!=VOID) {
+	    printf("\tmr r3,r29\n");
+	}
+    }
     fwddef(retlabel);
     printf("\tlwz r1,0(r1)\n");
     if (max_freg_var>=0 && max_freg_var<=3) max_freg_var=3; 
@@ -1965,17 +1972,17 @@
 void
 emit_data_closing(NMTBL *n)
 {
-/*
+#ifdef DOT_SIZE
     int lb;
- */
+#endif
     if (chk) return;
     if (mode==GDECL) {
 	data_mode(0);
-/*
+#ifdef DOT_SIZE
 	lb=fwdlabel();
 	printf("L_%d:\n",lb);
 	printf("\t.size\t%s,L_%d-%s\n",n->nm,lb,n->nm);
- */
+#endif
     }
 }
 
--- a/mc-code.h	Mon Mar 24 12:15:53 2003 +0900
+++ b/mc-code.h	Wed Mar 26 16:50:12 2003 +0900
@@ -23,8 +23,8 @@
 extern int register_var(int r);
 extern int get_register_var(NMTBL *n);
 extern int get_fregister_var(NMTBL *n);
-extern int get_input_register_var(int,NMTBL *);
-extern int get_input_fregister_var(int,NMTBL *);
+extern int get_input_register_var(int,NMTBL *,int);
+extern int get_input_fregister_var(int,NMTBL *,int);
 extern void emit_push();
 extern int emit_pop(int type);
 extern void gexpr_code_init();
--- a/mc-codegen.c	Mon Mar 24 12:15:53 2003 +0900
+++ b/mc-codegen.c	Wed Mar 26 16:50:12 2003 +0900
@@ -441,6 +441,20 @@
     }
 }
 
+int 
+is_code(NMTBL *fnptr)
+{
+    int type = fnptr->ty;
+    return type==CODE|| (type>0 && car(type)==CODE);
+}
+
+int 
+is_function(NMTBL *fnptr)
+{
+    int type = fnptr->ty;
+    return type==FUNCTION || (type>0 && car(type)==FUNCTION);
+}
+
 
 void
 arg_register(NMTBL *fnptr)
@@ -450,38 +464,30 @@
     int reg_var = 0;
     int freg_var = 0;
     int type;
-    int max_input_register_var;
-    int max_input_fregister_var;
-
-    if (is_function(fnptr)) {
-	max_input_register_var = MAX_INPUT_REGISTER_VAR;
-	max_input_fregister_var = MAX_INPUT_DREGISTER_VAR;
-    } else {
-	max_input_register_var = MAX_CODE_INPUT_REGISTER_VAR;
-	max_input_fregister_var = MAX_CODE_INPUT_DREGISTER_VAR;
-    }
+    int reg;
+    int is_code0 = is_code(fnptr);
 
     while (args) {
 	/* process in reverse order */
         n = (NMTBL*)caddr(args);
 	type = n->ty;
         if (scalar(type)) {
-            if(reg_var<max_input_register_var) {
+	    if ((reg = get_input_register_var(reg_var,n,is_code0))) {
                 n->sc = REGISTER;
-		n->dsp = cadr(get_input_register_var(reg_var,n));
+		n->dsp = cadr(reg);
 		regv[n->dsp]= 1;
 		regs[n->dsp]= INPUT_REG;
                 reg_var++;
                 cadddr(args)=size_of_int; /* why we need this? */
             }
         } else if (type==FLOAT||type==DOUBLE) {
-            if(freg_var<max_input_fregister_var) {
+	    if ((reg = get_input_fregister_var(freg_var,n,is_code0))) {
                 n->sc = DREGISTER;
-		n->dsp = cadr(get_input_fregister_var(freg_var,n));
+		n->dsp = cadr(reg);
 		fregv[n->dsp]= 1;
 		fregs[n->dsp]= INPUT_REG;
                 freg_var++;
-                cadddr(args)=size_of_double; /* why we need this? */
+                cadddr(args)=size(type); /* why we need this? */
             }
         }
 	args = cadr(args);
@@ -719,20 +725,6 @@
     );
 }
 
-int 
-is_code(NMTBL *fnptr)
-{
-    int type = fnptr->ty;
-    return type==CODE|| (type>0 && car(type)==CODE);
-}
-
-int 
-is_function(NMTBL *fnptr)
-{
-    int type = fnptr->ty;
-    return type==FUNCTION || (type>0 && car(type)==FUNCTION);
-}
-
 
 void
 jump(int e1, int env)
@@ -753,11 +745,11 @@
 	e2 = car(e3); sz = size(ty=caddr(e3)); 
 	if (scalar(ty) && 
 		regs < MAX_CODE_INPUT_REGISTER_VAR) {
-	    target=list4(get_input_register_var(regs++,0), 
+	    target=list4(get_input_register_var(regs++,0,1), 
 		    target,ty,e2);
 	} else if ((ty==DOUBLE||ty==FLOAT) && 
 		fregs < MAX_CODE_INPUT_DREGISTER_VAR) {
-	    target=list4(get_input_fregister_var(fregs++,0), 
+	    target=list4(get_input_fregister_var(fregs++,0,1), 
 		    target,ty,e2);
 	} else {
 	    target=list4(list2(LVAR,0), target,ty,e2);
--- a/mc-parse.c	Mon Mar 24 12:15:53 2003 +0900
+++ b/mc-parse.c	Wed Mar 26 16:50:12 2003 +0900
@@ -583,8 +583,8 @@
 		    stmode=sstmode;
 		}
 		type=glist3(FUNCTION,type,t);
-		n->ty=type;
 	    }
+	    n->ty=type;
             /* 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  */