reduces amount of saved/restored regs (random game):
arm32: ~45%
arm64: ~80%
#include "pcnt.h"
#include "arm_features.h"
#include "pcnt.h"
#include "arm_features.h"
-#ifndef __MACH__
-#define CALLER_SAVE_REGS 0x100f
-#else
-#define CALLER_SAVE_REGS 0x120f
-#endif
-
#define unused __attribute__((unused))
#ifdef DRC_DBG
#define unused __attribute__((unused))
#ifdef DRC_DBG
-#define HOST_REGS 13
-#define HOST_CCREG 10
-#define HOST_BTREG 8
-#define EXCLUDE_REG 11
-
#define HOST_IMM8 1
#define HAVE_CMOV_IMM 1
#define HAVE_CONDITIONAL_CALL 1
#define HOST_IMM8 1
#define HAVE_CMOV_IMM 1
#define HAVE_CONDITIONAL_CALL 1
r14 = lr (link register)
r15 = pc (program counter) */
r14 = lr (link register)
r15 = pc (program counter) */
+#define HOST_REGS 13
+#define HOST_CCREG 10
+#define HOST_BTREG 8
+#define EXCLUDE_REG 11
+
+// Note: FP is set to &dynarec_local when executing generated code.
+// Thus the local variables are actually global and not on the stack.
#define FP 11
#define LR 14
#define HOST_TEMPREG 14
#define FP 11
#define LR 14
#define HOST_TEMPREG 14
-// Note: FP is set to &dynarec_local when executing generated code.
-// Thus the local variables are actually global and not on the stack.
+#ifndef __MACH__
+#define CALLER_SAVE_REGS 0x100f
+#else
+#define CALLER_SAVE_REGS 0x120f
+#endif
+#define PREFERRED_REG_FIRST 4
+#define PREFERRED_REG_LAST 9
#include "pcnt.h"
#include "arm_features.h"
#include "pcnt.h"
#include "arm_features.h"
-#define CALLER_SAVE_REGS 0x0007ffff
-
#define unused __attribute__((unused))
void do_memhandler_pre();
#define unused __attribute__((unused))
void do_memhandler_pre();
emit_jmp(stubs[n].retaddr); // return address (invcode check)
set_jump_target(handler_jump, out);
emit_jmp(stubs[n].retaddr); // return address (invcode check)
set_jump_target(handler_jump, out);
- // TODO FIXME: regalloc should prefer callee-saved regs
if(!regs_saved)
save_regs(reglist);
void *handler=NULL;
if(!regs_saved)
save_regs(reglist);
void *handler=NULL;
-#define HOST_REGS 29
-#define HOST_BTREG 27
-#define EXCLUDE_REG -1
-
#define HOST_IMM8 1
/* calling convention:
r0 -r17: caller-save
r19-r29: callee-save */
#define HOST_IMM8 1
/* calling convention:
r0 -r17: caller-save
r19-r29: callee-save */
+#define HOST_REGS 29
+#define HOST_BTREG 27
+#define EXCLUDE_REG -1
+
#define SP 31
#define WZR SP
#define XZR SP
#define SP 31
#define WZR SP
#define XZR SP
#define HOST_CCREG 28
#define rCC w28
#define HOST_CCREG 28
#define rCC w28
+#define CALLER_SAVE_REGS 0x0007ffff
+#define PREFERRED_REG_FIRST 19
+#define PREFERRED_REG_LAST 27
+
// stack space
#define SSP_CALLEE_REGS (8*12)
#define SSP_CALLER_REGS (8*20)
// stack space
#define SSP_CALLEE_REGS (8*12)
#define SSP_CALLER_REGS (8*20)
static void alloc_reg(struct regstat *cur,int i,signed char reg)
{
int r,hr;
static void alloc_reg(struct regstat *cur,int i,signed char reg)
{
int r,hr;
- int preferred_reg = (reg&7);
- if(reg==CCREG) preferred_reg=HOST_CCREG;
- if(reg==PTEMP||reg==FTEMP) preferred_reg=12;
+ int preferred_reg = PREFERRED_REG_FIRST
+ + reg % (PREFERRED_REG_LAST - PREFERRED_REG_FIRST + 1);
+ if (reg == CCREG) preferred_reg = HOST_CCREG;
+ if (reg == PTEMP || reg == FTEMP) preferred_reg = 12;
+ assert(PREFERRED_REG_FIRST != EXCLUDE_REG && EXCLUDE_REG != HOST_REGS);
// Don't allocate unused registers
if((cur->u>>reg)&1) return;
// Don't allocate unused registers
if((cur->u>>reg)&1) return;
if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;}
}
}
if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;}
}
}
// Try to allocate any available register, but prefer
// registers that have not been used recently.
// Try to allocate any available register, but prefer
// registers that have not been used recently.
- if(i>0) {
- for(hr=0;hr<HOST_REGS;hr++) {
- if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
- if(regs[i-1].regmap[hr]!=dops[i-1].rs1&®s[i-1].regmap[hr]!=dops[i-1].rs2&®s[i-1].regmap[hr]!=dops[i-1].rt1&®s[i-1].regmap[hr]!=dops[i-1].rt2) {
+ if (i > 0) {
+ for (hr = PREFERRED_REG_FIRST; ; ) {
+ if (cur->regmap[hr] < 0) {
+ int oldreg = regs[i-1].regmap[hr];
+ if (oldreg < 0 || (oldreg != dops[i-1].rs1 && oldreg != dops[i-1].rs2
+ && oldreg != dops[i-1].rt1 && oldreg != dops[i-1].rt2))
+ {
cur->regmap[hr]=reg;
cur->dirty&=~(1<<hr);
cur->isconst&=~(1<<hr);
return;
}
}
cur->regmap[hr]=reg;
cur->dirty&=~(1<<hr);
cur->isconst&=~(1<<hr);
return;
}
}
+ hr++;
+ if (hr == EXCLUDE_REG)
+ hr++;
+ if (hr == HOST_REGS)
+ hr = 0;
+ if (hr == PREFERRED_REG_FIRST)
+ break;
// Try to allocate any available register
// Try to allocate any available register
- for(hr=0;hr<HOST_REGS;hr++) {
- if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
+ for (hr = PREFERRED_REG_FIRST; ; ) {
+ if (cur->regmap[hr] < 0) {
cur->regmap[hr]=reg;
cur->dirty&=~(1<<hr);
cur->isconst&=~(1<<hr);
return;
}
cur->regmap[hr]=reg;
cur->dirty&=~(1<<hr);
cur->isconst&=~(1<<hr);
return;
}
+ hr++;
+ if (hr == EXCLUDE_REG)
+ hr++;
+ if (hr == HOST_REGS)
+ hr = 0;
+ if (hr == PREFERRED_REG_FIRST)
+ break;
}
// Ok, now we have to evict someone
}
// Ok, now we have to evict someone