diff options
Diffstat (limited to 'i386-gen.c')
-rw-r--r-- | i386-gen.c | 733 |
1 files changed, 368 insertions, 365 deletions
@@ -100,47 +100,50 @@ ST_DATA const int reg_classes[NB_REGS] = { static unsigned long func_sub_sp_offset; static int func_ret_sub; #ifdef CONFIG_TCC_BCHECK -static void gen_bounds_prolog(TCCState* S); -static void gen_bounds_epilog(TCCState* S); +static addr_t func_bound_offset; +static unsigned long func_bound_ind; +ST_DATA int func_bound_add_epilog; +static void gen_bounds_prolog(void); +static void gen_bounds_epilog(void); #endif /* XXX: make it faster ? */ -ST_FUNC void g(TCCState* S, int c) +ST_FUNC void g(int c) { int ind1; - if (S->tccgen_nocode_wanted) + if (nocode_wanted) return; - ind1 = S->tccgen_ind + 1; + ind1 = ind + 1; if (ind1 > cur_text_section->data_allocated) - section_realloc(S, cur_text_section, ind1); - cur_text_section->data[S->tccgen_ind] = c; - S->tccgen_ind = ind1; + section_realloc(cur_text_section, ind1); + cur_text_section->data[ind] = c; + ind = ind1; } -ST_FUNC void o(TCCState* S, unsigned int c) +ST_FUNC void o(unsigned int c) { while (c) { - g(S, c); + g(c); c = c >> 8; } } -ST_FUNC void gen_le16(TCCState* S, int v) +ST_FUNC void gen_le16(int v) { - g(S, v); - g(S, v >> 8); + g(v); + g(v >> 8); } -ST_FUNC void gen_le32(TCCState* S, int c) +ST_FUNC void gen_le32(int c) { - g(S, c); - g(S, c >> 8); - g(S, c >> 16); - g(S, c >> 24); + g(c); + g(c >> 8); + g(c >> 16); + g(c >> 24); } /* output a symbol and patch all calls to it */ -ST_FUNC void gsym_addr(TCCState* S, int t, int a) +ST_FUNC void gsym_addr(int t, int a) { while (t) { unsigned char *ptr = cur_text_section->data + t; @@ -151,73 +154,73 @@ ST_FUNC void gsym_addr(TCCState* S, int t, int a) } /* instruction + 4 bytes data. Return the address of the data */ -static int oad(TCCState* S, int c, int s) +static int oad(int c, int s) { int t; - if (S->tccgen_nocode_wanted) + if (nocode_wanted) return s; - o(S, c); - t = S->tccgen_ind; - gen_le32(S, s); + o(c); + t = ind; + gen_le32(s); return t; } -ST_FUNC void gen_fill_nops(TCCState* S, int bytes) +ST_FUNC void gen_fill_nops(int bytes) { while (bytes--) - g(S, 0x90); + g(0x90); } /* generate jmp to a label */ -#define gjmp2(s, instr,lbl) oad(s, instr,lbl) +#define gjmp2(instr,lbl) oad(instr,lbl) /* output constant with relocation if 'r & VT_SYM' is true */ -ST_FUNC void gen_addr32(TCCState* S, int r, Sym *sym, int c) +ST_FUNC void gen_addr32(int r, Sym *sym, int c) { if (r & VT_SYM) - greloc(S, cur_text_section, sym, S->tccgen_ind, R_386_32); - gen_le32(S, c); + greloc(cur_text_section, sym, ind, R_386_32); + gen_le32(c); } -ST_FUNC void gen_addrpc32(TCCState* S, int r, Sym *sym, int c) +ST_FUNC void gen_addrpc32(int r, Sym *sym, int c) { if (r & VT_SYM) - greloc(S, cur_text_section, sym, S->tccgen_ind, R_386_PC32); - gen_le32(S, c - 4); + greloc(cur_text_section, sym, ind, R_386_PC32); + gen_le32(c - 4); } /* generate a modrm reference. 'op_reg' contains the additional 3 opcode bits */ -static void gen_modrm(TCCState* S, int op_reg, int r, Sym *sym, int c) +static void gen_modrm(int op_reg, int r, Sym *sym, int c) { op_reg = op_reg << 3; if ((r & VT_VALMASK) == VT_CONST) { /* constant memory reference */ - o(S, 0x05 | op_reg); - gen_addr32(S, r, sym, c); + o(0x05 | op_reg); + gen_addr32(r, sym, c); } else if ((r & VT_VALMASK) == VT_LOCAL) { /* currently, we use only ebp as base */ if (c == (char)c) { /* short reference */ - o(S, 0x45 | op_reg); - g(S, c); + o(0x45 | op_reg); + g(c); } else { - oad(S, 0x85 | op_reg, c); + oad(0x85 | op_reg, c); } } else { - g(S, 0x00 | op_reg | (r & VT_VALMASK)); + g(0x00 | op_reg | (r & VT_VALMASK)); } } /* load 'r' from value 'sv' */ -ST_FUNC void load(TCCState* S, int r, SValue *sv) +ST_FUNC void load(int r, SValue *sv) { int v, t, ft, fc, fr; SValue v1; #ifdef TCC_TARGET_PE SValue v2; - sv = pe_getimport(S, sv, &v2); + sv = pe_getimport(sv, &v2); #endif fr = sv->r; @@ -235,68 +238,68 @@ ST_FUNC void load(TCCState* S, int r, SValue *sv) v1.sym = NULL; fr = r; if (!(reg_classes[fr] & RC_INT)) - fr = get_reg(S, RC_INT); - load(S, fr, &v1); + fr = get_reg(RC_INT); + load(fr, &v1); } if ((ft & VT_BTYPE) == VT_FLOAT) { - o(S, 0xd9); /* flds */ + o(0xd9); /* flds */ r = 0; } else if ((ft & VT_BTYPE) == VT_DOUBLE) { - o(S, 0xdd); /* fldl */ + o(0xdd); /* fldl */ r = 0; } else if ((ft & VT_BTYPE) == VT_LDOUBLE) { - o(S, 0xdb); /* fldt */ + o(0xdb); /* fldt */ r = 5; } else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) { - o(S, 0xbe0f); /* movsbl */ + o(0xbe0f); /* movsbl */ } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { - o(S, 0xb60f); /* movzbl */ + o(0xb60f); /* movzbl */ } else if ((ft & VT_TYPE) == VT_SHORT) { - o(S, 0xbf0f); /* movswl */ + o(0xbf0f); /* movswl */ } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) { - o(S, 0xb70f); /* movzwl */ + o(0xb70f); /* movzwl */ } else { - o(S, 0x8b); /* movl */ + o(0x8b); /* movl */ } - gen_modrm(S, r, fr, sv->sym, fc); + gen_modrm(r, fr, sv->sym, fc); } else { if (v == VT_CONST) { - o(S, 0xb8 + r); /* mov $xx, r */ - gen_addr32(S, fr, sv->sym, fc); + o(0xb8 + r); /* mov $xx, r */ + gen_addr32(fr, sv->sym, fc); } else if (v == VT_LOCAL) { if (fc) { - o(S, 0x8d); /* lea xxx(%ebp), r */ - gen_modrm(S, r, VT_LOCAL, sv->sym, fc); + o(0x8d); /* lea xxx(%ebp), r */ + gen_modrm(r, VT_LOCAL, sv->sym, fc); } else { - o(S, 0x89); - o(S, 0xe8 + r); /* mov %ebp, r */ + o(0x89); + o(0xe8 + r); /* mov %ebp, r */ } } else if (v == VT_CMP) { - o(S, 0x0f); /* setxx %br */ - o(S, fc); - o(S, 0xc0 + r); - o(S, 0xc0b60f + r * 0x90000); /* movzbl %al, %eax */ + o(0x0f); /* setxx %br */ + o(fc); + o(0xc0 + r); + o(0xc0b60f + r * 0x90000); /* movzbl %al, %eax */ } else if (v == VT_JMP || v == VT_JMPI) { t = v & 1; - oad(S, 0xb8 + r, t); /* mov $1, r */ - o(S, 0x05eb); /* jmp after */ - gsym(S, fc); - oad(S, 0xb8 + r, t ^ 1); /* mov $0, r */ + oad(0xb8 + r, t); /* mov $1, r */ + o(0x05eb); /* jmp after */ + gsym(fc); + oad(0xb8 + r, t ^ 1); /* mov $0, r */ } else if (v != r) { - o(S, 0x89); - o(S, 0xc0 + r + v * 8); /* mov v, r */ + o(0x89); + o(0xc0 + r + v * 8); /* mov v, r */ } } } /* store register 'r' in lvalue 'v' */ -ST_FUNC void store(TCCState* S, int r, SValue *v) +ST_FUNC void store(int r, SValue *v) { int fr, bt, ft, fc; #ifdef TCC_TARGET_PE SValue v2; - v = pe_getimport(S, v, &v2); + v = pe_getimport(v, &v2); #endif ft = v->type.t; @@ -306,66 +309,66 @@ ST_FUNC void store(TCCState* S, int r, SValue *v) bt = ft & VT_BTYPE; /* XXX: incorrect if float reg to reg */ if (bt == VT_FLOAT) { - o(S, 0xd9); /* fsts */ + o(0xd9); /* fsts */ r = 2; } else if (bt == VT_DOUBLE) { - o(S, 0xdd); /* fstpl */ + o(0xdd); /* fstpl */ r = 2; } else if (bt == VT_LDOUBLE) { - o(S, 0xc0d9); /* fld %st(0) */ - o(S, 0xdb); /* fstpt */ + o(0xc0d9); /* fld %st(0) */ + o(0xdb); /* fstpt */ r = 7; } else { if (bt == VT_SHORT) - o(S, 0x66); + o(0x66); if (bt == VT_BYTE || bt == VT_BOOL) - o(S, 0x88); + o(0x88); else - o(S, 0x89); + o(0x89); } if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) { - gen_modrm(S, r, v->r, v->sym, fc); + gen_modrm(r, v->r, v->sym, fc); } else if (fr != r) { - o(S, 0xc0 + fr + r * 8); /* mov r, fr */ + o(0xc0 + fr + r * 8); /* mov r, fr */ } } -static void gadd_sp(TCCState* S, int val) +static void gadd_sp(int val) { if (val == (char)val) { - o(S, 0xc483); - g(S, val); + o(0xc483); + g(val); } else { - oad(S, 0xc481, val); /* add $xxx, %esp */ + oad(0xc481, val); /* add $xxx, %esp */ } } #if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE -static void gen_static_call(TCCState* S, int v) +static void gen_static_call(int v) { Sym *sym; - sym = external_helper_sym(S, v); - oad(S, 0xe8, -4); - greloc(S, cur_text_section, sym, S->tccgen_ind-4, R_386_PC32); + sym = external_helper_sym(v); + oad(0xe8, -4); + greloc(cur_text_section, sym, ind-4, R_386_PC32); } #endif /* 'is_jmp' is '1' if it is a jump */ -static void gcall_or_jmp(TCCState* S, int is_jmp) +static void gcall_or_jmp(int is_jmp) { int r; - if ((S->tccgen_vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (S->tccgen_vtop->r & VT_SYM)) { + if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) { /* constant and relocation case */ - greloc(S, cur_text_section, S->tccgen_vtop->sym, S->tccgen_ind + 1, R_386_PC32); - oad(S, 0xe8 + is_jmp, S->tccgen_vtop->c.i - 4); /* call/jmp im */ + greloc(cur_text_section, vtop->sym, ind + 1, R_386_PC32); + oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */ } else { /* otherwise, indirect call */ - r = gv(S, RC_INT); - o(S, 0xff); /* call/jmp *r */ - o(S, 0xd0 + r + (is_jmp << 4)); + r = gv(RC_INT); + o(0xff); /* call/jmp *r */ + o(0xd0 + r + (is_jmp << 4)); } } @@ -402,75 +405,75 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int /* Generate function call. The function address is pushed first, then all the parameters in call order. This functions pops all the parameters and the function address. */ -ST_FUNC void gfunc_call(TCCState* S, int nb_args) +ST_FUNC void gfunc_call(int nb_args) { int size, align, r, args_size, i, func_call; Sym *func_sym; #ifdef CONFIG_TCC_BCHECK - if (S->do_bounds_check) - gbound_args(S, nb_args); + if (tcc_state->do_bounds_check) + gbound_args(nb_args); #endif args_size = 0; for(i = 0;i < nb_args; i++) { - if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_STRUCT) { - size = type_size(&S->tccgen_vtop->type, &align); + if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { + size = type_size(&vtop->type, &align); /* align to stack align size */ size = (size + 3) & ~3; /* allocate the necessary size on stack */ #ifdef TCC_TARGET_PE if (size >= 4096) { - r = get_reg(S, RC_EAX); - oad(S, 0x68, size); // push size + r = get_reg(RC_EAX); + oad(0x68, size); // push size /* cannot call normal 'alloca' with bound checking */ - gen_static_call(S, tok_alloc_const(S, "__alloca")); - gadd_sp(S, 4); + gen_static_call(tok_alloc_const("__alloca")); + gadd_sp(4); } else #endif { - oad(S, 0xec81, size); /* sub $xxx, %esp */ + oad(0xec81, size); /* sub $xxx, %esp */ /* generate structure store */ - r = get_reg(S, RC_INT); - o(S, 0xe089 + (r << 8)); /* mov %esp, r */ + r = get_reg(RC_INT); + o(0xe089 + (r << 8)); /* mov %esp, r */ } - vset(S, &S->tccgen_vtop->type, r | VT_LVAL, 0); - vswap(S); - vstore(S); + vset(&vtop->type, r | VT_LVAL, 0); + vswap(); + vstore(); args_size += size; - } else if (is_float(S->tccgen_vtop->type.t)) { - gv(S, RC_FLOAT); /* only one float register */ - if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_FLOAT) + } else if (is_float(vtop->type.t)) { + gv(RC_FLOAT); /* only one float register */ + if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) size = 4; - else if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_DOUBLE) + else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) size = 8; else size = 12; - oad(S, 0xec81, size); /* sub $xxx, %esp */ + oad(0xec81, size); /* sub $xxx, %esp */ if (size == 12) - o(S, 0x7cdb); + o(0x7cdb); else - o(S, 0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */ - g(S, 0x24); - g(S, 0x00); + o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */ + g(0x24); + g(0x00); args_size += size; } else { /* simple type (currently always same size) */ /* XXX: implicit cast ? */ - r = gv(S, RC_INT); - if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_LLONG) { + r = gv(RC_INT); + if ((vtop->type.t & VT_BTYPE) == VT_LLONG) { size = 8; - o(S, 0x50 + S->tccgen_vtop->r2); /* push r */ + o(0x50 + vtop->r2); /* push r */ } else { size = 4; } - o(S, 0x50 + r); /* push r */ + o(0x50 + r); /* push r */ args_size += size; } - S->tccgen_vtop--; + vtop--; } - save_regs(S, 0); /* save used temporary registers */ - func_sym = S->tccgen_vtop->type.ref; + save_regs(0); /* save used temporary registers */ + func_sym = vtop->type.ref; func_call = func_sym->f.func_call; /* fast call case */ if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || @@ -487,21 +490,21 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args) for(i = 0;i < fastcall_nb_regs; i++) { if (args_size <= 0) break; - o(S, 0x58 + fastcall_regs_ptr[i]); /* pop r */ + o(0x58 + fastcall_regs_ptr[i]); /* pop r */ /* XXX: incorrect for struct/floats */ args_size -= 4; } } #if !defined(TCC_TARGET_PE) && !TARGETOS_FreeBSD || TARGETOS_OpenBSD - else if ((S->tccgen_vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT) + else if ((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT) args_size -= 4; #endif - gcall_or_jmp(S, 0); + gcall_or_jmp(0); if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW) - gadd_sp(S, args_size); - S->tccgen_vtop--; + gadd_sp(args_size); + vtop--; } #ifdef TCC_TARGET_PE @@ -511,7 +514,7 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args) #endif /* generate function prolog of type 't' */ -ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym) +ST_FUNC void gfunc_prolog(Sym *func_sym) { CType *func_type = &func_sym->type; int addr, align, size, func_call, fastcall_nb_regs; @@ -523,8 +526,8 @@ ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym) sym = func_type->ref; func_call = sym->f.func_call; addr = 8; - S->tccgen_loc = 0; - S->tccgen_func_vc = 0; + loc = 0; + func_vc = 0; if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) { fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1; @@ -538,19 +541,19 @@ ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym) } param_index = 0; - S->tccgen_ind += FUNC_PROLOG_SIZE; - func_sub_sp_offset = S->tccgen_ind; + ind += FUNC_PROLOG_SIZE; + func_sub_sp_offset = ind; /* if the function returns a structure, then add an implicit pointer parameter */ #if defined(TCC_TARGET_PE) || TARGETOS_FreeBSD || TARGETOS_OpenBSD - size = type_size(&S->tccgen_func_vt,&align); - if (((S->tccgen_func_vt.t & VT_BTYPE) == VT_STRUCT) + size = type_size(&func_vt,&align); + if (((func_vt.t & VT_BTYPE) == VT_STRUCT) && (size > 8 || (size & (size - 1)))) { #else - if ((S->tccgen_func_vt.t & VT_BTYPE) == VT_STRUCT) { + if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { #endif /* XXX: fastcall case ? */ - S->tccgen_func_vc = addr; + func_vc = addr; addr += 4; param_index++; } @@ -567,15 +570,15 @@ ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym) #endif if (param_index < fastcall_nb_regs) { /* save FASTCALL register */ - S->tccgen_loc -= 4; - o(S, 0x89); /* movl */ - gen_modrm(S, fastcall_regs_ptr[param_index], VT_LOCAL, NULL, S->tccgen_loc); - param_addr = S->tccgen_loc; + loc -= 4; + o(0x89); /* movl */ + gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc); + param_addr = loc; } else { param_addr = addr; addr += size; } - sym_push(S, sym->v & ~SYM_FIELD, type, + sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, param_addr); param_index++; } @@ -584,94 +587,94 @@ ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym) if (func_call == FUNC_STDCALL || func_call == FUNC_FASTCALLW) func_ret_sub = addr - 8; #if !defined(TCC_TARGET_PE) && !TARGETOS_FreeBSD || TARGETOS_OpenBSD - else if (S->tccgen_func_vc) + else if (func_vc) func_ret_sub = 4; #endif #ifdef CONFIG_TCC_BCHECK - if (S->do_bounds_check) - gen_bounds_prolog(S); + if (tcc_state->do_bounds_check) + gen_bounds_prolog(); #endif } /* generate function epilog */ -ST_FUNC void gfunc_epilog(TCCState* S) +ST_FUNC void gfunc_epilog(void) { addr_t v, saved_ind; #ifdef CONFIG_TCC_BCHECK - if (S->do_bounds_check) - gen_bounds_epilog(S); + if (tcc_state->do_bounds_check) + gen_bounds_epilog(); #endif /* align local size to word & save local variables */ - v = (-S->tccgen_loc + 3) & -4; + v = (-loc + 3) & -4; #if USE_EBX - o(S, 0x8b); - gen_modrm(S, TREG_EBX, VT_LOCAL, NULL, -(v+4)); + o(0x8b); + gen_modrm(TREG_EBX, VT_LOCAL, NULL, -(v+4)); #endif - o(S, 0xc9); /* leave */ + o(0xc9); /* leave */ if (func_ret_sub == 0) { - o(S, 0xc3); /* ret */ + o(0xc3); /* ret */ } else { - o(S, 0xc2); /* ret n */ - g(S, func_ret_sub); - g(S, func_ret_sub >> 8); + o(0xc2); /* ret n */ + g(func_ret_sub); + g(func_ret_sub >> 8); } - saved_ind = S->tccgen_ind; - S->tccgen_ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; + saved_ind = ind; + ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; #ifdef TCC_TARGET_PE if (v >= 4096) { - oad(S, 0xb8, v); /* mov stacksize, %eax */ - gen_static_call(S, TOK___chkstk); /* call __chkstk, (does the stackframe too) */ + oad(0xb8, v); /* mov stacksize, %eax */ + gen_static_call(TOK___chkstk); /* call __chkstk, (does the stackframe too) */ } else #endif { - o(S, 0xe58955); /* push %ebp, mov %esp, %ebp */ - o(S, 0xec81); /* sub esp, stacksize */ - gen_le32(S, v); + o(0xe58955); /* push %ebp, mov %esp, %ebp */ + o(0xec81); /* sub esp, stacksize */ + gen_le32(v); #ifdef TCC_TARGET_PE - o(S, 0x90); /* adjust to FUNC_PROLOG_SIZE */ + o(0x90); /* adjust to FUNC_PROLOG_SIZE */ #endif } - o(S, 0x53 * USE_EBX); /* push ebx */ - S->tccgen_ind = saved_ind; + o(0x53 * USE_EBX); /* push ebx */ + ind = saved_ind; } /* generate a jump to a label */ -ST_FUNC int gjmp(TCCState* S, int t) +ST_FUNC int gjmp(int t) { - return gjmp2(S, 0xe9, t); + return gjmp2(0xe9, t); } /* generate a jump to a fixed address */ -ST_FUNC void gjmp_addr(TCCState* S, int a) +ST_FUNC void gjmp_addr(int a) { int r; - r = a - S->tccgen_ind - 2; + r = a - ind - 2; if (r == (char)r) { - g(S, 0xeb); - g(S, r); + g(0xeb); + g(r); } else { - oad(S, 0xe9, a - S->tccgen_ind - 5); + oad(0xe9, a - ind - 5); } } #if 0 /* generate a jump to a fixed address */ -ST_FUNC void gjmp_cond_addr(TCCState* S, int a, int op) +ST_FUNC void gjmp_cond_addr(int a, int op) { - int r = a - S->tccgen_ind - 2; + int r = a - ind - 2; if (r == (char)r) - g(S, op - 32), g(r); + g(op - 32), g(r); else - g(S, 0x0f), gjmp2(S, op - 16, r - 4); + g(0x0f), gjmp2(op - 16, r - 4); } #endif -ST_FUNC int gjmp_append(TCCState* S, int n, int t) +ST_FUNC int gjmp_append(int n, int t) { void *p; /* insert vtop->c jump list in t */ @@ -685,14 +688,14 @@ ST_FUNC int gjmp_append(TCCState* S, int n, int t) return t; } -ST_FUNC int gjmp_cond(TCCState* S, int op, int t) +ST_FUNC int gjmp_cond(int op, int t) { - g(S, 0x0f); - t = gjmp2(S, op - 16, t); + g(0x0f); + t = gjmp2(op - 16, t); return t; } -ST_FUNC void gen_opi(TCCState* S, int op) +ST_FUNC void gen_opi(int op) { int r, fr, opc, c; @@ -701,36 +704,36 @@ ST_FUNC void gen_opi(TCCState* S, int op) case TOK_ADDC1: /* add with carry generation */ opc = 0; gen_op8: - if ((S->tccgen_vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { /* constant case */ - vswap(S); - r = gv(S, RC_INT); - vswap(S); - c = S->tccgen_vtop->c.i; + vswap(); + r = gv(RC_INT); + vswap(); + c = vtop->c.i; if (c == (char)c) { /* generate inc and dec for smaller code */ if ((c == 1 || c == -1) && (op == '+' || op == '-')) { opc = (c == 1) ^ (op == '+'); - o(S, 0x40 | (opc << 3) | r); // inc,dec + o (0x40 | (opc << 3) | r); // inc,dec } else { - o(S, 0x83); - o(S, 0xc0 | (opc << 3) | r); - g(S, c); + o(0x83); + o(0xc0 | (opc << 3) | r); + g(c); } } else { - o(S, 0x81); - oad(S, 0xc0 | (opc << 3) | r, c); + o(0x81); + oad(0xc0 | (opc << 3) | r, c); } } else { - gv2(S, RC_INT, RC_INT); - r = S->tccgen_vtop[-1].r; - fr = S->tccgen_vtop[0].r; - o(S, (opc << 3) | 0x01); - o(S, 0xc0 + r + fr * 8); + gv2(RC_INT, RC_INT); + r = vtop[-1].r; + fr = vtop[0].r; + o((opc << 3) | 0x01); + o(0xc0 + r + fr * 8); } - S->tccgen_vtop--; + vtop--; if (op >= TOK_ULT && op <= TOK_GT) - vset_VT_CMP(S, op); + vset_VT_CMP(op); break; case '-': case TOK_SUBC1: /* sub with carry generation */ @@ -752,12 +755,12 @@ ST_FUNC void gen_opi(TCCState* S, int op) opc = 1; goto gen_op8; case '*': - gv2(S, RC_INT, RC_INT); - r = S->tccgen_vtop[-1].r; - fr = S->tccgen_vtop[0].r; - S->tccgen_vtop--; - o(S, 0xaf0f); /* imul fr, r */ - o(S, 0xc0 + fr + r * 8); + gv2(RC_INT, RC_INT); + r = vtop[-1].r; + fr = vtop[0].r; + vtop--; + o(0xaf0f); /* imul fr, r */ + o(0xc0 + fr + r * 8); break; case TOK_SHL: opc = 4; @@ -769,23 +772,23 @@ ST_FUNC void gen_opi(TCCState* S, int op) opc = 7; gen_shift: opc = 0xc0 | (opc << 3); - if ((S->tccgen_vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { /* constant case */ - vswap(S); - r = gv(S, RC_INT); - vswap(S); - c = S->tccgen_vtop->c.i & 0x1f; - o(S, 0xc1); /* shl/shr/sar $xxx, r */ - o(S, opc | r); - g(S, c); + vswap(); + r = gv(RC_INT); + vswap(); + c = vtop->c.i & 0x1f; + o(0xc1); /* shl/shr/sar $xxx, r */ + o(opc | r); + g(c); } else { /* we generate the shift in ecx */ - gv2(S, RC_INT, RC_ECX); - r = S->tccgen_vtop[-1].r; - o(S, 0xd3); /* shl/shr/sar %cl, r */ - o(S, opc | r); + gv2(RC_INT, RC_ECX); + r = vtop[-1].r; + o(0xd3); /* shl/shr/sar %cl, r */ + o(opc | r); } - S->tccgen_vtop--; + vtop--; break; case '/': case TOK_UDIV: @@ -795,32 +798,32 @@ ST_FUNC void gen_opi(TCCState* S, int op) case TOK_UMULL: /* first operand must be in eax */ /* XXX: need better constraint for second operand */ - gv2(S, RC_EAX, RC_ECX); - r = S->tccgen_vtop[-1].r; - fr = S->tccgen_vtop[0].r; - S->tccgen_vtop--; - save_reg(S, TREG_EDX); + gv2(RC_EAX, RC_ECX); + r = vtop[-1].r; + fr = vtop[0].r; + vtop--; + save_reg(TREG_EDX); /* save EAX too if used otherwise */ - save_reg_upstack(S, TREG_EAX, 1); + save_reg_upstack(TREG_EAX, 1); if (op == TOK_UMULL) { - o(S, 0xf7); /* mul fr */ - o(S, 0xe0 + fr); - S->tccgen_vtop->r2 = TREG_EDX; + o(0xf7); /* mul fr */ + o(0xe0 + fr); + vtop->r2 = TREG_EDX; r = TREG_EAX; } else { if (op == TOK_UDIV || op == TOK_UMOD) { - o(S, 0xf7d231); /* xor %edx, %edx, div fr, %eax */ - o(S, 0xf0 + fr); + o(0xf7d231); /* xor %edx, %edx, div fr, %eax */ + o(0xf0 + fr); } else { - o(S, 0xf799); /* cltd, idiv fr, %eax */ - o(S, 0xf8 + fr); + o(0xf799); /* cltd, idiv fr, %eax */ + o(0xf8 + fr); } if (op == '%' || op == TOK_UMOD) r = TREG_EDX; else r = TREG_EAX; } - S->tccgen_vtop->r = r; + vtop->r = r; break; default: opc = 7; @@ -831,74 +834,74 @@ ST_FUNC void gen_opi(TCCState* S, int op) /* generate a floating point operation 'v = t1 op t2' instruction. The two operands are guaranteed to have the same floating point type */ /* XXX: need to use ST1 too */ -ST_FUNC void gen_opf(TCCState* S, int op) +ST_FUNC void gen_opf(int op) { int a, ft, fc, swapped, r; if (op == TOK_NEG) { /* unary minus */ - gv(S, RC_FLOAT); - o(S, 0xe0d9); /* fchs */ + gv(RC_FLOAT); + o(0xe0d9); /* fchs */ return; } /* convert constants to memory references */ - if ((S->tccgen_vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { - vswap(S); - gv(S, RC_FLOAT); - vswap(S); + if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { + vswap(); + gv(RC_FLOAT); + vswap(); } - if ((S->tccgen_vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) - gv(S, RC_FLOAT); + if ((vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) + gv(RC_FLOAT); /* must put at least one value in the floating point register */ - if ((S->tccgen_vtop[-1].r & VT_LVAL) && - (S->tccgen_vtop[0].r & VT_LVAL)) { - vswap(S); - gv(S, RC_FLOAT); - vswap(S); + if ((vtop[-1].r & VT_LVAL) && + (vtop[0].r & VT_LVAL)) { + vswap(); + gv(RC_FLOAT); + vswap(); } swapped = 0; /* swap the stack if needed so that t1 is the register and t2 is the memory reference */ - if (S->tccgen_vtop[-1].r & VT_LVAL) { - vswap(S); + if (vtop[-1].r & VT_LVAL) { + vswap(); swapped = 1; } if (op >= TOK_ULT && op <= TOK_GT) { /* load on stack second operand */ - load(S, TREG_ST0, S->tccgen_vtop); - save_reg(S, TREG_EAX); /* eax is used by FP comparison code */ + load(TREG_ST0, vtop); + save_reg(TREG_EAX); /* eax is used by FP comparison code */ if (op == TOK_GE || op == TOK_GT) swapped = !swapped; else if (op == TOK_EQ || op == TOK_NE) swapped = 0; if (swapped) - o(S, 0xc9d9); /* fxch %st(1) */ + o(0xc9d9); /* fxch %st(1) */ if (op == TOK_EQ || op == TOK_NE) - o(S, 0xe9da); /* fucompp */ + o(0xe9da); /* fucompp */ else - o(S, 0xd9de); /* fcompp */ - o(S, 0xe0df); /* fnstsw %ax */ + o(0xd9de); /* fcompp */ + o(0xe0df); /* fnstsw %ax */ if (op == TOK_EQ) { - o(S, 0x45e480); /* and $0x45, %ah */ - o(S, 0x40fC80); /* cmp $0x40, %ah */ + o(0x45e480); /* and $0x45, %ah */ + o(0x40fC80); /* cmp $0x40, %ah */ } else if (op == TOK_NE) { - o(S, 0x45e480); /* and $0x45, %ah */ - o(S, 0x40f480); /* xor $0x40, %ah */ + o(0x45e480); /* and $0x45, %ah */ + o(0x40f480); /* xor $0x40, %ah */ op = TOK_NE; } else if (op == TOK_GE || op == TOK_LE) { - o(S, 0x05c4f6); /* test $0x05, %ah */ + o(0x05c4f6); /* test $0x05, %ah */ op = TOK_EQ; } else { - o(S, 0x45c4f6); /* test $0x45, %ah */ + o(0x45c4f6); /* test $0x45, %ah */ op = TOK_EQ; } - S->tccgen_vtop--; - vset_VT_CMP(S, op); + vtop--; + vset_VT_CMP(op); } else { /* no memory reference possible for long double operations */ - if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { - load(S, TREG_ST0, S->tccgen_vtop); + if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { + load(TREG_ST0, vtop); swapped = !swapped; } @@ -921,213 +924,213 @@ ST_FUNC void gen_opf(TCCState* S, int op) a++; break; } - ft = S->tccgen_vtop->type.t; - fc = S->tccgen_vtop->c.i; + ft = vtop->type.t; + fc = vtop->c.i; if ((ft & VT_BTYPE) == VT_LDOUBLE) { - o(S, 0xde); /* fxxxp %st, %st(1) */ - o(S, 0xc1 + (a << 3)); + o(0xde); /* fxxxp %st, %st(1) */ + o(0xc1 + (a << 3)); } else { /* if saved lvalue, then we must reload it */ - r = S->tccgen_vtop->r; + r = vtop->r; if ((r & VT_VALMASK) == VT_LLOCAL) { SValue v1; - r = get_reg(S, RC_INT); + r = get_reg(RC_INT); v1.type.t = VT_INT; v1.r = VT_LOCAL | VT_LVAL; v1.c.i = fc; v1.sym = NULL; - load(S, r, &v1); + load(r, &v1); fc = 0; } if ((ft & VT_BTYPE) == VT_DOUBLE) - o(S, 0xdc); + o(0xdc); else - o(S, 0xd8); - gen_modrm(S, a, r, S->tccgen_vtop->sym, fc); + o(0xd8); + gen_modrm(a, r, vtop->sym, fc); } - S->tccgen_vtop--; + vtop--; } } /* convert integers to fp 't' type. Must handle 'int', 'unsigned int' and 'long long' cases. */ -ST_FUNC void gen_cvt_itof(TCCState* S, int t) +ST_FUNC void gen_cvt_itof(int t) { - save_reg(S, TREG_ST0); - gv(S, RC_INT); - if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_LLONG) { + save_reg(TREG_ST0); + gv(RC_INT); + if ((vtop->type.t & VT_BTYPE) == VT_LLONG) { /* signed long long to float/double/long double (unsigned case is handled generically) */ - o(S, 0x50 + S->tccgen_vtop->r2); /* push r2 */ - o(S, 0x50 + (S->tccgen_vtop->r & VT_VALMASK)); /* push r */ - o(S, 0x242cdf); /* fildll (%esp) */ - o(S, 0x08c483); /* add $8, %esp */ - S->tccgen_vtop->r2 = VT_CONST; - } else if ((S->tccgen_vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == + o(0x50 + vtop->r2); /* push r2 */ + o(0x50 + (vtop->r & VT_VALMASK)); /* push r */ + o(0x242cdf); /* fildll (%esp) */ + o(0x08c483); /* add $8, %esp */ + vtop->r2 = VT_CONST; + } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) { /* unsigned int to float/double/long double */ - o(S, 0x6a); /* push $0 */ - g(S, 0x00); - o(S, 0x50 + (S->tccgen_vtop->r & VT_VALMASK)); /* push r */ - o(S, 0x242cdf); /* fildll (%esp) */ - o(S, 0x08c483); /* add $8, %esp */ + o(0x6a); /* push $0 */ + g(0x00); + o(0x50 + (vtop->r & VT_VALMASK)); /* push r */ + o(0x242cdf); /* fildll (%esp) */ + o(0x08c483); /* add $8, %esp */ } else { /* int to float/double/long double */ - o(S, 0x50 + (S->tccgen_vtop->r & VT_VALMASK)); /* push r */ - o(S, 0x2404db); /* fildl (%esp) */ - o(S, 0x04c483); /* add $4, %esp */ + o(0x50 + (vtop->r & VT_VALMASK)); /* push r */ + o(0x2404db); /* fildl (%esp) */ + o(0x04c483); /* add $4, %esp */ } - S->tccgen_vtop->r2 = VT_CONST; - S->tccgen_vtop->r = TREG_ST0; + vtop->r2 = VT_CONST; + vtop->r = TREG_ST0; } /* convert fp to int 't' type */ -ST_FUNC void gen_cvt_ftoi(TCCState* S, int t) +ST_FUNC void gen_cvt_ftoi(int t) { - int bt = S->tccgen_vtop->type.t & VT_BTYPE; + int bt = vtop->type.t & VT_BTYPE; if (bt == VT_FLOAT) - vpush_helper_func(S, TOK___fixsfdi); + vpush_helper_func(TOK___fixsfdi); else if (bt == VT_LDOUBLE) - vpush_helper_func(S, TOK___fixxfdi); + vpush_helper_func(TOK___fixxfdi); else - vpush_helper_func(S, TOK___fixdfdi); - vswap(S); - gfunc_call(S, 1); - vpushi(S, 0); - S->tccgen_vtop->r = REG_IRET; + vpush_helper_func(TOK___fixdfdi); + vswap(); + gfunc_call(1); + vpushi(0); + vtop->r = REG_IRET; if ((t & VT_BTYPE) == VT_LLONG) - S->tccgen_vtop->r2 = REG_IRE2; + vtop->r2 = REG_IRE2; } /* convert from one floating point type to another */ -ST_FUNC void gen_cvt_ftof(TCCState* S, int t) +ST_FUNC void gen_cvt_ftof(int t) { /* all we have to do on i386 is to put the float in a register */ - gv(S, RC_FLOAT); + gv(RC_FLOAT); } /* char/short to int conversion */ -ST_FUNC void gen_cvt_csti(TCCState* S, int t) +ST_FUNC void gen_cvt_csti(int t) { int r, sz, xl; - r = gv(S, RC_INT); + r = gv(RC_INT); sz = !(t & VT_UNSIGNED); xl = (t & VT_BTYPE) == VT_SHORT; - o(S, 0xc0b60f /* mov[sz] %a[xl], %eax */ + o(0xc0b60f /* mov[sz] %a[xl], %eax */ | (sz << 3 | xl) << 8 | (r << 3 | r) << 16 ); } /* increment tcov counter */ -ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv) +ST_FUNC void gen_increment_tcov (SValue *sv) { - o(S, 0x0583); /* addl $1, xxx */ - greloc(S, cur_text_section, sv->sym, S->tccgen_ind, R_386_32); - gen_le32(S, 0); - o(S, 1); - o(S, 0x1583); /* addcl $0, xxx */ - greloc(S, cur_text_section, sv->sym, S->tccgen_ind, R_386_32); - gen_le32(S, 4); - g(S, 0); + o(0x0583); /* addl $1, xxx */ + greloc(cur_text_section, sv->sym, ind, R_386_32); + gen_le32(0); + o(1); + o(0x1583); /* addcl $0, xxx */ + greloc(cur_text_section, sv->sym, ind, R_386_32); + gen_le32(4); + g(0); } /* computed goto support */ -ST_FUNC void ggoto(TCCState* S) +ST_FUNC void ggoto(void) { - gcall_or_jmp(S, 1); - S->tccgen_vtop--; + gcall_or_jmp(1); + vtop--; } /* bound check support functions */ #ifdef CONFIG_TCC_BCHECK -static void gen_bounds_prolog(TCCState* S) +static void gen_bounds_prolog(void) { /* leave some room for bound checking code */ - S->func_bound_offset = lbounds_section->data_offset; - S->func_bound_ind = S->tccgen_ind; - S->func_bound_add_epilog = 0; - oad(S, 0xb8, 0); /* lbound section pointer */ - oad(S, 0xb8, 0); /* call to function */ + func_bound_offset = lbounds_section->data_offset; + func_bound_ind = ind; + func_bound_add_epilog = 0; + oad(0xb8, 0); /* lbound section pointer */ + oad(0xb8, 0); /* call to function */ } -static void gen_bounds_epilog(TCCState* S) +static void gen_bounds_epilog(void) { addr_t saved_ind; addr_t *bounds_ptr; Sym *sym_data; - int offset_modified = S->func_bound_offset != lbounds_section->data_offset; + int offset_modified = func_bound_offset != lbounds_section->data_offset; - if (!offset_modified && !S->func_bound_add_epilog) + if (!offset_modified && !func_bound_add_epilog) return; /* add end of table info */ - bounds_ptr = section_ptr_add(S, lbounds_section, sizeof(addr_t)); + bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); *bounds_ptr = 0; - sym_data = get_sym_ref(S, &S->tccgen_char_pointer_type, lbounds_section, - S->func_bound_offset, lbounds_section->data_offset); + sym_data = get_sym_ref(&char_pointer_type, lbounds_section, + func_bound_offset, lbounds_section->data_offset); /* generate bound local allocation */ if (offset_modified) { - saved_ind = S->tccgen_ind; - S->tccgen_ind = S->func_bound_ind; - greloc(S, cur_text_section, sym_data, S->tccgen_ind + 1, R_386_32); - S->tccgen_ind = S->tccgen_ind + 5; - gen_static_call(S, TOK___bound_local_new); - S->tccgen_ind = saved_ind; + saved_ind = ind; + ind = func_bound_ind; + greloc(cur_text_section, sym_data, ind + 1, R_386_32); + ind = ind + 5; + gen_static_call(TOK___bound_local_new); + ind = saved_ind; } /* generate bound check local freeing */ - o(S, 0x5250); /* save returned value, if any */ - greloc(S, cur_text_section, sym_data, S->tccgen_ind + 1, R_386_32); - oad(S, 0xb8, 0); /* mov %eax, xxx */ - gen_static_call(S, TOK___bound_local_delete); - o(S, 0x585a); /* restore returned value, if any */ + o(0x5250); /* save returned value, if any */ + greloc(cur_text_section, sym_data, ind + 1, R_386_32); + oad(0xb8, 0); /* mov %eax, xxx */ + gen_static_call(TOK___bound_local_delete); + o(0x585a); /* restore returned value, if any */ } #endif /* Save the stack pointer onto the stack */ -ST_FUNC void gen_vla_sp_save(TCCState* S, int addr) { +ST_FUNC void gen_vla_sp_save(int addr) { /* mov %esp,addr(%ebp)*/ - o(S, 0x89); - gen_modrm(S, TREG_ESP, VT_LOCAL, NULL, addr); + o(0x89); + gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr); } /* Restore the SP from a location on the stack */ -ST_FUNC void gen_vla_sp_restore(TCCState* S, int addr) { - o(S, 0x8b); - gen_modrm(S, TREG_ESP, VT_LOCAL, NULL, addr); +ST_FUNC void gen_vla_sp_restore(int addr) { + o(0x8b); + gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr); } /* Subtract from the stack pointer, and push the resulting value onto the stack */ -ST_FUNC void gen_vla_alloc(TCCState* S, CType *type, int align) { +ST_FUNC void gen_vla_alloc(CType *type, int align) { int use_call = 0; #if defined(CONFIG_TCC_BCHECK) - use_call = S->do_bounds_check; + use_call = tcc_state->do_bounds_check; #endif #ifdef TCC_TARGET_PE /* alloca does more than just adjust %rsp on Windows */ use_call = 1; #endif if (use_call) { - vpush_helper_func(S, TOK_alloca); - vswap(S); /* Move alloca ref past allocation size */ - gfunc_call(S, 1); + vpush_helper_func(TOK_alloca); + vswap(); /* Move alloca ref past allocation size */ + gfunc_call(1); } else { int r; - r = gv(S, RC_INT); /* allocation size */ + r = gv(RC_INT); /* allocation size */ /* sub r,%rsp */ - o(S, 0x2b); - o(S, 0xe0 | r); + o(0x2b); + o(0xe0 | r); /* We align to 16 bytes rather than align */ /* and ~15, %esp */ - o(S, 0xf0e483); - vpop(S); + o(0xf0e483); + vpop(); } } |