static long savedf[32];
static long savedi[32];
static int savedtop;
+static unsigned long lfs_set;
/* Calculate the register score of a local variable. */
int
/* Don't put reg_float in reg_any. */
if (totype != reg_float)
return -1;
- assert(size == 8);
+ assert(size == 4 || size == 8);
break;
default:
assert(size == 4);
/* Set top of register save area, relative to fp. */
savedtop = -framesize;
+
+ lfs_set = 0; /* empty set */
}
/* Mark a register as being saved. */
case 'f':
savedf[regnum] = offset;
framesize += 8;
+ if (size == 4)
+ lfs_set |= (1U << regnum);
break;
case 'r':
savedi[regnum] = offset;
emit_prolog();
saveloadregs("stw", "stmw", "stfd");
+ /*
+ * Register variables with offset >= 0 must load an argument
+ * from that offset.
+ */
for (reg = 31; reg >= 0; reg--)
if (savedf[reg] >= 0)
- fprintf(codefile, "lfd f%d, %ld(fp)\n",
+ fprintf(codefile, "%s f%d, %ld(fp)\n",
+ (lfs_set & (1U << reg)) ? "lfs" : "lfd",
reg, savedf[reg]);
for (reg = 31; reg >= 0; reg--)
fs13("f13")=f13
: FSREG.
+ /* reglap: reg_float may have subregister of different size */
+ fs14("f14")=f14, fs15("f15")=f15, fs16("f16")=f16, fs17("f17")=f17,
+ fs18("f18")=f18, fs19("f19")=f19, fs20("f20")=f20, fs21("f21")=f21,
+ fs22("f22")=f22, fs23("f23")=f23, fs24("f24")=f24, fs25("f25")=f25,
+ fs26("f26")=f26, fs27("f27")=f27, fs28("f28")=f28, fs29("f29")=f29,
+ fs30("f30")=f30, fs31("f31")=f31
+ : FSREG regvar(reg_float).
+
lr, ctr : SPR.
cr0 : CR.
fdiv FREG+DLOCAL:wo, FREG:ro, FREG:ro cost(4, 35).
fdivs FSREG:wo, FSREG:ro, FSREG:ro cost(4, 21).
fmr FPR+DLOCAL:wo, FPR:ro cost(4, 5).
- fmr FSREG:wo, FSREG:ro cost(4, 5).
+ fmr FSREG+LOCAL:wo, FSREG:ro cost(4, 5).
fmul FREG+DLOCAL:wo, FREG:ro, FREG:ro cost(4, 5).
fmuls FSREG:wo, FSREG:ro, FSREG:ro cost(4, 5).
fneg FREG+DLOCAL:wo, FREG:ro cost(4, 5).
lfd FPR+DLOCAL:wo, IND_RC_D+IND_RL_D:ro cost(4, 5).
lfdu FPR:wo, IND_RC_D:ro cost(4, 5).
lfdx FPR+DLOCAL:wo, GPR:ro, GPR:ro cost(4, 5).
- lfs FSREG:wo, IND_RC_W+IND_RL_W:ro cost(4, 4).
+ lfs FSREG+LOCAL:wo, IND_RC_W+IND_RL_W:ro cost(4, 4).
lfsu FSREG:wo, IND_RC_W:rw cost(4, 4).
- lfsx FSREG:wo, GPR:ro, GPR:ro cost(4, 4).
+ lfsx FSREG+LOCAL:wo, GPR:ro, GPR:ro cost(4, 4).
lha GPR:wo, IND_RC_H_S+IND_RL_H_S:ro cost(4, 3).
lhax GPR:wo, GPR:ro, GPR:ro cost(4, 3).
lhz GPR:wo, IND_RC_H+IND_RL_H:ro cost(4, 3).
stfdu FPR+DLOCAL:ro, IND_RC_D:rw cost(4, 4).
stfdx FPR:ro, GPR:ro, GPR:ro cost(4, 4).
stfs FSREG:ro, IND_RC_W+IND_RL_W:rw cost(4, 3).
- stfsu FSREG:ro, IND_RC_W:rw cost(4, 3).
+ stfsu FSREG+LOCAL:ro, IND_RC_W:rw cost(4, 3).
stfsx FSREG:ro, GPR:ro, GPR:ro cost(4, 3).
sth GPR:ro, IND_RC_H+IND_RL_H:rw cost(4, 3).
sthx GPR:ro, GPR:ro, GPR:ro cost(4, 3).
from GPR to GPR
gen mr %2, %1
+ from FSREG to FSREG
+ gen fmr %2, %1
+
from FPR to FPR+DLOCAL
gen fmr %2, %1
STACKINGRULES
+ from LOCAL inreg(%off)==reg_float to STACK
+ gen
+ COMMENT("stack LOCAL")
+ stfsu %1, {IND_RC_W, sp, 0-4}
+
from LOCAL to STACK
gen
COMMENT("stack LOCAL")
yields {SUM_RC, %a, los($1)}
/* Load word from local */
- pat lol inreg($1)==reg_any
+ pat lol inreg($1)==reg_any || inreg($1)==reg_float
yields {LOCAL, $1}
pat lol
leaving
with ANY_BHW
kills regvar($1), LOCAL %off==$1
gen move %1, {GPRE, regvar($1)}
+ pat stl inreg($1)==reg_float
+ with exact FSREG
+ gen fmr {LOCAL, $1}, %1
+ with STACK
+ gen
+ lfs {LOCAL, $1}, {IND_RC_W, sp, 0}
+ addi sp, sp, {CONST, 4}
pat stl
leaving
lal $1
struct regvar *save;
if (typ != reg_any && nregvar[typ]!=0) {
- if (machregs[rvnumbers[typ][0]].r_size!=rvlp->rv_size)
+ struct reginfo *ri = &machregs[rvnumbers[typ][0]];
+ int size, wrong;
+
+ size = ri->r_size;
+ wrong = (size!=rvlp->rv_size);
+#ifdef REGLAP
+ /* reg_float may have one subregister */
+ if (wrong && ri->r_members[0]!=0) {
+ size = machregs[ri->r_members[0]].r_size;
+ wrong = (size!=rvlp->rv_size);
+ }
+#endif /* REGLAP */
+ if (wrong)
score = -1;
else
score = regscore(rvlp->rv_off,
if (saveall) {
struct reginfo *rp;
rp= &machregs[rvnumbers[rvtyp][i]];
- regsave(codestrings[rp->r_repr],(long)-TEM_WSIZE,rp->r_size);
+ regsave(codestrings[rp->r_repr],
+ (long)-TEM_WSIZE,rp->r_size);
+#ifdef REGLAP
+ /* reg_float may have one subregister */
+ if (rp->r_members[0]!=0) {
+ rp= &machregs[rp->r_members[0]];
+ regsave(codestrings[rp->r_repr],
+ (long)-TEM_WSIZE,rp->r_size);
+ }
+#endif
} else if(regassigned[rvtyp][i].ra_score>0) {
rv=regassigned[rvtyp][i].ra_rv;
rv->rv_reg=rvnumbers[rvtyp][i];
rv->rv_type = rvtyp;
+#ifdef REGLAP
+ /* reg_float may have alternate size */
+ if (machregs[rv->rv_reg].r_size != rv->rv_size) {
+ rv->rv_reg = machregs[rv->rv_reg].r_members[0];
+ assert(rv->rv_reg != 0);
+ assert(machregs[rv->rv_reg].r_size ==
+ rv->rv_size);
+ }
+#endif
regsave(codestrings[machregs[rv->rv_reg].r_repr],
rv->rv_off,rv->rv_size);
}
#include "expr.h"
#include "regvar.h"
#include <cgg_cg.h>
+#include <em_reg.h>
#include "extern.h"
extern set_t l_sets[];
expr_t regvar_expr(e,regtyp) expr_t e; {
expr_t result;
register i;
-
+
result = make_expr(TYPREG,EX_REGVAR,i_expr(e),0);
for(i=0;i<SZOFSET(MAXREGS);i++)
result.ex_regset[i]=0;
for(i=0;i<nregvar[regtyp];i++)
BIS(result.ex_regset,rvnumbers[regtyp][i]);
+ /* reglap: float may overlap with one subregister */
+ if (reglap!=0 && regtyp==reg_float) {
+ for(i=0;i<nregvar[regtyp];i++) {
+ /* reg = first subregister */
+ int reg = l_regs[rvnumbers[regtyp][i]].ri_memb[0];
+ if (reg!=0)
+ BIS(result.ex_regset,reg);
+ }
+ }
return(result);
}
}
clashlist[iclashlist++] = 0;
}
- fprintf(ctable,",%d",l_regs[i].ri_rregvar>=0);
+ /*
+ * Write .r_refcount = 1 for register variables or 0
+ * for other registers.
+ *
+ * reglap: Write .r_refcount = 0 if the register
+ * variable has a subregister.
+ */
+ fprintf(ctable,",%d",
+ l_regs[i].ri_rregvar>=0 && l_regs[i].ri_memb[0]==0);
fprintf(ctable,"},\n");
}
fprintf(ctable,"};\n\n short clashlist[] = {\n\t");
register i,j;
fprintf(htable,"#define REGVARS\n");
+ if (reglap!=0)
+ fprintf(htable,"#define REGLAP\n");
fprintf(ctable,"#include \"regvar.h\"\n");
fprintf(ctable,"int nregvar[4] = { ");
for (i=0;i<4;i++) {
#define DL_REGVAR 0x4
extern int rvused;
+extern int reglap;
extern int nregvar[4];
extern int rvsize[4];
extern int rvnumbers[4][MAXREGVAR];
#include "token.h"
#include "regvar.h"
#include <cgg_cg.h>
+#include <em_reg.h>
#include "extern.h"
n_proc(name) char *name; {
sy_p->sy_value.syv_stringno = strlookup(val);
}
+static void
+add_regvar(int rvnum, reginfo *regp, int rv)
+{
+ int overlap, wrong;
+
+ overlap = wrong = 0;
+ if (regp->ri_memb[0]!=0) {
+ /* reglap: float may overlap with one subregister */
+ if (rv==reg_float && regp->ri_memb[1]==0)
+ overlap = 1;
+ else
+ wrong = 1;
+ }
+ if (wrong)
+ error("Register variables may not have subregisters");
+
+ rvused |= ANY_REGVAR;
+ if (regp->ri_size == wordsize)
+ rvused |= SL_REGVAR;
+ else if (regp->ri_size == 2*wordsize)
+ rvused |= DL_REGVAR;
+
+ wrong = 0;
+ if (overlap) {
+ /* reglap = size of overlap float */
+ if (reglap==0)
+ reglap = regp->ri_size;
+ else if (reglap!=regp->ri_size)
+ wrong = 1;
+ } else {
+ if (nregvar[rv]==0)
+ rvsize[rv] = regp->ri_size;
+ else if (rvsize[rv]!=regp->ri_size)
+ wrong = 1;
+ }
+ if (wrong)
+ error("All register variables of one type must have the same size");
+
+ if (overlap) {
+ reginfo *member_p = &l_regs[regp->ri_memb[0]];
+ int i;
+
+ /*
+ * reglap: Remove member_p from rvnumbers.
+ * Add reg_p in its place.
+ */
+ wrong = 1;
+ for (i = 0; i < nregvar[rv]; i++) {
+ if (rvnumbers[rv][i] == regp->ri_memb[0]) {
+ rvnumbers[rv][i] = rvnum;
+ wrong = 0;
+ break;
+ }
+ }
+ if (wrong)
+ error("Register variable %s can't overlap %s",
+ regp->ri_name, member_p->ri_name);
+ } else {
+ NEXT(nregvar[rv],MAXREGVAR,"Register variable");
+ rvnumbers[rv][nregvar[rv]-1] = rvnum;
+ }
+}
+
+void
regline(rl,pl,rv) varinfo *rl,*pl; {
register varinfo *rrl,*rpl;
register short *sp;
regp->ri_size = thissize;
regp->ri_class = regclass;
regp->ri_rregvar = rv;
- if (rv>=0) {
- if (regp->ri_memb[0]!=0)
- error("Register variables may not have subregisters");
- rvused |= ANY_REGVAR;
- if (regp->ri_size == wordsize)
- rvused |= SL_REGVAR;
- else if (regp->ri_size == 2*wordsize)
- rvused |= DL_REGVAR;
- if (nregvar[rv]==0)
- rvsize[rv] = regp->ri_size;
- else if (rvsize[rv]!=regp->ri_size)
- error("All register variables of one type must have the same size");
- NEXT(nregvar[rv],MAXREGVAR,"Register variable");
- rvnumbers[rv][nregvar[rv]-1] = rrl->vi_int[0];
- }
+ if (rv>=0)
+ add_regvar(rrl->vi_int[0], regp, rv);
}
regclass++;
}
int regclass=1;
int maxtokensize=0;
int rvused=0;
+int reglap=0;
int nregvar[4];
int rvsize[4];
int rvnumbers[4][MAXREGVAR];