cgmodule_x86.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #include "cgstd.h"
  2. #include "cgmodule_x86.h"
  3. #include "cgfixfp_x86.h"
  4. static bool USE_NASM=false; //NASM doesn't seem to work at all
  5. CGModule_X86::CGModule_X86( ostream &o ):CGModule(o){
  6. }
  7. void CGModule_X86::setSeg( string t ){
  8. if( seg==t ) return;
  9. seg=t;
  10. if( USE_NASM ){
  11. out<<"\tsection\t."<<seg<<'\n';
  12. }else{
  13. out<<"\tsection\t"<<seg<<'\n';
  14. }
  15. }
  16. CGFrame *CGModule_X86::frame( CGFun *fun ){
  17. return new CGFrame_X86( fun,this );
  18. }
  19. void CGModule_X86::emitHeader(){
  20. if( env_platform=="win32" ){
  21. out<<"\tformat\tMS COFF\n";
  22. }else if( env_platform=="linux" ){
  23. out<<"\tformat\tELF\n";
  24. }else if( env_platform!="macos" ){
  25. assert(0);
  26. }
  27. }
  28. void CGModule_X86::emitImport( string t ){
  29. if( USE_NASM ){
  30. out<<"\textern\t"<<t<<'\n';
  31. }else{
  32. out<<"\textrn\t"<<t<<'\n';
  33. }
  34. }
  35. void CGModule_X86::emitExport( string t ){
  36. if( USE_NASM ){
  37. out<<"\tglobal\t"<<t<<'\n';
  38. }else{
  39. out<<"\tpublic\t"<<t<<'\n';
  40. }
  41. }
  42. void CGModule_X86::emitFrame( CGFrame *f ){
  43. if( env_platform=="win32" ){
  44. setSeg( "\"code\" code" );
  45. }else if( env_platform=="linux" ){
  46. setSeg( "\"code\" executable" );
  47. }else if( env_platform=="macos" ){
  48. setSeg( "text" );
  49. }
  50. if( env_platform=="macos" ){
  51. emitMacFrame( f );
  52. return;
  53. }
  54. CGFrame_X86 *frame=dynamic_cast<CGFrame_X86*>(f);
  55. assert( frame );
  56. int k,n_use[7]={0};
  57. for( k=0;k<frame->regs.size();++k ){
  58. CGReg *r=frame->regs[k];
  59. if( r->isint() && r->id>=14 && r->color>=0 && r->color<7 ) ++n_use[r->color];
  60. }
  61. if( frame->extern_jsrs ){
  62. n_use[3]=n_use[4]=n_use[5]=-1;
  63. }
  64. int local_sz=frame->local_sz;
  65. //create frame
  66. out<<frame->fun->sym->value<<":\n";
  67. out<<"\tpush\tebp\n";
  68. out<<"\tmov\tebp,esp\n";
  69. emitSubEsp( local_sz );
  70. //push callee save
  71. if( n_use[3] ) out<<"\tpush\tebx\n";
  72. if( n_use[4] ) out<<"\tpush\tesi\n";
  73. if( n_use[5] ) out<<"\tpush\tedi\n";
  74. CGAsm *as;
  75. for( as=frame->assem.begin;as!=frame->assem.end;as=as->succ ){
  76. if( as->stm && as->stm->ret() ){
  77. //pop callee save
  78. if( n_use[5] ) out<<"\tpop\tedi\n";
  79. if( n_use[4] ) out<<"\tpop\tesi\n";
  80. if( n_use[3] ) out<<"\tpop\tebx\n";
  81. out<<"\tmov\tesp,ebp\n";
  82. out<<"\tpop\tebp\n";
  83. }
  84. const char *p=as->assem;
  85. if( !p ) continue;
  86. out<<p;
  87. }
  88. }
  89. void CGModule_X86::emitSubEsp( int sz ){
  90. while( sz>4096 ){
  91. out<<"\tsub\tesp,4092\n\tpush\teax\n";
  92. sz-=4096;
  93. }
  94. if( sz ) out<<"\tsub\tesp,"<<sz<<'\n';
  95. }
  96. void CGModule_X86::emitMacFrame( CGFrame *f ){
  97. CGFrame_X86 *frame=dynamic_cast<CGFrame_X86*>(f);
  98. assert( frame );
  99. int k,n_use[7]={0};
  100. for( k=0;k<frame->regs.size();++k ){
  101. CGReg *r=frame->regs[k];
  102. if( r->isint() && r->id>=14 && r->color>=0 && r->color<7 ) ++n_use[r->color];
  103. }
  104. int save_sz=8; //ret address+ebp
  105. if( n_use[3] ) save_sz+=4; //ebx
  106. if( n_use[4] ) save_sz+=4; //esi
  107. if( n_use[5] ) save_sz+=4; //edi
  108. int local_sz=frame->local_sz;
  109. int param_sz=frame->param_sz;
  110. int frame_sz=param_sz+local_sz+save_sz;
  111. frame_sz=(frame_sz+15)&~15;
  112. param_sz=frame_sz-(local_sz+save_sz);
  113. //create frame
  114. out<<frame->fun->sym->value<<":\n";
  115. //push ebp
  116. out<<"\tpush\tebp\n";
  117. out<<"\tmov\tebp,esp\n";
  118. if( save_sz>8 ){
  119. emitSubEsp( local_sz );
  120. if( n_use[3] ) out<<"\tpush\tebx\n";
  121. if( n_use[4] ) out<<"\tpush\tesi\n";
  122. if( n_use[5] ) out<<"\tpush\tedi\n";
  123. emitSubEsp( param_sz );
  124. }else{
  125. emitSubEsp( local_sz+param_sz );
  126. }
  127. CGAsm *as;
  128. for( as=frame->assem.begin;as!=frame->assem.end;as=as->succ ){
  129. if( as->stm && as->stm->ret() ){
  130. //pop callee save
  131. if( save_sz>8 ){
  132. if( param_sz ) out<<"\tadd\tesp,"<<param_sz<<'\n';
  133. if( n_use[5] ) out<<"\tpop\tedi\n";
  134. if( n_use[4] ) out<<"\tpop\tesi\n";
  135. if( n_use[3] ) out<<"\tpop\tebx\n";
  136. }
  137. out<<"\tmov\tesp,ebp\n";
  138. out<<"\tpop\tebp\n";
  139. }
  140. const char *p=as->assem;
  141. if( !p ) continue;
  142. out<<p;
  143. }
  144. }
  145. void CGModule_X86::emitData( CGDat *d ){
  146. if( env_platform=="win32" ){
  147. setSeg( "\"data\" data writeable align 8" );
  148. }else if( env_platform=="linux" ){
  149. setSeg( "\"data\" writeable align 8" );
  150. }else if( env_platform=="macos" ){
  151. setSeg( "data" );
  152. }
  153. int align=4;
  154. if( d->exps.size()==1 ){
  155. switch( d->exps[0]->type ){
  156. case CG_INT8:
  157. case CG_CSTRING:
  158. align=1;
  159. break;
  160. case CG_INT16:
  161. align=2;
  162. break;
  163. case CG_INT64:case CG_FLOAT64:
  164. align=8;
  165. break;
  166. }
  167. }
  168. if( align!=1 ){
  169. out<<"\talign\t"<<align<<"\n";
  170. }
  171. out<<d->value<<":\n";
  172. for( int k=0;k<d->exps.size();++k ){
  173. CGExp *e=d->exps[k];
  174. if( CGLit *t=e->lit() ){
  175. if( t->type==CG_INT8 ){
  176. out<<"\tdb\t"<<unsigned(t->int_value)<<'\n';
  177. }else if( t->type==CG_INT16 ){
  178. out<<"\tdw\t"<<unsigned(t->int_value)<<'\n';
  179. }else if( t->type==CG_INT32 ){
  180. out<<"\tdd\t"<<int(t->int_value)<<'\n';
  181. }else if( t->type==CG_INT64 ){
  182. out<<"\tdd\t"<<int(t->int_value)<<','<<int(t->int_value>>int64(32))<<'\n';
  183. }else if( t->type==CG_FLOAT32 ){
  184. float f=t->float_value;
  185. int n=*(int*)&f;
  186. out<<"\tdd\t0x"<<hex<<n<<dec<<'\n';
  187. // float f=t->float_value;
  188. // out<<"\tdd\t0x"<<hex<<*((int*)&f)<<dec<<'\n';
  189. }else if( t->type==CG_FLOAT64 ){
  190. double f=t->float_value;
  191. int64 n=*(int64*)&f;
  192. out<<"\tdd\t0x"<<hex<<int(n)<<",0x"<<int(n>>int64(32))<<dec<<'\n';
  193. // double f=t->float_value;
  194. //#if __APPLE__ && __BIG_ENDIAN__
  195. // out<<"\tdd\t0x"<<hex<<*((int*)&f+1)<<",0x"<<*((int*)&f)<<dec<<'\n';
  196. //#else
  197. // out<<"\tdd\t0x"<<hex<<*((int*)&f)<<",0x"<<*((int*)&f+1)<<dec<<'\n';
  198. //#endif
  199. }else if( t->type==CG_CSTRING ){
  200. bstring s=t->string_value;
  201. out<<"\tdb\t\"";
  202. for( int k=0;k<s.size();++k ){
  203. if( s[k]==34 ){
  204. if( env_platform=="macos" ){
  205. out<<"\\\"";
  206. }else{
  207. out<<"\",34,\"";
  208. }
  209. }else{
  210. out<<(char)s[k];
  211. }
  212. }
  213. out<<"\",0\n";
  214. }else if( t->type==CG_BSTRING ){
  215. bstring s=t->string_value;
  216. out<<"\tdd\t"<<s.size();
  217. for( int k=0;k<s.size();++k ){
  218. if( k%16 ) out<<','<<(unsigned)s[k];
  219. else out<<"\n\tdw\t"<<(unsigned)s[k];
  220. }
  221. out<<"\n";
  222. }else if( t->type==CG_BINFILE ){
  223. string file=tostring(t->string_value);
  224. out<<"\tfile\t\""+file+"\"\n";
  225. }else if( t->type==CG_LABEL ){
  226. out<<tostring(t->string_value)<<":\n";
  227. }else{
  228. assert(0);
  229. }
  230. }else if( CGSym *t=e->sym() ){
  231. out<<"\tdd\t"<<t->value<<'\n';
  232. }else if( CGLea *t=e->lea() ){
  233. CGMem *m=t->exp->mem();
  234. assert(m);
  235. if( CGReg *t=m->exp->reg() ){
  236. out<<"\tdd\t"<<m->offset<<'\n';
  237. }else if( CGSym *t=m->exp->sym() ){
  238. assert(t);
  239. if( m->offset ){
  240. out<<"\tdd\t"<<t->value<<'+'<<m->offset<<'\n';
  241. }else{
  242. out<<"\tdd\t"<<t->value<<'\n';
  243. }
  244. }else{
  245. assert(0);
  246. }
  247. }else{
  248. fail( "cgmodule_x86::emitData - unrecognized data format" );
  249. }
  250. }
  251. }
  252. void CGModule_X86::emitFooter(){
  253. }