diff options
Diffstat (limited to 'arm-gen.c')
-rw-r--r-- | arm-gen.c | 1133 |
1 files changed, 570 insertions, 563 deletions
@@ -179,17 +179,24 @@ ST_DATA const int reg_classes[NB_REGS] = { static int func_sub_sp_offset, last_itod_magic; static int leaffunc; +#if defined(CONFIG_TCC_BCHECK) +static addr_t func_bound_offset; +static unsigned long func_bound_ind; +ST_DATA int func_bound_add_epilog; +#endif + #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) -ST_FUNC void arm_init(TCCState *S) +static CType float_type, double_type, func_float_type, func_double_type; +ST_FUNC void arm_init(struct TCCState *s) { - S->armgen_float_type.t = VT_FLOAT; - S->armgen_double_type.t = VT_DOUBLE; - S->armgen_func_float_type.t = VT_FUNC; - S->armgen_func_float_type.ref = sym_push(S, SYM_FIELD, &S->armgen_float_type, FUNC_CDECL, FUNC_OLD); - S->armgen_func_double_type.t = VT_FUNC; - S->armgen_func_double_type.ref = sym_push(S, SYM_FIELD, &S->armgen_double_type, FUNC_CDECL, FUNC_OLD); - - float_abi = S->float_abi; + float_type.t = VT_FLOAT; + double_type.t = VT_DOUBLE; + func_float_type.t = VT_FUNC; + func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD); + func_double_type.t = VT_FUNC; + func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD); + + float_abi = s->float_abi; #ifndef TCC_ARM_HARDFLOAT // XXX: Works on OpenBSD // # warning "soft float ABI currently not supported: default to softfp" @@ -216,15 +223,15 @@ ST_FUNC void arm_init(struct TCCState *s) #define CHECK_R(r) ((r) >= TREG_R0 && (r) <= TREG_LR) -static int two2mask(TCCState* S, int a,int b) { +static int two2mask(int a,int b) { if (!CHECK_R(a) || !CHECK_R(b)) - tcc_error(S, "compiler error! registers %i,%i is not valid",a,b); + tcc_error("compiler error! registers %i,%i is not valid",a,b); return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT); } -static int regmask(TCCState* S, int r) { +static int regmask(int r) { if (!CHECK_R(r)) - tcc_error(S, "compiler error! register %i is not valid",r); + tcc_error("compiler error! register %i is not valid",r); return reg_classes[r]&~(RC_INT|RC_FLOAT); } @@ -240,25 +247,25 @@ const char *default_elfinterp(struct TCCState *s) } #endif -void o(TCCState* S, uint32_t i) +void o(uint32_t i) { /* this is a good place to start adding big-endian support*/ int ind1; - if (S->tccgen_nocode_wanted) + if (nocode_wanted) return; - ind1 = S->tccgen_ind + 4; + ind1 = ind + 4; if (!cur_text_section) - tcc_error(S, "compiler error! This happens f.ex. if the compiler\n" + tcc_error("compiler error! This happens f.ex. if the compiler\n" "can't evaluate constant expressions outside of a function."); if (ind1 > cur_text_section->data_allocated) - section_realloc(S, cur_text_section, ind1); - cur_text_section->data[S->tccgen_ind++] = i&255; + section_realloc(cur_text_section, ind1); + cur_text_section->data[ind++] = i&255; i>>=8; - cur_text_section->data[S->tccgen_ind++] = i&255; + cur_text_section->data[ind++] = i&255; i>>=8; - cur_text_section->data[S->tccgen_ind++] = i&255; + cur_text_section->data[ind++] = i&255; i>>=8; - cur_text_section->data[S->tccgen_ind++] = i; + cur_text_section->data[ind++] = i; } static uint32_t stuff_const(uint32_t op, uint32_t c) @@ -315,11 +322,11 @@ static uint32_t stuff_const(uint32_t op, uint32_t c) //only add,sub -void stuff_const_harder(TCCState* S, uint32_t op, uint32_t v) { +void stuff_const_harder(uint32_t op, uint32_t v) { uint32_t x; x=stuff_const(op,v); if(x) - o(S, x); + o(x); else { uint32_t a[16], nv, no, o2, n2; int i,j,k; @@ -330,8 +337,8 @@ void stuff_const_harder(TCCState* S, uint32_t op, uint32_t v) { for(i=0;i<12;i++) for(j=i<4?i+12:15;j>=i+4;j--) if((v&(a[i]|a[j]))==v) { - o(S, stuff_const(op,v&a[i])); - o(S, stuff_const(o2,v&a[j])); + o(stuff_const(op,v&a[i])); + o(stuff_const(o2,v&a[j])); return; } no=op^0xC00000; @@ -340,17 +347,17 @@ void stuff_const_harder(TCCState* S, uint32_t op, uint32_t v) { for(i=0;i<12;i++) for(j=i<4?i+12:15;j>=i+4;j--) if((nv&(a[i]|a[j]))==nv) { - o(S, stuff_const(no,nv&a[i])); - o(S, stuff_const(n2,nv&a[j])); + o(stuff_const(no,nv&a[i])); + o(stuff_const(n2,nv&a[j])); return; } for(i=0;i<8;i++) for(j=i+4;j<12;j++) for(k=i<4?i+12:15;k>=j+4;k--) if((v&(a[i]|a[j]|a[k]))==v) { - o(S, stuff_const(op,v&a[i])); - o(S, stuff_const(o2,v&a[j])); - o(S, stuff_const(o2,v&a[k])); + o(stuff_const(op,v&a[i])); + o(stuff_const(o2,v&a[j])); + o(stuff_const(o2,v&a[k])); return; } no=op^0xC00000; @@ -359,31 +366,31 @@ void stuff_const_harder(TCCState* S, uint32_t op, uint32_t v) { for(j=i+4;j<12;j++) for(k=i<4?i+12:15;k>=j+4;k--) if((nv&(a[i]|a[j]|a[k]))==nv) { - o(S, stuff_const(no,nv&a[i])); - o(S, stuff_const(n2,nv&a[j])); - o(S, stuff_const(n2,nv&a[k])); + o(stuff_const(no,nv&a[i])); + o(stuff_const(n2,nv&a[j])); + o(stuff_const(n2,nv&a[k])); return; } - o(S, stuff_const(op,v&a[0])); - o(S, stuff_const(o2,v&a[4])); - o(S, stuff_const(o2,v&a[8])); - o(S, stuff_const(o2,v&a[12])); + o(stuff_const(op,v&a[0])); + o(stuff_const(o2,v&a[4])); + o(stuff_const(o2,v&a[8])); + o(stuff_const(o2,v&a[12])); } } -uint32_t encbranch(TCCState* S, int pos, int addr, int fail) +uint32_t encbranch(int pos, int addr, int fail) { addr-=pos+8; addr/=4; if(addr>=0x1000000 || addr<-0x1000000) { if(fail) - tcc_error(S, "FIXME: function bigger than 32MB"); + tcc_error("FIXME: function bigger than 32MB"); return 0; } return 0x0A000000|(addr&0xffffff); } -int decbranch(TCCState* S, int pos) +int decbranch(int pos) { int x; x=*(uint32_t *)(cur_text_section->data + pos); @@ -394,50 +401,50 @@ int decbranch(TCCState* S, int pos) } /* output a symbol and patch all calls to it */ -void gsym_addr(TCCState* S, int t, int a) +void gsym_addr(int t, int a) { uint32_t *x; int lt; while(t) { x=(uint32_t *)(cur_text_section->data + t); - t=decbranch(S, lt=t); + t=decbranch(lt=t); if(a==lt+4) *x=0xE1A00000; // nop else { *x &= 0xff000000; - *x |= encbranch(S, lt,a,1); + *x |= encbranch(lt,a,1); } } } #ifdef TCC_ARM_VFP -static uint32_t vfpr(TCCState* S, int r) +static uint32_t vfpr(int r) { if(r<TREG_F0 || r>TREG_F7) - tcc_error(S, "compiler error! register %i is no vfp register",r); + tcc_error("compiler error! register %i is no vfp register",r); return r - TREG_F0; } #else -static uint32_t fpr(TCCState* S, int r) +static uint32_t fpr(int r) { if(r<TREG_F0 || r>TREG_F3) - tcc_error(S, "compiler error! register %i is no fpa register",r); + tcc_error("compiler error! register %i is no fpa register",r); return r - TREG_F0; } #endif -static uint32_t intr(TCCState* S, int r) +static uint32_t intr(int r) { if(r == TREG_R12) return 12; if(r >= TREG_R0 && r <= TREG_R3) return r - TREG_R0; if (!(r >= TREG_SP && r <= TREG_LR)) - tcc_error(S, "compiler error! register %i is no int register",r); + tcc_error("compiler error! register %i is no int register",r); return r + (13 - TREG_SP); } -static void calcaddr(TCCState* S, uint32_t *base, int *off, int *sgn, int maxoff, unsigned shift) +static void calcaddr(uint32_t *base, int *off, int *sgn, int maxoff, unsigned shift) { if(*off>maxoff || *off&((1<<shift)-1)) { uint32_t x, y; @@ -448,23 +455,23 @@ static void calcaddr(TCCState* S, uint32_t *base, int *off, int *sgn, int maxoff *base=14; // lr y=stuff_const(x,*off&~maxoff); if(y) { - o(S, y); + o(y); *off&=maxoff; return; } y=stuff_const(x,(*off+maxoff)&~maxoff); if(y) { - o(S, y); + o(y); *sgn=!*sgn; *off=((*off+maxoff)&~maxoff)-*off; return; } - stuff_const_harder(S, x,*off&~maxoff); + stuff_const_harder(x,*off&~maxoff); *off&=maxoff; } } -static uint32_t mapcc(TCCState* S, int cc) +static uint32_t mapcc(int cc) { switch(cc) { @@ -493,11 +500,11 @@ static uint32_t mapcc(TCCState* S, int cc) case TOK_GT: return 0xC0000000; /* GT */ } - tcc_error(S, "unexpected condition code"); + tcc_error("unexpected condition code"); return 0xE0000000; /* AL */ } -static int negcc(TCCState* S, int cc) +static int negcc(int cc) { switch(cc) { @@ -526,44 +533,44 @@ static int negcc(TCCState* S, int cc) case TOK_GT: return TOK_LE; } - tcc_error(S, "unexpected condition code"); + tcc_error("unexpected condition code"); return TOK_NE; } /* Load value into register r. Use relative/got addressing to avoid setting DT_TEXTREL */ -static void load_value(TCCState* S, SValue *sv, int r) +static void load_value(SValue *sv, int r) { - o(S, 0xE59F0000|(intr(S, r)<<12)); /* ldr r, [pc] */ - o(S, 0xEA000000); /* b $+4 */ + o(0xE59F0000|(intr(r)<<12)); /* ldr r, [pc] */ + o(0xEA000000); /* b $+4 */ #ifndef CONFIG_TCC_PIE if(sv->r & VT_SYM) - greloc(S, cur_text_section, sv->sym, S->tccgen_ind, R_ARM_ABS32); - o(S, sv->c.i); + greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); + o(sv->c.i); #else if(sv->r & VT_SYM) { if (sv->sym->type.t & VT_STATIC) { greloc(cur_text_section, sv->sym, ind, R_ARM_REL32); - o(S, sv->c.i - 12); - o(S, 0xe080000f | (intr(S, r)<<12) | (intr(S, r)<<16)); // add rx,rx,pc + o(sv->c.i - 12); + o(0xe080000f | (intr(r)<<12) | (intr(r)<<16)); // add rx,rx,pc } else { greloc(cur_text_section, sv->sym, ind, R_ARM_GOT_PREL); - o(S, -12); - o(S, 0xe080000f | (intr(S, r)<<12) | (intr(S, r)<<16)); // add rx,rx,pc - o(S, 0xe5900000 | (intr(S, r)<<12) | (intr(S, r)<<16)); // ldr rx,[rx] + o(-12); + o(0xe080000f | (intr(r)<<12) | (intr(r)<<16)); // add rx,rx,pc + o(0xe5900000 | (intr(r)<<12) | (intr(r)<<16)); // ldr rx,[rx] if (sv->c.i) - stuff_const_harder(S, 0xe2800000 | (intr(S, r)<<12) | (intr(S, r)<<16), + stuff_const_harder(0xe2800000 | (intr(r)<<12) | (intr(r)<<16), sv->c.i); } } else - o(S, sv->c.i); + o(sv->c.i); #endif } /* load 'r' from value 'sv' */ -void load(TCCState* S, int r, SValue *sv) +void load(int r, SValue *sv) { int v, ft, fc, fr, sign; uint32_t op; @@ -587,7 +594,7 @@ void load(TCCState* S, int r, SValue *sv) v1.type.t = VT_PTR; v1.r = VT_LOCAL | VT_LVAL; v1.c.i = sv->c.i; - load(S, TREG_LR, &v1); + load(TREG_LR, &v1); base = 14; /* lr */ fc=sign=0; v=VT_LOCAL; @@ -596,25 +603,25 @@ void load(TCCState* S, int r, SValue *sv) v1.r = fr&~VT_LVAL; v1.c.i = sv->c.i; v1.sym=sv->sym; - load(S, TREG_LR, &v1); + load(TREG_LR, &v1); base = 14; /* lr */ fc=sign=0; v=VT_LOCAL; } else if(v < VT_CONST) { - base=intr(S, v); + base=intr(v); fc=sign=0; v=VT_LOCAL; } if(v == VT_LOCAL) { if(is_float(ft)) { - calcaddr(S, &base,&fc,&sign,1020,2); + calcaddr(&base,&fc,&sign,1020,2); #ifdef TCC_ARM_VFP op=0xED100A00; /* flds */ if(!sign) op|=0x800000; if ((ft & VT_BTYPE) != VT_FLOAT) op|=0x100; /* flds -> fldd */ - o(S, op|(vfpr(S, r)<<12)|(fc>>2)|(base<<16)); + o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16)); #else op=0xED100100; if(!sign) @@ -628,11 +635,11 @@ void load(TCCState* S, int r, SValue *sv) else if ((ft & VT_BTYPE) == VT_LDOUBLE) op|=0x400000; #endif - o(S, op|(fpr(S, r)<<12)|(fc>>2)|(base<<16)); + o(op|(fpr(r)<<12)|(fc>>2)|(base<<16)); #endif } else if((ft & (VT_BTYPE|VT_UNSIGNED)) == VT_BYTE || (ft & VT_BTYPE) == VT_SHORT) { - calcaddr(S, &base,&fc,&sign,255,0); + calcaddr(&base,&fc,&sign,255,0); op=0xE1500090; if ((ft & VT_BTYPE) == VT_SHORT) op|=0x20; @@ -640,63 +647,63 @@ void load(TCCState* S, int r, SValue *sv) op|=0x40; if(!sign) op|=0x800000; - o(S, op|(intr(S, r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf)); + o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf)); } else { - calcaddr(S, &base,&fc,&sign,4095,0); + calcaddr(&base,&fc,&sign,4095,0); op=0xE5100000; if(!sign) op|=0x800000; if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) op|=0x400000; - o(S, op|(intr(S, r)<<12)|fc|(base<<16)); + o(op|(intr(r)<<12)|fc|(base<<16)); } return; } } else { if (v == VT_CONST) { - op=stuff_const(0xE3A00000|(intr(S, r)<<12),sv->c.i); + op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.i); if (fr & VT_SYM || !op) - load_value(S, sv, r); + load_value(sv, r); else - o(S, op); + o(op); return; } else if (v == VT_LOCAL) { - op=stuff_const(0xE28B0000|(intr(S, r)<<12),sv->c.i); + op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.i); if (fr & VT_SYM || !op) { - load_value(S, sv, r); - o(S, 0xE08B0000|(intr(S, r)<<12)|intr(S, r)); + load_value(sv, r); + o(0xE08B0000|(intr(r)<<12)|intr(r)); } else - o(S, op); + o(op); return; } else if(v == VT_CMP) { - o(S, mapcc(S, sv->c.i)|0x3A00001|(intr(S, r)<<12)); - o(S, mapcc(S, negcc(S, sv->c.i))|0x3A00000|(intr(S, r)<<12)); + o(mapcc(sv->c.i)|0x3A00001|(intr(r)<<12)); + o(mapcc(negcc(sv->c.i))|0x3A00000|(intr(r)<<12)); return; } else if (v == VT_JMP || v == VT_JMPI) { int t; t = v & 1; - o(S, 0xE3A00000|(intr(S, r)<<12)|t); - o(S, 0xEA000000); - gsym(S, sv->c.i); - o(S, 0xE3A00000|(intr(S, r)<<12)|(t^1)); + o(0xE3A00000|(intr(r)<<12)|t); + o(0xEA000000); + gsym(sv->c.i); + o(0xE3A00000|(intr(r)<<12)|(t^1)); return; } else if (v < VT_CONST) { if(is_float(ft)) #ifdef TCC_ARM_VFP - o(S, 0xEEB00A40|(vfpr(S, r)<<12)|vfpr(S, v)|T2CPR(ft)); /* fcpyX */ + o(0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft)); /* fcpyX */ #else - o(S, 0xEE008180|(fpr(S, r)<<12)|fpr(S, v)); + o(0xEE008180|(fpr(r)<<12)|fpr(v)); #endif else - o(S, 0xE1A00000|(intr(S, r)<<12)|intr(S, v)); + o(0xE1A00000|(intr(r)<<12)|intr(v)); return; } } - tcc_error(S, "load unimplemented!"); + tcc_error("load unimplemented!"); } /* store register 'r' in lvalue 'v' */ -void store(TCCState* S, int r, SValue *sv) +void store(int r, SValue *sv) { SValue v1; int v, ft, fc, fr, sign; @@ -717,7 +724,7 @@ void store(TCCState* S, int r, SValue *sv) if (fr & VT_LVAL || fr == VT_LOCAL) { uint32_t base = 0xb; /* fp */ if(v < VT_CONST) { - base=intr(S, v); + base=intr(v); v=VT_LOCAL; fc=sign=0; } else if(v == VT_CONST) { @@ -725,21 +732,21 @@ void store(TCCState* S, int r, SValue *sv) v1.r = fr&~VT_LVAL; v1.c.i = sv->c.i; v1.sym=sv->sym; - load(S, TREG_LR, &v1); + load(TREG_LR, &v1); base = 14; /* lr */ fc=sign=0; v=VT_LOCAL; } if(v == VT_LOCAL) { if(is_float(ft)) { - calcaddr(S, &base,&fc,&sign,1020,2); + calcaddr(&base,&fc,&sign,1020,2); #ifdef TCC_ARM_VFP op=0xED000A00; /* fsts */ if(!sign) op|=0x800000; if ((ft & VT_BTYPE) != VT_FLOAT) op|=0x100; /* fsts -> fstd */ - o(S, op|(vfpr(S, r)<<12)|(fc>>2)|(base<<16)); + o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16)); #else op=0xED000100; if(!sign) @@ -753,138 +760,138 @@ void store(TCCState* S, int r, SValue *sv) if ((ft & VT_BTYPE) == VT_LDOUBLE) op|=0x400000; #endif - o(S, op|(fpr(S, r)<<12)|(fc>>2)|(base<<16)); + o(op|(fpr(r)<<12)|(fc>>2)|(base<<16)); #endif return; } else if((ft & VT_BTYPE) == VT_SHORT) { - calcaddr(S, &base,&fc,&sign,255,0); + calcaddr(&base,&fc,&sign,255,0); op=0xE14000B0; if(!sign) op|=0x800000; - o(S, op|(intr(S, r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf)); + o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf)); } else { - calcaddr(S, &base,&fc,&sign,4095,0); + calcaddr(&base,&fc,&sign,4095,0); op=0xE5000000; if(!sign) op|=0x800000; if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) op|=0x400000; - o(S, op|(intr(S, r)<<12)|fc|(base<<16)); + o(op|(intr(r)<<12)|fc|(base<<16)); } return; } } - tcc_error(S, "store unimplemented"); + tcc_error("store unimplemented"); } -static void gadd_sp(TCCState* S, int val) +static void gadd_sp(int val) { - stuff_const_harder(S, 0xE28DD000,val); + stuff_const_harder(0xE28DD000,val); } /* '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; uint32_t x; - if ((S->tccgen_vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { + if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { /* constant case */ - if(S->tccgen_vtop->r & VT_SYM){ - x=encbranch(S, S->tccgen_ind, S->tccgen_ind+S->tccgen_vtop->c.i,0); + if(vtop->r & VT_SYM){ + x=encbranch(ind,ind+vtop->c.i,0); if(x) { /* relocation case */ - greloc(S, cur_text_section, S->tccgen_vtop->sym, S->tccgen_ind, R_ARM_PC24); - o(S, x|(is_jmp?0xE0000000:0xE1000000)); + greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24); + o(x|(is_jmp?0xE0000000:0xE1000000)); } else { r = TREG_LR; - load_value(S, S->tccgen_vtop, r); + load_value(vtop, r); if(is_jmp) - o(S, 0xE1A0F000 | intr(S, r)); // mov pc, r + o(0xE1A0F000 | intr(r)); // mov pc, r else - o(S, 0xe12fff30 | intr(S, r)); // blx r + o(0xe12fff30 | intr(r)); // blx r } }else{ if(!is_jmp) - o(S, 0xE28FE004); // add lr,pc,#4 - o(S, 0xE51FF004); // ldr pc,[pc,#-4] - o(S, S->tccgen_vtop->c.i); + o(0xE28FE004); // add lr,pc,#4 + o(0xE51FF004); // ldr pc,[pc,#-4] + o(vtop->c.i); } } else { /* otherwise, indirect call */ #ifdef CONFIG_TCC_BCHECK - S->tccgen_vtop->r &= ~VT_MUSTBOUND; + vtop->r &= ~VT_MUSTBOUND; #endif - r = gv(S, RC_INT); + r = gv(RC_INT); if(!is_jmp) - o(S, 0xE1A0E00F); // mov lr,pc - o(S, 0xE1A0F000|intr(S, r)); // mov pc,r + o(0xE1A0E00F); // mov lr,pc + o(0xE1A0F000|intr(r)); // mov pc,r } } #if defined(CONFIG_TCC_BCHECK) -static void gen_bounds_call(TCCState* S, int v) +static void gen_bounds_call(int v) { - Sym *sym = external_helper_sym(S, v); + Sym *sym = external_helper_sym(v); - greloc(S, cur_text_section, sym, S->tccgen_ind, R_ARM_PC24); - o(S, 0xebfffffe); + greloc(cur_text_section, sym, ind, R_ARM_PC24); + o(0xebfffffe); } -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; - o(S, 0xe1a00000); /* ld r0,lbounds_section->data_offset */ - o(S, 0xe1a00000); - o(S, 0xe1a00000); - o(S, 0xe1a00000); - o(S, 0xe1a00000); /* call __bound_local_new */ + func_bound_offset = lbounds_section->data_offset; + func_bound_ind = ind; + func_bound_add_epilog = 0; + o(0xe1a00000); /* ld r0,lbounds_section->data_offset */ + o(0xe1a00000); + o(0xe1a00000); + o(0xe1a00000); + o(0xe1a00000); /* call __bound_local_new */ } -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; - o(S, 0xe59f0000); /* ldr r0, [pc] */ - o(S, 0xea000000); /* b $+4 */ - greloc(S, cur_text_section, sym_data, S->tccgen_ind, R_ARM_REL32); - o(S, -12); /* lbounds_section->data_offset */ - o(S, 0xe080000f); /* add r0,r0,pc */ - gen_bounds_call(S, TOK___bound_local_new); - S->tccgen_ind = saved_ind; + saved_ind = ind; + ind = func_bound_ind; + o(0xe59f0000); /* ldr r0, [pc] */ + o(0xea000000); /* b $+4 */ + greloc(cur_text_section, sym_data, ind, R_ARM_REL32); + o(-12); /* lbounds_section->data_offset */ + o(0xe080000f); /* add r0,r0,pc */ + gen_bounds_call(TOK___bound_local_new); + ind = saved_ind; } /* generate bound check local freeing */ - o(S, 0xe92d0003); /* push {r0,r1} */ - o(S, 0xed2d0b02); /* vpush {d0} */ - o(S, 0xe59f0000); /* ldr r0, [pc] */ - o(S, 0xea000000); /* b $+4 */ - greloc(S, cur_text_section, sym_data, S->tccgen_ind, R_ARM_REL32); - o(S, -12); /* lbounds_section->data_offset */ - o(S, 0xe080000f); /* add r0,r0,pc */ - gen_bounds_call(S, TOK___bound_local_delete); - o(S, 0xecbd0b02); /* vpop {d0} */ - o(S, 0xe8bd0003); /* pop {r0,r1} */ + o(0xe92d0003); /* push {r0,r1} */ + o(0xed2d0b02); /* vpush {d0} */ + o(0xe59f0000); /* ldr r0, [pc] */ + o(0xea000000); /* b $+4 */ + greloc(cur_text_section, sym_data, ind, R_ARM_REL32); + o(-12); /* lbounds_section->data_offset */ + o(0xe080000f); /* add r0,r0,pc */ + gen_bounds_call(TOK___bound_local_delete); + o(0xecbd0b02); /* vpop {d0} */ + o(0xe8bd0003); /* pop {r0,r1} */ } #endif @@ -1070,7 +1077,7 @@ static void add_param_plan(struct plan* plan, int cls, int start, int end, SValu Note: this function allocated an array in plan->pplans with tcc_malloc. It is the responsibility of the caller to free this array once used (ie not before copy_params). */ -static int assign_regs(TCCState *S, int nb_args, int float_abi, struct plan *plan, int *todo) +static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo) { int i, size, align; int ncrn /* next core register number */, nsaa /* next stacked argument address*/; @@ -1081,12 +1088,12 @@ static int assign_regs(TCCState *S, int nb_args, int float_abi, struct plan *pla for(i = nb_args; i-- ;) { int j, start_vfpreg = 0; - CType type = S->tccgen_vtop[-i].type; + CType type = vtop[-i].type; type.t &= ~VT_ARRAY; size = type_size(&type, &align); size = (size + 3) & ~3; align = (align + 3) & ~3; - switch(S->tccgen_vtop[-i].type.t & VT_BTYPE) { + switch(vtop[-i].type.t & VT_BTYPE) { case VT_STRUCT: case VT_FLOAT: case VT_DOUBLE: @@ -1094,15 +1101,15 @@ static int assign_regs(TCCState *S, int nb_args, int float_abi, struct plan *pla if (float_abi == ARM_HARD_FLOAT) { int is_hfa = 0; /* Homogeneous float aggregate */ - if (is_float(S->tccgen_vtop[-i].type.t) - || (is_hfa = is_hgen_float_aggr(&S->tccgen_vtop[-i].type))) { + if (is_float(vtop[-i].type.t) + || (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) { int end_vfpreg; start_vfpreg = assign_vfpreg(&avregs, align, size); end_vfpreg = start_vfpreg + ((size - 1) >> 2); if (start_vfpreg >= 0) { add_param_plan(plan, is_hfa ? VFP_STRUCT_CLASS : VFP_CLASS, - start_vfpreg, end_vfpreg, &S->tccgen_vtop[-i]); + start_vfpreg, end_vfpreg, &vtop[-i]); continue; } else break; @@ -1115,7 +1122,7 @@ static int assign_regs(TCCState *S, int nb_args, int float_abi, struct plan *pla * CORE_STRUCT_CLASS or the first of STACK_CLASS. */ for (j = ncrn; j < 4 && j < ncrn + size / 4; j++) *todo|=(1<<j); - add_param_plan(plan, CORE_STRUCT_CLASS, ncrn, j, &S->tccgen_vtop[-i]); + add_param_plan(plan, CORE_STRUCT_CLASS, ncrn, j, &vtop[-i]); ncrn += size/4; if (ncrn > 4) nsaa = (ncrn - 4) * 4; @@ -1126,20 +1133,20 @@ static int assign_regs(TCCState *S, int nb_args, int float_abi, struct plan *pla continue; default: if (ncrn < 4) { - int is_long = (S->tccgen_vtop[-i].type.t & VT_BTYPE) == VT_LLONG; + int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG; if (is_long) { ncrn = (ncrn + 1) & -2; if (ncrn == 4) break; } - add_param_plan(plan, CORE_CLASS, ncrn, ncrn + is_long, &S->tccgen_vtop[-i]); + add_param_plan(plan, CORE_CLASS, ncrn, ncrn + is_long, &vtop[-i]); ncrn += 1 + is_long; continue; } } nsaa = (nsaa + (align - 1)) & ~(align - 1); - add_param_plan(plan, STACK_CLASS, nsaa, nsaa + size, &S->tccgen_vtop[-i]); + add_param_plan(plan, STACK_CLASS, nsaa, nsaa + size, &vtop[-i]); nsaa += size; /* size already rounded up before */ } return nsaa; @@ -1153,7 +1160,7 @@ static int assign_regs(TCCState *S, int nb_args, int float_abi, struct plan *pla todo: a bitmap indicating what core reg will hold a parameter Returns the number of SValue added by this function on the value stack */ -static int copy_params(TCCState* S, int nb_args, struct plan *plan, int todo) +static int copy_params(int nb_args, struct plan *plan, int todo) { int size, align, r, i, nb_extra_sval = 0; struct param_plan *pplan; @@ -1182,7 +1189,7 @@ again: && (i != CORE_CLASS || pplan->sval->r < VT_CONST)) continue; - vpushv(S, pplan->sval); + vpushv(pplan->sval); pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */ switch(i) { case STACK_CLASS: @@ -1197,16 +1204,16 @@ again: padding = pplan->start - pplan->prev->end; size += padding; /* Add padding if any */ /* allocate the necessary size on stack */ - gadd_sp(S, -size); + gadd_sp(-size); /* generate structure store */ - r = get_reg(S, RC_INT); - o(S, 0xE28D0000|(intr(S, r)<<12)|padding); /* add r, sp, padding */ - vset(S, &S->tccgen_vtop->type, r | VT_LVAL, 0); - vswap(S); + r = get_reg(RC_INT); + o(0xE28D0000|(intr(r)<<12)|padding); /* add r, sp, padding */ + vset(&vtop->type, r | VT_LVAL, 0); + vswap(); /* XXX: optimize. Save all register because memcpy can use them */ - o(S, 0xED2D0A00|(0&1)<<22|(0>>1)<<12|16); /* vpush {s0-s15} */ - vstore(S); /* memcpy to current sp + potential padding */ - o(S, 0xECBD0A00|(0&1)<<22|(0>>1)<<12|16); /* vpop {s0-s15} */ + o(0xED2D0A00|(0&1)<<22|(0>>1)<<12|16); /* vpush {s0-s15} */ + vstore(); /* memcpy to current sp + potential padding */ + o(0xECBD0A00|(0&1)<<22|(0>>1)<<12|16); /* vpop {s0-s15} */ /* Homogeneous float aggregate are loaded to VFP registers immediately since there is no way of loading data in multiple @@ -1215,23 +1222,23 @@ again: if (i == VFP_STRUCT_CLASS) { int first = pplan->start, nb = pplan->end - first + 1; /* vpop.32 {pplan->start, ..., pplan->end} */ - o(S, 0xECBD0A00|(first&1)<<22|(first>>1)<<12|nb); + o(0xECBD0A00|(first&1)<<22|(first>>1)<<12|nb); /* No need to write the register used to a SValue since VFP regs cannot be used for gcall_or_jmp */ } } else { if (is_float(pplan->sval->type.t)) { #ifdef TCC_ARM_VFP - r = vfpr(S, gv(S, RC_FLOAT)) << 12; + r = vfpr(gv(RC_FLOAT)) << 12; if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) size = 4; else { size = 8; r |= 0x101; /* vpush.32 -> vpush.64 */ } - o(S, 0xED2D0A01 + r); /* vpush */ + o(0xED2D0A01 + r); /* vpush */ #else - r = fpr(S, gv(S, RC_FLOAT)) << 12; + r = fpr(gv(RC_FLOAT)) << 12; if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) size = 4; else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE) @@ -1244,49 +1251,49 @@ again: else if(size == 8) r|=0x8000; - o(S, 0xED2D0100|r|(size>>2)); /* some kind of vpush for FPA */ + o(0xED2D0100|r|(size>>2)); /* some kind of vpush for FPA */ #endif } else { /* simple type (currently always same size) */ /* XXX: implicit cast ? */ size=4; if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { - lexpand(S); + lexpand(); size = 8; - r = gv(S, RC_INT); - o(S, 0xE52D0004|(intr(S, r)<<12)); /* push r */ - S->tccgen_vtop--; + r = gv(RC_INT); + o(0xE52D0004|(intr(r)<<12)); /* push r */ + vtop--; } - r = gv(S, RC_INT); - o(S, 0xE52D0004|(intr(S, r)<<12)); /* push r */ + r = gv(RC_INT); + o(0xE52D0004|(intr(r)<<12)); /* push r */ } if (i == STACK_CLASS && pplan->prev) - gadd_sp(S, pplan->prev->end - pplan->start); /* Add padding if any */ + gadd_sp(pplan->prev->end - pplan->start); /* Add padding if any */ } break; case VFP_CLASS: - gv(S, regmask(S, TREG_F0 + (pplan->start >> 1))); + gv(regmask(TREG_F0 + (pplan->start >> 1))); if (pplan->start & 1) { /* Must be in upper part of double register */ - o(S, 0xEEF00A40|((pplan->start>>1)<<12)|(pplan->start>>1)); /* vmov.f32 s(n+1), sn */ - S->tccgen_vtop->r = VT_CONST; /* avoid being saved on stack by gv for next float */ + o(0xEEF00A40|((pplan->start>>1)<<12)|(pplan->start>>1)); /* vmov.f32 s(n+1), sn */ + vtop->r = VT_CONST; /* avoid being saved on stack by gv for next float */ } break; case CORE_CLASS: if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { - lexpand(S); - gv(S, regmask(S, pplan->end)); - pplan->sval->r2 = S->tccgen_vtop->r; - S->tccgen_vtop--; + lexpand(); + gv(regmask(pplan->end)); + pplan->sval->r2 = vtop->r; + vtop--; } - gv(S, regmask(S, pplan->start)); + gv(regmask(pplan->start)); /* Mark register as used so that gcall_or_jmp use another one (regs >=4 are free as never used to pass parameters) */ - pplan->sval->r = S->tccgen_vtop->r; + pplan->sval->r = vtop->r; break; } - S->tccgen_vtop--; + vtop--; } } @@ -1297,10 +1304,10 @@ again: /* Manually free remaining registers since next parameters are loaded * manually, without the help of gv(int). */ - save_regs(S, nb_args); + save_regs(nb_args); if(todo) { - o(S, 0xE8BD0000|todo); /* pop {todo} */ + o(0xE8BD0000|todo); /* pop {todo} */ for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) { int r; pplan->sval->r = pplan->start; @@ -1311,8 +1318,8 @@ again: for (r = pplan->start + 1; r <= pplan->end; r++) { if (todo & (1 << r)) { nb_extra_sval++; - vpushi(S, 0); - S->tccgen_vtop->r = r; + vpushi(0); + vtop->r = r; } } } @@ -1323,7 +1330,7 @@ again: /* 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. */ -void gfunc_call(TCCState* S, int nb_args) +void gfunc_call(int nb_args) { int r, args_size; int def_float_abi = float_abi; @@ -1334,62 +1341,62 @@ void gfunc_call(TCCState* S, int nb_args) #endif #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 #ifdef TCC_ARM_EABI if (float_abi == ARM_HARD_FLOAT) { - variadic = (S->tccgen_vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS); - if (variadic || floats_in_core_regs(&S->tccgen_vtop[-nb_args])) + variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS); + if (variadic || floats_in_core_regs(&vtop[-nb_args])) float_abi = ARM_SOFTFP_FLOAT; } #endif /* cannot let cpu flags if other instruction are generated. Also avoid leaving VT_JMP anywhere except on the top of the stack because it would complicate the code generator. */ - r = S->tccgen_vtop->r & VT_VALMASK; + r = vtop->r & VT_VALMASK; if (r == VT_CMP || (r & ~1) == VT_JMP) - gv(S, RC_INT); + gv(RC_INT); memset(&plan, 0, sizeof plan); if (nb_args) - plan.pplans = tcc_malloc(S, nb_args * sizeof(*plan.pplans)); + plan.pplans = tcc_malloc(nb_args * sizeof(*plan.pplans)); - args_size = assign_regs(S, nb_args, float_abi, &plan, &todo); + args_size = assign_regs(nb_args, float_abi, &plan, &todo); #ifdef TCC_ARM_EABI if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */ args_size = (args_size + 7) & ~7; - o(S, 0xE24DD004); /* sub sp, sp, #4 */ + o(0xE24DD004); /* sub sp, sp, #4 */ } #endif - nb_args += copy_params(S, nb_args, &plan, todo); - tcc_free(S, plan.pplans); + nb_args += copy_params(nb_args, &plan, todo); + tcc_free(plan.pplans); /* Move fct SValue on top as required by gcall_or_jmp */ - vrotb(S, nb_args + 1); - gcall_or_jmp(S, 0); + vrotb(nb_args + 1); + gcall_or_jmp(0); if (args_size) - gadd_sp(S, args_size); /* pop all parameters passed on the stack */ + gadd_sp(args_size); /* pop all parameters passed on the stack */ #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) - if(float_abi == ARM_SOFTFP_FLOAT && is_float(S->tccgen_vtop->type.ref->type.t)) { - if((S->tccgen_vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) { - o(S, 0xEE000A10); /*vmov s0, r0 */ + if(float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) { + if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) { + o(0xEE000A10); /*vmov s0, r0 */ } else { - o(S, 0xEE000B10); /* vmov.32 d0[0], r0 */ - o(S, 0xEE201B10); /* vmov.32 d0[1], r1 */ + o(0xEE000B10); /* vmov.32 d0[0], r0 */ + o(0xEE201B10); /* vmov.32 d0[1], r1 */ } } #endif - S->tccgen_vtop -= nb_args + 1; /* Pop all params and fct address from value stack */ + vtop -= nb_args + 1; /* Pop all params and fct address from value stack */ leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */ float_abi = def_float_abi; } /* generate function prolog of type 't' */ -void gfunc_prolog(TCCState* S, Sym *func_sym) +void gfunc_prolog(Sym *func_sym) { CType *func_type = &func_sym->type; Sym *sym,*sym2; @@ -1404,17 +1411,17 @@ void gfunc_prolog(TCCState* S, Sym *func_sym) sym = func_type->ref; n = nf = 0; - if ((S->tccgen_func_vt.t & VT_BTYPE) == VT_STRUCT && - !gfunc_sret(&S->tccgen_func_vt, S->tccgen_func_var, &ret_type, &align, &rs)) + if ((func_vt.t & VT_BTYPE) == VT_STRUCT && + !gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs)) { n++; struct_ret = 1; - S->tccgen_func_vc = 12; /* Offset from fp of the place to store the result */ + func_vc = 12; /* Offset from fp of the place to store the result */ } for(sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) { size = type_size(&sym2->type, &align); #ifdef TCC_ARM_EABI - if (float_abi == ARM_HARD_FLOAT && !S->tccgen_func_var && + if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) { int tmpnf = assign_vfpreg(&avregs, align, size); tmpnf += (size + 3) / 4; @@ -1424,8 +1431,8 @@ void gfunc_prolog(TCCState* S, Sym *func_sym) if (n < 4) n += (size + 3) / 4; } - o(S, 0xE1A0C00D); /* mov ip,sp */ - if (S->tccgen_func_var) + o(0xE1A0C00D); /* mov ip,sp */ + if (func_var) n=4; if (n) { if(n>4) @@ -1433,22 +1440,22 @@ void gfunc_prolog(TCCState* S, Sym *func_sym) #ifdef TCC_ARM_EABI n=(n+1)&-2; #endif - o(S, 0xE92D0000|((1<<n)-1)); /* save r0-r4 on stack if needed */ + o(0xE92D0000|((1<<n)-1)); /* save r0-r4 on stack if needed */ } if (nf) { if (nf>16) nf=16; nf=(nf+1)&-2; /* nf => HARDFLOAT => EABI */ - o(S, 0xED2D0A00|nf); /* save s0-s15 on stack if needed */ + o(0xED2D0A00|nf); /* save s0-s15 on stack if needed */ } - o(S, 0xE92D5800); /* save fp, ip, lr */ - o(S, 0xE1A0B00D); /* mov fp, sp */ - func_sub_sp_offset = S->tccgen_ind; - o(S, 0xE1A00000); /* nop, leave space for stack adjustment in epilog */ + o(0xE92D5800); /* save fp, ip, lr */ + o(0xE1A0B00D); /* mov fp, sp */ + func_sub_sp_offset = ind; + o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */ #ifdef TCC_ARM_EABI if (float_abi == ARM_HARD_FLOAT) { - S->tccgen_func_vc += nf * 4; + func_vc += nf * 4; memset(&avregs, 0, sizeof avregs); } #endif @@ -1460,7 +1467,7 @@ void gfunc_prolog(TCCState* S, Sym *func_sym) size = (size + 3) >> 2; align = (align + 3) & ~3; #ifdef TCC_ARM_EABI - if (float_abi == ARM_HARD_FLOAT && !S->tccgen_func_var && (is_float(sym->type.t) + if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym->type.t) || is_hgen_float_aggr(&sym->type))) { int fpn = assign_vfpreg(&avregs, align, size << 2); if (fpn >= 0) @@ -1485,42 +1492,42 @@ from_stack: addr = (n + nf + sn) * 4; sn += size; } - sym_push(S, sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, + sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr + 12); } last_itod_magic=0; leaffunc = 1; - S->tccgen_loc = 0; + loc = 0; #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 */ -void gfunc_epilog(TCCState* S) +void gfunc_epilog(void) { uint32_t x; int diff; #ifdef CONFIG_TCC_BCHECK - if (S->do_bounds_check) - gen_bounds_epilog(S); + if (tcc_state->do_bounds_check) + gen_bounds_epilog(); #endif /* Copy float return value to core register if base standard is used and float computation is made with VFP */ #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) - if ((float_abi == ARM_SOFTFP_FLOAT || S->tccgen_func_var) && is_float(S->tccgen_func_vt.t)) { - if((S->tccgen_func_vt.t & VT_BTYPE) == VT_FLOAT) - o(S, 0xEE100A10); /* fmrs r0, s0 */ + if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) { + if((func_vt.t & VT_BTYPE) == VT_FLOAT) + o(0xEE100A10); /* fmrs r0, s0 */ else { - o(S, 0xEE100B10); /* fmrdl r0, d0 */ - o(S, 0xEE301B10); /* fmrdh r1, d0 */ + o(0xEE100B10); /* fmrdl r0, d0 */ + o(0xEE301B10); /* fmrdh r1, d0 */ } } #endif - o(S, 0xE89BA800); /* restore fp, sp, pc */ - diff = (-S->tccgen_loc + 3) & -4; + o(0xE89BA800); /* restore fp, sp, pc */ + diff = (-loc + 3) & -4; #ifdef TCC_ARM_EABI if(!leaffunc) diff = ((diff + 11) & -8) - 4; @@ -1531,74 +1538,74 @@ void gfunc_epilog(TCCState* S) *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = x; else { int addr; - addr=S->tccgen_ind; - o(S, 0xE59FC004); /* ldr ip,[pc+4] */ - o(S, 0xE04BD00C); /* sub sp,fp,ip */ - o(S, 0xE1A0F00E); /* mov pc,lr */ - o(S, diff); - *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = 0xE1000000|encbranch(S, func_sub_sp_offset,addr,1); + addr=ind; + o(0xE59FC004); /* ldr ip,[pc+4] */ + o(0xE04BD00C); /* sub sp,fp,ip */ + o(0xE1A0F00E); /* mov pc,lr */ + o(diff); + *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = 0xE1000000|encbranch(func_sub_sp_offset,addr,1); } } } -ST_FUNC void gen_fill_nops(TCCState* S, int bytes) +ST_FUNC void gen_fill_nops(int bytes) { if ((bytes & 3)) - tcc_error(S, "alignment of code section not multiple of 4"); + tcc_error("alignment of code section not multiple of 4"); while (bytes > 0) { - o(S, 0xE1A00000); + o(0xE1A00000); bytes -= 4; } } /* generate a jump to a label */ -ST_FUNC int gjmp(TCCState* S, int t) +ST_FUNC int gjmp(int t) { int r; - if (S->tccgen_nocode_wanted) + if (nocode_wanted) return t; - r=S->tccgen_ind; - o(S, 0xE0000000|encbranch(S, r,t,1)); + r=ind; + o(0xE0000000|encbranch(r,t,1)); return r; } /* generate a jump to a fixed address */ -ST_FUNC void gjmp_addr(TCCState* S, int a) +ST_FUNC void gjmp_addr(int a) { - gjmp(S, a); + gjmp(a); } -ST_FUNC int gjmp_cond(TCCState* S, int op, int t) +ST_FUNC int gjmp_cond(int op, int t) { int r; - if (S->tccgen_nocode_wanted) + if (nocode_wanted) return t; - r=S->tccgen_ind; - op=mapcc(S, op); - op|=encbranch(S, r,t,1); - o(S, op); + r=ind; + op=mapcc(op); + op|=encbranch(r,t,1); + o(op); return r; } -ST_FUNC int gjmp_append(TCCState* S, int n, int t) +ST_FUNC int gjmp_append(int n, int t) { uint32_t *x; int p,lp; if(n) { p = n; do { - p = decbranch(S, lp=p); + p = decbranch(lp=p); } while(p); x = (uint32_t *)(cur_text_section->data + lp); *x &= 0xff000000; - *x |= encbranch(S, lp,t,1); + *x |= encbranch(lp,t,1); t = n; } return t; } /* generate an integer binary operation */ -void gen_opi(TCCState* S, int op) +void gen_opi(int op) { int c, func = 0; uint32_t opc = 0, r, fr; @@ -1643,11 +1650,11 @@ void gen_opi(TCCState* S, int op) c=1; break; case '*': - gv2(S, RC_INT, RC_INT); - r = S->tccgen_vtop[-1].r; - fr = S->tccgen_vtop[0].r; - S->tccgen_vtop--; - o(S, 0xE0000090|(intr(S, r)<<16)|(intr(S, r)<<8)|intr(S, fr)); + gv2(RC_INT, RC_INT); + r = vtop[-1].r; + fr = vtop[0].r; + vtop--; + o(0xE0000090|(intr(r)<<16)|(intr(r)<<8)|intr(fr)); return; case TOK_SHL: opc = 0; @@ -1689,12 +1696,12 @@ void gen_opi(TCCState* S, int op) c=3; break; case TOK_UMULL: - gv2(S, RC_INT, RC_INT); - r=intr(S, S->tccgen_vtop[-1].r2=get_reg(S, RC_INT)); - c=S->tccgen_vtop[-1].r; - S->tccgen_vtop[-1].r=get_reg_ex(S, RC_INT,regmask(S, c)); - S->tccgen_vtop--; - o(S, 0xE0800090|(r<<16)|(intr(S, S->tccgen_vtop->r)<<12)|(intr(S, c)<<8)|intr(S, S->tccgen_vtop[1].r)); + gv2(RC_INT, RC_INT); + r=intr(vtop[-1].r2=get_reg(RC_INT)); + c=vtop[-1].r; + vtop[-1].r=get_reg_ex(RC_INT,regmask(c)); + vtop--; + o(0xE0800090|(r<<16)|(intr(vtop->r)<<12)|(intr(c)<<8)|intr(vtop[1].r)); return; default: opc = 0x15; @@ -1703,128 +1710,128 @@ void gen_opi(TCCState* S, int op) } switch(c) { case 1: - if((S->tccgen_vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + if((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { if(opc == 4 || opc == 5 || opc == 0xc) { - vswap(S); + vswap(); opc|=2; // sub -> rsb } } - if ((S->tccgen_vtop->r & VT_VALMASK) == VT_CMP || - (S->tccgen_vtop->r & (VT_VALMASK & ~1)) == VT_JMP) - gv(S, RC_INT); - vswap(S); - c=intr(S, gv(S, RC_INT)); - vswap(S); + if ((vtop->r & VT_VALMASK) == VT_CMP || + (vtop->r & (VT_VALMASK & ~1)) == VT_JMP) + gv(RC_INT); + vswap(); + c=intr(gv(RC_INT)); + vswap(); opc=0xE0000000|(opc<<20); - if((S->tccgen_vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { uint32_t x; - x=stuff_const(opc|0x2000000|(c<<16),S->tccgen_vtop->c.i); + x=stuff_const(opc|0x2000000|(c<<16),vtop->c.i); if(x) { if ((x & 0xfff00000) == 0xe3500000) // cmp rx,#c - o(S, x); + o(x); else { - r=intr(S, S->tccgen_vtop[-1].r=get_reg_ex(S, RC_INT,regmask(S, S->tccgen_vtop[-1].r))); - o(S, x|(r<<12)); + r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r))); + o(x|(r<<12)); } goto done; } } - fr=intr(S, gv(S, RC_INT)); + fr=intr(gv(RC_INT)); #ifdef CONFIG_TCC_BCHECK - if ((S->tccgen_vtop[-1].r & VT_VALMASK) >= VT_CONST) { - vswap(S); - c=intr(S, gv(S, RC_INT)); - vswap(S); + if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { + vswap(); + c=intr(gv(RC_INT)); + vswap(); } #endif if ((opc & 0xfff00000) == 0xe1500000) // cmp rx,ry - o(S, opc|(c<<16)|fr); + o(opc|(c<<16)|fr); else { - r=intr(S, S->tccgen_vtop[-1].r=get_reg_ex(S, RC_INT,two2mask(S, S->tccgen_vtop->r,S->tccgen_vtop[-1].r))); - o(S, opc|(c<<16)|(r<<12)|fr); + r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r))); + o(opc|(c<<16)|(r<<12)|fr); } done: - S->tccgen_vtop--; + vtop--; if (op >= TOK_ULT && op <= TOK_GT) - vset_VT_CMP(S, op); + vset_VT_CMP(op); break; case 2: opc=0xE1A00000|(opc<<5); - if ((S->tccgen_vtop->r & VT_VALMASK) == VT_CMP || - (S->tccgen_vtop->r & (VT_VALMASK & ~1)) == VT_JMP) - gv(S, RC_INT); - vswap(S); - r=intr(S, gv(S, RC_INT)); - vswap(S); - if ((S->tccgen_vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - fr=intr(S, S->tccgen_vtop[-1].r=get_reg_ex(S, RC_INT,regmask(S, S->tccgen_vtop[-1].r))); - c = S->tccgen_vtop->c.i & 0x1f; - o(S, opc|r|(c<<7)|(fr<<12)); + if ((vtop->r & VT_VALMASK) == VT_CMP || + (vtop->r & (VT_VALMASK & ~1)) == VT_JMP) + gv(RC_INT); + vswap(); + r=intr(gv(RC_INT)); + vswap(); + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + fr=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r))); + c = vtop->c.i & 0x1f; + o(opc|r|(c<<7)|(fr<<12)); } else { - fr=intr(S, gv(S, RC_INT)); + fr=intr(gv(RC_INT)); #ifdef CONFIG_TCC_BCHECK - if ((S->tccgen_vtop[-1].r & VT_VALMASK) >= VT_CONST) { - vswap(S); - r=intr(S, gv(S, RC_INT)); - vswap(S); + if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { + vswap(); + r=intr(gv(RC_INT)); + vswap(); } #endif - c=intr(S, S->tccgen_vtop[-1].r=get_reg_ex(S, RC_INT,two2mask(S, S->tccgen_vtop->r,S->tccgen_vtop[-1].r))); - o(S, opc|r|(c<<12)|(fr<<8)|0x10); + c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r))); + o(opc|r|(c<<12)|(fr<<8)|0x10); } - S->tccgen_vtop--; + vtop--; break; case 3: - vpush_helper_func(S, func); - vrott(S, 3); - gfunc_call(S, 2); - vpushi(S, 0); - S->tccgen_vtop->r = retreg; + vpush_helper_func(func); + vrott(3); + gfunc_call(2); + vpushi(0); + vtop->r = retreg; break; default: - tcc_error(S, "gen_opi %i unimplemented!",op); + tcc_error("gen_opi %i unimplemented!",op); } } #ifdef TCC_ARM_VFP -static int is_zero(TCCState* S, int i) +static int is_zero(int i) { - if((S->tccgen_vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) + if((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) return 0; - if (S->tccgen_vtop[i].type.t == VT_FLOAT) - return (S->tccgen_vtop[i].c.f == 0.f); - else if (S->tccgen_vtop[i].type.t == VT_DOUBLE) - return (S->tccgen_vtop[i].c.d == 0.0); - return (S->tccgen_vtop[i].c.ld == 0.l); + if (vtop[i].type.t == VT_FLOAT) + return (vtop[i].c.f == 0.f); + else if (vtop[i].type.t == VT_DOUBLE) + return (vtop[i].c.d == 0.0); + return (vtop[i].c.ld == 0.l); } /* generate a floating point operation 'v = t1 op t2' instruction. The * two operands are guaranteed to have the same floating point type */ -void gen_opf(TCCState* S, int op) +void gen_opf(int op) { uint32_t x; int fneg=0,r; - x=0xEE000A00|T2CPR(S->tccgen_vtop->type.t); + x=0xEE000A00|T2CPR(vtop->type.t); switch(op) { case '+': - if(is_zero(S, -1)) - vswap(S); - if(is_zero(S, 0)) { - S->tccgen_vtop--; + if(is_zero(-1)) + vswap(); + if(is_zero(0)) { + vtop--; return; } x|=0x300000; break; case '-': x|=0x300040; - if(is_zero(S, 0)) { - S->tccgen_vtop--; + if(is_zero(0)) { + vtop--; return; } - if(is_zero(S, -1)) { + if(is_zero(-1)) { x|=0x810000; /* fsubX -> fnegX */ - vswap(S); - S->tccgen_vtop--; + vswap(); + vtop--; fneg=1; } break; @@ -1836,11 +1843,11 @@ void gen_opf(TCCState* S, int op) break; default: if(op < TOK_ULT || op > TOK_GT) { - tcc_error(S, "unknown fp op %x!",op); + tcc_error("unknown fp op %x!",op); return; } - if(is_zero(S, -1)) { - vswap(S); + if(is_zero(-1)) { + vswap(); switch(op) { case TOK_LT: op=TOK_GT; break; case TOK_GE: op=TOK_ULE; break; @@ -1851,16 +1858,16 @@ void gen_opf(TCCState* S, int op) x|=0xB40040; /* fcmpX */ if(op!=TOK_EQ && op!=TOK_NE) x|=0x80; /* fcmpX -> fcmpeX */ - if(is_zero(S, 0)) { - S->tccgen_vtop--; - o(S, x|0x10000|(vfpr(S, gv(S, RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */ + if(is_zero(0)) { + vtop--; + o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */ } else { - gv2(S, RC_FLOAT,RC_FLOAT); - x|=vfpr(S, S->tccgen_vtop[0].r); - o(S, x|(vfpr(S, S->tccgen_vtop[-1].r) << 12)); - S->tccgen_vtop--; + gv2(RC_FLOAT,RC_FLOAT); + x|=vfpr(vtop[0].r); + o(x|(vfpr(vtop[-1].r) << 12)); + vtop--; } - o(S, 0xEEF1FA10); /* fmstat */ + o(0xEEF1FA10); /* fmstat */ switch(op) { case TOK_LE: op=TOK_ULE; break; @@ -1868,46 +1875,46 @@ void gen_opf(TCCState* S, int op) case TOK_UGE: op=TOK_GE; break; case TOK_UGT: op=TOK_GT; break; } - vset_VT_CMP(S, op); + vset_VT_CMP(op); return; } - r=gv(S, RC_FLOAT); - x|=vfpr(S, r); - r=regmask(S, r); + r=gv(RC_FLOAT); + x|=vfpr(r); + r=regmask(r); if(!fneg) { int r2; - vswap(S); - r2=gv(S, RC_FLOAT); - x|=vfpr(S, r2)<<16; - r|=regmask(S, r2); + vswap(); + r2=gv(RC_FLOAT); + x|=vfpr(r2)<<16; + r|=regmask(r2); #ifdef CONFIG_TCC_BCHECK - if ((S->tccgen_vtop[-1].r & VT_VALMASK) >= VT_CONST) { - vswap(S); - r=gv(S, RC_FLOAT); - vswap(S); - x=(x&~0xf)|vfpr(S, r); + if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { + vswap(); + r=gv(RC_FLOAT); + vswap(); + x=(x&~0xf)|vfpr(r); } #endif } - S->tccgen_vtop->r=get_reg_ex(S, RC_FLOAT,r); + vtop->r=get_reg_ex(RC_FLOAT,r); if(!fneg) - S->tccgen_vtop--; - o(S, x|(vfpr(S, S->tccgen_vtop->r)<<12)); + vtop--; + o(x|(vfpr(vtop->r)<<12)); } #else -static uint32_t is_fconst(TCCState* S) +static uint32_t is_fconst() { long double f; uint32_t r; - if((S->tccgen_vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) + if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) return 0; - if (S->tccgen_vtop->type.t == VT_FLOAT) - f = S->tccgen_vtop->c.f; - else if (S->tccgen_vtop->type.t == VT_DOUBLE) - f = S->tccgen_vtop->c.d; + if (vtop->type.t == VT_FLOAT) + f = vtop->c.f; + else if (vtop->type.t == VT_DOUBLE) + f = vtop->c.d; else - f = S->tccgen_vtop->c.ld; + f = vtop->c.ld; if(!ieee_finite(f)) return 0; r=0x8; @@ -1936,45 +1943,45 @@ static uint32_t is_fconst(TCCState* S) /* generate a floating point operation 'v = t1 op t2' instruction. The two operands are guaranteed to have the same floating point type */ -void gen_opf(TCCState* S, int op) +void gen_opf(int op) { uint32_t x, r, r2, c1, c2; //fputs("gen_opf\n",stderr); - vswap(S); - c1 = is_fconst(S); - vswap(S); - c2 = is_fconst(S); + vswap(); + c1 = is_fconst(); + vswap(); + c2 = is_fconst(); x=0xEE000100; #if LDOUBLE_SIZE == 8 - if ((S->tccgen_vtop->type.t & VT_BTYPE) != VT_FLOAT) + if ((vtop->type.t & VT_BTYPE) != VT_FLOAT) x|=0x80; #else - if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_DOUBLE) + if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) x|=0x80; - else if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_LDOUBLE) + else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) x|=0x80000; #endif switch(op) { case '+': if(!c2) { - vswap(S); + vswap(); c2=c1; } - vswap(S); - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); if(c2) { if(c2>0xf) x|=0x200000; // suf r2=c2&0xf; } else { - r2=fpr(S, gv(S, RC_FLOAT)); + r2=fpr(gv(RC_FLOAT)); #ifdef CONFIG_TCC_BCHECK - if ((S->tccgen_vtop[-1].r & VT_VALMASK) >= VT_CONST) { - vswap(S); - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); + if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); } #endif } @@ -1984,46 +1991,46 @@ void gen_opf(TCCState* S, int op) if(c2<=0xf) x|=0x200000; // suf r2=c2&0xf; - vswap(S); - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); } else if(c1 && c1<=0xf) { x|=0x300000; // rsf r2=c1; - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); + r=fpr(gv(RC_FLOAT)); + vswap(); } else { x|=0x200000; // suf - vswap(S); - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); - r2=fpr(S, gv(S, RC_FLOAT)); + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); + r2=fpr(gv(RC_FLOAT)); #ifdef CONFIG_TCC_BCHECK - if ((S->tccgen_vtop[-1].r & VT_VALMASK) >= VT_CONST) { - vswap(S); - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); + if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); } #endif } break; case '*': if(!c2 || c2>0xf) { - vswap(S); + vswap(); c2=c1; } - vswap(S); - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); if(c2 && c2<=0xf) r2=c2; else { - r2=fpr(S, gv(S, RC_FLOAT)); + r2=fpr(gv(RC_FLOAT)); #ifdef CONFIG_TCC_BCHECK - if ((S->tccgen_vtop[-1].r & VT_VALMASK) >= VT_CONST) { - vswap(S); - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); + if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); } #endif } @@ -2033,25 +2040,25 @@ void gen_opf(TCCState* S, int op) if(c2 && c2<=0xf) { x|=0x400000; // dvf r2=c2; - vswap(S); - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); } else if(c1 && c1<=0xf) { x|=0x500000; // rdf r2=c1; - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); + r=fpr(gv(RC_FLOAT)); + vswap(); } else { x|=0x400000; // dvf - vswap(S); - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); - r2=fpr(S, gv(S, RC_FLOAT)); + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); + r2=fpr(gv(RC_FLOAT)); #ifdef CONFIG_TCC_BCHECK - if ((S->tccgen_vtop[-1].r & VT_VALMASK) >= VT_CONST) { - vswap(S); - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); + if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); } #endif } @@ -2066,7 +2073,7 @@ void gen_opf(TCCState* S, int op) case TOK_UGE: case TOK_ULE: case TOK_UGT: - tcc_error(S, "unsigned comparison on floats?"); + tcc_error("unsigned comparison on floats?"); break; case TOK_LT: op=TOK_Nset; @@ -2081,7 +2088,7 @@ void gen_opf(TCCState* S, int op) } if(c1 && !c2) { c2=c1; - vswap(S); + vswap(); switch(op) { case TOK_Nset: op=TOK_GT; @@ -2097,86 +2104,86 @@ void gen_opf(TCCState* S, int op) break; } } - vswap(S); - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); if(c2) { if(c2>0xf) x|=0x200000; r2=c2&0xf; } else { - r2=fpr(S, gv(S, RC_FLOAT)); + r2=fpr(gv(RC_FLOAT)); #ifdef CONFIG_TCC_BCHECK - if ((S->tccgen_vtop[-1].r & VT_VALMASK) >= VT_CONST) { - vswap(S); - r=fpr(S, gv(S, RC_FLOAT)); - vswap(S); + if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); } #endif } - --S->tccgen_vtop; - vset_VT_CMP(S, op); - ++S->tccgen_vtop; + --vtop; + vset_VT_CMP(op); + ++vtop; } else { - tcc_error(S, "unknown fp op %x!",op); + tcc_error("unknown fp op %x!",op); return; } } - if(S->tccgen_vtop[-1].r == VT_CMP) + if(vtop[-1].r == VT_CMP) c1=15; else { - c1=S->tccgen_vtop->r; + c1=vtop->r; if(r2&0x8) - c1=S->tccgen_vtop[-1].r; - S->tccgen_vtop[-1].r=get_reg_ex(S, RC_FLOAT,two2mask(S, S->tccgen_vtop[-1].r,c1)); - c1=fpr(S, S->tccgen_vtop[-1].r); + c1=vtop[-1].r; + vtop[-1].r=get_reg_ex(RC_FLOAT,two2mask(vtop[-1].r,c1)); + c1=fpr(vtop[-1].r); } - S->tccgen_vtop--; - o(S, x|(r<<16)|(c1<<12)|r2); + vtop--; + o(x|(r<<16)|(c1<<12)|r2); } #endif /* 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) { uint32_t r, r2; int bt; - bt=S->tccgen_vtop->type.t & VT_BTYPE; + bt=vtop->type.t & VT_BTYPE; if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) { #ifndef TCC_ARM_VFP uint32_t dsize = 0; #endif - r=intr(S, gv(S, RC_INT)); + r=intr(gv(RC_INT)); #ifdef TCC_ARM_VFP - r2=vfpr(S, S->tccgen_vtop->r=get_reg(S, RC_FLOAT)); - o(S, 0xEE000A10|(r<<12)|(r2<<16)); /* fmsr */ + r2=vfpr(vtop->r=get_reg(RC_FLOAT)); + o(0xEE000A10|(r<<12)|(r2<<16)); /* fmsr */ r2|=r2<<12; - if(!(S->tccgen_vtop->type.t & VT_UNSIGNED)) + if(!(vtop->type.t & VT_UNSIGNED)) r2|=0x80; /* fuitoX -> fsituX */ - o(S, 0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/ + o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/ #else - r2=fpr(S, S->tccgen_vtop->r=get_reg(S, RC_FLOAT)); + r2=fpr(vtop->r=get_reg(RC_FLOAT)); if((t & VT_BTYPE) != VT_FLOAT) dsize=0x80; /* flts -> fltd */ - o(S, 0xEE000110|dsize|(r2<<16)|(r<<12)); /* flts */ - if((S->tccgen_vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) { + o(0xEE000110|dsize|(r2<<16)|(r<<12)); /* flts */ + if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) { uint32_t off = 0; - o(S, 0xE3500000|(r<<12)); /* cmp */ - r=fpr(S, get_reg(S, RC_FLOAT)); + o(0xE3500000|(r<<12)); /* cmp */ + r=fpr(get_reg(RC_FLOAT)); if(last_itod_magic) { - off=S->tccgen_ind+8-last_itod_magic; + off=ind+8-last_itod_magic; off/=4; if(off>255) off=0; } - o(S, 0xBD1F0100|(r<<12)|off); /* ldflts */ + o(0xBD1F0100|(r<<12)|off); /* ldflts */ if(!off) { - o(S, 0xEA000000); /* b */ - last_itod_magic=S->tccgen_ind; - o(S, 0x4F800000); /* 4294967296.0f */ + o(0xEA000000); /* b */ + last_itod_magic=ind; + o(0x4F800000); /* 4294967296.0f */ } - o(S, 0xBE000100|dsize|(r2<<16)|(r2<<12)|r); /* adflt */ + o(0xBE000100|dsize|(r2<<16)|(r2<<12)|r); /* adflt */ } #endif return; @@ -2184,15 +2191,15 @@ ST_FUNC void gen_cvt_itof(TCCState* S, int t) int func; CType *func_type = 0; if((t & VT_BTYPE) == VT_FLOAT) { - func_type = &S->armgen_func_float_type; - if(S->tccgen_vtop->type.t & VT_UNSIGNED) + func_type = &func_float_type; + if(vtop->type.t & VT_UNSIGNED) func=TOK___floatundisf; else func=TOK___floatdisf; #if LDOUBLE_SIZE != 8 } else if((t & VT_BTYPE) == VT_LDOUBLE) { - func_type = &S->armgen_func_ldouble_type; - if(S->tccgen_vtop->type.t & VT_UNSIGNED) + func_type = &func_ldouble_type; + if(vtop->type.t & VT_UNSIGNED) func=TOK___floatundixf; else func=TOK___floatdixf; @@ -2200,39 +2207,39 @@ ST_FUNC void gen_cvt_itof(TCCState* S, int t) #else } else if((t & VT_BTYPE) == VT_DOUBLE || (t & VT_BTYPE) == VT_LDOUBLE) { #endif - func_type = &S->armgen_func_double_type; - if(S->tccgen_vtop->type.t & VT_UNSIGNED) + func_type = &func_double_type; + if(vtop->type.t & VT_UNSIGNED) func=TOK___floatundidf; else func=TOK___floatdidf; } if(func_type) { - vpushsym(S, func_type, external_helper_sym(S, func)); - vswap(S); - gfunc_call(S, 1); - vpushi(S, 0); - S->tccgen_vtop->r=TREG_F0; + vpushsym(func_type, external_helper_sym(func)); + vswap(); + gfunc_call(1); + vpushi(0); + vtop->r=TREG_F0; return; } } - tcc_error(S, "unimplemented gen_cvt_itof %x!",S->tccgen_vtop->type.t); + tcc_error("unimplemented gen_cvt_itof %x!",vtop->type.t); } /* convert fp to int 't' type */ -void gen_cvt_ftoi(TCCState* S, int t) +void gen_cvt_ftoi(int t) { uint32_t r, r2; int u, func = 0; u=t&VT_UNSIGNED; t&=VT_BTYPE; - r2=S->tccgen_vtop->type.t & VT_BTYPE; + r2=vtop->type.t & VT_BTYPE; if(t==VT_INT) { #ifdef TCC_ARM_VFP - r=vfpr(S, gv(S, RC_FLOAT)); + r=vfpr(gv(RC_FLOAT)); u=u?0:0x10000; - o(S, 0xEEBC0AC0|(r<<12)|r|T2CPR(r2)|u); /* ftoXizY */ - r2=intr(S, S->tccgen_vtop->r=get_reg(S, RC_INT)); - o(S, 0xEE100A10|(r<<16)|(r2<<12)); + o(0xEEBC0AC0|(r<<12)|r|T2CPR(r2)|u); /* ftoXizY */ + r2=intr(vtop->r=get_reg(RC_INT)); + o(0xEE100A10|(r<<16)|(r2<<12)); return; #else if(u) { @@ -2247,9 +2254,9 @@ void gen_cvt_ftoi(TCCState* S, int t) #endif func=TOK___fixunsdfsi; } else { - r=fpr(S, gv(S, RC_FLOAT)); - r2=intr(S, S->tccgen_vtop->r=get_reg(S, RC_INT)); - o(S, 0xEE100170|(r2<<12)|r); + r=fpr(gv(RC_FLOAT)); + r2=intr(vtop->r=get_reg(RC_INT)); + o(0xEE100170|(r2<<12)|r); return; } #endif @@ -2266,93 +2273,93 @@ void gen_cvt_ftoi(TCCState* S, int t) func=TOK___fixdfdi; } if(func) { - vpush_helper_func(S, func); - vswap(S); - gfunc_call(S, 1); - vpushi(S, 0); + vpush_helper_func(func); + vswap(); + gfunc_call(1); + vpushi(0); if(t == VT_LLONG) - S->tccgen_vtop->r2 = REG_IRE2; - S->tccgen_vtop->r = REG_IRET; + vtop->r2 = REG_IRE2; + vtop->r = REG_IRET; return; } - tcc_error(S, "unimplemented gen_cvt_ftoi!"); + tcc_error("unimplemented gen_cvt_ftoi!"); } /* convert from one floating point type to another */ -void gen_cvt_ftof(TCCState* S, int t) +void gen_cvt_ftof(int t) { #ifdef TCC_ARM_VFP - if(((S->tccgen_vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) { - uint32_t r = vfpr(S, gv(S, RC_FLOAT)); - o(S, 0xEEB70AC0|(r<<12)|r|T2CPR(S->tccgen_vtop->type.t)); + if(((vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) { + uint32_t r = vfpr(gv(RC_FLOAT)); + o(0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t)); } #else /* all we have to do on i386 and FPA ARM is to put the float in a register */ - gv(S, RC_FLOAT); + gv(RC_FLOAT); #endif } /* increment tcov counter */ -ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv) +ST_FUNC void gen_increment_tcov (SValue *sv) { int r1, r2; - vpushv(S, sv); - S->tccgen_vtop->r = r1 = get_reg(S, RC_INT); - r2 = get_reg(S, RC_INT); - o(S, 0xE59F0000 | (intr(S, r1)<<12)); // ldr r1,[pc] - o(S, 0xEA000000); // b $+4 - greloc(S, cur_text_section, sv->sym, S->tccgen_ind, R_ARM_REL32); - o(S, -12); - o(S, 0xe080000f | (intr(S, r1)<<16) | (intr(S, r1)<<12)); // add r1,r1,pc - o(S, 0xe5900000 | (intr(S, r1)<<16) | (intr(S, r2)<<12)); // ldr r2, [r1] - o(S, 0xe2900001 | (intr(S, r2)<<16) | (intr(S, r2)<<12)); // adds r2, r2, #1 - o(S, 0xe5800000 | (intr(S, r1)<<16) | (intr(S, r2)<<12)); // str r2, [r1] - o(S, 0xe2800004 | (intr(S, r1)<<16) | (intr(S, r1)<<12)); // add r1, r1, #4 - o(S, 0xe5900000 | (intr(S, r1)<<16) | (intr(S, r2)<<12)); // ldr r2, [r1] - o(S, 0xe2a00000 | (intr(S, r2)<<16) | (intr(S, r2)<<12)); // adc r2, r2, #0 - o(S, 0xe5800000 | (intr(S, r1)<<16) | (intr(S, r2)<<12)); // str r2, [r1] - vpop(S); + vpushv(sv); + vtop->r = r1 = get_reg(RC_INT); + r2 = get_reg(RC_INT); + o(0xE59F0000 | (intr(r1)<<12)); // ldr r1,[pc] + o(0xEA000000); // b $+4 + greloc(cur_text_section, sv->sym, ind, R_ARM_REL32); + o(-12); + o(0xe080000f | (intr(r1)<<16) | (intr(r1)<<12)); // add r1,r1,pc + o(0xe5900000 | (intr(r1)<<16) | (intr(r2)<<12)); // ldr r2, [r1] + o(0xe2900001 | (intr(r2)<<16) | (intr(r2)<<12)); // adds r2, r2, #1 + o(0xe5800000 | (intr(r1)<<16) | (intr(r2)<<12)); // str r2, [r1] + o(0xe2800004 | (intr(r1)<<16) | (intr(r1)<<12)); // add r1, r1, #4 + o(0xe5900000 | (intr(r1)<<16) | (intr(r2)<<12)); // ldr r2, [r1] + o(0xe2a00000 | (intr(r2)<<16) | (intr(r2)<<12)); // adc r2, r2, #0 + o(0xe5800000 | (intr(r1)<<16) | (intr(r2)<<12)); // str r2, [r1] + vpop(); } /* computed goto support */ -void ggoto(TCCState* S) +void ggoto(void) { - gcall_or_jmp(S, 1); - S->tccgen_vtop--; + gcall_or_jmp(1); + vtop--; } /* Save the stack pointer onto the stack and return the location of its address */ -ST_FUNC void gen_vla_sp_save(TCCState* S, int addr) { +ST_FUNC void gen_vla_sp_save(int addr) { SValue v; v.type.t = VT_PTR; v.r = VT_LOCAL | VT_LVAL; v.c.i = addr; - store(S, TREG_SP, &v); + store(TREG_SP, &v); } /* Restore the SP from a location on the stack */ -ST_FUNC void gen_vla_sp_restore(TCCState* S, int addr) { +ST_FUNC void gen_vla_sp_restore(int addr) { SValue v; v.type.t = VT_PTR; v.r = VT_LOCAL | VT_LVAL; v.c.i = addr; - load(S, TREG_SP, &v); + load(TREG_SP, &v); } /* 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 r; #if defined(CONFIG_TCC_BCHECK) - if (S->do_bounds_check) - vpushv(S, S->tccgen_vtop); + if (tcc_state->do_bounds_check) + vpushv(vtop); #endif - r = intr(S, gv(S, RC_INT)); + r = intr(gv(RC_INT)); #if defined(CONFIG_TCC_BCHECK) - if (S->do_bounds_check) - o(S, 0xe2800001 | (r<<16)|(r<<12)); /* add r,r,#1 */ + if (tcc_state->do_bounds_check) + o(0xe2800001 | (r<<16)|(r<<12)); /* add r,r,#1 */ #endif - o(S, 0xE04D0000|(r<<12)|r); /* sub r, sp, r */ + o(0xE04D0000|(r<<12)|r); /* sub r, sp, r */ #ifdef TCC_ARM_EABI if (align < 8) align = 8; @@ -2361,19 +2368,19 @@ ST_FUNC void gen_vla_alloc(TCCState* S, CType *type, int align) { align = 4; #endif if (align & (align - 1)) - tcc_error(S, "alignment is not a power of 2: %i", align); - o(S, stuff_const(0xE3C0D000|(r<<16), align - 1)); /* bic sp, r, #align-1 */ - vpop(S); + tcc_error("alignment is not a power of 2: %i", align); + o(stuff_const(0xE3C0D000|(r<<16), align - 1)); /* bic sp, r, #align-1 */ + vpop(); #if defined(CONFIG_TCC_BCHECK) - if (S->do_bounds_check) { - vpushi(S, 0); - S->tccgen_vtop->r = TREG_R0; - o(S, 0xe1a0000d | (S->tccgen_vtop->r << 12)); // mov r0,sp - vswap(S); - vpush_helper_func(S, TOK___bound_new_region); - vrott(S, 3); - gfunc_call(S, 2); - S->func_bound_add_epilog = 1; + if (tcc_state->do_bounds_check) { + vpushi(0); + vtop->r = TREG_R0; + o(0xe1a0000d | (vtop->r << 12)); // mov r0,sp + vswap(); + vpush_helper_func(TOK___bound_new_region); + vrott(3); + gfunc_call(2); + func_bound_add_epilog = 1; } #endif } |