cgfixfp_x86.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. #include "cgstd.h"
  2. #include "cgframe_x86.h"
  3. #include "cgutil.h"
  4. #include "cgdebug.h"
  5. //#define _DEBUG_FPSTACK
  6. static CGFrame_X86 *frame;
  7. static char tmpbuf8[256],tmpbuf16[256],tmpbuf32[256],*buf,*buf_a,*buf_b,*out;
  8. struct FPStack;
  9. typedef set<CGBlock*> BlockSet;
  10. typedef map<CGBlock*,FPStack*> StackMap;
  11. static BlockSet blocks_todo;
  12. static StackMap stack_map;
  13. static void emit( const char *fmt,... ){
  14. va_list args;
  15. va_start( args,fmt );
  16. vsprintf( out,fmt,args );
  17. out+=strlen(out);
  18. }
  19. struct FPStack{
  20. int regs[8],stack[8],sp;
  21. FPStack( int live ):sp(8){
  22. memset( regs,-1,sizeof(regs) );
  23. memset( stack,0,sizeof(stack) );
  24. for( int k=0;k<8;++k ){
  25. if( live & (1<<k) ) push(k);
  26. }
  27. }
  28. FPStack( FPStack *st ):sp(st->sp){
  29. memcpy( regs,st->regs,sizeof(regs) );
  30. memcpy( stack,st->stack,sizeof(stack) );
  31. }
  32. int liveMask(){
  33. int n=0;
  34. for( int k=sp;k<8;++k ) n|=1<<stack[k];
  35. return n;
  36. }
  37. bool equals( FPStack *st ){
  38. if( sp!=st->sp ) return false;
  39. for( int k=sp;k<8;++k ){
  40. if( stack[k]!=st->stack[k] ) return false;
  41. }
  42. return true;
  43. }
  44. int top(){
  45. return stack[sp];
  46. }
  47. void pop(){
  48. int r=stack[sp];
  49. regs[r]=-1;
  50. ++sp;
  51. }
  52. void push( int r ){
  53. --sp;
  54. regs[r]=sp;
  55. stack[sp]=r;
  56. }
  57. void swap( int rd,int rs ){
  58. assert(regs[rs]>=0 && regs[rd]>=0);
  59. std::swap( stack[regs[rs]],stack[regs[rd]] );
  60. std::swap( regs[rs],regs[rd] );
  61. }
  62. int stoff( int r ){
  63. return regs[r]-sp;
  64. }
  65. void fpop(){
  66. emit( "\tfstp\tst0\n" );
  67. pop();
  68. }
  69. void fxch( int r ){
  70. if( r==top() ) return;
  71. emit( "\tfxch\tst%i\n",stoff(r) );
  72. swap( r,top() );
  73. }
  74. void fpop( int r ){
  75. if( regs[r]<0 ) return;
  76. fxch(r);
  77. fpop();
  78. }
  79. void debug(){
  80. for( int k=0;k<8;++k ){
  81. if( k<sp ) cout<<"-- ";
  82. else cout<<'f'<<stack[k]<<' ';
  83. }
  84. cout<<" sp:"<<sp<<endl;
  85. }
  86. void fdebug(){
  87. //#ifdef _DEBUG_FPSTACK
  88. emit( "\t;" );
  89. for( int k=0;k<8;++k ){
  90. if( k<sp ) emit( "-- " );
  91. else emit( "f%i ",stack[k] );
  92. }
  93. emit( "\n" );
  94. //#endif
  95. }
  96. void fadjust( int live ){
  97. for( int k=sp;k<8;++k ){
  98. if( !(live & (1<<stack[k])) ) fpop( stack[k] );
  99. }
  100. }
  101. void fadjust( FPStack *st ){
  102. #ifdef _DEBUG_FPSTACK
  103. emit( "\t;fadjust...\n" );
  104. #endif
  105. for( int t_sp=7;t_sp>=st->sp;--t_sp ){
  106. int t=top();
  107. for( ;st->regs[t]==-1;t=top() ) fpop();
  108. int rs=stack[t_sp];
  109. int rd=st->stack[t_sp];
  110. if( rs==rd ){
  111. }else if( st->regs[rs]==-1 ){
  112. fxch( rd );
  113. emit( "\tfstp\tst%i\n",t_sp-sp );
  114. stack[regs[rd]=t_sp]=rd;
  115. pop();
  116. }else{
  117. fxch( rd );
  118. fxch( rs );
  119. }
  120. }
  121. while( sp<st->sp ) fpop();
  122. }
  123. void fcopy( int rd,int rs,int live ){
  124. if( rd==rs || !(live&(1<<rd)) ){
  125. if( !(live&(1<<rd)) ) fpop(rd);
  126. if( !(live&(1<<rs)) ) fpop(rs);
  127. return;
  128. }
  129. if( live&(1<<rs) ){
  130. if( regs[rd]>=0 ){
  131. fxch(rs);
  132. emit( "\tfst\tst%i\n",stoff(rd) );
  133. }else{
  134. emit( "\tfld\tst%i\n",stoff(rs) );
  135. push(rd);
  136. }
  137. }else{
  138. if( regs[rd]>=0 ){
  139. fxch(rs);
  140. emit( "\tfstp\tst%i\n",stoff(rd) );
  141. pop();
  142. }else{
  143. stack[regs[rs]]=rd;
  144. regs[rd]=regs[rs];
  145. regs[rs]=-1;
  146. }
  147. }
  148. }
  149. void fload( int rd,double val,int live ){
  150. if( !(live&(1<<rd)) ){
  151. fpop(rd);
  152. return;
  153. }
  154. if( val==0.0 ) emit( "\tfldz\n" );
  155. else if( val==1.0 ) emit( "\tfld1\n" );
  156. else assert(0);
  157. if( regs[rd]>=0 ){
  158. emit( "\tfstp\tst%i\n",stoff(rd)+1 );
  159. }else{
  160. push(rd);
  161. }
  162. }
  163. void fload( int rd,const char *ea,const char *op,int live ){
  164. if( live&(1<<rd) ){
  165. emit( "\t%s\t%s\n",op,ea );
  166. if( regs[rd]>=0 ){
  167. emit( "\tfstp\tst%i\n",stoff(rd)+1 );
  168. }else{
  169. push(rd);
  170. }
  171. }else{
  172. fpop(rd);
  173. }
  174. }
  175. void fstore( int rs,const char *ea,const char *op,int live ){
  176. fxch( rs );
  177. if( live&(1<<rs) ){
  178. emit( "\t%s\t%s\n",op,ea );
  179. }else{
  180. emit( "\t%sp\t%s\n",op,ea );
  181. pop();
  182. }
  183. }
  184. void funiop( int rd,const char *op,int live ){
  185. if( !(live&(1<<rd)) ){
  186. fpop(rd);
  187. return;
  188. }
  189. fxch(rd);
  190. emit( "\t%s\n",op );
  191. }
  192. void fbinop( int rd,int rs,const char *op,int live ){
  193. if( !(live&(1<<rd)) ){
  194. fpop(rd);
  195. if( !(live&(1<<rs)) ) fpop(rs);
  196. return;
  197. }
  198. if( live&(1<<rs) ){
  199. if( top()==rs ){
  200. emit( "\t%s\tst%i,st0\n",op,stoff(rd) );
  201. }else{
  202. fxch(rd);
  203. emit( "\t%s\tst0,st%i\n",op,stoff(rs) );
  204. }
  205. }else{
  206. if( top()==rd ){
  207. const char *r_op=op;
  208. if( !strcmp(op,"fsub") ) r_op="fsubr";
  209. else if( !strcmp(op,"fdiv") ) r_op="fdivr";
  210. emit( "\t%sp\tst%i,st0\n",r_op,stoff(rs) );
  211. stack[regs[rs]]=rd;
  212. regs[rd]=regs[rs];
  213. regs[rs]=-1;
  214. ++sp;
  215. }else{
  216. fxch(rs);
  217. emit( "\t%sp\tst%i,st0\n",op,stoff(rd) );
  218. pop();
  219. }
  220. }
  221. }
  222. void fbinop( int rd,const char *ea,const char *op,int live ){
  223. if( !(live&(1<<rd)) ){
  224. fpop(rd);
  225. return;
  226. }
  227. fxch(rd);
  228. emit( "\t%s\t%s\n",op,ea );
  229. }
  230. void fcomp( int rd,int rs,int live ){
  231. fxch(rd);
  232. if( live&(1<<rd) ){
  233. emit( "\tfucom\tst%i\n",stoff(rs) );
  234. if( !(live&(1<<rs)) ) fpop(rs);
  235. }else{
  236. if( live&(1<<rs) ){
  237. emit( "\tfucomp\tst%i\n",stoff(rs) );
  238. pop();
  239. }else if( stoff(rs)==1 ){
  240. emit( "\tfucompp\n" );
  241. pop();
  242. pop();
  243. }else{
  244. emit( "\tfucomp\tst%i\n",stoff(rs) );
  245. pop();
  246. fpop(rs);
  247. }
  248. }
  249. emit( "\tfnstsw\tax\n" );
  250. emit( "\tsahf\n" );
  251. }
  252. };
  253. static int liveMask( const CGIntSet &t ){
  254. int live=0;
  255. CGIntCIter it;
  256. for( it=t.begin();it!=t.end();++it ){
  257. CGReg *r=frame->regs[*it];
  258. if( r->isfloat() ){
  259. assert(r->color>=0);
  260. live|=(1<<r->color);
  261. }
  262. }
  263. return live;
  264. }
  265. static void adjustStack( FPStack *st,CGBlock *blk ){
  266. StackMap::iterator it=stack_map.find(blk);
  267. if( it!=stack_map.end() ){
  268. st->fadjust( it->second );
  269. return;
  270. }
  271. st->fadjust( liveMask(blk->live_in) );
  272. stack_map.insert( make_pair(blk,new FPStack(st)) );
  273. blocks_todo.insert( blk );
  274. }
  275. static const char *op1( CGAsm *as ){
  276. static char buf[256];
  277. const char *b=strchr( as->assem+1,'\t' );
  278. assert(b);
  279. ++b;
  280. const char *e=strchr( as->assem,',' );
  281. if( !e ) e=b+strlen(b);
  282. int sz=e-b;
  283. memcpy(buf,b,sz);
  284. buf[sz]=0;
  285. return buf;
  286. }
  287. static const char *op2( CGAsm *as ){
  288. static char buf[256];
  289. const char *b=strchr( as->assem,',' );
  290. assert(b);
  291. ++b;
  292. const char *e=strchr( b,'\n' );
  293. assert(e);
  294. int sz=e-b;
  295. memcpy(buf,b,sz);
  296. buf[sz]=0;
  297. return buf;
  298. }
  299. static void allocTmp32(){
  300. if( tmpbuf32[0] ) return;
  301. CGMem *m=frame->allocLocal(CG_INT32);
  302. sprintf( tmpbuf8,"byte [ebp+%i]",m->offset );
  303. sprintf( tmpbuf16,"word [ebp+%i]",m->offset );
  304. sprintf( tmpbuf32,"dword [ebp+%i]",m->offset );
  305. }
  306. static bool fixXop( CGAsm *as,CGXop *op,FPStack *st,int live ){
  307. CGExp *exp=op->exp;
  308. if( op->op==CGFrame_X86::XOP_PUSH4 ){
  309. //push dword
  310. if( exp->isint() || exp->mem() ) return false;
  311. int rs=exp->reg()->color;
  312. emit( "\tsub\tesp,4\n" );
  313. st->fstore( rs,"dword [esp]","fst",live );
  314. return true;
  315. }
  316. if( op->op==CGFrame_X86::XOP_PUSH8 ){
  317. //push qword
  318. if( exp->isint() ) return false;
  319. assert( !exp->mem() );
  320. int rs=exp->reg()->color;
  321. emit( "\tsub\tesp,8\n" );
  322. st->fstore( rs,"qword [esp]","fst",live );
  323. return true;
  324. }
  325. return false;
  326. }
  327. static bool fixEva( CGAsm *as,CGEva *ev,FPStack *st,int live ){
  328. CGExp *exp=ev->exp;
  329. if( CGJsr *t=exp->jsr() ){
  330. if( !exp->isfloat() ) return false;
  331. if( !live ){
  332. emit(as->assem);
  333. emit("\tfstp\tst0\n");
  334. return true;
  335. }else if( live==1 ){
  336. if( st->regs[0]<0 ) st->push(0);
  337. return false;
  338. }
  339. cout<<"Invalid FP stack state after FP jsr"<<endl;
  340. return false;
  341. }
  342. return false;
  343. }
  344. static bool fixMov( CGAsm *as,CGMov *mv,FPStack *st,int live ){
  345. CGExp *lhs=mv->lhs;
  346. CGExp *rhs=mv->rhs;
  347. if( CGCvt *t=rhs->cvt() ){
  348. if( lhs->isfloat() ){
  349. if( t->exp->isfloat() ){
  350. //float to float
  351. st->fcopy( lhs->reg()->color,t->exp->reg()->color,live );
  352. return true;
  353. }
  354. //int to float
  355. allocTmp32();
  356. int rd=lhs->reg()->color;
  357. emit( "\tmov\t%s,%s\n",tmpbuf32,op2(as) );
  358. st->fload( rd,tmpbuf32,"fild",live );
  359. return true;
  360. }else if( t->exp->isfloat() ){
  361. //float to int
  362. allocTmp32();
  363. int rs=t->exp->reg()->color;
  364. st->fstore( rs,tmpbuf32,"fist",live );
  365. if( lhs->type==CG_INT8 ){
  366. emit( "\tmovzx\t%s,%s\n",op1(as),tmpbuf8 );
  367. }else if( lhs->type==CG_INT16 ){
  368. emit( "\tmovzx\t%s,%s\n",op1(as),tmpbuf16 );
  369. }else{
  370. emit( "\tmov\t%s,%s\n",op1(as),tmpbuf32 );
  371. }
  372. return true;
  373. }
  374. return false;
  375. }else if( CGScc *t=rhs->scc() ){
  376. if( !t->lhs->isfloat() ) return false;
  377. int rd=t->lhs->reg()->color;
  378. int rs=t->rhs->reg()->color;
  379. st->fcomp( rd,rs,live );
  380. const char *op;
  381. switch( t->cc ){
  382. case CG_EQ:op="z";break;
  383. case CG_NE:op="nz";break;
  384. case CG_LT:op="b";break;
  385. case CG_GT:op="a";break;
  386. case CG_LE:op="be";break;
  387. case CG_GE:op="ae";break;
  388. }
  389. emit( "\tset%s\tal\n",op );
  390. emit( "\tmovzx\teax,al\n" );
  391. return true;
  392. }
  393. if( lhs->isint() && rhs->isint() ) return false;
  394. assert( lhs->isfloat() && rhs->isfloat() );
  395. if( lhs->reg() && rhs->reg() ){
  396. st->fcopy( lhs->reg()->color,rhs->reg()->color,live );
  397. return true;
  398. }
  399. if( CGJsr *t=rhs->jsr() ){
  400. if( !live ){
  401. emit(as->assem);
  402. emit("\tfstp\tst0\n");
  403. return true;
  404. }else if( live==1 ){
  405. if( st->regs[0]<0 ) st->push(0);
  406. return false;
  407. }
  408. cout<<"Invalid FP stack state after FP jsr"<<endl;
  409. return false;
  410. /*
  411. emit(as->assem);
  412. if( live&1 ){
  413. if( st->regs[0]<0 ) st->push(0);
  414. }else if( st->regs[0]>=0 ){
  415. st->fpop();
  416. }
  417. return true;
  418. */
  419. }
  420. if( CGMem *t=rhs->mem() ){
  421. int rd=lhs->reg()->color;
  422. st->fload( rd,op2(as),"fld",live );
  423. return true;
  424. }
  425. if( CGMem *t=lhs->mem() ){
  426. int rs=rhs->reg()->color;
  427. st->fstore( rs,op1(as),"fst",live );
  428. return true;
  429. }
  430. if( CGUop *t=rhs->uop() ){
  431. int rd=lhs->reg()->color;
  432. const char *op;
  433. switch( t->op ){
  434. case CG_NEG:op="fchs";break;
  435. default:assert(0);
  436. }
  437. st->funiop( rd,op,live );
  438. return true;
  439. }
  440. if( CGBop *t=rhs->bop() ){
  441. int rd=lhs->reg()->color;
  442. const char *op;
  443. switch( t->op ){
  444. case CG_ADD:op="fadd";break;
  445. case CG_SUB:op="fsub";break;
  446. case CG_MUL:op="fmul";break;
  447. case CG_DIV:op="fdiv";break;
  448. default:assert(0);
  449. }
  450. if( CGReg *r=t->rhs->reg() ){
  451. st->fbinop( rd,r->color,op,live );
  452. }else{
  453. st->fbinop( rd,op2(as),op,live );
  454. }
  455. return true;
  456. }
  457. if( CGLit *t=rhs->lit() ){
  458. int rd=lhs->reg()->color;
  459. st->fload( rd,t->float_value,live );
  460. return true;
  461. }
  462. assert(0);
  463. return false;
  464. }
  465. static void fix( CGBlock *blk ){
  466. if( blk->begin==blk->end ) return;
  467. vector<int> live_stack;
  468. int live=liveMask( blk->live_out );
  469. CGAsm *as=blk->end;
  470. while( as!=blk->begin ){
  471. as=as->pred;
  472. live_stack.push_back( live );
  473. live&=~liveMask(as->def);
  474. live|=liveMask(as->use);
  475. }
  476. assert( stack_map.count(blk) );
  477. FPStack *st=new FPStack( stack_map[blk] );
  478. assert( st->liveMask()==live );
  479. for( as=blk->begin;as!=blk->end;as=as->succ ){
  480. live=live_stack.back();
  481. live_stack.pop_back();
  482. *(out=buf)=0;
  483. bool fix=false;
  484. if( CGMov *t=as->stm->mov() ){
  485. fix=fixMov( as,t,st,live );
  486. }else if( CGXop *t=as->stm->xop() ){
  487. fix=fixXop( as,t,st,live );
  488. }else if( CGEva *t=as->stm->eva() ){
  489. fix=fixEva( as,t,st,live );
  490. }
  491. if( fix ) as->assem=strdup(buf);
  492. }
  493. as=as->pred;
  494. buf_a[0]=0;
  495. CGBlock *blk_a=blk->succ.size()>0 ? blk->succ[0] : 0;
  496. if( blk_a ){
  497. out=buf_a;
  498. adjustStack( new FPStack(st),blk_a );
  499. }
  500. buf_b[0]=0;
  501. CGBlock *blk_b=blk->succ.size()>1 ? blk->succ[1] : 0;
  502. if( blk_b ){
  503. assert( as->stm->bcc() );
  504. out=buf_b;
  505. adjustStack( new FPStack(st),blk_b );
  506. }
  507. if( !buf_a[0] && !buf_b[0] ) return;
  508. *(out=buf)=0;
  509. assert( blk_a );
  510. if( !blk_b ){
  511. if( as->stm->bra() ){
  512. emit( buf_a );
  513. emit( as->assem );
  514. }else{
  515. emit( as->assem );
  516. emit( buf_a );
  517. }
  518. }else if( !buf_b[0] ){
  519. emit( as->assem );
  520. emit( buf_a );
  521. }else{
  522. CGBcc *t=as->stm->bcc();
  523. CGSym *skip=CG::sym();
  524. const char *cc=CGFrame_X86::x86cc( CG::swapcc(t->cc) );
  525. //find the jmp
  526. char *p=strstr( as->assem,"\tj" );assert(p);
  527. //cmp...
  528. memcpy( out,as->assem,p-as->assem );out+=p-as->assem;
  529. //new jmp
  530. emit( "\tj%s\t%s\n",cc,skip->value.c_str() );
  531. //normalize bra block
  532. emit( buf_b );
  533. //bra to block
  534. emit( "\tjmp\t%s\n",t->sym->value.c_str() );
  535. //our new symbol!
  536. emit( "%s:\n",skip->value.c_str() );
  537. emit( buf_a );
  538. }
  539. as->assem=strdup(buf);
  540. }
  541. void CGFrame_X86::fixFp(){
  542. if( !flow->blocks.size() ) return;
  543. ::frame=this;
  544. tmpbuf32[0]=0;
  545. buf=new char[1024];
  546. buf_a=new char[1024];
  547. buf_b=new char[1024];
  548. CGBlock *blk=*flow->blocks.begin();
  549. stack_map.clear();
  550. stack_map.insert( make_pair(blk,new FPStack(0)) );
  551. blocks_todo.clear();
  552. blocks_todo.insert( blk );
  553. while( blocks_todo.size() ){
  554. BlockSet::iterator it=blocks_todo.begin();
  555. CGBlock *blk=*it;
  556. blocks_todo.erase(it);
  557. fix(blk);
  558. }
  559. blocks_todo.clear();
  560. stack_map.clear();
  561. delete[] buf_b;
  562. delete[] buf_a;
  563. delete[] buf;
  564. }