From 0e5c0ee04527ac3bcd76230e8144dd7081244a66 Mon Sep 17 00:00:00 2001 From: grischka Date: Sat, 19 Dec 2009 00:06:41 +0100 Subject: [PATCH] x86-64: use r8,r9 as load/store registers --- x86_64-gen.c | 117 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 74 insertions(+), 43 deletions(-) diff --git a/x86_64-gen.c b/x86_64-gen.c index 79b18efe..4a581022 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -23,7 +23,7 @@ #ifdef TARGET_DEFS_ONLY /* number of available registers */ -#define NB_REGS 5 +#define NB_REGS 10 #define NB_ASM_REGS 8 /* a register can belong to several classes. The classes must be @@ -34,6 +34,8 @@ #define RC_RAX 0x0004 #define RC_RCX 0x0008 #define RC_RDX 0x0010 +#define RC_R8 0x0100 +#define RC_R9 0x0200 #define RC_XMM0 0x0020 #define RC_ST0 0x0040 /* only for long double */ #define RC_IRET RC_RAX /* function return: integer register */ @@ -45,16 +47,17 @@ enum { TREG_RAX = 0, TREG_RCX = 1, TREG_RDX = 2, + TREG_XMM0 = 3, + TREG_ST0 = 4, + TREG_RSI = 6, TREG_RDI = 7, TREG_R8 = 8, TREG_R9 = 9, + TREG_R10 = 10, TREG_R11 = 11, - TREG_XMM0 = 3, - TREG_ST0 = 4, - TREG_MEM = 0x10, }; @@ -107,6 +110,13 @@ ST_DATA const int reg_classes[NB_REGS] = { /* edx */ RC_INT | RC_RDX, /* xmm0 */ RC_FLOAT | RC_XMM0, /* st0 */ RC_ST0, +#if NB_REGS == 10 + 0, + 0, + 0, + RC_R8, + RC_R9, +#endif }; static unsigned long func_sub_sp_offset; @@ -286,7 +296,7 @@ static void gen_modrm_impl(int op_reg, int r, Sym *sym, int c, int is_got) g(0x00 | op_reg | REG_VALUE(r)); } } else { - g(0x00 | op_reg | (r & VT_VALMASK)); + g(0x00 | op_reg | REG_VALUE(r)); } } @@ -364,62 +374,78 @@ void load(int r, SValue *sv) } else if ((ft & VT_BTYPE) == VT_LDOUBLE) { o(0xdb); /* fldt */ r = 5; - } else if ((ft & VT_TYPE) == VT_BYTE) { - o(0xbe0f); /* movsbl */ - } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { - o(0xb60f); /* movzbl */ - } else if ((ft & VT_TYPE) == VT_SHORT) { - o(0xbf0f); /* movswl */ - } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) { - o(0xb70f); /* movzwl */ - } else if (is64_type(ft)) { - gen_modrm64(0x8b, r, fr, sv->sym, fc); - return; } else { - o(0x8b); /* movl */ + int x; + if ((ft & VT_TYPE) == VT_BYTE) { + x = 0xbe0f; /* movsbl */ + } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { + x = 0xb60f; /* movzbl */ + } else if ((ft & VT_TYPE) == VT_SHORT) { + x = 0xbf0f; /* movswl */ + } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) { + x = 0xb70f; /* movzwl */ + } else if (is64_type(ft)) { + gen_modrm64(0x8b, r, fr, sv->sym, fc); + return; + } else { + x = 0x8b; /* movl */ + } + if (REX_BASE(r) || (!(fr & ~0x0f) && REX_BASE(fr))) + o(0x40 + REX_BASE(fr) + (REX_BASE(r) << 2)); + o(x); } gen_modrm(r, fr, sv->sym, fc); } else { if (v == VT_CONST) { if (fr & VT_SYM) { #ifdef TCC_TARGET_PE - o(0x8d48); + o(0x8d48 + (REX_BASE(r) << 2)); o(0x05 + REG_VALUE(r) * 8); /* lea xx(%rip), r */ gen_addrpc32(fr, sv->sym, fc); #else if (sv->sym->type.t & VT_STATIC) { - o(0x8d48); + o(0x8d48 + REX_BASE(r)); o(0x05 + REG_VALUE(r) * 8); /* lea xx(%rip), r */ gen_addrpc32(fr, sv->sym, fc); } else { - o(0x8b48); + o(0x8b48 + REX_BASE(r)); o(0x05 + REG_VALUE(r) * 8); /* mov xx(%rip), r */ gen_gotpcrel(r, sv->sym, fc); } #endif } else if (is64_type(ft)) { - o(0x48); + o(0x48 + REX_BASE(r)); o(0xb8 + REG_VALUE(r)); /* mov $xx, r */ gen_le64(sv->c.ull); } else { + if (REX_BASE(r)) + o(0x41); o(0xb8 + REG_VALUE(r)); /* mov $xx, r */ gen_le32(fc); } } else if (v == VT_LOCAL) { - o(0x48 | REX_BASE(r)); + o(0x48 | (REX_BASE(r) << 2)); o(0x8d); /* lea xxx(%ebp), r */ gen_modrm(r, VT_LOCAL, sv->sym, fc); } else if (v == VT_CMP) { - oad(0xb8 + r, 0); /* mov $0, r */ + if (REX_BASE(r)) + o(0x41); + oad(0xb8 + REG_VALUE(r), 0); /* mov $0, r */ + if (REX_BASE(r)) + o(0x41); o(0x0f); /* setxx %br */ o(fc); - o(0xc0 + r); + o(0xc0 + REG_VALUE(r)); } else if (v == VT_JMP || v == VT_JMPI) { t = v & 1; - oad(0xb8 + r, t); /* mov $1, r */ - o(0x05eb); /* jmp after */ + if (REX_BASE(r)) + o(0x41); + oad(0xb8 + REG_VALUE(r), t); /* mov $1, r */ + o(0x05eb + (REX_BASE(r) << 8)); /* jmp after */ gsym(fc); - oad(0xb8 + r, t ^ 1); /* mov $0, r */ + if (REX_BASE(r)) + o(0x41); + oad(0xb8 + REG_VALUE(r), t ^ 1); /* mov $0, r */ } else if (v != r) { if (r == TREG_XMM0) { assert(v == TREG_ST0); @@ -438,7 +464,7 @@ void load(int r, SValue *sv) } else { o(0x48 | REX_BASE(r) | (REX_BASE(v) << 2)); o(0x89); - o(0xc0 + r + v * 8); /* mov v, r */ + o(0xc0 + REG_VALUE(r) + REG_VALUE(v) * 8); /* mov v, r */ } } } @@ -505,9 +531,7 @@ void store(int r, SValue *v) o(op64); o(3 + (r << 3)); } else if (op64) { - if (fr == VT_CONST || - fr == VT_LOCAL || - (v->r & VT_LVAL)) { + if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) { gen_modrm64(op64, r, v->r, v->sym, fc); } else if (fr != r) { /* XXX: don't we really come here? */ @@ -515,9 +539,7 @@ void store(int r, SValue *v) o(0xc0 + fr + r * 8); /* mov r, fr */ } } else { - if (fr == VT_CONST || - fr == VT_LOCAL || - (v->r & VT_LVAL)) { + if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) { gen_modrm(r, v->r, v->sym, fc); } else if (fr != r) { /* XXX: don't we really come here? */ @@ -591,7 +613,6 @@ void gfunc_call(int nb_args) } args_size = (nb_reg_args < REGN ? REGN : nb_reg_args) * PTR_SIZE; - save_regs(0); /* save used temporary registers */ /* for struct arguments, we need to call memcpy and the function call breaks register passing arguments we are preparing. @@ -627,12 +648,14 @@ void gfunc_call(int nb_args) if (func_scratch < args_size) func_scratch = args_size; + for (i = 0; i < REGN; ++i) + save_reg(arg_regs[i]); + gen_reg = nb_reg_args; for(i = 0; i < nb_args; i++) { bt = (vtop->type.t & VT_BTYPE); if (bt == VT_STRUCT || bt == VT_LDOUBLE) { ; /* done */ - } else if (is_sse_float(vtop->type.t)) { gv(RC_FLOAT); /* only one float register */ j = --gen_reg; @@ -641,31 +664,39 @@ void gfunc_call(int nb_args) /* movq %xmm0, j*8(%rsp) */ gen_offs_sp(0x2444d6, 0, j*8); } else { - d = arg_regs[j]; /* movaps %xmm0, %xmmN */ o(0x280f); o(0xc0 + (j << 3)); + d = arg_regs[j]; /* mov %xmm0, %rxx */ o(0x66); - o(0x7e0f48 + (d >= 8)); - o(0xc0 + (d & 7)); + o(0x7e0f48 + REX_BASE(d)); + o(0xc0 + REG_VALUE(d)); } } else { - r = gv(RC_INT); j = --gen_reg; if (j >= REGN) { + r = gv(RC_INT); o(0x48); gen_offs_sp(0x244489, r, j*8); } else { d = arg_regs[j]; - if (d != r) { - o(0x8948 + (d >= 8)); - o(0xc0 + r*8 + (d & 7)); + if (d < NB_REGS) { + gv(reg_classes[d] & ~RC_INT); + } else { + r = gv(RC_INT); + if (d != r) { + o(0x8948 + REX_BASE(d)); + o(0xc0 + r*8 + REG_VALUE(d)); + } } + } } vtop--; } + + save_regs(0); gcall_or_jmp(0); vtop--; } -- 2.11.4.GIT