changeset 667:dbfbeb05210c before-ia32-function

*** empty log message ***
author kono
date Tue, 01 May 2007 13:26:42 +0900
parents 7c42cf329666
children adbb9c25eb1a
files Makefile.powerpc mc-code-powerpc.c mc-parse.c test/stackframe.c
diffstat 4 files changed, 268 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.powerpc	Mon Apr 30 02:19:48 2007 +0900
+++ b/Makefile.powerpc	Tue May 01 13:26:42 2007 +0900
@@ -55,6 +55,9 @@
 mc-arm : mc-code-arm.o $(COMPLIB) $(CONVERTER)
 	$(CC) $(LDFLAGS) -g mc-code-arm.o $(COMPLIB) $(CONVERTER) -o $@
 
+mc-spu : mc-code-arm.o $(COMPLIB) $(CONVERTER)
+	$(CC) $(LDFLAGS) -g mc-code-spu.o $(COMPLIB) $(CONVERTER) -o $@
+
 conv/conv.h: conv_func.tbl tools/conv_func.pl
 	perl tools/conv_func.pl
 conv/convdef.h: conv_func.tbl tools/conv_func.pl
--- a/mc-code-powerpc.c	Mon Apr 30 02:19:48 2007 +0900
+++ b/mc-code-powerpc.c	Tue May 01 13:26:42 2007 +0900
@@ -34,7 +34,9 @@
 // #undef __APPLE__
 
 static
-char *init_src0 = "\
+char *init_src0 = 
+#ifdef __APPLE__
+"\
 #define __ppc__ 1\n\
 #define __BIG_ENDIAN__ 1\n\
 #define __STDC__ 1\n\
@@ -49,6 +51,103 @@
 #define    __DBL_MIN__ 2.2250738585072014e-308\n\
 #define    __LDBL_MIN__ 2.00416836000897277799610805135016e-292L\n\
 "
+#else 
+"\
+#define __inline inline\n\
+#define __extension__\n\
+#define __const const\n\
+#define __inline__ inline\n\
+#define __builtin_va_list int\n\
+#define __builtin_va_start(ap,arg) ap=(((int)(&arg))+sizeof(arg))\n\
+#define __builtin_va_arg(ap,type)  (*((type *)ap)++)\n\
+#define alloca __builtin_alloca\n\
+#define __DBL_MIN_EXP__ (-1021)\n\
+#define __FLT_MIN__ 1.17549435e-38F\n\
+#define __CHAR_BIT__ 8\n\
+#define __WCHAR_MAX__ 2147483647\n\
+#define __DBL_DENORM_MIN__ 4.9406564584124654e-324\n\
+#define __FLT_EVAL_METHOD__ 0\n\
+#define __DBL_MIN_10_EXP__ (-307)\n\
+#define __FINITE_MATH_ONLY__ 0\n\
+#define __GNUC_PATCHLEVEL__ 0\n\
+#define __SHRT_MAX__ 32767\n\
+#define __LDBL_MAX__ 1.79769313486231580793728971405301e+308L\n\
+#define __UINTMAX_TYPE__ long long unsigned int\n\
+#define __linux 1\n\
+#define __CHAR_UNSIGNED__ 1\n\
+#define __LDBL_MAX_EXP__ 1024\n\
+#define __linux__ 1\n\
+#define __SCHAR_MAX__ 127\n\
+#define __USER_LABEL_PREFIX__ \n\
+#define __STDC_HOSTED__ 1\n\
+#define __LDBL_HAS_INFINITY__ 1\n\
+#define __DBL_DIG__ 15\n\
+#define __FLT_EPSILON__ 1.19209290e-7F\n\
+#define _CALL_SYSV 1\n\
+#define __LDBL_MIN__ 2.00416836000897277799610805135016e-292L\n\
+#define __unix__ 1\n\
+#define __DECIMAL_DIG__ 33\n\
+#define __gnu_linux__ 1\n\
+#define __LDBL_HAS_QUIET_NAN__ 1\n\
+#define __GNUC__ 4\n\
+#define __DBL_MAX__ 1.7976931348623157e+308\n\
+#define __DBL_HAS_INFINITY__ 1\n\
+#define __DBL_MAX_EXP__ 1024\n\
+#define __LONG_LONG_MAX__ 9223372036854775807LL\n\
+#define __PPC__ 1\n\
+#define __GXX_ABI_VERSION 1002\n\
+#define __FLT_MIN_EXP__ (-125)\n\
+#define __DBL_MIN__ 2.2250738585072014e-308\n\
+#define __DBL_HAS_QUIET_NAN__ 1\n\
+#define __REGISTER_PREFIX__ \n\
+#define __NO_INLINE__ 1\n\
+#define _ARCH_PPC 1\n\
+#define __FLT_MANT_DIG__ 24\n\
+#define __VERSION__ \"mc-powerpc\"\n\
+#define __BIG_ENDIAN__ 1\n\
+#define __powerpc__ 1\n\
+#define unix 1\n\
+#define __SIZE_TYPE__ unsigned int\n\
+#define __ELF__ 1\n\
+#define __FLT_RADIX__ 2\n\
+#define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L\n\
+#define __GNUC_RH_RELEASE__ 3\n\
+#define __LDBL_DIG__ 31\n\
+#define __FLT_HAS_QUIET_NAN__ 1\n\
+#define __FLT_MAX_10_EXP__ 38\n\
+#define __LONG_MAX__ 2147483647L\n\
+#define __FLT_HAS_INFINITY__ 1\n\
+#define __unix 1\n\
+#define _BIG_ENDIAN 1\n\
+#define linux 1\n\
+#define __PPC 1\n\
+#define __LDBL_MANT_DIG__ 106\n\
+#define __WCHAR_TYPE__ long int\n\
+#define __FLT_DIG__ 6\n\
+#define __powerpc 1\n\
+#define __INT_MAX__ 2147483647\n\
+#define __LONG_DOUBLE_128__ 1\n\
+#define __FLT_MAX_EXP__ 128\n\
+#define __DBL_MANT_DIG__ 53\n\
+#define __WINT_TYPE__ unsigned int\n\
+#define __LDBL_MIN_EXP__ (-968)\n\
+#define __LDBL_MAX_10_EXP__ 308\n\
+#define __DBL_EPSILON__ 2.2204460492503131e-16\n\
+#define PPC 1\n\
+#define powerpc 1\n\
+#define __INTMAX_MAX__ 9223372036854775807LL\n\
+#define __FLT_DENORM_MIN__ 1.40129846e-45F\n\
+#define __FLT_MAX__ 3.40282347e+38F\n\
+#define __FLT_MIN_10_EXP__ (-37)\n\
+#define __INTMAX_TYPE__ long long int\n\
+#define __GNUC_MINOR__ 1\n\
+#define __DBL_MAX_10_EXP__ 308\n\
+#define __LDBL_DENORM_MIN__ 4.94065645841246544176568792868221e-324L\n\
+#define __STDC__ 1\n\
+#define __PTRDIFF_TYPE__ int\n\
+#define __LDBL_MIN_10_EXP__ (-291)\n\
+"
+#endif
 #ifdef __APPLE__
 "#define __APPLE__ 1\n"
 #endif
@@ -112,6 +211,7 @@
 static int  lreg_sp;  /* longlong  REGister Stack-Pointer */
 static int lreg_stack[MAX_MAX]; /* 実際のレジスタの領域 */
 
+#ifdef __APPLE__
 #define REG_sp   1
 #define REG_fp   30
 #define REG_VAR_BASE 29
@@ -123,6 +223,19 @@
 #define FREG_VAR_MIN  20
 #define MIN_TMP_FREG 1
 #define MAX_TMP_FREG 14
+#else
+#define REG_sp   1
+#define REG_fp   31
+#define REG_VAR_BASE 29
+#define REG_VAR_MIN  18
+#define MIN_TMP_REG 3
+#define MAX_TMP_REG 11
+
+#define FREG_VAR_BASE 31
+#define FREG_VAR_MIN  20
+#define MIN_TMP_FREG 1
+#define MAX_TMP_FREG 9
+#endif
 
 int MAX_REGISTER=30;             /* PowerPCのレジスタを10個まで使う*/
 int MAX_FREGISTER=31;
@@ -141,10 +254,10 @@
 
 int MAX_INPUT_REGISTER_VAR = 11-MIN_TMP_REG;
 int MAX_CODE_INPUT_REGISTER_VAR = 11-MIN_TMP_REG;
-int MAX_INPUT_DREGISTER_VAR = 14-MIN_TMP_FREG;
-int MAX_INPUT_FREGISTER_VAR = 14-MIN_TMP_FREG;
-int MAX_CODE_INPUT_DREGISTER_VAR = 14-MIN_TMP_FREG;
-int MAX_CODE_INPUT_FREGISTER_VAR = 14-MIN_TMP_FREG;
+int MAX_INPUT_DREGISTER_VAR = MAX_TMP_FREG-MIN_TMP_FREG;
+int MAX_INPUT_FREGISTER_VAR = MAX_TMP_FREG-MIN_TMP_FREG;
+int MAX_CODE_INPUT_DREGISTER_VAR = MAX_TMP_FREG-MIN_TMP_FREG;
+int MAX_CODE_INPUT_FREGISTER_VAR = MAX_TMP_FREG-MIN_TMP_FREG;
 
 static int powerpc_regs[REAL_MAX_REGISTER+REAL_MAX_FREGISTER+
    REAL_MAX_LREGISTER];
@@ -345,13 +458,28 @@
                               *SIZE_OF_INT                  *SIZE_OF_INT
 
  */
+
+
+#ifdef __APPLE__
+
 #define arg_offset  24
 #define arg_offset1  24
-int disp_offset = 0;
 
 #define func_disp_offset 68
 #define code_disp_offset0 (0)
 
+#else
+
+#define arg_offset  (-24)
+#define arg_offset1  (-24)
+
+#define func_disp_offset (16)
+#define code_disp_offset0 (0)
+
+#endif
+
+int disp_offset = 0;
+
 #define CODE_LVAR(l) ((l)+code_disp_offset0)
 #define CODE_CALLER_ARG(l) ((l)+arg_offset1)
 #define FUNC_LVAR(l) ((l)+disp_offset)
@@ -497,13 +625,13 @@
 	    if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
 		printf("%d@l(1)\n",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET));
 	    } else
-		printf("%d@l(30)\n",CODE_LVAR(l));
+		printf("%d@l(%d)\n",CODE_LVAR(l),REG_fp);
 	} else if (l<0) {  /* local variable */
-	    printf("%d@l(30)\n",FUNC_LVAR(l));
+	    printf("%d@l(%d)\n",FUNC_LVAR(l),REG_fp);
 	} else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
 	    printf("%d@l(1)\n",CALLER_ARG(l-ARG_LVAR_OFFSET));
 	} else { /* callee's arguments */
-	    printf("%d+%s%d@l(30)\n",CALLEE_ARG(l),lpfx,lvar_offset_label);
+	    printf("%d+%s%d@l(%d)\n",CALLEE_ARG(l),lpfx,lvar_offset_label,REG_fp);
 	}
     } else {
         rn = register_name(large_offset_reg);
@@ -547,13 +675,13 @@
         } else {
             if (LARGE_OFFSET(CODE_LVAR(l))) {
                 rn=register_name(large_offset_reg=get_register());
-                printf("\tla %s,30,%d@ha\n",rn,CODE_LVAR(l));
+                printf("\tla %s,%d,%d@ha\n",rn,REG_fp,CODE_LVAR(l));
             }
         }
     } else if (l<0) {  /* local variable */
         if (LARGE_OFFSET(FUNC_LVAR(l))) {
             rn=register_name(large_offset_reg=get_register());
-            printf("\tla %s,30,%d@ha\n",rn,FUNC_LVAR(l));
+            printf("\tla %s,%d,%d@ha\n",rn,REG_fp,FUNC_LVAR(l));
         }
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
         if (LARGE_OFFSET(CALLER_ARG(l-ARG_LVAR_OFFSET))) {
@@ -563,8 +691,8 @@
     } else { /* callee's arguments */
         if (LARGE_OFFSET(CALLEE_ARG(l))) {
             rn=register_name(large_offset_reg=get_register());
-            printf("\tla %s,30,%d+%s%d@ha\n",
-		rn,CALLEE_ARG(l),lpfx,lvar_offset_label);
+            printf("\tla %s,%d,%d+%s%d@ha\n",
+		rn,REG_fp,CALLEE_ARG(l),lpfx,lvar_offset_label);
         }
     }
 }
@@ -1597,7 +1725,7 @@
 #if R1SAVE
     printf("\tlwz %s,0(%s)\n",register_name(creg),register_name(1));
 #else
-    printf("\tmr %s,%s\n",register_name(creg),register_name(30));
+    printf("\tmr %s,%s\n",register_name(creg),register_name(REG_fp));
 //    int l = 0;
 //    printf("\tla %s,",register_name(creg));
 //    printf("lo16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label);
@@ -2122,6 +2250,8 @@
     return reg_arg_list;
 }
 
+
+#ifdef __APPLE__
 static void
 increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) {
     int nargs=0,reg_arg=0,freg_arg=0;
@@ -2144,8 +2274,8 @@
 	if (*preg_arg<MAX_INPUT_REGISTER_VAR) {
 	    reg_arg += 2;
 	}
+	nargs += size(t)/SIZE_OF_INT;
 	freg_arg++;
-	nargs += size(t)/SIZE_OF_INT;
     } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
 	nargs += round4(size(t))/SIZE_OF_INT;
     } else {
@@ -2156,6 +2286,36 @@
     *preg_arg += reg_arg;
     *pfreg_arg += freg_arg;
 }
+#else
+static void
+increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) {
+    int nargs=0,reg_arg=0,freg_arg=0;
+    int t=type_value(caddr(e3));
+    if (t>=0&&(car(t)==BIT_FIELD)) {
+	t = type_value(cadr(t));
+    }
+    if(scalar(t)) {
+	nargs ++ ; reg_arg++;
+    } else if (t==LONGLONG||t==ULONGLONG) {
+	nargs ++ ; reg_arg++;
+	nargs ++ ; reg_arg++;
+    } else if (t==FLOAT) {
+	freg_arg++;
+	nargs += size(t)/SIZE_OF_INT;
+    } else if (t==DOUBLE) {
+	nargs += round4(size(t))/SIZE_OF_INT;
+	freg_arg++;
+    } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
+	nargs += round4(size(t))/SIZE_OF_INT;
+    } else {
+	error(TYERR);
+	nargs ++ ;
+    }
+    *pnargs += nargs;
+    *preg_arg += reg_arg;
+    *pfreg_arg += freg_arg;
+}
+#endif
 
 #define AS_SAVE 1
 #define AS_ARG  0
@@ -2192,7 +2352,7 @@
 	if (mode==AS_SAVE) {
 	    return get_dregister_var(0,1);
 	} else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
-	    return list3(LVAR,caller_arg_offset_v(nargs),0);
+	    return list3(LVAR,caller_arg_offset_v(nargs)-36,0);
 	} else
 	    return get_input_dregister_var(freg_arg,0,0,1);
     } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
@@ -2209,7 +2369,7 @@
 int
 function(int e1)
 {
-    int e2,e3,e4,e5,nargs,t,r0,r1;
+    int e2,e3,e4,e5,nargs,t,r0;
     int arg,reg_arg,freg_arg,arg_assign;
     int dots;
     int reg_arg_list=0,ret_type,special_lvar;
@@ -2364,11 +2524,13 @@
 	    reg_arg_list = list2(arg,reg_arg_list);
 	    g_expr_u(assign_expr0(arg,e4,t,t));
 	} else if (t==DOUBLE||t==FLOAT) {
+#ifdef __APPLE__
 	    if (reg_arg<MAX_INPUT_REGISTER_VAR) {
 		/* sigh... 
                    printf requires floating value in integer registers
                  */
 		if (dots) {
+		    int r1;
 		    if (car(e4)==DRLVAR) {
 			special_lvar = cadr(e4);
 			e5 = list3(LVAR,special_lvar,0);
@@ -2406,6 +2568,7 @@
 			    get_input_dregister_var(freg_arg,0,0,1),t,t),
 		    arg_assign);
 	    }
+#endif
 	    reg_arg_list = list2(arg,reg_arg_list);
 	    if (car(arg)==DREGISTER)
 		use_input_reg(cadr(arg),1); /* protect from input register free */
@@ -2418,6 +2581,13 @@
 	g_expr_u(car(arg_assign));
     }
     clear_ptr_cache();
+#ifndef __APPLE__
+    if (dots && freg_arg) {
+	//  variadic function has floating value in register
+	printf("\tcreqv 6,6,6\n");
+	//  printf("\tcrxor 6,6,6\n"); for value in stack 
+    }
+#endif
     if (car(e2) == FNAME) {	
 #ifdef __APPLE__
 	printf("\tbl\tL_%s$stub\n",fn->nm);
@@ -2484,7 +2654,7 @@
 #if R1SAVE
     printf("\tmr %s,%s\n",register_name(1),register_name(e3));
 #else
-    printf("\tmr %s,%s\n",register_name(30),register_name(e3));
+    printf("\tmr %s,%s\n",register_name(REG_fp),register_name(e3));
 #endif
 }
 
@@ -3166,17 +3336,11 @@
     printf("\tbl .LC%d\n",code_setup);
     r1_offset_label = fwdlabel();
     lvar_offset_label = fwdlabel();
-#if 0
-    printf("\taddi r30,r1,lo16(-L_%d)\n",lvar_offset_label);
-    printf("\tstwu r1,lo16(-L_%d)(r1)\n",r1_offset_label);
-    // printf("\tmr r30,r1\n");
-#else
-    printf("\taddi 30,1,-%s%d@l\n",lpfx,lvar_offset_label);
-    printf("\tlis 31,-%s%d@ha\n",lpfx,r1_offset_label);
-    printf("\taddi 31,31,-%s%d@l\n",lpfx,r1_offset_label);
-    printf("\tstwux 1,1,31\n");
-#endif
-    printf("\tmflr 31\n");
+
+    printf("\taddi %d,%d,-%s%d@l\n",REG_fp,1,lpfx,lvar_offset_label);
+    printf("\tlis %d,-%s%d@ha\n",30,lpfx,r1_offset_label);
+    printf("\taddi %d,%d,-%s%d@l\n",30,REG_fp,lpfx,r1_offset_label);
+    printf("\tstwux 1,1,%d\n",30);
 #endif
     max_func_args = 0;
     clear_ptr_cache();
@@ -3296,8 +3460,8 @@
 	    emit_copy(6,3,sz,0,1,1);
 #else
 	    printf("\tli 7,%d\n",sz);
-	    printf("\tsubl 6,7,30\n");
-	    printf("\tlwz 3,%d@l(30)\n",(my_func_args-1)*SIZE_OF_INT);
+	    printf("\tsubl 6,7,%d\n",REG_fp);
+	    printf("\tlwz 3,%d@l(%d)\n",(my_func_args-1)*SIZE_OF_INT,REG_fp);
 	    emit_copy(6,3,sz,0,1,1);
 #endif
 	} else if (cadr(fnptr->ty)!=VOID) {
@@ -3318,7 +3482,7 @@
 #ifdef __APPLE__
     printf("\taddi r1,r30,lo16(L_%d)\n",lvar_offset_label);
 #else
-    printf("\taddi 1,30,.LC%d@l\n",lvar_offset_label);
+    printf("\taddi 1,%d,.LC%d@l\n",REG_fp,lvar_offset_label);
 #endif
 #endif
     if (max_freg_var>=0) {
@@ -5826,7 +5990,11 @@
 	    printf("\tsub\t%s,%s,%s\n",trn,crn,trn);
 	}
     } else {
+#ifdef __APPLE__
 	printf("\taddi\t%s,%s,lo16(%d)\n",trn,crn,-min);
+#else
+	printf("\taddi\t%s,%s,%d@l\n",trn,crn,-min);
+#endif
     }
     printf("\tcmplwi   %s,%s,%d\n",crname(cmpflag),trn,max-min);
     printf("\tbgt-\t%s,%s%d\n",crname(cmpflag),lpfx,dlabel);
@@ -5837,22 +6005,14 @@
 	printf("\tli %s,1\n",srn);
 	printf("\tand %s,%s,%s\n",srn,srn,trn);
 	printf("\tcmplwi   %s,%s,0\n",crname(cmpflag),srn);
-#ifdef __APPLE__
-	printf("\tbne\t%s,L_%d\n",crname(cmpflag),dlabel);
-#else
-	printf("\tbne\t%s,.L%d\n",crname(cmpflag),dlabel);
-#endif
+	printf("\tbne\t%s,%s%d\n",crname(cmpflag),lpfx,dlabel);
 	printf("\tslwi %s,%s,1\n",trn,trn);
 	break;
     case 4: 
 	printf("\tli %s,3\n",srn);
 	printf("\tand %s,%s,%s\n",srn,srn,trn);
 	printf("\tcmplwi   %s,%s,0\n",crname(cmpflag),srn);
-#ifdef __APPLE__
-	printf("\tbne\t%s,L_%d\n",crname(cmpflag),dlabel);
-#else
-	printf("\tbne\t%s,.L%d\n",crname(cmpflag),dlabel);
-#endif
+	printf("\tbne\t%s,%s%d\n",crname(cmpflag),lpfx,dlabel);
 	break;
     default:
 	urn = register_name(u=get_register());
@@ -5861,11 +6021,7 @@
 	printf("\tmullw %s,%s,%s\n",srn,urn,srn);
 	printf("\tsubf %s,%s,%s\n",srn,trn,srn);
 	printf("\tcmplwi   %s,%s,0\n",crname(cmpflag),srn);
-#ifdef __APPLE__
-	printf("\tbne\t%s,L_%d\n",crname(cmpflag),dlabel);
-#else
-	printf("\tbne\t%s,.L%d\n",crname(cmpflag),dlabel);
-#endif
+	printf("\tbne\t%s,%s%d\n",crname(cmpflag),lpfx,dlabel);
 	printf("\tslwi %s,%s,2\n",trn,urn);
     }
 #ifdef __APPLE__
@@ -5879,10 +6035,10 @@
     printf("\tmtctr r0\n");
     printf("\tbctr\n");
 #else
-    printf("\taddis %s,31,L_%d@h\n",
-	     srn,l);
-    printf("\tla %s,L_%d@l(%s)\n",
-	     srn,l,srn);
+    printf("\taddis %s,31,%s%d@h\n",
+	     srn,lpfx,l);
+    printf("\tla %s,%s%d@l(%s)\n",
+	     srn,lpfx,l,srn);
     printf("\tadd %s,%s,%s\n",trn,srn,trn);
     printf("\tlwz 0,0(%s)\n",trn);
     printf("\tadd 0,0,%s\n",srn);
--- a/mc-parse.c	Mon Apr 30 02:19:48 2007 +0900
+++ b/mc-parse.c	Tue May 01 13:26:42 2007 +0900
@@ -2043,15 +2043,16 @@
     arg_disp = args;
     args = 0;
     disp=0;
-    if (!inmode)
+    control=1;
+    if (!inmode) {
 	arg_register(fnptr);
+    }
     typedefed=0;
     conv->function_(fnptr,sd); conv->lc_();
     init_vars=0;
 
     /* local variable declaration */
     local_decl(1);
-    control=1;
     cslabel = -1;
     if (!inmode && !chk) gen_enter1();
     emit_init_vars();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/stackframe.c	Tue May 01 13:26:42 2007 +0900
@@ -0,0 +1,55 @@
+extern int printf(const char *,...);
+// extern void *alloca(int);
+
+#define A0 0xa0a0a0a0
+#define A1 0xa1a1a1a1
+#define A2 0xa2a2a2a2
+#define A3 0xa3a3a3a3
+#define A4 0xa4a4a4a4
+
+#define L0 0xb0b0b0b0
+#define L1 0xb1b1b1b1
+#define L2 0xb2b2b2b2
+#define L3 0xb3b3b3b3
+#define L4 0xb4b4b4b4
+
+void *ret;
+
+void
+frame(int a0,int a1,int a2)
+{
+    int l0 = L0;
+    int *top = (int *)__builtin_alloca(16);
+    int *p;
+    int i = 0;
+    int l1 = L1;
+
+    *top = L2;
+    for(p = top;p<top+0x100; ) {
+	if (*p==(int)ret) {
+	    printf("%04x: ret address\n",i);
+	} else if (*p==A0) {
+	    printf("%04x: caller arg 1\n",i);
+	} else if (*p==A2) {
+	    printf("%04x: caller arg last\n",i);
+	} else if (*p==L0) {
+	    printf("%04x: local var top\n",i);
+	} else if (*p==L1) {
+	    printf("%04x: local var end\n",i);
+	} else if (*p==L2) {
+	    printf("%04x: stack top (alloca)\n",i);
+	}
+	i+= sizeof(int);
+	p++;
+    }
+}
+
+
+int
+main()
+{
+    ret = &&label;
+    frame(A0,A1,A2);
+label:
+    return 0;
+}