/* cache.c */ #include #include #include #include "mach.h" #ifdef __STDC__ #include #else extern char *strcpy(); #endif #define free_reg_num(i) if (1) { assert(reg[i].inuse > 0); reg[i].inuse--; if (debug) fprintf(stderr,"free_reg(%s)\n", regnam[i]); } else #define POP1 cache_need(1); #define POP2 { --tos; assert(c_count); --c_count; } static int indent_count = 0; #define enter(x) indent_count++; #define indent() { int i = indent_count; while (i--) putc('\t', stderr); } #define leave(x) indent_count--; /* procedures: const13(int) boolean proc init_cache() mandatory free_reg(reg_t) forced_alloc_reg(reg_t) soft_alloc_reg(reg_t) change_reg(reg_t) used when reg on stack has changed type_of_tos() bit-field representation of ext/reg/cst inc_tos(int) tos->cst += n push_const(int) push_reg(reg_t) push_ext(char *) flush_cache() after branches and labels cache_read(int) read-ahead. optimization only dump_cache(File *) debug info: show current stack pop_nop() remove element from cache reg_t alloc_reg() reg_t pop_reg() reg_t pop_reg_c13(char*) arith pop_const(char *) arith top_const() alloc_float, alloc_double, free_double, pop_float, pop_double, push_float, push_double */ typedef struct regdat_t { int inuse; /* free == 0, otherwise #owners */ } regdat_t; /* typedef struct cache_elt { reg_t reg, reg2; char *ext; arith cst; } cache_elt; */ #define REG_NUM(r) (((char(*)[8])(r))-regnam) static char regnam[][8] = { /*x*/ "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7", /*x*/ "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%i6", "%i7", /*x*/ "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7", /*x*/ "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o6", "%o7", /*x*/ "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", /*x*/ "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15", /*x*/ "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23", /*x*/ "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31" }; reg_t reg_g0, reg_g1, reg_g2, reg_g3, reg_g4, reg_g5, reg_g6, reg_g7; reg_t reg_i0, reg_i1, reg_i2, reg_i3, reg_i4, reg_i5, reg_i6, reg_i7; reg_t reg_l0, reg_l1, reg_l2, reg_l3, reg_l4, reg_l5, reg_l6, reg_l7; reg_t reg_o0, reg_o1, reg_o2, reg_o3, reg_o4, reg_o5, reg_o6, reg_o7; reg_t reg_f0; reg_t reg_sp, reg_lb, reg_gap; reg_t reg_tmp, reg_lin, reg_fil; static struct regdat_t reg[NR_REGS]; #define POP_SIZE 1 /* maybe >1 (read-ahead cache) or explicit?! */ #define CACHE_SIZE 32 /* ? */ #define LO_GLOB 0 #define HI_GLOB 7 #define LO_IN 8 #define HI_IN 15 #define LO_LOC 16 #define HI_LOC 23 #define LO_OUT 24 #define HI_OUT 31 #define LO_FLOAT 32 #define HI_FLOAT 63 const13(x) { return (x < 4096 && x >= -4096); } static struct cache_elt cache[CACHE_SIZE], *tos = 0; static int c_count = 0; static const_str_t s; _PROTOTYPE(static void panic, (char*)); _PROTOTYPE(static void dump_cache, (File *stream)); _PROTOTYPE(static int cache_read, (int n, int i)); _PROTOTYPE(static void flush_part_cache, (int c, int r, int f, int d)); _PROTOTYPE(static void subst_reg, (reg_t, reg_t)); static void panic(s) char *s; { printf("PANIC: %s\n", s); exit(1); } void init_cache() { int i; for (i = 0; i < NR_REGS; i++) reg[i].inuse = 0; reg_g0 = regnam[000]; reg_g1 = regnam[001]; reg_g2 = regnam[002]; reg_g3 = regnam[003]; reg_g4 = regnam[004]; reg_g5 = regnam[005]; reg_g6 = regnam[006]; reg_g7 = regnam[007]; reg_i0 = regnam[010]; reg_i1 = regnam[011]; reg_i2 = regnam[012]; reg_i3 = regnam[013]; reg_i4 = regnam[014]; reg_i5 = regnam[015]; reg_i6 = regnam[016]; reg_i7 = regnam[017]; reg_l0 = regnam[020]; reg_l1 = regnam[021]; reg_l2 = regnam[022]; reg_l3 = regnam[023]; reg_l4 = regnam[024]; reg_l5 = regnam[025]; reg_l6 = regnam[026]; reg_l7 = regnam[027]; reg_o0 = regnam[030]; reg_o1 = regnam[031]; reg_o2 = regnam[032]; reg_o3 = regnam[033]; reg_o4 = regnam[034]; reg_o5 = regnam[035]; reg_o6 = regnam[036]; reg_o7 = regnam[037]; reg_f0 = regnam[040]; reg_sp = reg_l0; reg_lb = reg_l1; reg_gap = reg_g4; reg_tmp = reg_o7; forced_alloc_reg(reg_g0); /* can not be used as a reg */ forced_alloc_reg(reg_o6); forced_alloc_reg(reg_o7); forced_alloc_reg(reg_i6); forced_alloc_reg(reg_i7); } static void flush_part_cache(n,r,f,d) int n,r,f,d; { /* free at least n entries, r integer registers, f float regs and d double regs */ int i, ready; int rn, j; const_str_t i_str, e_str, n_str; char *ext, R1, R2; reg_t rh, rt; enter("flush_part_cache"); for (i = 0; i < c_count; i++) { if (i >= n && !r && !f && !d) break; if (cache[i].reg != reg_g0) { rn= REG_NUM(cache[i].reg); free_reg_num(rn); if (!reg[rn].inuse) if (rn= LO_FLOAT; i--) { if (reg[i].inuse) continue; reg[i].inuse = 1; /* allocate */ res = regnam[i]; break; } if (!res) { flush_part_cache(c_count/2,0,1,0); res = alloc_float(); } if (debug) { indent(); fprintf(stderr,"alloc_float() = %s\n", res ? regnam[i] : "NULL"); } leave("alloc_float"); return res; } reg_t alloc_double(sub_reg) reg_t *sub_reg; { int i; reg_t res = NULL; enter("alloc_double"); for (i = LO_FLOAT+14; i >= LO_FLOAT; i -= 2) { if (reg[i].inuse || reg[i+1].inuse) continue; reg[i].inuse = 1; /* allocate */ reg[i+1].inuse = 1; /* allocate */ if (debug) { indent(); fprintf(stderr,"alloc_double() = %s\n", regnam[i]); } if (sub_reg) *sub_reg= regnam[i+1]; res = regnam[i]; break; } if (!res) { flush_part_cache(c_count/2,0,0,1); res = alloc_double(sub_reg); } if (debug) { indent(); fprintf(stderr,"alloc_double() = %s\n", res ? regnam[i] : "NULL"); } leave("alloc_double"); return res; } reg_t alloc_reg_var() /* ins and locals only */ { int i; reg_t res = NULL; enter("alloc_reg_var"); for (i = LO_LOC +2 /* SPEED-HACK */; i <= HI_LOC; i++) { if (reg[i].inuse) continue; reg[i].inuse = 1; /* allocate */ res = regnam[i]; break; } if (!res) for (i = LO_IN; i <= HI_IN; i++) { if (reg[i].inuse) continue; reg[i].inuse = 1; /* allocate */ res = regnam[i]; break; } if (debug) { indent(); fprintf(stderr,"alloc_reg_var() = %s\n", res ? regnam[i] : "NULL"); } leave("alloc_reg_var"); return res; } reg_t alloc_float_var() { int i; reg_t res = NULL; enter("alloc_float_var"); for (i= LO_FLOAT+16; i<= HI_FLOAT; i++) { if (reg[i].inuse) continue; reg[i].inuse = 1; /* allocate */ res = regnam[i]; break; } if (debug) { indent(); fprintf(stderr,"alloc_reg_var() = %s\n", res ? regnam[i] : "NULL"); } leave("alloc_float_var"); return res; } reg_t alloc_double_var(sub_reg) reg_t *sub_reg; { int i; reg_t res = NULL; enter("alloc_double_var"); for (i = LO_FLOAT+16; i < HI_FLOAT; i += 2) { if (reg[i].inuse || reg[i+1].inuse) continue; reg[i].inuse = 1; /* allocate */ reg[i+1].inuse = 1; /* allocate */ if (debug) { indent(); fprintf(stderr,"alloc_double_var() = %s\n", regnam[i]); } if (sub_reg) *sub_reg= regnam[i+1]; res = regnam[i]; break; } if (debug) { indent(); fprintf(stderr,"alloc_double_var() = %s\n", res? regnam[i] : "NULL"); } leave("alloc_double_var"); return res; } void free_reg(i) reg_t i; { int r; enter("free_reg"); if (i != 0 && i != reg_g0) { r = REG_NUM(i); assert(0 <= r && r <= NR_REGS); assert(reg[r].inuse > 0); /* "freeing unused register" */ reg[r].inuse--; } if (debug) { indent(); fprintf(stderr,"free_reg(%s)\n", i); } leave("free_reg"); } void free_double_reg(i) reg_t i; { int rn; enter("free_double_reg"); rn= REG_NUM(i); assert (!(rn & 1)); free_reg(i); free_reg(regnam[rn+1]); leave("free_double_reg"); } void force_alloc_output() /* TMP HACK */ { int i; enter("force_alloc_output"); if (debug) { indent(); fprintf(stderr,"force_alloc_output\n"); } for (i = REG_NUM(reg_o0); i <= REG_NUM(reg_o5); i++) forced_alloc_reg(regnam[i]); leave("force_alloc_output"); } void free_output() { int i; enter("free_output"); leave("free_output"); if (debug) { indent(); fprintf(stderr,"free_output\n"); } for (i = REG_NUM(reg_o0); i <= REG_NUM(reg_o5); i++) { assert(reg[i].inuse > 0); reg[i].inuse--; } } void soft_alloc_reg(i) reg_t i; { enter("soft_alloc_reg"); if (debug) { indent(); fprintf(stderr,"soft_alloc_reg(%s)\n", i); } /* assert(reg[REG_NUM(i)].inuse); */ reg[REG_NUM(i)].inuse++; leave("soft_alloc_reg"); } void forced_alloc_reg(i) reg_t i; { int r; enter("forced_alloc_reg"); if (debug) { indent(); fprintf(stderr,"forced_alloc_reg(%s)\n", i); } r = REG_NUM(i); if (reg[r].inuse) { reg_t S1; char *V2; S1 = alloc_reg(); if (debug) { indent(); fprintf(stderr,"---> inuse: moving to %s\n", S1); } "mov $i, $S1"; subst_reg(i, S1); free_reg(S1); if (reg[r].inuse) panic("forced_alloc_reg: external owners left!"); } reg[r].inuse = 1; leave("forced_alloc_reg"); } void change_reg(r) /* to be called when register r changes */ reg_t r; { int i; enter("change_reg"); if (debug) { indent(); fprintf(stderr, "change_reg(%s)\n", r); } if (r != reg_g0) for (i = 0; i < c_count; i++) if (cache[i].reg == r || cache[i].reg2 == r) { reg_t S1; if (r >= reg_f0) { S1 = alloc_float(); "fmovs $r, $S1"; } else { S1 = alloc_reg(); "mov $r, $S1"; } subst_reg(r, S1); free_reg(S1); break; } leave("change_reg"); } static void subst_reg(old, new) reg_t old, new; { int i; enter("subst_reg"); if (debug) { indent(); fprintf(stderr,"subst_reg(%s, %s)\n", old, new); } for (i = 0; i < c_count; i++) { if (cache[i].reg == old) { cache[i].reg = new; free_reg(old); soft_alloc_reg(new); } if (cache[i].reg2 == old) { cache[i].reg2 = new; free_reg(old); soft_alloc_reg(new); } } leave("subst_reg"); } int type_of_tos() { int r = 0; cache_need(1); if (tos->ext) r |= T_ext; if (tos->reg != reg_g0) if (tos->reg >= reg_f0) r |= T_float; else r |= T_reg; if (tos->reg2 != reg_g0) if (tos->reg2 >= reg_f0) r |= T_float2; else r |= T_reg2; if (tos->cst) r |= T_cst; return r; } arith top_const() { enter("top_const"); assert(type_of_tos() == T_cst); if (debug) { indent(); fprintf(stderr,"top_const()=%d\n", tos->cst); } leave("top_const"); return tos->cst; } reg_t pop_reg_reg(r) reg_t *r; { reg_t s; enter("pop_reg_reg"); POP1; if (!(type_of_tos() & T_reg2)) push_reg(pop_reg()); assert(r); *r = tos->reg2; s = tos->reg; POP2; if (debug) { indent(); fprintf(stderr,"pop_reg_reg()=%s\n", s); fprint(codefile,"\t\t! "); dump_cache(codefile); } leave("pop_reg_reg"); return s; } reg_t pop_reg_c13(n) /* returns reg_t + optional n (as string) */ char *n; { reg_t S1, S2, S3; register char *V1; const_str_t V2; enter("pop_reg_c13"); if (debug) { indent(); fprintf(stderr,"pop_reg_c13()=...\n"); } *n = '0'; *(n+1) = 0; cache_need(1); if (tos->reg >= reg_f0) { /* convert float to int */ S1= pop_float(); S2= alloc_reg(); "st $S1, [%fp+64]"; "ld [%fp+64], $S2"; free_reg(S1); S1 = S2; } else if (tos->reg2 != reg_g0) { /* add integers */ S1 = pop_reg(); } else if (tos->ext) { assert(tos->reg == reg_g0); S1 = alloc_reg(); V1 = tos->ext; sprint(V2, "%d", tos->cst); "sethi %hi($V1+$V2), $S1"; sprint(n, "%%lo(%s+%d)", tos->ext, tos->cst); free(V1); POP2; } else { S1 = tos->reg; if (!(const13(tos->cst))) { S3 = alloc_reg(); sprint(V2, "%d", tos->cst); "sethi %hi($V2), $S3"; if (tos->reg != reg_g0) { S2 = alloc_reg(); "add $S3, $S1, $S2"; free_reg(S1); free_reg(S3); S1 = S2; } else { free_reg(S1); S1 = S3; } tos->cst &= 0x3FF; } sprint(n, "%d", tos->cst); POP2; } if (debug) { indent(); fprint(codefile, "\t\t! %s+%s cache:", S1, n); dump_cache(codefile);} leave("pop_reg_c13"); return S1; } reg_t pop_float() { reg_t S1, R1, R2; char *V1, *V2; enter("pop_float"); cache_need(1); S1 = tos->reg; if (!(type_of_tos() & T_float)) { S1 = pop_reg(); R2 = alloc_float(); "st $S1, [%fp+64]"; "ld [%fp+64], $R2"; free_reg(S1); S1 = R2; } else if (tos->reg2 >= reg_f0) { R1 = tos->reg2; R2 = alloc_float(); "fadds $S1, $R1, $R2"; free_reg(S1); free_reg(R1); S1 = R2; POP2; } else POP2; if (debug) { indent(); fprint(codefile, "\t\t! %s cache:", S1); dump_cache(codefile); } leave("pop_float"); return S1; } void inc_tos_reg(r) reg_t r; { enter("inc_tos_reg"); if (debug) { indent(); fprintf(stderr, "inc_tos_reg(%s)\n", r); } if (type_of_tos() != T_reg) push_reg(pop_reg()); tos->reg2 = r; if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); } leave("inc_tos_reg"); } void inc_tos(n) arith n; { reg_t S1; char *V1, *V2; enter("inc_tos"); if (debug) { indent(); fprintf(stderr,"inc_tos(%d)\n", n); } cache_need(1); if (tos->reg >= reg_f0) { S1= pop_reg(); push_reg(S1); } else if (tos->reg2 != reg_g0) { S1= pop_reg(); push_reg(S1); } tos->cst += n; if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); } leave("inc_tos"); } #define INC_TOS if (c_count >= CACHE_SIZE) flush_part_cache(c_count/2,0,0,0); \ tos = &cache[c_count++]; void push_const(n) arith n; { enter("push_const"); INC_TOS; tos->reg = reg_g0; tos->reg2 = reg_g0; tos->ext = 0; tos->cst = n; if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); } leave("push_const"); } void push_reg(i) reg_t i; { enter("push_reg"); assert(0 <= REG_NUM(i) && REG_NUM(i) < NR_REGS); INC_TOS; tos->reg = i; tos->reg2 = reg_g0; tos->ext = 0; tos->cst = 0; if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); } leave("push_reg"); } void push_double_reg(i) reg_t i; { int rn; enter("push_double_reg"); rn= REG_NUM(i); assert (!(rn & 1)); INC_TOS; tos->ext = 0; tos->cst = 0; tos->reg = regnam[rn+1]; tos->reg2 = reg_g0; INC_TOS; tos->ext = 0; tos->cst = 0; tos->reg = i; tos->reg2 = reg_g0; if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); } leave("push_double_reg"); } void push_ext(s) char *s; { char *p; enter("push_ext"); p = Malloc(strlen(s)+1); INC_TOS; tos->reg = reg_g0; tos->reg2 = reg_g0; tos->ext = strcpy(p, s); tos->cst = 0; if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); } leave("push_ext"); } arith pop_const(n) char *n; { arith x; enter("pop_const"); POP1; x = top_const(); POP2; if (n) sprint(n, "%d", x); if (debug) { indent(); fprint(codefile, "\t\t! %d cache:", x); dump_cache(codefile); } leave("pop_const"); return x; } void pop_reg_as(r) reg_t r; { reg_t S1, S2; register char *V1, *V3; const_str_t V2, c_str; char *tos_ext; reg_t tos_reg, tos_reg2; int tos_cst; enter("pop_reg_as"); if (debug) { indent(); fprintf(stderr,"pop_reg_as(%s)=...\n", r); } if (c_count == 0) { /* special case */ "ld [%l0], $r"; "inc 4, %l0"; } else if (r >= reg_f0) { if (tos->reg < reg_f0) { S1= pop_reg(); change_reg(r); "st $S1, [%fp+64]"; "ld [%fp+64], $r"; free_reg(S1); } else { if (tos->reg2 == reg_g0) { S1= pop_float(); change_reg(r); if (S1 != r) "fmovs $S1, $r"; free_reg(S1); } else { V1 = tos->reg; V3 = tos->reg2; POP2; change_reg(r); "fadds $V1, $V3, $r"; free_reg(V1); free_reg(V3); } } } else if (tos->reg >= reg_f0) { S1= pop_float(); change_reg(r); "st $S1, [%fp+64]"; "ld [%fp+64], $r"; free_reg(S1); } else if (tos->ext) { assert(tos->reg == reg_g0); V1 = tos->ext; sprint(V2, "%d", tos->cst); "set $V1+$V2, $r"; free(V1); POP2; } else { POP1; tos_reg= tos->reg; tos_reg2= tos->reg2; tos_cst= tos->cst; POP2; change_reg(r); if (!const13(tos_cst)) { assert (tos_reg2 == reg_g0); if (tos_reg != reg_g0 || (tos_cst & 0x3ff)) tos_reg2= alloc_reg(); else { soft_alloc_reg(r); tos_reg2= r; } sprint(c_str, "%d", tos_cst); "sethi %hi($c_str), $tos_reg2"; tos_cst &= 0x3ff; if (tos_reg == reg_g0) { tos_reg= tos_reg2; tos_reg2= reg_g0; } } if (tos_reg2 != reg_g0) { assert (tos_reg != reg_g0); if (tos_cst) S1= alloc_reg(); else { soft_alloc_reg(r); S1= r; } "add $tos_reg, $tos_reg2, $S1"; free_reg(tos_reg); free_reg(tos_reg2); tos_reg= S1; tos_reg2= reg_g0; } if (tos_cst) { sprint(c_str, "%d", tos_cst); soft_alloc_reg(r); "add $tos_reg, $c_str, $r"; free_reg(tos_reg); tos_reg= r; } if (tos_reg != r) "mov $tos_reg, $r"; free_reg(tos_reg); } leave("pop_reg_as"); } void pop_double_reg_as(rdl) reg_t rdl; { reg_t rl, rh; reg_t rdh; reg_t t; int rn; enter("pop_double_reg_as"); rn= REG_NUM(rdl); assert (!(rn & 1)); rdh= regnam[rn+1]; if (rdl>= reg_f0) { if (c_count == 0) { "ld [%l0], $rdl"; "ld [%l0+4], $rdh"; "inc 8, %l0"; } else { if (type_of_tos() & T_float) rl= pop_float(); else rl= pop_reg(); if (type_of_tos() & T_float) rh= pop_float(); else rh= pop_reg(); change_reg(rdl); change_reg(rdh); if (rl < reg_f0 && rh < reg_f0) { "st $rl, [%fp+64]"; "st $rh, [%fp+68]"; "ldd [%fp+64], $rdl"; free_reg(rl); free_reg(rh); } else if (rl < reg_f0) { if (rh != rdh) "fmovs $rh, $rdh"; "st $rl, [%fp+64]"; "ld [%fp+64], $rdl"; free_reg(rl); free_reg(rh); } else if (rh < reg_f0) { if (rl != rdl) "fmovs $rl, $rdl"; "st $rh, [%fp+64]"; "ld [%fp+64], $rdh"; free_reg(rl); free_reg(rh); } else { if (rdl == rl) free_reg(rl); if (rdh == rh) free_reg(rh); if (rdl == rh && rdh == rl) { t= alloc_float(); "fmovs $rl, $t"; free_reg(rl); rl= t; } if (rdl != rl && rdl != rh) { "fmovs $rl, $rdl"; free_reg(rl); rl= rdl; } if (rdh != rh && rdh != rl) { "fmovs $rh, $rdh"; free_reg(rh); rh= rdh; } if (rdl != rl && rdl != rh) { "fmovs $rl, $rdl"; free_reg(rl); rl= rdl; } assert (rdl == rl && rdh == rh); } } } else { pop_reg_as (rdl); pop_reg_as (rdh); } leave("pop_double_reg_as"); } reg_t pop_reg() { reg_t S1; enter("pop_reg"); POP1; if (type_of_tos() == T_reg) { S1 = tos->reg; POP2; } else { S1 = alloc_reg(); pop_reg_as(S1); } if (debug) { indent(); fprint(codefile, "\t\t! %s cache:", S1); dump_cache(codefile); } leave("pop_reg"); return S1; } reg_t pop_double(sub_reg) /* pop_double_float actually */ reg_t *sub_reg; { reg_t R1, R2, R3, R4; char *V1, *V2; enter("pop_double"); if (c_count == 0) { R1 = alloc_double(&R2); "ld [%l0], $R1"; "ld [%l0+4], $R2"; "inc 8, %l0"; if (sub_reg) *sub_reg = R2; } else { cache_need(2); if (tos->reg >= reg_f0 && tos[-1].reg >= reg_f0 && REG_NUM(tos->reg) == REG_NUM(tos[-1].reg)-1 && tos->reg2 == reg_g0 && tos[-1].reg2 == reg_g0) { R1= tos->reg; if (sub_reg) *sub_reg= tos[-1].reg; POP2; POP2; } else { R1= alloc_double(&R2); if (sub_reg) *sub_reg= R2; if (tos->reg >= reg_f0 || tos[-1].reg >= reg_f0) { pop_reg_as(R1); pop_reg_as(R2); } else { /* two normal registers */ R3= pop_reg(); R4= pop_reg(); "st $R3, [%fp+64]"; "st $R4, [%fp+68]"; "ldd [%fp+64], $R1"; free_reg(R3); free_reg(R4); } } } leave("pop_double"); return R1; } void pop_nop(i) int i; { const_str_t V1; int j = i; enter("pop_nop"); while (c_count && i) { i--; POP1; free_reg(tos->reg); free_reg(tos->reg2); if (tos->ext) free(tos->ext); POP2; } if (i) { sprint(V1, "%d", 4*i); if (const13(4*i)) { "inc $V1, %l0"; } else { "set $V1, $reg_tmp"; "add %l0, $reg_tmp, %l0"; } } if (debug) { indent(); fprint(codefile, "\t\t! %dw cache:",j); dump_cache(codefile); } leave("pop_nop"); } check_cache() { int i; if (debug) for (i = 0; i < NR_REGS; i++) fprintf(stderr, "%c", reg[i].inuse ? (reg[i].inuse)+48 : '.'); fprintf(stderr, "\n"); } void flush_cache() /* flush the cache onto the stack */ { enter("flush_cache"); if (debug) { indent(); fprintf(stderr,"flush_cache\n"); } if (c_count) flush_part_cache(c_count, 0, 0, 0); /* TEST */ if (debug) check_cache(); leave("flush_cache"); } void cache_need(n) int n; { enter("cache_need"); if (c_count < n) (void) cache_read(n, 0); assert(c_count >= n); leave("cache_need"); } static int cache_read(n, i) int n; int i; { const_str_t V1; reg_t S1; int j; int old_c_count; enter("cache_read"); if (debug) { indent(); fprintf(stderr,"cache_read(%d, %d)\n", n,i); } if (i+c_count=0; j--) cache[j+i]= cache[j]; c_count += i; tos= &cache[c_count-1]; old_c_count = i; } leave("cache_read"); return old_c_count; } static void dump_cache(stream) /* to codefile! */ File *stream; { int i; assert (c_count >= 0); for (i = c_count -1; i >= 0; i--) { if (cache[i].ext) fprint(stream, "%s", cache[i].ext); if (cache[i].reg != reg_g0) { if (cache[i].ext) fprint(stream, "+"); fprint(stream, "%s", cache[i].reg); if (cache[i].reg2 != reg_g0) { fprint(stream, "+"); fprint(stream, "%s", cache[i].reg2); } } if (cache[i].cst || (!cache[i].ext && cache[i].reg == reg_g0)) { if (cache[i].ext || cache[i].reg != reg_g0) fprint(stream, "+"); fprint(stream, "%d", cache[i].cst); } fprint(stream, " "); } fprint(stream, "\n"); if (debug) check_cache(); } void dup_tos(n) int n; { reg_t a; int i; const_str_t i_str; enter("dup_tos"); for (i = 0;i < n; i++) { INC_TOS; tos->reg = reg_g0; tos->reg2 = reg_g0; tos->cst = 0; tos->ext = 0; if (c_count > n) { char *ext; *tos = tos[-n]; if (tos->ext) { ext= Malloc(strlen(tos->ext)+1); strcpy(ext, tos->ext); tos->ext= ext; } soft_alloc_reg(tos->reg); soft_alloc_reg(tos->reg2); } else { a= alloc_reg(); sprint(i_str, "%d", (n-c_count)*4); "ld [$reg_sp+$i_str], $a"; tos->reg = a; } } if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); } leave("dup_tos"); }