Mercurial > hg > CbC > old > device
changeset 277:d5467cf30f58
Prallel Register Assignment
author | kono |
---|---|
date | Fri, 21 May 2004 21:29:40 +0900 |
parents | ebaec1ae566e |
children | 5b50813d0c45 |
files | Changes mc-code-mips.c mc-codegen.c mc-codegen.h |
diffstat | 4 files changed, 82 insertions(+), 64 deletions(-) [+] |
line wrap: on
line diff
--- a/Changes Fri May 21 18:59:56 2004 +0900 +++ b/Changes Fri May 21 21:29:40 2004 +0900 @@ -4383,3 +4383,5 @@ えーと、double register がconflict しまくるなぁ。 さすがに function では起きないらしいが... ということは、set_[dl]operand の問題か。 + +やっぱり register parallel assign を書くのが簡単だよね。
--- a/mc-code-mips.c Fri May 21 18:59:56 2004 +0900 +++ b/mc-code-mips.c Fri May 21 21:29:40 2004 +0900 @@ -1673,6 +1673,7 @@ } } +/* static void set_lreg_operand1(int reg,int mode) { @@ -1682,6 +1683,7 @@ lmove(LREGISTER_OPERAND_1,reg); } } + */ static void set_dreg_operand(int reg,int mode) @@ -1689,11 +1691,13 @@ set_lreg_operand(reg,mode); } +/* static void set_dreg_operand1(int reg,int mode) { set_lreg_operand1(reg,mode); } + */ void use_reg(int arg) @@ -2282,30 +2286,27 @@ #endif } + static void lmove(int to,int from) { - int tmp; - if (regv_h(to)==regv_h(from)&&(regv_l(to)==regv_l(from))) { - return; - } else if (regv_h(to)!=regv_l(from)) { - if (regv_h(to)!=regv_h(from)) - printf("\tmove %s,%s\n",lregister_name_high(to),lregister_name_high(from)); - if (regv_l(to)!=regv_l(from)) - printf("\tmove %s,%s\n",lregister_name_low(to),lregister_name_low(from)); - } else if (regv_l(to)!=regv_h(from)) { - if (regv_l(to)!=regv_l(from)) - printf("\tmove %s,%s\n",lregister_name_low(to),lregister_name_low(from)); - if (regv_h(to)!=regv_h(from)) - printf("\tmove %s,%s\n",lregister_name_high(to),lregister_name_high(from)); - } else { - tmp = get_register(); - printf("\tmove %s,%s\n",register_name(tmp),lregister_name_low(from)); - printf("\tmove %s,%s\n",lregister_name_high(to),lregister_name_high(from)); - printf("\tmove %s,%s\n",lregister_name_low(to),register_name(tmp)); - free_register(tmp); - } -} + int l; + l = list3(regv_l(to),0,regv_l(from)); + l = list3(regv_h(to),l,regv_h(from)); + parallel_rassign(l); +} + +static void +set_operands(int r0,int r1,int r2,int r3) +{ + int l; + l = list3(DREGISTER_OPERAND_L,0,r0); + l = list3(DREGISTER_OPERAND_H,l,r1); + l = list3(DREGISTER_OPERAND_1_L,l,r2); + l = list3(DREGISTER_OPERAND_1_H,l,r3); + parallel_rassign(l); +} + static void lstore(int e2,int creg) @@ -3595,24 +3596,9 @@ static void code_double_lib(char *lib,int to,int reg,int oreg) { - int tmp; code_save_stacks(); clear_ptr_cache(); - if (regs[DREGISTER_OPERAND_L]||regs[DREGISTER_OPERAND_H]) { - if (regs[DREGISTER_OPERAND_1_L]||regs[DREGISTER_OPERAND_1_H]) { - tmp = new_lvar(SIZE_OF_DOUBLE); - code_lassign_lvar(tmp,reg); - set_dreg_operand1(oreg,1); - code_lrlvar(tmp,DREGISTER_OPERAND); - free_lvar(tmp); - } else { - set_dreg_operand1(oreg,1); - set_dreg_operand(reg,1); - } - } else { - set_dreg_operand(reg,1); - set_dreg_operand1(oreg,1); - } + set_operands(regv_l(reg),regv_h(reg),regv_l(oreg),regv_h(oreg)); extern_conv(lib); set_dreg(RET_DREGISTER,0); if (to!=RET_DREGISTER) { @@ -3857,23 +3843,21 @@ if (car(e2)==DREGISTER) { xreg = cadr(e2); code_double_lib_c("dpadd",xreg,RET_DREGISTER,dir); + // xreg は increment する + // USE_CREG だと increment する前の値を creg にセット + // reg が指定されていれば、それに前の値をセット if (reg==USE_CREG) { use_float(d,reg); if (reg==RET_DREGISTER) { reg = get_dregister(d); - set_dreg(reg,0); } + set_dreg(reg,0); } - if (reg==RET_DREGISTER) { - g = get_dregister(d); - lmove(g,xreg); - lmove(xreg,reg); - lmove(reg,g); - free_register(g); - return; - } - if (reg!=xreg) lmove(reg,xreg); - lmove(xreg,RET_DREGISTER); + g = list3(regv_l(reg),0,regv_l(xreg)); + g = list3(regv_h(reg),g,regv_h(xreg)); + g = list3(regv_l(xreg),g,regv_l(RET_DREGISTER)); + g = list3(regv_h(xreg),g,regv_h(RET_DREGISTER)); + parallel_rassign(g); return; } g_expr(e2); @@ -4400,24 +4384,9 @@ static void code_longlong_lib(char *lib,int reg,int oreg) { - int tmp; code_save_stacks(); clear_ptr_cache(); - if (regs[LREGISTER_OPERAND_L]||regs[LREGISTER_OPERAND_H]) { - if (regs[LREGISTER_OPERAND_1_L]||regs[LREGISTER_OPERAND_1_H]) { - tmp = new_lvar(SIZE_OF_LONGLONG); - code_lassign_lvar(tmp,reg); - set_lreg_operand1(oreg,1); - code_lrlvar(tmp,LREGISTER_OPERAND); - free_lvar(tmp); - } else { - set_lreg_operand1(oreg,1); - set_lreg_operand(reg,1); - } - } else { - set_lreg_operand(reg,1); - set_lreg_operand1(oreg,1); - } + set_operands(regv_l(reg),regv_h(reg),regv_l(oreg),regv_h(oreg)); extern_conv(lib); set_lreg(RET_LREGISTER,0); }
--- a/mc-codegen.c Fri May 21 18:59:56 2004 +0900 +++ b/mc-codegen.c Fri May 21 21:29:40 2004 +0900 @@ -717,6 +717,52 @@ #endif } +// parallel assignment of registers. +// +// target = list3(target_regnum,next,source_regnum); + +void +parallel_rassign(int assigns) +{ + int free,tmp,tmp_target,remains,t0,t2,src; + tmp = 0; + for(;;) { + remains = 0; + // find free target + for(free=assigns;free;free=cadr(free)) { + if (!caddr(free)) continue; // already done + remains++; + t0 = car(free); // target register + // check target is free + for(src=assigns;src;src=cadr(src)) { + if ((t2=caddr(src)) && t0==t2) break; // target is in source + } + if (src==0) { + break; // free is a free target + } + } + if (remains==0) { + if (tmp) { + code_rlvar(tmp,tmp_target); + } + return; + } + if (free) { // free target + if (t0!=caddr(free)) + code_assign_register(t0,0,caddr(free)); + } else { // no free target + for(free=assigns;free;free=cadr(free)) { + if (caddr(free)) break; // not yet done + } + if (!free) error(-1); + tmp = new_lvar(size_of_int); + tmp_target = car(free); + code_assign_lvar(tmp,caddr(free),0); + } + caddr(free)=0; // mark it done + } +} + /* goto arguments list */ /* target list4(list2(tag,disp),cdr,ty,source_expr) */ /* source expr=listn(tag,...) */