Mercurial > hg > CbC > old > device
changeset 398:bf583e04936f
ARM continue... calling sequence, float/duble arg function
author | kono |
---|---|
date | Fri, 15 Oct 2004 13:33:03 +0900 |
parents | 33a09aa401ba |
children | 9d0015a1fa54 |
files | .gdbinit Changes mc-code-arm.c mc-code-mips.c |
diffstat | 4 files changed, 135 insertions(+), 65 deletions(-) [+] |
line wrap: on
line diff
--- a/.gdbinit Fri Oct 15 02:08:06 2004 +0900 +++ b/.gdbinit Fri Oct 15 13:33:03 2004 +0900 @@ -5,8 +5,8 @@ # run -s nkf203/nkf.c # run -s -ob01.s mc-switch.c # run -s l.c -run -s test/const.c -# run -s test/basic.c +# run -s test/const.c +run -s test/basic.c # run -s test/code-gen-all.c define regs printf "pc =%08x lr =%08x r0 =%08x r1 =%08x r3= %08x r4= %08x\n",$pc,$lr,$r0,$r1,$r3,$r4
--- a/Changes Fri Oct 15 02:08:06 2004 +0900 +++ b/Changes Fri Oct 15 13:33:03 2004 +0900 @@ -6023,3 +6023,24 @@ (gdb) quit うーむ。 + +Fri Oct 15 08:46:59 JST 2004 + + mov ip, sp + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #4 + sub sp, sp, #16 + str r0, [fp, #-16] 引数1 + str r1, [fp, #-20] 引数2 + str r2, [fp, #-24] 引数3 + str r3, [fp, #-28] 引数4 + ... + ldr r2, [fp, #4] 引数5 + add r3, r3, r2 + ldr r2, [fp, #8] 引数6 + +そうか。レジスタの引数分はメモリには取られないで、局所変数側 +におかれるらしい。spは、stmfd で自動的に調製されるから、sub sp +は局所変数分だけ。fp の#4は戻り番地だけ? + +でも、それだと va_next が困るんだけど。
--- a/mc-code-arm.c Fri Oct 15 02:08:06 2004 +0900 +++ b/mc-code-arm.c Fri Oct 15 13:33:03 2004 +0900 @@ -46,13 +46,15 @@ static void code_float_lib_c(char *lib,int from,int to,double value); static void code_double_lib(char *lib,int to,int reg,int oreg); static void code_double_lib_c(char *lib,int from,int to,double value); +static void dconst(int l,int h,double value); + #endif static int creg; static int output_mode = TEXT_EMIT_MODE; static int register_save_return_label; -static int r1_offset_label; +// static int r1_offset_label; static int lvar_offset_label; static int max_func_args = 0; @@ -105,8 +107,8 @@ int MAX_INPUT_REGISTER_VAR = 4; int MAX_CODE_INPUT_REGISTER_VAR = 9-MIN_TMP_REG; -int MAX_INPUT_DREGISTER_VAR = 0; -int MAX_INPUT_FREGISTER_VAR = 0; +int MAX_INPUT_DREGISTER_VAR = 4; +int MAX_INPUT_FREGISTER_VAR = 4; int MAX_CODE_INPUT_DREGISTER_VAR = 3-MIN_TMP_FREG; int MAX_CODE_INPUT_FREGISTER_VAR = 7-MIN_TMP_FREG; @@ -302,12 +304,14 @@ code segment stack frame +register_save is done by callee + * gotoを呼び出した関数のr1 ! r1(goto前のr1) - # * $fp <---r1_offset---------> $sp -r+ +----------+--+----------+----------------+-----------+----------+----+ - cousin arg xx reg save !callee arg !code local caller arg xx - ($fp)r20-r29 lvar>0 lvar<0 lvar>0x1000 000 - f20-f31 <-my_func_args--><--disp-----><-max_func_arg-> + # * $fp <-----------------r1_offset---------> $sp +r+ +----------+-------------+--------+-------+-----------+----------+----+ + cousin arg! callee arg !reg_save!reg_arg!code local caller arg xx + (arg4..) lvar>0 (arg0.3) lvar<0 lvar>0x1000 000 + <-----------my_func_args--><--disp-----><-max_func_arg-> *SIZE_OF_INT *SIZE_OF_INT prev $sp=$fp $fp $sp @@ -322,9 +326,9 @@ prev $sp=$fp $sp=$fp */ -#define arg_offset 0 +#define arg_offset (-12) #define arg_offset1 (-16) -int disp_offset = 0; +int disp_offset=0; // fore mc-codegen.c #define disp_offset 0 #define func_disp_offset 8 @@ -340,25 +344,16 @@ static int code_offset_set(NMTBL *fnptr) { - int lvar_offsetv,r1_offsetv; + int lvar_offsetv; // int code_f = (fnptr->sc==CODE); disp &= -SIZE_OF_INT; - lvar_offsetv = // round16(-disp) + - round16((max_func_args<2?2:max_func_args)*SIZE_OF_INT) + - 2*SIZE_OF_INT; - r1_offsetv = lvar_offsetv + arg_offset + SIZE_OF_INT*2 + - max_reg_var*SIZE_OF_INT+max_freg_var*SIZE_OF_FLOAT+2*SIZE_OF_INT ; - lvar_offsetv += round16(r1_offsetv)-r1_offsetv; - r1_offsetv = round16(r1_offsetv); - + lvar_offsetv = + -12 - max_reg_var*SIZE_OF_INT-max_freg_var*SIZE_OF_FLOAT; // printf(" @ args = %d, pretend = %d, frame = %d\n", // max_func_args,0,round16(-disp)); // printf(" @ frame_needed = 1, current_function_anonymous_args = 0\n"); -// printf("\t.set .L%d, %d\n",lvar_offset_label,lvar_offsetv); -printf("\t.set .L%d, %d\n",lvar_offset_label,-16); -printf("\t.set .L%d, %d\n",r1_offset_label,r1_offsetv); - + printf("\t.set .L%d, %d\n",lvar_offset_label,lvar_offsetv); #if 0 printf("# vars= %d, regs= %d/%d, args= %d, extra= %d\n", @@ -368,8 +363,7 @@ round16(max_func_args*SIZE_OF_INT), 0 ); - printf("# callee arg top=\t%d\n",CALLEE_ARG(0)+r1_offsetv); - printf("# r1_offset=\t\t%d %d\n",r1_offsetv,r1_offsetv%16); + printf("# callee arg top=\t%d\n",CALLEE_ARG(0)); printf("# reg_save_top=\t\t%d\n",r1_offsetv); printf("# reg_save_end=\t\t%d\n", -max_reg_var*SIZE_OF_INT-max_freg_var*SIZE_OF_FLOAT-2*SIZE_OF_INT+ @@ -383,7 +377,7 @@ printf("#\n"); #endif - return r1_offsetv; + return 0; } #define LARGE_OFFSET(l) (l<-511||l>511) @@ -430,12 +424,10 @@ printf("[fp, #%d]%s\n",CODE_LVAR(l),cext); } else if (l<0) { /* local variable */ printf("[fp, #%d+.L%d]%s\n",FUNC_LVAR(l),lvar_offset_label,cext); -// printf("[fp, #%d]%s\n",FUNC_LVAR(l),cext); } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ printf("[sp, #%d]%s\n",CALLER_ARG(l-ARG_LVAR_OFFSET),cext); } else { /* callee's arguments */ - printf("[fp, #%d+.L%d]%s\n",CALLEE_ARG(l),r1_offset_label,cext); -// printf("[fp, #%d]%s\n",CALLEE_ARG(l),cext); + printf("[fp, #%d]%s\n",CALLEE_ARG(l),cext); } } @@ -460,12 +452,7 @@ } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ code_add(creg,CALLER_ARG(l-ARG_LVAR_OFFSET),REG_sp); } else { /* callee's arguments */ -// printf("\tsub\t%s, fp, #%d+.L%d\n", -// register_name(creg),CALLEE_ARG(l),r1_offset_label); - trn = register_name(tmp = get_register()); - disp = search_const(LVAR,glist2(r1_offset_label,CALLEE_ARG(l)),&label); - printf("\tldr\t%s, .L%d+%d\n",trn,label,disp); - printf("\tsub\t%s, fp, %s\n",register_name(creg),trn); + code_add(creg,CALLEE_ARG(l),REG_fp); } if (tmp!=-1) free_register(tmp); } @@ -591,7 +578,7 @@ } } else { if ((reg = get_input_dregister_var(freg_var,n,is_code0,0))) { - n->sc = REGISTER; + n->sc = FREGISTER; n->dsp = cadr(reg); regs[n->dsp]= INPUT_REG; freg_var++; @@ -863,7 +850,6 @@ } } if (d) { - // if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0; j = get_input_lregister_var(i,n,is_code); return j; } else { @@ -880,14 +866,13 @@ { int ll; ll = get_lregister0(); - if (i!=-1) { + if (ll!=-1) { if (is_code) { if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; i = REG_VAR_BASE-i; } else { if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0; - i = i+MIN_TMP_REG; - if (i%2==1) i++; + i++; } #if ENDIAN==0 regv_l(ll)=i; @@ -2146,13 +2131,13 @@ if (!n||n==&null_nptr) error(REG_ERR); if (tag==REGISTER) { /* regs[reg]==INPUT_REG case should be considered */ - n->dsp = offset; + n->dsp = new_lvar(SIZE_OF_INT); offset+=SIZE_OF_INT; t = INT; reg_var++; } else if (tag==LREGISTER) { /* regs[reg]==INPUT_REG case should be considered */ - n->dsp = offset; + n->dsp = new_lvar(SIZE_OF_LONGLONG); // t = n->ty; t = LONGLONG; offset+=SIZE_OF_LONGLONG; reg_offset+=2; @@ -2202,6 +2187,7 @@ return ARG_LVAR_OFFSET+arg*SIZE_OF_INT; } + void use_input_reg(int reg,int mode) { @@ -2248,6 +2234,64 @@ if (mode) use_reg(reg); } +static void +code_assign_input_float_int(int e1,int e2) { + int r,tmp=-1; + float f; + char *frn; + // e1 = e2; + if (car(e1)!=REGISTER) { error(-1); return; } + frn = register_name(r=cadr(e1)); + switch(car(e2)) { + case FCONST: + f = dcadr(e2); + code_const(*((int*)&f),r); + break; + case FRGVAR: + code_rgvar(e2,r); + break; + case FRLVAR: + code_rlvar(cadr(e2),r); + break; + default: + g_expr(e2); + case FREGISTER: + tmp = new_lvar(SIZE_OF_INT); + code_dassign_lvar(tmp, (car(e2)==FREGISTER)?cadr(e2):freg,0); + code_rlvar(tmp,r); + if (tmp!=-1) free_lvar(tmp); + } +} + +static void +code_assign_input_double_long(int e1,int e2) { + int r,tmp=-1,reg; + double value; + // e1 = e2; + if (car(e1)!=LREGISTER) { error(-1); return; } + r=cadr(e1); + switch(car(e2)) { + case DCONST: + value = dcadr(e2); + dconst(regv_l(r),regv_h(r),value); + break; + case DRGVAR: + code_lrgvar(e2,r); + break; + case DRLVAR: + code_lrlvar(cadr(e2),r); + break; + default: + g_expr(e2); + reg = freg; + case DREGISTER: + if (car(e2)==DREGISTER) reg = cadr(e2); + printf("\tstfd\t%s, [sp, #-8]!\n",fregister_name(reg)); + printf("\tldmfd\tsp!, {%s, %s}\n",lregister_name_low(r),lregister_name_high(r)); + } + if (tmp!=-1) free_lvar(tmp); +} + static int compute_complex_arg(int e3,int reg_arg_list,int arg) { int t=caddr(e3); @@ -2256,7 +2300,12 @@ if (car(arg)==REGISTER||car(arg)==DREGISTER|| car(arg)==FREGISTER||car(arg)==LREGISTER) use_input_reg(cadr(arg),1); - g_expr_u(assign_expr0(arg,e4,t,t)); + if (t==FLOAT&&car(arg)==REGISTER) + code_assign_input_float_int(arg, e4); + else if (t==DOUBLE&&car(arg)==LREGISTER) + code_assign_input_double_long(arg, e4); + else + g_expr_u(assign_expr0(arg,e4,t,t)); car(e3) = arg; return reg_arg_list; } @@ -2316,8 +2365,6 @@ } else return get_input_dregister_var(freg_arg,0,0,0); } else if (t==DOUBLE) { - if (reg_arg%2==1) reg_arg++; // alignment - if (nargs%2==1) nargs++; // alignment if (mode==AS_SAVE) { return get_dregister_var(0,1); } else if (reg_arg+1>=MAX_INPUT_DREGISTER_VAR) { @@ -2498,17 +2545,17 @@ g_expr_u(assign_expr0(arg,e4,t,t)); } else if (t==DOUBLE) { reg_arg_list = list2(arg,reg_arg_list); - if (car(arg)==DREGISTER) + if (car(arg)==LREGISTER) { use_input_reg(cadr(arg),1); - g_expr_u(assign_expr0(arg,e4,t,t)); + code_assign_input_double_long(arg, e4); + } else { + g_expr_u(assign_expr0(arg,e4,t,t)); + } } else if (t==FLOAT) { reg_arg_list = list2(arg,reg_arg_list); - if (car(arg)==FREGISTER) { + if (car(arg)==REGISTER) { use_input_reg(cadr(arg),1);/* protect from input register free */ - g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */ - - - + code_assign_input_float_int(arg, e4); } else { g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */ } @@ -3198,7 +3245,7 @@ max_func_args = 0; lvar_offset_label = fwdlabel(); - r1_offset_label = fwdlabel(); + // r1_offset_label = fwdlabel(); printf("\t.type\t%s,function\n",name); if (stmode!=STATIC) printf("\t.globl\t%s\n",name); @@ -3222,7 +3269,6 @@ leave(int control, char *name) { int retcont1=0,sz; - int r1_offsetv; if (control) { code_set_return_register(1); @@ -3263,18 +3309,20 @@ } fwddef(retlabel); - r1_offsetv = code_offset_set(fnptr); - code_register_restore(max_reg_var,max_freg_var,-arg_offset-SIZE_OF_INT*2); + code_offset_set(fnptr); + code_register_restore(max_reg_var,max_freg_var,0); // leave part end // entry part (save register) fwddef(entry_label); - code_register_save(max_reg_var,max_freg_var,-arg_offset-SIZE_OF_INT*2); - - code_add(REG_fp,-4,REG_ip); - code_add(REG_sp,disp,REG_sp); + code_register_save(max_reg_var,max_freg_var,0); + + // code_add(REG_fp,-4,REG_ip); + printf("\tsub\tfp, ip, #4\n"); + + code_add(REG_sp,disp-max_func_args*SIZE_OF_INT,REG_sp); jmp(register_save_return_label); local_table(); @@ -3606,8 +3654,6 @@ #define set_double(freg) if (regs[freg]) {regs[freg]=USING_DREG;} #define set_float(freg) if (regs[freg]) {regs[freg]=USING_DREG;} -static void dconst(int l,int h,double value); - void code_cmp_dregister(int e2,int d,int label,int cond) {
--- a/mc-code-mips.c Fri Oct 15 02:08:06 2004 +0900 +++ b/mc-code-mips.c Fri Oct 15 13:33:03 2004 +0900 @@ -1962,7 +1962,10 @@ if (car(arg)==REGISTER||car(arg)==DREGISTER|| car(arg)==FREGISTER||car(arg)==LREGISTER) use_input_reg(cadr(arg),1); - g_expr_u(assign_expr0(arg,e4,t,t)); + if (t==FLOAT&&car(arg)==REGISTER) + code_assign_input_float_int(list3(FASS_INPUT, arg, e4)); + else + g_expr_u(assign_expr0(arg,e4,t,t)); car(e3) = arg; return reg_arg_list; }