⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arm-gen.c

📁 Tiny C&C++,看看吧,也许用的着
💻 C
📖 第 1 页 / 共 2 页
字号:
      /* simple type (currently always same size) */      /* XXX: implicit cast ? */      size=4;      if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {	lexpand_nr();	s=RC_INT;	if(nb_args-i<5 && plan[nb_args-i-1][1]!=-1) {	  s=regmask(plan[nb_args-i-1][1]);	  todo&=~(1<<plan[nb_args-i-1][1]);	}	if(s==RC_INT) {	  r = gv(s);	  o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */	  vtop--;	} else {	  plan2[keep]=s;	  keep++;          vswap();	}	size = 8;      }      s=RC_INT;      if(nb_args-i<5 && plan[nb_args-i-1][0]!=-1) {        s=regmask(plan[nb_args-i-1][0]);	todo&=~(1<<plan[nb_args-i-1][0]);      }      if(s==RC_INT) {	r = gv(s);	o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */	vtop--;      } else {	plan2[keep]=s;	keep++;      }      args_size += size;    }  }  for(i=keep;i--;) {    gv(plan2[i]);    vrott(keep);  }  save_regs(keep); /* save used temporary registers */  keep++;  if(args_size) {    int n;    n=args_size/4;    if(n>4)      n=4;    todo&=((1<<n)-1);    if(todo) {      int i;      o(0xE8BD0000|todo);      for(i=0;i<4;i++)	if(todo&(1<<i)) {	  vpushi(0);	  vtop->r=i;	  keep++;	}    }    args_size-=n*4;  }  vnrott(keep);  func_sym = vtop->type.ref;  gcall_or_jmp(0);  if (args_size)      gadd_sp(args_size);  vtop-=keep;}/* generate function prolog of type 't' */void gfunc_prolog(CType *func_type){  Sym *sym,*sym2;  int n,addr,size,align;  sym = func_type->ref;  func_vt = sym->type;    n=0;  addr=12;  if((func_vt.t & VT_BTYPE) == VT_STRUCT) {    func_vc = addr;    addr += 4;    n++;  }  for(sym2=sym->next;sym2 && n<4;sym2=sym2->next) {    size = type_size(&sym2->type, &align);    size = (size + 3) & ~3;    n+=size/4;  }  o(0xE1A0C00D); /* mov ip,sp */  if(func_type->ref->c == FUNC_ELLIPSIS)    n=4;  if(n) {    if(n>4)      n=4;    o(0xE92D0000|((1<<n)-1)); /* save r0-r4 on stack if needed */  }  o(0xE92D5800); /* save fp, ip, lr*/  o(0xE1A0B00D); /* mov fp,sp */  func_sub_sp_offset = ind;  o(0xE1A00000); /* nop, leave space for stack adjustment */  while ((sym = sym->next)) {    CType *type;    type = &sym->type;    sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr);    size = type_size(type, &align);    size = (size + 3) & ~3;    addr += size;  }  last_itod_magic=0;  loc = 0;}/* generate function epilog */void gfunc_epilog(void){  unsigned long x;  o(0xE89BA800); /* restore fp, sp, pc */  if(loc) {    x=stuff_const(0xE24DD000, (-loc + 3) & -4); /* sub sp,sp,# */    if(x)      *(unsigned long *)(cur_text_section->data + func_sub_sp_offset) = x;    else {      unsigned long addr;      addr=ind;      o(0xE59FC004); /* ldr ip,[pc+4] */      o(0xE04DD00C); /* sub sp,sp,ip  */      o(0xE1A0F00E); /* mov pc,lr */      o((-loc + 3) & -4);      *(unsigned long *)(cur_text_section->data + func_sub_sp_offset) = 0xE1000000|encbranch(func_sub_sp_offset,addr,1);    }  }}/* generate a jump to a label */int gjmp(int t){  int r;  r=ind;  o(0xE0000000|encbranch(r,t,1));  return r;}/* generate a jump to a fixed address */void gjmp_addr(int a){  gjmp(a);}/* generate a test. set 'inv' to invert test. Stack entry is popped */int gtst(int inv, int t){  int v, r;  unsigned long op;  v = vtop->r & VT_VALMASK;  r=ind;  if (v == VT_CMP) {    op=mapcc(inv?negcc(vtop->c.i):vtop->c.i);    op|=encbranch(r,t,1);    o(op);    t=r;  } else if (v == VT_JMP || v == VT_JMPI) {    if ((v & 1) == inv) {      if(!vtop->c.i)	vtop->c.i=t;      else {	unsigned long *x;	int p,lp;	if(t) {          p = vtop->c.i;          do {	    p = decbranch(lp=p);          } while(p);	  x = (unsigned long *)(cur_text_section->data + lp);	  *x &= 0xff000000;	  *x |= encbranch(lp,t,1);	}	t = vtop->c.i;      }    } else {      t = gjmp(t);      gsym(vtop->c.i);    }  } else {    if (is_float(vtop->type.t)) {      r=gv(RC_FLOAT);      o(0xEE90F118|fpr(r)<<16);      vtop->r = VT_CMP;      vtop->c.i = TOK_NE;      return gtst(inv, t);    } else if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {      /* constant jmp optimization */      if ((vtop->c.i != 0) != inv) 	t = gjmp(t);    } else {      v = gv(RC_INT);      o(0xE3300000|(intr(v)<<16));      vtop->r = VT_CMP;      vtop->c.i = TOK_NE;      return gtst(inv, t);    }     }  vtop--;  return t;}/* generate an integer binary operation */void gen_opi(int op){  int c, func = 0;  unsigned long opc = 0,r,fr;  c=0;  switch(op) {    case '+':      opc = 0x8;      c=1;      break;    case TOK_ADDC1: /* add with carry generation */      opc = 0x9;      c=1;      break;    case '-':      opc = 0x4;      c=1;      break;    case TOK_SUBC1: /* sub with carry generation */      opc = 0x5;      c=1;      break;    case TOK_ADDC2: /* add with carry use */      opc = 0xA;      c=1;      break;    case TOK_SUBC2: /* sub with carry use */      opc = 0xC;      c=1;      break;    case '&':      opc = 0x0;      c=1;      break;    case '^':      opc = 0x2;      c=1;      break;    case '|':      opc = 0x18;      c=1;      break;    case '*':      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;      c=2;      break;    case TOK_SHR:      opc = 1;      c=2;      break;    case TOK_SAR:      opc = 2;      c=2;      break;    case '/':    case TOK_PDIV:      func=TOK___divsi3;      c=3;      break;    case TOK_UDIV:      func=TOK___udivsi3;      c=3;      break;    case '%':      func=TOK___modsi3;      c=3;      break;    case TOK_UMOD:      func=TOK___umodsi3;      c=3;      break;    case TOK_UMULL:      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;      c=1;      break;  }  switch(c) {    case 1:      if((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {	if(opc == 4 || opc == 5 || opc == 0xc) {	  vswap();	  opc|=2; // sub -> rsb	}      }      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)|(c<<16);      if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {	unsigned long x;	x=stuff_const(opc|0x2000000,vtop->c.i);	if(x) {	  r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));	  o(x|(r<<12));	  goto done;	}      }      fr=intr(gv(RC_INT));      r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));      o(opc|(r<<12)|fr);done:      vtop--;      if (op >= TOK_ULT && op <= TOK_GT) {        vtop->r = VT_CMP;        vtop->c.i = op;      }      break;    case 2:      opc=0xE1A00000|(opc<<5);      if ((vtop->r & VT_VALMASK) == VT_CMP ||          (vtop->r & (VT_VALMASK & ~1)) == VT_JMP)        gv(RC_INT);      vswap();      r=intr(gv(RC_INT));      vswap();      opc|=r;      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|(c<<7)|(fr<<12));      } else {        fr=intr(gv(RC_INT));	c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));	o(opc|(c<<12)|(fr<<8)|0x10);      }      vtop--;      break;    case 3:      vpush_global_sym(&func_old_type, func);      vrott(3);      gfunc_call(2);      vpushi(0);      vtop->r = REG_IRET;      break;    default:      error("gen_opi %i unimplemented!",op);  }}static int is_fconst(){  long double f;  int r;  if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)    return 0;  if (vtop->type.t == VT_FLOAT)    f = vtop->c.f;  else if (vtop->type.t == VT_DOUBLE)    f = vtop->c.d;  else    f = vtop->c.ld;  if(!ieee_finite(f))    return 0;  r=0x8;  if(f<0.0) {    r=0x18;    f=-f;  }  if(f==0.0)    return r;  if(f==1.0)    return r|1;  if(f==2.0)    return r|2;  if(f==3.0)    return r|3;  if(f==4.0)    return r|4;  if(f==5.0)    return r|5;  if(f==0.5)    return r|6;  if(f==10.0)    return r|7;  return 0;}/* generate a floating point operation 'v = t1 op t2' instruction. The   two operands are guaranted to have the same floating point type */void gen_opf(int op){  unsigned long x;  int r,r2,c1,c2;  //fputs("gen_opf\n",stderr);  vswap();  c1 = is_fconst();  vswap();  c2 = is_fconst();  x=0xEE000100;#if LDOUBLE_SIZE == 8  if ((vtop->type.t & VT_BTYPE) != VT_FLOAT)    x|=0x80;#else  if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)    x|=0x80;  else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)    x|=0x80000;#endif  switch(op)  {    case '+':      if(!c2) {	vswap();	c2=c1;      }      vswap();      r=fpr(gv(RC_FLOAT));      vswap();      if(c2) {	if(c2>0xf)	  x|=0x200000; // suf	r2=c2&0xf;      } else {	r2=fpr(gv(RC_FLOAT));      }      break;    case '-':      if(c2) {	if(c2<=0xf)	  x|=0x200000; // suf	r2=c2&0xf;	vswap();	r=fpr(gv(RC_FLOAT));	vswap();      } else if(c1 && c1<=0xf) {	x|=0x300000; // rsf	r2=c1;	r=fpr(gv(RC_FLOAT));	vswap();      } else {	x|=0x200000; // suf	vswap();	r=fpr(gv(RC_FLOAT));	vswap();	r2=fpr(gv(RC_FLOAT));      }      break;    case '*':      if(!c2 || c2>0xf) {	vswap();	c2=c1;      }      vswap();      r=fpr(gv(RC_FLOAT));      vswap();      if(c2 && c2<=0xf)	r2=c2;      else	r2=fpr(gv(RC_FLOAT));      x|=0x100000; // muf      break;    case '/':      if(c2 && c2<=0xf) {	x|=0x400000; // dvf	r2=c2;	vswap();	r=fpr(gv(RC_FLOAT));	vswap();      } else if(c1 && c1<=0xf) {	x|=0x500000; // rdf	r2=c1;	r=fpr(gv(RC_FLOAT));	vswap();      } else {	x|=0x400000; // dvf	vswap();	r=fpr(gv(RC_FLOAT));	vswap();	r2=fpr(gv(RC_FLOAT));      }           break;    default:      if(op >= TOK_ULT && op <= TOK_GT) {	x|=0xd0f110; // cmfe	switch(op) {	  case TOK_ULT:	  case TOK_UGE:	  case TOK_ULE:	  case TOK_UGT:	    fputs("unsigned comparision on floats?\n",stderr);	    break;	  case TOK_LT:	    op=TOK_ULT;	    break;	  case TOK_GE:	    op=TOK_UGE;	    break;	  case TOK_LE:	    op=TOK_ULE;	    break;	  case TOK_GT:	    op=TOK_UGT;	    break;	  case TOK_EQ:	  case TOK_NE:	    x&=~0x400000; // cmfe -> cmf	    break;	}	if(c1 && !c2) {	  c2=c1;	  vswap();	  switch(op) {	    case TOK_ULT:	      op=TOK_UGT;	      break;	    case TOK_UGE:	      op=TOK_ULE;	      break;	    case TOK_ULE:	      op=TOK_UGE;	      break;	    case TOK_UGT:	      op=TOK_ULT;	      break;	  }	}// bug (intention?) in Linux FPU emulator// doesn't set carry if equal	if(op==TOK_ULT)	  op=TOK_LT;	else if(op==TOK_UGE)	  op=TOK_GE;	vswap();	r=fpr(gv(RC_FLOAT));	vswap();	if(c2) {	  if(c2>0xf)	    x|=0x200000;	  r2=c2&0xf;	} else {	  r2=fpr(gv(RC_FLOAT));	}	vtop[-1].r = VT_CMP;	vtop[-1].c.i = op;      } else {	error("unknown fp op %x!\n",op);	return;      }  }  if(vtop[-1].r == VT_CMP)    c1=15;  else {    c1=vtop->r;    if(r2&0x8)      c1=vtop[-1].r;    vtop[-1].r=get_reg_ex(RC_FLOAT,two2mask(vtop[-1].r,c1));    c1=fpr(vtop[-1].r);  }  vtop--;  o(x|(r<<16)|(c1<<12)|r2);}/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'   and 'long long' cases. */void gen_cvt_itof(int t){  int r,r2,bt;  bt=vtop->type.t & VT_BTYPE;  if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) {    r=intr(gv(RC_INT));    r2=fpr(vtop->r=get_reg(RC_FLOAT));    o(0xEE000190|(r2<<16)|(r<<12));    if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) {      unsigned int off=0;      o(0xE3500000|(r<<12));      r=fpr(get_reg(RC_FLOAT));      if(last_itod_magic) {	off=ind+8-last_itod_magic;	off/=4;	if(off>255)	  off=0;      }      o(0xBD1F8100|(r<<12)|off);      if(!off) {        o(0xEA000001);        last_itod_magic=ind;        o(0x41F00000);        o(0);      }      o(0xBE000180|(r2<<16)|(r2<<12)|r);    }    return;  } else if(bt == VT_LLONG) {    int func;    if(vtop->type.t & VT_UNSIGNED)      func=TOK___ulltold;    else      func=TOK___slltold;    vpush_global_sym(&func_old_type, func);    vswap();    gfunc_call(1);    vpushi(0);    vtop->r=TREG_F0;    return;  }  error("unimplemented gen_cvt_itof %x!",vtop->type.t);}/* convert fp to int 't' type */void gen_cvt_ftoi(int t){  int r,r2,u,func=0;  u=t&VT_UNSIGNED;  t&=VT_BTYPE;  r2=vtop->type.t & VT_BTYPE;  if(t==VT_INT) {    if(u) {      if(r2 == VT_FLOAT)        func=TOK___fixunssfsi;      else if(r2 == VT_DOUBLE)	func=TOK___fixunsdfsi;      else if(r2 == VT_LDOUBLE)#if LDOUBLE_SIZE == 8	func=TOK___fixunsdfsi;#else	func=TOK___fixunsxfsi;#endif    } else {      r=fpr(gv(RC_FLOAT));      r2=intr(vtop->r=get_reg(RC_INT));      o(0xEE100170|(r2<<12)|r);    return;    }  } else if(t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1    if(r2 == VT_FLOAT)      func=TOK___fixsfdi;    else if(r2 == VT_DOUBLE)      func=TOK___fixdfdi;    else if(r2 == VT_LDOUBLE)#if LDOUBLE_SIZE == 8      func=TOK___fixdfdi;#else      func=TOK___fixxfdi;#endif    }  if(func) {    vpush_global_sym(&func_old_type, func);    vswap();    gfunc_call(1);    vpushi(0);    if(t == VT_LLONG)      vtop->r2 = REG_LRET;    vtop->r = REG_IRET;    return;  }  error("unimplemented gen_cvt_ftoi!");}/* convert from one floating point type to another */void gen_cvt_ftof(int t){  /* all we have to do on i386 and ARM is to put the float in a register */  gv(RC_FLOAT);}/* computed goto support */void ggoto(void){  gcall_or_jmp(1);  vtop--;}/* end of ARM code generator *//*************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -