operand.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #include "../std.h"
  2. #include "../ex.h"
  3. #include "operand.h"
  4. #include "insts.h"
  5. static const char *regs[]={
  6. "al","cl","dl","bl","ah","ch","dh","bh",
  7. "ax","cx","dx","bx","sp","bp","si","di",
  8. "eax","ecx","edx","ebx","esp","ebp","esi","edi"
  9. };
  10. static void opError(){
  11. throw Ex( "error in operand" );
  12. }
  13. static void sizeError(){
  14. throw Ex( "illegal operand size" );
  15. }
  16. Operand::Operand()
  17. :mode(NONE),reg(-1),imm(0),offset(0),baseReg(-1),indexReg(-1),shift(0){
  18. }
  19. Operand::Operand( const string &s )
  20. :mode(NONE),reg(-1),imm(0),offset(0),baseReg(-1),indexReg(-1),shift(0),s(s){
  21. }
  22. bool Operand::parseSize( int *sz ){
  23. if( !s.size() ) return false;
  24. if( s.find( "byte " )==0 ){
  25. *sz=1;s=s.substr( 5 );
  26. }else if( s.find( "word " )==0 ){
  27. *sz=2;s=s.substr( 5 );
  28. }else if( s.find( "dword " )==0 ){
  29. *sz=4;s=s.substr( 6 );
  30. }else return false;
  31. return true;
  32. }
  33. bool Operand::parseChar( char c ){
  34. if( !s.size() || s[0]!=c ) return false;
  35. s=s.substr( 1 );return true;
  36. }
  37. bool Operand::parseReg( int *reg ){
  38. int i;
  39. for( i=0;i<s.size() && isalpha( s[i] );++i ){}
  40. if( !i ) return false;
  41. string t=s.substr(0,i);
  42. for( int j=0;j<24;++j ){
  43. if( t==regs[j] ){ *reg=j;s=s.substr( i );return true; }
  44. }
  45. return false;
  46. }
  47. bool Operand::parseFPReg( int *reg ){
  48. //eg: st(0)
  49. if( s.size()<5 ) return false;
  50. if( s[0]!='s' || s[1]!='t' || s[2]!='(' || s[4]!=')' ) return false;
  51. if( s[3]<'0' || s[3]>'7' ) return false;
  52. *reg=s[3]-'0';s=s.substr( 5 );return true;
  53. }
  54. bool Operand::parseLabel( string *label ){
  55. if( !s.size() || (!isalpha( s[0] ) && s[0]!='_') ) return false;
  56. int i;
  57. for( i=1;i<s.size() && (isalnum( s[i] ) || s[i]=='_');++i ){}
  58. *label=s.substr(0,i);s=s.substr( i );return true;
  59. }
  60. bool Operand::parseConst( int *iconst ){
  61. int i,sgn=s.size() && (s[0]=='-'||s[0]=='+');
  62. for( i=sgn;i<s.size() && isdigit( s[i] );++i ){}
  63. if( i==sgn ) return false;
  64. int n=atoi( s.c_str() );
  65. *iconst=n;s=s.substr( i );return true;
  66. }
  67. void Operand::parse(){
  68. if( !s.size() ) return;
  69. int sz;if( !parseSize( &sz ) ) sz=0;
  70. if( s[0]!='[' ){
  71. int r;
  72. if( parseReg( &r ) ){
  73. mode=REG|R_M;
  74. if( r<8 ){
  75. if( sz && sz!=1 ) sizeError();
  76. mode|=REG8|R_M8;
  77. if( r==0 ) mode|=AL;else if( r==1 ) mode|=CL;
  78. }else if( r<16 ){
  79. if( sz && sz!=2 ) sizeError();
  80. mode|=REG16|R_M16;
  81. if( r==8 ) mode|=AX;else if( r==9 ) mode|=CX;
  82. }else{
  83. if( sz && sz!=4 ) sizeError();
  84. mode|=REG32|R_M32;
  85. if( r==16 ) mode|=EAX;else if( r==17 ) mode|=ECX;
  86. }
  87. reg=r&7;
  88. }else if( parseFPReg( &r ) ){
  89. mode=FPUREG;
  90. if( !r ) mode|=ST0;
  91. reg=r;
  92. }else if( parseLabel( &immLabel ) ){
  93. if( sz && sz!=4 ) sizeError();
  94. mode=IMM|IMM32;
  95. }else if( parseConst( &imm ) ){
  96. mode=IMM;
  97. if( sz==1 ) mode|=IMM8;
  98. else if( sz==2 ) mode|=IMM16;
  99. else mode|=IMM32;
  100. }else opError();
  101. if( s.size() ) opError();
  102. return;
  103. }
  104. if( s[s.size()-1]!=']' ) opError();
  105. s=s.substr( 1,s.size()-2 );
  106. mode=MEM|R_M;
  107. if( sz==1 ) mode|=MEM8|R_M8;
  108. else if( sz==2 ) mode|=MEM16|R_M16;
  109. else mode|=MEM32|R_M32;
  110. for(;;){
  111. int n;string l;
  112. if( parseReg( &n ) ){
  113. if( n<16 ) throw Ex( "register must be 32 bit" );
  114. n&=7;
  115. if( parseChar( '*' ) ){
  116. if( n==4 ) break; //esp cannot be index reg!
  117. if( indexReg>=0 ) break;
  118. if( parseChar( '1' ) ) shift=0;
  119. else if( parseChar( '2' ) ) shift=1;
  120. else if( parseChar( '4' ) ) shift=2;
  121. else if( parseChar( '8' ) ) shift=3;
  122. else break;
  123. indexReg=n;
  124. }else{
  125. if( baseReg<0 ) baseReg=n;
  126. else if( indexReg<0 ){ indexReg=n; }
  127. else break;
  128. }
  129. }else if( parseLabel( &l ) ){
  130. if( baseLabel.size() ) opError();
  131. baseLabel=l;
  132. }else if( parseConst( &n ) ){
  133. offset+=n;
  134. }else break;
  135. if( !s.size() ) return;
  136. }
  137. opError();
  138. }