Mercurial > hg > CbC > old > device
changeset 372:81345636387d
arm continue...
author | kono |
---|---|
date | Sat, 10 Jul 2004 21:46:21 +0900 |
parents | 238c3704ee3d |
children | a9bc85fe6702 |
files | Changes mc-code-arm.c mc-parse.c test/code-gen.c |
diffstat | 4 files changed, 292 insertions(+), 61 deletions(-) [+] |
line wrap: on
line diff
--- a/Changes Fri Jul 09 14:47:40 2004 +0900 +++ b/Changes Sat Jul 10 21:46:21 2004 +0900 @@ -5586,3 +5586,117 @@ LDECL は、disp < 0 const も実装しないといけないんだよな〜 + +arm は、大域変数を、 + ldr r3, .L28+88 + .... +.L29: + .align 2 +.L28: + .word i1 + .word i2 + .word s1 + .word s2 + .word us1 + +みたいな形で間接参照するわけだけど、参照した順にリストに格納しないと +だめ? 変数表に格納したい所だが... make scope で出来ないかな? +linear list で持ってもいいんだけど。 + +ptr_cache の方でリストを持てば? + +なんか、add # の意味が良くわからないよ。別に常にメモリ +参照で問題はないんでしょ? + +良くわからないけど、 + 8bit 幅の定数で、シフトが2ずつ +みたいな感じ? + +でいいけど、どんなアルゴリズムで生成するんだよ。 + + 8bit mask を2ずつシフトして、 + 残りが取れるかどうかをみる + +えーと、16x8x8 ぐらいのオーダ? + for(sign=-1;sign<=1;sign+=2) { + if (sign==1) d = c; else d = -c; + for(i=0;i<32;i+=2) { + if (!(im=mask8(d,i))) continue; + id = d - im; + if (id==0) goto found; + for(j=i+8;j<32;i+=2) { + if (!(jm=mask8(id,j))) continue; + jd = id - jm; + if (jm==0) goto found; + for(k=i+8;k<32;k+=2) { + if (!(km=mask8(jd,j))) continue; + kd = jd - km; + if (km==0) goto found; + } + } + } + } + emit_const(c); + found: + if (sign==1) emit_add(im,jm,km); + else emit_sub(im,jm,km) +ですかね。1024 ループか。。。 const 毎に? + +しかも、その中で、もっとも短い命令を探さないとだめなのか。 + +pointer offset も、そうなのかな? (その可能性はあると思う) + +12*8*4 = 384 ぐらいか(最悪で) + + sub mask8 { + my ($d,$bit) = @_; + $d & (255 << $bit); + } + + sub make_const { + my ($c) = @_; + my ($sign,$im,$jm,$km); + my ($min_stage) = 4; + my ($msign,$mim,$mjm,$mkm); + for($sign=1;$sign>=-1;$sign-=2) { + my $d; + if ($sign==1) { $d = $c; } else { $d = -$c; } + last if ($min_stage==1); + for(my $i=24;$i>=0;$i-=2) { + $jm = $km = 0; + next if (!($im=mask8($d,$i))); + my $id = $d - $im; + if ($id==0) { + $min_stage=1; $msign = $sign; + $mim = $im;$mjm = $jm;$mkm = $km; + last; + } + next if ($min_stage<=2); + for(my $j=$i-8;$j>=0;$j-=2) { + $km = 0; + next if (!($jm=mask8($id,$j))); + $jd = $id - $jm; + if ($jd==0) { + $min_stage=2; $msign = $sign; + $mim = $im;$mjm = $jm;$mkm = $km; + last; + } + next if ($min_stage<=3); + for(my $k=$j-8;$k>=0;$k-=2) { + next if (!($km=mask8($jd,$k))); + $kd = $jd - $km; + if ($kd==0) { + $min_stage=3; $msign = $sign; + $mim = $im;$mjm = $jm;$mkm = $km; + last; + } + } + } + } + } + if ($min_stage<=3) { emit($sign,$im,$jm,$km); } + else { print "emit const $c\n"; } + } + +ぐらいでした。 +
--- a/mc-code-arm.c Fri Jul 09 14:47:40 2004 +0900 +++ b/mc-code-arm.c Sat Jul 10 21:46:21 2004 +0900 @@ -11,7 +11,7 @@ #define Linux_Zaurus 1 #define GameBoyAdvance 2 -int arc_mode = Linux_Zaurus; +int arch_mode = Linux_Zaurus; char **l_include_path[]; @@ -45,8 +45,6 @@ static int output_mode = TEXT_EMIT_MODE; -static FILE *asi; - static int cprestore_label; static int fmask_label; static int fmask_offset_label; @@ -131,12 +129,12 @@ #define RET_LREGISTER (LREG_OFFSET+REAL_MAX_LREGISTER) #define LREGISTER_OPERAND (LREG_OFFSET +REAL_MAX_LREGISTER +1) #define LREGISTER_OPERAND_1 (LREG_OFFSET +REAL_MAX_LREGISTER +2) -#define RET_LREGISTER_L 2 /* low word */ -#define RET_LREGISTER_H 3 /* high word */ -#define LREGISTER_OPERAND_L 4 /* low word */ -#define LREGISTER_OPERAND_H 5 /* high word */ -#define LREGISTER_OPERAND_1_L 6 /* low word */ -#define LREGISTER_OPERAND_1_H 7 /* high word */ +#define RET_LREGISTER_L 0 /* low word */ +#define RET_LREGISTER_H 1 /* high word */ +#define LREGISTER_OPERAND_L 0 /* low word */ +#define LREGISTER_OPERAND_H 1 /* high word */ +#define LREGISTER_OPERAND_1_L 2 /* low word */ +#define LREGISTER_OPERAND_1_H 3 /* high word */ #define RET_DREGISTER RET_LREGISTER #define DREGISTER_OPERAND LREGISTER_OPERAND @@ -181,7 +179,7 @@ #define is_int_reg(i) (0<i&&i<REAL_MAX_REGISTER) #define is_float_reg(i) (REAL_MAX_REGISTER<=i&&i<REAL_MAX_FREGISTER+REAL_MAX_REGISTER) #define is_longlong_reg(i) (LREG_OFFSET<=i&&i<LREG_OFFSET+REAL_MAX_LREGISTER+LREG_V) -#define is_double_reg(i) is_longlong_reg(i) +#define is_double_reg(i) (arch_mode==GameBoyAdvance?is_longlong_reg(i):is_float_reg(i)) #define use_int(reg) if (reg==USE_CREG) reg=use_int0() static @@ -224,7 +222,7 @@ #if FLOAT_CODE -#define use_float(d,reg) if (reg==USE_CREG) reg=d?use_double0():use_float0() +#define use_float(d,reg) if (reg==USE_CREG) arch_mode==GameBoyAdvance?(reg=d?use_double0():use_float0()):use_float0() static int use_float0() { int i = creg; @@ -297,17 +295,17 @@ delayed slot done within .set noreorder. r0 return value etc. - $2,$3 return value. (dpcmp return value on $2) - $0 special register - $4-$7 input register - r18-r24 saved register variable (input register for code segment) - $25 jump register - $31 stack pointer - $fp frame pointer - - $f0 return value etc. - $f14,$f12 input register - $f20-$f31 saved register variable + r0,r1 return value. (dpcmp return value on $2) + 00 special register + r0-r3 input register + r7-r9 saved register variable (input register for code segment) + jump register + sp stack pointer + fp frame pointer + + f0 return value etc. + r0-r3 input register + f20-f31 saved register variable code segment stack frame @@ -361,6 +359,11 @@ lvar_offsetv += round16(r1_offsetv)-r1_offsetv; r1_offsetv = round16(r1_offsetv); +printf(" @ args = %d, pretend = %d, frame = %d\n", + max_func_args,0,round16(-disp)); +printf(" @ frame_needed = 1, current_function_anonymous_args = 0\n"); + + #if 0 printf("# vars= %d, regs= %d/%d, args= %d, extra= %d\n", round16(-disp), @@ -389,14 +392,6 @@ printf("# max caller arg var=\t%d\n",CALLER_ARG(0)); printf("#\n"); #endif - fprintf(asi,"$L_%d=0x%x\n",mask_label,code_mask()); - fprintf(asi,"$L_%d=%d\n",mask_offset_label,code_mask_offset()); - fprintf(asi,"$L_%d=0x%x\n",fmask_label,code_fmask()); - fprintf(asi,"$L_%d=%d\n",fmask_offset_label,code_fmask_offset()); - fprintf(asi,"$L_%d=%d\n",cprestore_label , - round16((max_func_args>2?max_func_args:2)*SIZE_OF_INT)); - fprintf(asi,"$L_%d=%d\n",r1_offset_label,r1_offsetv); - fprintf(asi,"$L_%d=%d\n",lvar_offset_label,lvar_offsetv); return r1_offsetv; } @@ -406,15 +401,15 @@ { if (fnptr->sc==CODE) { if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ - printf("%d($sp)\n",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET)); + printf("[sp, #%d]\n",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET)); } else - printf("%d($fp)\n",CODE_LVAR(l)); + printf("[fp, #%d]\n",CODE_LVAR(l)); } else if (l<0) { /* local variable */ - printf("%d+$L_%d($fp)\n",FUNC_LVAR(l),lvar_offset_label); + printf("[fp, #%d+.L%d]\n",FUNC_LVAR(l),lvar_offset_label); } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ - printf("%d($sp)\n",CALLER_ARG(l-ARG_LVAR_OFFSET)); + printf("[sp, #%d]\n",CALLER_ARG(l-ARG_LVAR_OFFSET)); } else { /* callee's arguments */ - printf("%d+$L_%d($fp)\n",CALLEE_ARG(l),r1_offset_label); + printf("[fp, #%d+.L%d]\n",CALLEE_ARG(l),r1_offset_label); } } @@ -423,18 +418,18 @@ { if (fnptr->sc==CODE) { if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ - printf("\taddu\t%s,$sp,%d\n", + printf("\tadd\t%s, sp, #%d\n", register_name(creg),CODE_CALLER_ARG(l-ARG_LVAR_OFFSET)); } else - printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_LVAR(l)); + printf("\tadd\t%s, fp,#%d\n",register_name(creg),CODE_LVAR(l)); } else if (l<0) { /* local variable */ - printf("\taddu\t%s,$fp,%d+$L_%d\n",register_name(creg), + printf("\tsub\t%s, fp, #%d+$L_%d\n",register_name(creg), FUNC_LVAR(l),lvar_offset_label); } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ - printf("\taddu\t%s,$sp,%d\n", + printf("\tadd\t%s, $sp, #%d\n", register_name(creg),CALLER_ARG(l-ARG_LVAR_OFFSET)); } else { /* callee's arguments */ - printf("\taddu\t%s,$fp,%d+$L_%d\n", + printf("\tsub\t%s, fp, #%d+$L_%d\n", register_name(creg),CALLEE_ARG(l),r1_offset_label); } } @@ -652,7 +647,7 @@ get_dregister(int d) { /* 使われていないレジスタを調べる */ int i,reg; - if (d) { + if (arch_mode==GameBoyAdvance) { i = get_lregister(); if (i!=-1) regs[i]=USING_DREG; return i; @@ -1141,11 +1136,105 @@ return xreg; } +static int gvar_ref_list; +static int gvar_ref_disp; + +static int +new_gvar_ref(NMTBL *nptr) +{ + return + gvar_ref_list = + glist3((int)nptr,gvar_ref_list,gvar_ref_disp+=SIZE_OF_INT); +} + +static int +search_gvar_ref(NMTBL *nptr) +{ + int p; + for(p = gvar_ref_list; + p && neqname(((NMTBL *)car(p))->nm,nptr->nm);p=cadr(p)); + if (p) return caddr(p); + return caddr(new_gvar_ref(nptr)); +} + +static void +gvar_ref_list() +{ + int p,next,lb; + if (control) { + lb = fwdlabel(); + jmp(lb); + printf("\t.align\t2\n"); + } + gvar_ref_list = reverse0(gvar_ref_list); + fwddef(gvar_ref_label); + for(p = gvar_ref_list; p ;) { + printf("\t.word\t%s\n",((NMTBL *)car(p))->nm); + next = cadr(p); + free_glist3(p); + p = next; + } + if (lb) { + fwddef(lb); + } +} + extern void code_ptr_cache_def(int r, NMTBL *nptr) { char *rrn = register_name(r); - printf("\tla %s,%s\n",rrn,nptr->nm); + printf("\tldr %s, .L%d+%d\n",rrn,gvar_ref_label, + search_gvar_ref(nptr)); +} + +#define mask8(d,bit) (d & (255 << bit)) + +static void +make_const(int c) +{ + int sign,im,jm,km; + int min_stage = 4; + int msign,mim,mjm,mkm; + int id,jd,kd; + int i,j,k; + for(sign=1;sign>=-1;sign-=2) { + int d; + if (sign==1) { d = c; } else { d = -c; } + if (min_stage==1) break; + for(i=24;i>=0;i-=2) { + jm = km = 0; + if (!(im=mask8(d,i))) continue; + id = d - im; + if (id==0) { + min_stage=1; msign = sign; + mim = im;mjm = jm;mkm = km; + break; + } + if (min_stage<=2) continue; + for(j=i-8;j>=0;j-=2) { + km = 0; + if (!(jm=mask8(id,j))) continue; + jd = id - jm; + if (jd==0) { + min_stage=2; msign = sign; + mim = im;mjm = jm;mkm = km; + break; + } + if (min_stage<=3) continue; + for(k=j-8;k>=0;k-=2) { + if (!(km=mask8(jd,k))) continue; + kd = jd - km; + if (kd==0) { + min_stage=3; msign = sign; + mim = im;mjm = jm;mkm = km; + break; + } + } + } + } + } + if (min_stage<=3) { emit(sign,im,jm,km); } + else { print "emit const c\n"; } } static void @@ -1155,9 +1244,12 @@ char *rrn = register_name(r); if (offset==0) { if(r!=reg) - printf("\tmove %s,%s\n",crn,rrn); - } else - printf("\taddu %s,%s,%d\n",crn,rrn,offset); + printf("\tmov %s,%s\n",crn,rrn); + } else if (offset > 0) { + if (offset> + printf("\tadd %s, %s, #%d\n",crn,rrn,offset); + } else { + } } @@ -2749,20 +2841,10 @@ code_opening(char *filename) { static int count=0; - char *asi_name; /* this is called once per file */ printf("\t.file %d \"%s\"\n",count++,filename); - printf(".abicalls\n"); printf(".text\n"); - if (asi) { - fclose(asi); - asi = 0; - } - asi_name = make_filename_with_extension(filename,"i"); - if ( (asi = fopen(asi_name,"w")) == NULL ) error(FILERR); - if (!asi) error(-1); - printf(".include \"%s\"\n",asi_name); } // should have pcond_const @@ -3148,8 +3230,6 @@ // entry part (save register) if (max_reg_var+max_freg_var==0) { - fprintf(asi,"$L_%d=$L_%d\n", - register_save_label,register_save_return_label); } else { code_label(register_save_label); code_register_save(max_reg_var,max_freg_var,-arg_offset-SIZE_OF_INT*2); @@ -3399,6 +3479,7 @@ { NMTBL *n; int init; + gvar_ref_list(); init=0; /* static local variables */ for(n=local_static_list;n;n=n->next) { @@ -5214,7 +5295,6 @@ { global_table(); /* printf("\t.ident \"Micro-C compiled\"\n"); */ - fclose(asi); asi=0; } #if CASE_CODE
--- a/mc-parse.c Fri Jul 09 14:47:40 2004 +0900 +++ b/mc-parse.c Sat Jul 10 21:46:21 2004 +0900 @@ -3157,7 +3157,9 @@ *cheap->ptr = '.'; /* .0 case */ cheap = increment_cheap(cheap,&num); } else if (ch == '0') { + *cheap->ptr = ch; cheap = increment_cheap(cheap,&num); if (getch() == 'x' || ch == 'X') { + *cheap->ptr = ch; cheap = increment_cheap(cheap,&num); /* hexadicimal */ while(1) { getch(); *cheap->ptr = ch; @@ -3172,8 +3174,7 @@ } if (is_ll()) { #if LONGLONG_CODE - *cheap->ptr = 0; - cheap = increment_cheap(cheap,&num); + cheap->ptr[-1] = 0; lsymval = strtoll(num,0,0); // we should keep this value? like string? cheap = reset_cheap(&scheap); @@ -3192,7 +3193,7 @@ } if (is_ll()) { #if LONGLONG_CODE - *cheap->ptr = 0; + cheap->ptr[-1] = 0; cheap = increment_cheap(cheap,&num); lsymval = strtoll(num,0,0); cheap = reset_cheap(&scheap);
--- a/test/code-gen.c Fri Jul 09 14:47:40 2004 +0900 +++ b/test/code-gen.c Sat Jul 10 21:46:21 2004 +0900 @@ -9,6 +9,24 @@ extern int printf(const char *fmt,...); void +code_endian() +{ + union { + unsigned char a[8]; + unsigned short s; + unsigned int i; + unsigned long long l; + } u; + u.s = 0x0123; + printf("endian s : %02x %02x\n",u.a[0],u.a[1]); + u.i = 0x01234567; + printf("endian i : %02x %02x %02x %02x\n",u.a[0],u.a[1],u.a[2],u.a[3]); + u.l = 0x0123456789abcdefULL; + printf("endian l : %02x %02x %02x %02x\n",u.a[0],u.a[1],u.a[2],u.a[3]); + printf("endian l : %02x %02x %02x %02x\n",u.a[4],u.a[5],u.a[6],u.a[7]); +} + +void code_lvar() { char c1,c2; @@ -24,6 +42,24 @@ printf("code_lvar %d %d %u %u\n",c1,c2,uc1,uc2); } +void +code_lvar_address() +{ + char c1,c2,*p; + unsigned char uc1,uc2,*up; + int i1,i2,*ip; + short s1,s2,*sp; + unsigned short us1,us2,*usp; + + ip = &i1; *ip = 1; ip = &i2 ; *ip = -2; + sp = &s1 ; *sp = -1; sp = &s2 ; *sp = -3; + usp = &us1 ; *usp = 65535; usp = &us2 ; *usp = 65535; + printf("code_lvar %d %d %d %d %u %u\n",i1,i2,s1,s2,us1,us2); + p = &c1; + *p = -1; p = &c2; *p = -3; up = &uc1; *up = 200; up=&uc2; *up = 202; + printf("code_lvar %d %d %u %u\n",c1,c2,uc1,uc2); +} + // code_label(int labelno) void code_label()