cgframe_x86.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983
  1. #include "cgstd.h"
  2. #include "cgutil.h"
  3. #include "cgframe_x86.h"
  4. #include "cgmodule_x86.h"
  5. #include "cgdebug.h"
  6. using namespace CG;
  7. //Can't use %lld 'coz it doesn't work on mingw!
  8. //#define FMTI64 "%lld"
  9. const char *CGFrame_X86::x86cc( int cc ){
  10. switch( cc ){
  11. case CG_EQ:return "e";
  12. case CG_NE:return "ne";
  13. case CG_LT:return "l";
  14. case CG_GT:return "g";
  15. case CG_LE:return "le";
  16. case CG_GE:return "ge";
  17. case CG_LTU:return "b";
  18. case CG_GTU:return "a";
  19. case CG_LEU:return "be";
  20. case CG_GEU:return "ae";
  21. }
  22. assert(0);
  23. return 0;
  24. }
  25. const char *CGFrame_X86::x86size( int type ){
  26. switch(type){
  27. case CG_PTR:return "dword";
  28. case CG_INT8:return "byte";
  29. case CG_INT16:return "word";
  30. case CG_INT32:return "dword";
  31. case CG_INT64:return "dword";
  32. case CG_FLOAT32:return "dword";
  33. case CG_FLOAT64:return "qword";
  34. }
  35. cout<<"Unrcognized type:"<<type<<endl;
  36. assert(0);
  37. return 0;
  38. }
  39. CGMem *CGFrame_X86::tmpMem( int type ){
  40. if( !tmp_mem ){
  41. local_sz+=8;
  42. tmp_mem=-local_sz;
  43. }
  44. return mem(type,ebp,tmp_mem);
  45. }
  46. CGMem *CGFrame_X86::optMem( CGMem *e,char *buf ){
  47. CGBop *t=e->exp->bop();
  48. if( !t ) return 0;
  49. if( t->op!=CG_ADD && t->op!=CG_SUB ) return 0;
  50. char c=t->op==CG_ADD ? '+' : '-';
  51. CGBop *q=t->rhs->bop();
  52. if( q && q->op==CG_MUL ){
  53. if( CGLit *n=q->rhs->lit() ){
  54. int f=n->int_value;
  55. if( f==2 || f==4 || f==8 ){
  56. char x_buf[256];
  57. CGExp *x=genExp( t->lhs,x_buf,EA_IMM );
  58. CGReg *y=genExp( q->lhs );
  59. //x+y*v
  60. const char *tm=e->offset ? "%s [%s%c'%i*%i+%i]" : "%s [%s%c'%i*%i]";
  61. sprintf( buf,tm,x86size(e->type),x_buf,c,y->id,f,e->offset );
  62. return mem(e->type,bop(t->op,x,bop(CG_MUL,y,n)),e->offset);
  63. }
  64. }
  65. }
  66. char x_buf[256],y_buf[256];
  67. CGExp *x=genExp( t->lhs,x_buf,EA_IMM );
  68. CGExp *y=genExp( t->rhs,y_buf,EA_IMM );
  69. const char *tm=e->offset ? "%s [%s%c%s+%i]" : "%s [%s%c%s]";
  70. sprintf( buf,tm,x86size(e->type),x_buf,c,y_buf,e->offset );
  71. return mem(e->type,bop(t->op,x,y),e->offset);
  72. }
  73. bool CGFrame_X86::optMov( CGExp *lhs,CGExp *rhs ){
  74. if( !lhs->mem() ) return false;
  75. if( lhs->isfloat() ) return false;
  76. CGBop *t=rhs->bop();
  77. if( !t ) return false;
  78. const char *op;
  79. switch( t->op ){
  80. case CG_ADD:op="add";break;
  81. case CG_SUB:op="sub";break;
  82. case CG_ORL:op="or";break;
  83. case CG_AND:op="and";break;
  84. case CG_XOR:op="xor";break;
  85. default:return false;
  86. }
  87. if( !lhs->equals(t->lhs) ) return false;
  88. char x_buf[256];
  89. CGExp *x=genExp( lhs,x_buf,EA_MEM );
  90. if( CGLit *y=t->rhs->lit() ){
  91. int n=y->int_value;
  92. const char *q=0;
  93. if( t->op==CG_ADD ){
  94. if( n==1 ) q="inc";
  95. else if( n==-1 ) q="dec";
  96. }else if( t->op==CG_SUB ){
  97. if( n==1 ) q="dec";
  98. else if( n==-1 ) q="inc";
  99. }
  100. if( q ){
  101. gen( mov(x,bop(t->op,x,y)),"\t%s\t%s\n",q,x_buf );
  102. return true;
  103. }
  104. }
  105. char y_buf[256];
  106. CGExp *y=genExp( t->rhs,y_buf,x->reg() ? EA_MEM|EA_IMM : EA_IMM );
  107. gen( mov(x,bop(t->op,x,y)),"\t%s\t%s,%s\n",op,x_buf,y_buf );
  108. return true;
  109. }
  110. CGReg *CGFrame_X86::genExp( CGExp *e ){
  111. if( CGReg *t=e->reg() ){
  112. return t;
  113. }else if( CGMem *t=e->mem() ){
  114. return genLoad( t );
  115. }else if( CGLea *t=e->lea() ){
  116. return genLea( t );
  117. }else if( CGCvt *t=e->cvt() ){
  118. return genCvt( t );
  119. }else if( CGUop *t=e->uop() ){
  120. return genUop( t );
  121. }else if( CGBop *t=e->bop() ){
  122. return genBop( t );
  123. }else if( CGScc *t=e->scc() ){
  124. return genScc( t );
  125. }else if( CGJsr *t=e->jsr() ){
  126. return genJsr( t );
  127. }else if( CGLit *t=e->lit() ){
  128. return genLit( t );
  129. }else if( CGSym *t=e->sym() ){
  130. return genSym( t );
  131. }else if( CGFrm *t=e->frm() ){
  132. return genFrm( t );
  133. }
  134. assert(0);
  135. return 0;
  136. }
  137. CGMem *CGFrame_X86::genMem( CGMem *e,char *buf ){
  138. if( CGMem *t=optMem(e,buf) ) return t;
  139. char t_buf[256];
  140. CGExp *t=genExp(e->exp,t_buf,EA_IMM );
  141. const char *tm=e->offset ? "%s [%s%+i]" : "%s [%s]";
  142. sprintf( buf,tm,x86size(e->type),t_buf,e->offset );
  143. return mem( e->type,t,e->offset );
  144. }
  145. CGExp *CGFrame_X86::genExp( CGExp *e,char *buf,int mask ){
  146. if( mask & EA_IMM ){
  147. if( CGLit *t=e->lit() ){
  148. if( t->isint() ){
  149. // sprintf( buf,FMTI64,t->int_value );
  150. strcpy( buf,fromint( t->int_value ).c_str() );
  151. return e;
  152. }
  153. }
  154. if( CGSym *t=e->sym() ){
  155. sprintf( buf,"%s",t->value.c_str() );
  156. return e;
  157. }
  158. }
  159. if( mask & EA_MEM ){
  160. if( CGLit *t=e->lit() ){
  161. if( t->type==CG_FLOAT32 ){
  162. CGDat *d=dat();
  163. d->push_back(t);
  164. return genMem( mem(CG_FLOAT32,d,0),buf );
  165. }
  166. }
  167. if( CGMem *t=e->mem() ){
  168. if( t->type!=CG_INT8 && t->type!=CG_INT16 ){
  169. return genMem( t,buf );
  170. }
  171. }
  172. }
  173. CGReg *r=genExp(e);
  174. sprintf( buf,"'%i",r->id );
  175. return r;
  176. }
  177. CGReg *CGFrame_X86::genLoad( CGMem *e ){
  178. char buf[256];
  179. e=genMem( e,buf );
  180. const char *zx=(e->type==CG_INT8 || e->type==CG_INT16) ? "zx" : "";
  181. CGReg *r=reg(e->type);
  182. gen( mov(r,e),
  183. "\tmov%s\t'%i,%s\n",zx,r->id,buf );
  184. return r;
  185. }
  186. void CGFrame_X86::genCopy( CGReg *r,CGReg *t ){
  187. if( r->id==t->id ) return;
  188. gen( mov(r,t),"\tmov\t'%i,'%i\n",r->id,t->id );
  189. }
  190. void CGFrame_X86::genMov( CGExp *lhs,CGExp *rhs ){
  191. if( lhs->equals(rhs) ) return;
  192. char lhs_buf[256];
  193. CGMem *lhs_mem=lhs->mem();
  194. CGReg *lhs_reg=lhs->reg();
  195. if( lhs_reg ){
  196. sprintf( lhs_buf,"'%i",lhs_reg->id );
  197. }else{
  198. lhs=lhs_mem=genMem( lhs_mem,lhs_buf );
  199. }
  200. if( CGBop *t=rhs->bop() ){
  201. if( t->lhs->equals(lhs) ){
  202. if( t->isint() ){
  203. const char *op=0;
  204. switch( t->op ){
  205. case CG_ADD:op="add";break;
  206. case CG_SUB:op="sub";break;
  207. case CG_ORL:op="or";break;
  208. case CG_AND:op="and";break;
  209. case CG_XOR:op="xor";break;
  210. }
  211. if( op ){
  212. char rhs_buf[256];
  213. int rhs_ea=EA_IMM;
  214. if( lhs_reg ) rhs_ea|=EA_MEM;
  215. rhs=genExp( t->rhs,rhs_buf,rhs_ea );
  216. gen( mov(lhs,bop(t->op,lhs,rhs)),
  217. "\t%s\t%s,%s\n",op,lhs_buf,rhs_buf );
  218. return;
  219. }
  220. switch( t->op ){
  221. case CG_SHL:op="shl";break;
  222. case CG_SHR:op="shr";break;
  223. case CG_SAR:op="sar";break;
  224. }
  225. if( op ){
  226. char rhs_buf[256];
  227. rhs=genExp( t->rhs,rhs_buf,EA_IMM );
  228. if( CGReg *r=rhs->reg() ){
  229. if( r->id!=ECX ){
  230. genMov( ecx,r );
  231. rhs=ecx;
  232. }
  233. strcpy( rhs_buf,"cl" );
  234. }
  235. gen( mov(lhs,bop(t->op,lhs,rhs)),
  236. "\t%s\t%s,%s\n",op,lhs_buf,rhs_buf );
  237. return;
  238. }
  239. }else if( lhs_reg && t->isfloat() ){
  240. const char *op=0;
  241. switch( t->op ){
  242. case CG_ADD:op="fadd";break;
  243. case CG_SUB:op="fsub";break;
  244. case CG_MUL:op="fmul";break;
  245. case CG_DIV:op="fdiv";break;
  246. }
  247. if( op ){
  248. int rhs_ea=0;
  249. char rhs_buf[256];
  250. if( lhs_reg ) rhs_ea|=EA_MEM;
  251. rhs=genExp( t->rhs,rhs_buf,rhs_ea );
  252. gen( mov(lhs,bop(t->op,lhs,rhs)),
  253. "\t%s\t%s,%s\n",op,lhs_buf,rhs_buf );
  254. return;
  255. }
  256. }
  257. }
  258. }
  259. char rhs_buf[256];
  260. int rhs_ea=EA_IMM;
  261. if( lhs_reg ) rhs_ea|=EA_MEM;
  262. rhs=genExp( rhs,rhs_buf,rhs_ea );
  263. if( lhs_mem && (lhs->type==CG_INT8 || lhs->type==CG_INT16) ){
  264. if( CGReg *r=rhs->reg() ){
  265. if( r->id!=EAX ){
  266. genMov( eax,cvt(CG_INT32,rhs) );
  267. rhs=cvt(lhs->type,eax);
  268. }
  269. strcpy( rhs_buf,lhs->type==CG_INT8 ? "al" : "ax" );
  270. }
  271. }
  272. gen( mov(lhs,rhs),
  273. "\tmov\t%s,%s\n",lhs_buf,rhs_buf );
  274. }
  275. CGReg *CGFrame_X86::genLea( CGLea *t ){
  276. CGReg *r=reg(t->type);
  277. CGMem *m=t->exp->mem();
  278. assert( m );
  279. char buf[256];
  280. m=genMem( m,buf );
  281. gen( mov(r,lea(m)),"\tlea\t'%i,%s\n",r->id,buf );
  282. return r;
  283. }
  284. CGReg *CGFrame_X86::genCvt( CGCvt *t ){
  285. CGReg *r;
  286. if( t->isint() && t->exp->isint() ){
  287. //int to int
  288. r=reg(t->type);
  289. char buf[256];
  290. CGExp *exp=genExp(t->exp,buf,EA_IMM|EA_MEM);
  291. if( r->type==CG_INT8 && t->exp->type!=CG_INT8 ){
  292. gen( mov(r,cvt(r->type,exp)),
  293. "\tmov\t'%i,%s\n"
  294. "\tand\t'%i,0xff\n",
  295. r->id,buf,r->id );
  296. }else if( t->type==CG_INT16 && (t->exp->type==CG_INT32 || t->exp->type==CG_PTR) ){
  297. gen( mov(r,cvt(r->type,exp)),
  298. "\tmov\t'%i,%s\n"
  299. "\tand\t'%i,0xffff\n",
  300. r->id,buf,r->id );
  301. }else{
  302. gen( mov(r,cvt(r->type,exp)),
  303. "\tmov\t'%i,%s\n",
  304. r->id,buf );
  305. }
  306. }else{
  307. r=reg(t->type);
  308. CGReg *exp=genExp(t->exp);
  309. gen( mov(r,cvt(r->type,exp)),
  310. "\tmov\t'%i,'%i\n",r->id,exp->id );
  311. }
  312. return r;
  313. }
  314. CGReg *CGFrame_X86::genUop( CGUop *t ){
  315. const char *op=0;
  316. switch( t->op ){
  317. case CG_NEG:op="neg";break;
  318. case CG_NOT:assert(t->isint());op="not";break;
  319. default:assert(0);
  320. }
  321. CGReg *r=reg(t->type);
  322. genMov( r,t->exp );
  323. gen( mov(r,uop(t->op,r)),"\t%s\t'%i\n",op,r->id );
  324. return r;
  325. }
  326. static int shifter( int n ){
  327. int k;
  328. for( k=0;k<32;++k ) if( (1<<k)==n ) return k;
  329. return -1;
  330. }
  331. CGReg *CGFrame_X86::genBop( CGBop *t ){
  332. if( t->isint() && (t->op==CG_MUL || t->op==CG_DIV) ){
  333. if( CGLit *c=t->rhs->lit() ){
  334. int i=c->int_value;
  335. if( t->op==CG_MUL ){
  336. int n=shifter(i);
  337. if( n!=-1 ){
  338. return genBop( bop(CG_SHL,t->lhs,lit(n)) );
  339. }
  340. }else if( t->op==CG_DIV ){
  341. int n=shifter(i);
  342. if( n!=-1 ){
  343. genMov( eax,t->lhs );
  344. gen( xop(XOP_CDQ,edx,eax),"\tcdq\n" );
  345. CGExp *e=edx;
  346. e=bop(CG_AND,edx,lit(i-1));
  347. e=bop(CG_ADD,eax,e);
  348. e=bop(CG_SAR,e,lit(n));
  349. return genExp(e);
  350. }
  351. }
  352. }
  353. }
  354. CGReg *r=reg(t->type);
  355. const char *op=0;
  356. if( t->isfloat() ){
  357. switch( t->op ){
  358. case CG_ADD:op="fadd";break;
  359. case CG_SUB:op="fsub";break;
  360. case CG_MUL:op="fmul";break;
  361. case CG_DIV:op="fdiv";break;
  362. }
  363. }else{
  364. switch( t->op ){
  365. case CG_ADD:op="add";break;
  366. case CG_SUB:op="sub";break;
  367. case CG_MUL:op="imul";break;
  368. case CG_AND:op="and";break;
  369. case CG_ORL:op="or";break;
  370. case CG_XOR:op="xor";break;
  371. }
  372. }
  373. if( op ){
  374. genMov( r,t->lhs );
  375. char buf[256];
  376. CGExp *rhs=genExp( t->rhs,buf,EA_MEM|EA_IMM );
  377. gen( mov(r,bop(t->op,r,rhs)),
  378. "\t%s\t'%i,%s\n",op,r->id,buf );
  379. return r;
  380. }
  381. assert( t->isint() );
  382. switch( t->op ){
  383. case CG_SHL:op="shl";break;
  384. case CG_SHR:op="shr";break;
  385. case CG_SAR:op="sar";break;
  386. }
  387. if( op ){
  388. genMov(r,t->lhs);
  389. if( CGLit *rhs=t->rhs->lit() ){
  390. // gen( mov(r,bop(t->op,r,rhs)),
  391. // "\t%s\t'%i," FMTI64 "\n",op,r->id,rhs->int_value );
  392. char buf[64];
  393. strcpy( buf,fromint( rhs->int_value ).c_str() );
  394. gen( mov(r,bop(t->op,r,rhs)),
  395. "\t%s\t'%i,%s\n",op,r->id,buf );
  396. }else{
  397. genMov( ecx,t->rhs );
  398. gen( mov(r,bop(t->op,r,ecx)),
  399. "\t%s\t'%i,cl\n",op,r->id );
  400. }
  401. return r;
  402. }
  403. switch( t->op ){
  404. case CG_MOD:case CG_DIV:break;
  405. default:assert(0);
  406. }
  407. char buf[256];
  408. CGExp *rhs=genExp( t->rhs,buf,EA_MEM );
  409. CGAsm *as;
  410. if( t->op==CG_MOD ){
  411. genMov( eax,t->lhs );
  412. gen( xop(XOP_CDQ,edx,eax),"\tcdq\n" );
  413. as=gen( mov(edx,bop(CG_MOD,eax,rhs)),"\tidiv\t%s\n",buf );
  414. as->use.insert( EDX );
  415. as->def.insert( EAX );
  416. genMov( r,edx );
  417. // genMov( eax,t->lhs );
  418. // as=gen( mov(edx,bop(CG_MOD,eax,rhs)),"\tcdq\n\tidiv\t%s\n",buf );
  419. // as->def.insert( EAX );
  420. // genMov( r,edx );
  421. }else{
  422. genMov( eax,t->lhs );
  423. gen( xop(XOP_CDQ,edx,eax),"\tcdq\n" );
  424. as=gen( mov(eax,bop(CG_DIV,eax,rhs)),"\tidiv\t%s\n",buf );
  425. as->use.insert( EDX );
  426. as->def.insert( EDX );
  427. genMov( r,eax );
  428. // genMov( eax,t->lhs );
  429. // as=gen( mov(eax,bop(CG_DIV,eax,rhs)),"\tcdq\n\tidiv\t%s\n",buf );
  430. // as->def.insert( EDX );
  431. // genMov( r,eax );
  432. }
  433. return r;
  434. }
  435. CGReg *CGFrame_X86::genScc( CGScc *t ){
  436. CGReg *lhs=genExp( t->lhs );
  437. if( lhs->isfloat() ){
  438. CGReg *rhs=genExp( t->rhs );
  439. gen( mov(eax,scc(t->cc,lhs,rhs)),"" );
  440. }else{
  441. char rhs_buf[256];
  442. CGExp *rhs=genExp( t->rhs,rhs_buf,EA_MEM|EA_IMM );
  443. gen( mov(eax,scc(t->cc,lhs,rhs)),
  444. "\tcmp\t'%i,%s\n"
  445. "\tset%s\tal\n"
  446. "\tmovzx\teax,al\n",lhs->id,rhs_buf,x86cc(t->cc) );
  447. }
  448. CGReg *r=reg(CG_INT32);
  449. genMov( r,eax );
  450. return r;
  451. }
  452. CGReg *CGFrame_X86::genJsr( CGJsr *t ){
  453. if( env_platform=="macos" ){
  454. return genMacJsr( t );
  455. }
  456. int k,arg_sz=0;
  457. CGExp *ea=t->exp;
  458. for( k=0;k<t->args.size();++k ){
  459. arg_sz+=t->args[k]->type==CG_FLOAT64 ? 8 : 4;
  460. }
  461. if( CGVfn *p=ea->vfn() ){
  462. arg_sz+=p->self->type==CG_FLOAT64 ? 8 : 4;
  463. }
  464. for( k=t->args.size()-1;k>=0;--k ){
  465. genPush( t->args[k] );
  466. }
  467. if( CGVfn *p=ea->vfn() ){
  468. //put 'this' on stack
  469. genPush( p->self );
  470. ea=p->exp;
  471. }
  472. char buf[256];
  473. ea=genExp( ea,buf,EA_MEM|EA_IMM );
  474. CGReg *dst=t->isfloat() ? fp0 : eax;
  475. CGAsm *as=gen( mov(dst,jsr(t->type,t->call_conv,ea)),"\tcall\t%s\n",buf );
  476. as->def.insert(EAX);as->def.insert(EDX);as->def.insert(ECX);
  477. as->def.insert(FP0);as->def.insert(FP1);as->def.insert(FP2);
  478. as->def.insert(FP3);as->def.insert(FP4);as->def.insert(FP5);
  479. as->def.insert(FP6);
  480. if( t->call_conv==CG_CDECL ){
  481. genPop( lit(arg_sz) );
  482. }else{
  483. ++extern_jsrs;
  484. }
  485. CGReg *r=reg(t->type);
  486. genMov( r,dst );
  487. return r;
  488. }
  489. static int argSize( CGExp *e ){
  490. return e->type==CG_FLOAT64 ? 8 : 4;
  491. }
  492. static int paramSize( CGJsr *t ){
  493. int i,sz=0;
  494. if( CGVfn *p=t->exp->vfn() ) sz+=argSize( p->self );
  495. for( i=0;i<t->args.size();++i ) sz+=argSize( t->args[i] );
  496. return sz;
  497. }
  498. struct MaxParamSizeVisitor : public CGVisitor{
  499. int size;
  500. MaxParamSizeVisitor():size(0){}
  501. CGExp *visit( CGExp *e ){
  502. CGJsr *t=e->jsr();
  503. if( !t ) return e;
  504. int sz=paramSize( t );
  505. if( sz>size ) size=sz;
  506. return e;
  507. }
  508. };
  509. static int maxParamSize( CGExp *e,int sz ){
  510. MaxParamSizeVisitor v;
  511. e->visit(v);
  512. return v.size>sz ? v.size : sz;
  513. }
  514. CGReg *CGFrame_X86::genMacJsr( CGJsr *t ){
  515. ///*
  516. int i;
  517. vector<int> maxszs;
  518. vector<CGExp*> args;
  519. vector<CGMov*> movs;
  520. CGExp *ea=t->exp,*self=0;
  521. if( CGVfn *p=ea->vfn() ){
  522. ea=p->exp;
  523. self=p->self;
  524. }
  525. args.push_back( ea );
  526. if( self ) args.push_back( self );
  527. for( i=0;i<t->args.size();++i ){
  528. args.push_back( t->args[i] );
  529. }
  530. int maxsz=0;
  531. for( i=0;i<args.size();++i ){
  532. maxszs.push_back( maxsz );
  533. maxsz=maxParamSize( args[i],maxsz );
  534. }
  535. char buf[256];
  536. int offset=paramSize( t );
  537. if( offset>param_sz ) param_sz=offset;
  538. for( i=args.size()-1;i>=0;--i ){
  539. if( i ){
  540. CGExp *arg=args[i];
  541. offset-=argSize( arg );
  542. CGExp *lhs=mem( arg->type,esp,offset );
  543. CGExp *rhs=genExp( args[i],buf,EA_IMM );
  544. movs.push_back( mov(lhs,rhs) );
  545. }else{
  546. ea=genExp( ea,buf,EA_MEM|EA_IMM );
  547. }
  548. bool again=true;
  549. vector<CGMov*>::iterator it;
  550. while( again ){
  551. again=false;
  552. for( it=movs.begin();it!=movs.end();++it ){
  553. CGMov *t=*it;
  554. if( t->lhs->mem()->offset>=maxszs[i] ){
  555. genMov( t->lhs,t->rhs );
  556. movs.erase( it );
  557. again=true;
  558. break;
  559. }
  560. }
  561. }
  562. }
  563. //*/
  564. /*
  565. vector<CGExp*> args;
  566. int k,arg_sz=0;
  567. for( k=t->args.size()-1;k>=0;--k ){
  568. CGExp *arg=t->args[k];
  569. args.push_back( genExp(t->args[k]) );
  570. }
  571. CGExp *ea=t->exp;
  572. if( CGVfn *t=ea->vfn() ){
  573. args.push_back( genExp(t->self) );
  574. ea=t->exp;
  575. }
  576. char buf[256];
  577. ea=genExp( ea,buf,EA_MEM|EA_IMM );
  578. for( k=args.size()-1;k>=0;--k ){
  579. CGExp *arg=args[k],*p;
  580. p=mem( arg->type,esp,arg_sz );
  581. arg_sz+=(arg->type==CG_FLOAT64) ? 8 : 4;
  582. genMov( p,arg );
  583. args[k]=p;
  584. }
  585. if( arg_sz>param_sz ) param_sz=arg_sz;
  586. */
  587. CGReg *dst=t->isfloat() ? fp0 : eax;
  588. CGAsm *as=gen( mov(dst,jsr(t->type,t->call_conv,ea)),"\tcall\t%s\n",buf );
  589. as->def.insert(EAX);as->def.insert(EDX);as->def.insert(ECX);
  590. as->def.insert(FP0);as->def.insert(FP1);as->def.insert(FP2);
  591. as->def.insert(FP3);as->def.insert(FP4);as->def.insert(FP5);
  592. as->def.insert(FP6);
  593. CGReg *r=reg( t->type );
  594. genMov( r,dst );
  595. return r;
  596. }
  597. CGReg *CGFrame_X86::genLit( CGLit *t ){
  598. CGReg *r=reg(t->type);
  599. if( t->isfloat() ){
  600. double val=t->float_value;
  601. if( val==0.0 || val==1.0 ){
  602. gen( mov(r,t),"\tmov\t'%i,%f\n",r->id,t->float_value );
  603. }else{
  604. CGDat *d=dat();
  605. d->push_back(t);
  606. genMov( r,mem(t->type,d,0) );
  607. }
  608. }else if( t->int_value==0 ){
  609. gen( mov(r,t),"\txor\t'%i,'%i\n",r->id,r->id );
  610. }else{
  611. // gen( mov(r,t),"\tmov\t'%i," FMTI64 "\n",r->id,t->int_value );
  612. char buf[64];
  613. strcpy( buf,fromint( t->int_value ).c_str() );
  614. gen( mov(r,t),"\tmov\t'%i,%s\n",r->id,buf );
  615. }
  616. return r;
  617. }
  618. CGReg *CGFrame_X86::genSym( CGSym *t ){
  619. CGReg *r=reg(t->type);
  620. gen( mov(r,t),"\tmov\t'%i,%s\n",r->id,t->value.c_str() );
  621. return r;
  622. }
  623. CGReg *CGFrame_X86::genFrm( CGFrm *t ){
  624. CGReg *r=reg(CG_PTR);
  625. genMov( r,ebp );
  626. return r;
  627. }
  628. void CGFrame_X86::genPush( CGExp *e ){
  629. if( e->type==CG_FLOAT32 ){
  630. if( CGLit *t=e->lit() ){
  631. float n=t->float_value;
  632. e=lit( *(int*)&n );
  633. }
  634. genPush4(e);
  635. }else if( e->type==CG_FLOAT64 ){
  636. genPush8(e);
  637. }else if( e->type==CG_INT8 || e->type==CG_INT16 ){
  638. if( e->mem() ) e=genExp(e);
  639. genPush4(e);
  640. }else{
  641. genPush4(e);
  642. }
  643. }
  644. void CGFrame_X86::genPush4( CGExp *e ){
  645. int ea=(e->type==CG_FLOAT64) ? 0 : EA_MEM|EA_IMM;
  646. char buf[256];
  647. e=genExp( e,buf,ea );
  648. gen( xop(XOP_PUSH4,0,e),"\tpush\t%s\n",buf );
  649. }
  650. void CGFrame_X86::genPush8( CGExp *e ){
  651. CGReg *r=genExp( e );
  652. gen( xop(XOP_PUSH8,0,r),"\tpush\t'%i\n",r->id );
  653. }
  654. void CGFrame_X86::genPop( CGExp *e ){
  655. if( CGLit *t=e->lit() ){
  656. if( !t->int_value ) return;
  657. }
  658. char buf[256];
  659. e=genExp( e,buf,EA_MEM|EA_IMM );
  660. if( buf[0]=='-' ){
  661. gen( xop(XOP_POP,0,e),"\tsub\tesp,%s\n",buf+1 );
  662. }else{
  663. gen( xop(XOP_POP,0,e),"\tadd\tesp,%s\n",buf );
  664. }
  665. }
  666. void CGFrame_X86::genBcc( int cc,CGExp *lhs,CGExp *rhs,CGSym *tgt ){
  667. //use scc for FP
  668. if( lhs->isfloat() ){
  669. lhs=genExp(lhs);
  670. rhs=genExp(rhs);
  671. gen( mov(eax,scc(cc,lhs,rhs)),"" );
  672. cc=CG_NE;
  673. lhs=eax;
  674. rhs=lit0;
  675. }
  676. char lhs_buf[256],rhs_buf[256];
  677. lhs=genExp(lhs,lhs_buf,EA_MEM);
  678. rhs=genExp(rhs,rhs_buf,lhs->mem() ? EA_IMM : EA_MEM|EA_IMM);
  679. gen(
  680. bcc(cc,lhs,rhs,tgt),
  681. "\tcmp\t%s,%s\n"
  682. "\tj%s\t%s\n",
  683. lhs_buf,rhs_buf,x86cc(cc),tgt->value.c_str() );
  684. }
  685. void CGFrame_X86::genRet( CGExp *e ){
  686. CGReg *r=0;
  687. if( e ){
  688. r=e->isfloat() ? fp0 : eax;
  689. genMov(r,e);
  690. }
  691. CGAsm *as;
  692. if( fun->call_conv==CG_CDECL ){
  693. as=gen( ret(r),"\tret\n" );
  694. }else{
  695. as=gen( ret(r),"\tret\t%i\n",arg_sz );
  696. }
  697. as->use.insert( EBP );
  698. }
  699. string CGFrame_X86::fixSym( string id ){
  700. if( env_platform=="linux" ) return id;
  701. return "_"+id;
  702. }
  703. void CGFrame_X86::genStm( CGStm *s ){
  704. if( CGAti *t=s->ati() ){
  705. char buf[256];
  706. CGMem *mem=genMem( t->mem,buf );
  707. gen( ati(mem),"\tinc\t%s\n",buf );
  708. }else if( CGAtd *t=s->atd() ){
  709. char buf[256];
  710. CGMem *mem=genMem( t->mem,buf );
  711. gen( atd(mem,t->sym),"\tdec\t%s\n\tjnz\t%s\n",buf,t->sym->value.c_str() );
  712. }else if( CGMov *t=s->mov() ){
  713. genMov( t->lhs,t->rhs );
  714. }else if( CGLab *t=s->lab() ){
  715. gen( t,"%s:\n",t->sym->value.c_str() );
  716. }else if( CGBra *t=s->bra() ){
  717. gen( t,"\tjmp\t%s\n",t->sym->value.c_str() );
  718. }else if( CGBcc *t=s->bcc() ){
  719. genBcc( t->cc,t->lhs,t->rhs,t->sym );
  720. }else if( CGEva *t=s->eva() ){
  721. if( t->exp->dat() ){
  722. gen( t,"" );
  723. }else{
  724. genExp( t->exp );
  725. }
  726. }else if( CGRem *t=s->rem() ){
  727. gen( t,"\t;%s\n",t->comment.c_str() );
  728. }else if( CGRet *t=s->ret() ){
  729. genRet( t->exp );
  730. }else if( CGXop *t=s->xop() ){
  731. switch( t->op ){
  732. case XOP_PUSH4:genPush4(t->exp);break;
  733. case XOP_PUSH8:genPush8(t->exp);break;
  734. case XOP_POP:genPop(t->exp);break;
  735. case XOP_CDQ:break;
  736. default:assert(0);
  737. }
  738. }else{
  739. assert(0);
  740. }
  741. }
  742. void CGFrame_X86::genFun(){
  743. if( CGExp *t=fun->self ){
  744. //get 'this' from stack
  745. genMov( t,mem(CG_PTR,ebp,arg_sz+8) );
  746. arg_sz+=4;
  747. }
  748. int k;
  749. for( k=0;k<fun->args.size();++k ){
  750. //get args from stack
  751. CGExp *t=fun->args[k];
  752. int n=t->type==CG_FLOAT64 ? 8 :4;
  753. genMov(t,mem(t->type,ebp,arg_sz+8));
  754. arg_sz+=n;
  755. }
  756. for( k=0;k<fun->stms.size();++k ){
  757. genStm( fun->stms[k] );
  758. }
  759. }
  760. CGMem *CGFrame_X86::allocLocal( int type ){
  761. int n=(type==CG_FLOAT64 || type==CG_INT64) ? 8 : 4;
  762. local_sz+=n;
  763. return mem(type,ebp,-local_sz);
  764. }
  765. CGExp *CGFrame_X86::allocSpill( CGReg *r ){
  766. int sz=8;
  767. if( fun->self ){
  768. if( r->equals(fun->self) ) return mem(CG_PTR,ebp,sz);
  769. sz+=4;
  770. }
  771. int k;
  772. for( k=0;k<fun->args.size();++k ){
  773. CGExp *t=fun->args[k];
  774. if( r->equals(t) ) return mem(t->type,ebp,sz);
  775. sz+=(t->type==CG_FLOAT64) ? 8 : 4;
  776. }
  777. return allocLocal( r->type );
  778. }
  779. void CGFrame_X86::finish(){
  780. fixFp();
  781. }
  782. CGFrame_X86::CGFrame_X86( CGFun *f,CGModule_X86 *m ):CGFrame(f),mod_x86(m){
  783. arg_sz=0;
  784. tmp_mem=0;
  785. param_sz=0;
  786. local_sz=0;
  787. extern_jsrs=0;
  788. //int types map to reg bank 0
  789. reg_banks[CG_PTR]=0;
  790. reg_banks[CG_INT8]=0;
  791. reg_banks[CG_INT16]=0;
  792. reg_banks[CG_INT32]=0;
  793. reg_banks[CG_INT64]=-1; //no int64 regs!
  794. //int regs
  795. eax=reg( CG_INT32,0,0 );
  796. edx=reg( CG_INT32,0,1 );
  797. ecx=reg( CG_INT32,0,2 );
  798. ebx=reg( CG_INT32,0,3 );
  799. esi=reg( CG_INT32,0,4 );
  800. edi=reg( CG_INT32,0,5 );
  801. ebp=reg( CG_INT32,0,6 );
  802. esp=reg( CG_INT32,0,7 );
  803. reg_masks[0]=0x3f; //no ebp or esp!
  804. //int reg names
  805. reg_names[0].push_back( "eax" );
  806. reg_names[0].push_back( "edx" );
  807. reg_names[0].push_back( "ecx" );
  808. reg_names[0].push_back( "ebx" );
  809. reg_names[0].push_back( "esi" );
  810. reg_names[0].push_back( "edi" );
  811. reg_names[0].push_back( "ebp" );
  812. reg_names[0].push_back( "esp" );
  813. //float types map to bank 1
  814. reg_banks[CG_FLOAT32]=1;
  815. reg_banks[CG_FLOAT64]=1;
  816. //float regs
  817. fp0=reg( CG_FLOAT64,0,0 );
  818. fp1=reg( CG_FLOAT64,0,1 );
  819. fp2=reg( CG_FLOAT64,0,2 );
  820. fp3=reg( CG_FLOAT64,0,3 );
  821. fp4=reg( CG_FLOAT64,0,4 );
  822. fp5=reg( CG_FLOAT64,0,5 );
  823. fp6=reg( CG_FLOAT64,0,6 );
  824. reg_masks[1]=0x7f; //no f7!
  825. //float reg names
  826. reg_names[1].push_back( "fp0" );
  827. reg_names[1].push_back( "fp1" );
  828. reg_names[1].push_back( "fp2" );
  829. reg_names[1].push_back( "fp3" );
  830. reg_names[1].push_back( "fp4" );
  831. reg_names[1].push_back( "fp5" );
  832. reg_names[1].push_back( "fp6" );
  833. }