mach4.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. #define RCSID4 "$Id$"
  2. /*
  3. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  4. * See the copyright notice in the ACK home directory, in the file "Copyright".
  5. *
  6. */
  7. operation
  8. :
  9. USE16
  10. { use32 = 0; address_long = 0; operand_long = 0; }
  11. |
  12. USE32
  13. { use32 = 1; address_long = 1; operand_long = 1; }
  14. | prefix oper
  15. { address_long = use32; operand_long = use32; }
  16. | prefix1 /* to allow for only prefixes on a line */
  17. ;
  18. prefix : /* empty */
  19. | prefix1
  20. ;
  21. prefix1: prefix PREFIX { emit1($2); }
  22. |
  23. prefix ATOGGLE
  24. { if ((($2&0200) >> 7) == address_long) {
  25. if (pass == PASS_3) warning("address size toggle ignored");
  26. } else {
  27. emit1($2 & 0177);
  28. address_long = ! address_long;
  29. }
  30. }
  31. |
  32. prefix OTOGGLE
  33. { if ((($2&0200) >> 7) == operand_long) {
  34. if (pass == PASS_3) warning("operand size toggle ignored");
  35. } else {
  36. emit1($2 & 0177);
  37. operand_long = ! operand_long;
  38. }
  39. }
  40. ;
  41. oper : NOOP_1
  42. { emit1($1);}
  43. | NOOP_2
  44. { emit2($1);}
  45. | JOP expr
  46. { branch($1,$2);}
  47. | JOP2 expr
  48. { ebranch($1,$2);}
  49. | PUSHOP ea_1
  50. { pushop($1);}
  51. | IOOP absexp
  52. { emit1($1);
  53. fit(ufitb($2));
  54. emit1((int)$2);
  55. }
  56. | IOOP R32
  57. { if ($2!=2) serror("register error");
  58. emit1($1+010);
  59. }
  60. | BITTEST ea_ea
  61. { bittestop($1);}
  62. | ADDOP ea_ea
  63. { addop($1);}
  64. | ROLOP ea_ea
  65. { rolop($1);}
  66. | INCOP ea_1
  67. { incop($1);}
  68. | NOTOP ea_1
  69. { regsize($1); emit1(0366|($1&1)); ea_1($1&070);}
  70. | CALLOP ea_1
  71. { callop($1&0xFFFF);}
  72. | CALFOP expr ':' expr
  73. { emit1($1>>8);
  74. adsize_exp($4, 0);
  75. #ifdef RELOCATION
  76. newrelo($2.typ, RELO2);
  77. #endif
  78. emit2((int)($2.val));
  79. }
  80. | CALFOP mem
  81. { emit1(0377); ea_2($1&0xFF);}
  82. | ENTER absexp ',' absexp
  83. { fit(fitw($2)); fit(fitb($4));
  84. emit1($1); emit2((int)$2); emit1((int)$4);
  85. }
  86. | LEAOP R32 ',' mem
  87. { emit1($1); ea_2($2<<3);}
  88. | LEAOP2 R32 ',' mem
  89. { emit1(0xF); emit1($1); ea_2($2<<3);}
  90. | ARPLOP ea_2 ',' R32
  91. { emit1($1); ea_2($4<<3);}
  92. | LSHFT ea_1 ',' R32 ',' ea_2
  93. { extshft($1, $4);}
  94. | EXTEND R32 ',' ea_2
  95. { emit1(0xF); emit1($1); ea_2($2<<3);}
  96. | EXTOP R32 ',' ea_2
  97. { emit1(0xF); emit1($1); ea_2($2<<3);}
  98. | EXTOP1 ea_1
  99. { emit1(0xF); emit1($1&07); ea_1($1&070);}
  100. | IMULB ea_1
  101. { regsize(0); emit1(0366); ea_1($1&070);}
  102. | IMUL ea_2
  103. { reg_1 = IS_R32 | (address_long ? 0 : 0310);
  104. imul(0);
  105. }
  106. | IMUL R32 ',' ea_2
  107. { reg_1 = $2 | IS_R32 | (address_long ? 0 : 0310);
  108. imul($2|0x10);
  109. }
  110. | IMUL R32 ',' ea_ea
  111. { imul($2|0x10);}
  112. | INT absexp
  113. { if ($2==3)
  114. emit1(0314);
  115. else {
  116. fit(ufitb($2));
  117. emit1(0315); emit1((int)$2);
  118. }
  119. }
  120. | RET
  121. { emit1($1);}
  122. | RET expr
  123. { emit1($1-1);
  124. #ifdef RELOCATION
  125. newrelo($2.typ, RELO2);
  126. #endif
  127. emit2((int)($2.val));
  128. }
  129. | SETCC ea_2
  130. { if (reg_2 & (IS_R32|IS_RSEG)) {
  131. serror("register error");
  132. }
  133. emit1(0xF); emit1($1|0x90); ea_2(0);
  134. }
  135. | XCHG ea_ea
  136. { xchg($1);}
  137. | TEST ea_ea
  138. { test($1);}
  139. | MOV ea_ea
  140. { mov($1);}
  141. | /* What is really needed is just
  142. MOV R32 ',' RSYSCR
  143. but this gives a bad yacc conflict
  144. */
  145. MOV ea_1 ',' RSYSCR
  146. {
  147. if ($1 != 1 || !(reg_1 & IS_R32))
  148. serror("syntax error");
  149. emit1(0xF); emit1(0x20); emit1(0300|($4<<3)|(reg_1&07));}
  150. | MOV ea_1 ',' RSYSDR
  151. {
  152. if ($1 != 1 || !(reg_1 & IS_R32))
  153. serror("syntax error");
  154. emit1(0xF); emit1(0x21); emit1(0300|($4<<3)|(reg_1&07));}
  155. | MOV ea_1 ',' RSYSTR
  156. {
  157. if ($1 != 1 || !(reg_1 & IS_R32))
  158. serror("syntax error");
  159. emit1(0xF); emit1(0x24); emit1(0300|($4<<3)|(reg_1&07));}
  160. | MOV RSYSCR ',' R32
  161. {
  162. if ($1 != 1) serror("syntax error");
  163. emit1(0xF); emit1(0x22); emit1(0300|($2<<3)|$4);}
  164. | MOV RSYSDR ',' R32
  165. {
  166. if ($1 != 1) serror("syntax error");
  167. emit1(0xF); emit1(0x23); emit1(0300|($2<<3)|$4);}
  168. | MOV RSYSTR ',' R32
  169. {
  170. if ($1 != 1) serror("syntax error");
  171. emit1(0xF); emit1(0x26); emit1(0300|($2<<3)|$4);}
  172. /* Intel 80[23]87 coprocessor instructions */
  173. | FNOOP
  174. { emit1($1); emit1($1>>8);}
  175. | FMEM mem
  176. { emit1($1); ea_2(($1>>8)&070);}
  177. | FMEM_AX mem
  178. { emit1($1); ea_2(($1>>8)&070);}
  179. | FMEM_AX R32
  180. { if ($2 != 0) {
  181. serror("illegal register");
  182. }
  183. emit1(FESC|7); emit1(7<<5);
  184. }
  185. | FST_I st_i
  186. { emit1($1); emit1(($1>>8)|$2); }
  187. | FST_I ST
  188. { emit1($1); emit1($1>>8); }
  189. | FST_ST ST ',' st_i
  190. { emit1($1); emit1(($1>>8)|$4); }
  191. | FST_ST2 ST ',' st_i
  192. { emit1($1); emit1(($1>>8)|$4); }
  193. | FST_ST st_i ',' ST
  194. { emit1($1|4); emit1((($1>>8)|$2)); }
  195. | FST_ST2 st_i ',' ST
  196. { emit1($1|4); emit1((($1>>8)|$2)^010); }
  197. /* 486 instructions */
  198. | BSWAP R32
  199. { emit1(0xF); emit1($1|$2); }
  200. | EXTOPBW ea_2 ',' reg
  201. { regsize($1);
  202. emit1(0xF); emit1($1); ea_2($4<<3);
  203. }
  204. ;
  205. st_i : ST '(' absexp ')'
  206. { if (!fit3($3)) {
  207. serror("illegal index in FP stack");
  208. }
  209. $$ = $3;
  210. }
  211. ;
  212. ;
  213. mem : '(' expr ')'
  214. { if (address_long) reg_2 = 05;
  215. else reg_2 = 06;
  216. mod_2 = 0;
  217. rm_2 = 05;
  218. exp_2 = $2;
  219. RELOMOVE(rel_2, relonami);
  220. }
  221. | bases
  222. { exp_2.val = 0; exp_2.typ = S_ABS; indexed();}
  223. | expr bases
  224. { exp_2 = $1; indexed();
  225. RELOMOVE(rel_2, relonami);
  226. }
  227. ;
  228. bases : '(' R32 ')'
  229. { if (address_long) reg_2 = $2;
  230. else reg_2 = sr_m[$2];
  231. sib_2 = 0; rm_2 = 0;
  232. }
  233. | '(' R32 ')' '(' R32 scale ')'
  234. { if (address_long) reg_2 = $2;
  235. else reg_2 = dr_m[$2][$5];
  236. rm_2 = 04;
  237. sib_2 |= regindex_ind[$2][$5];
  238. }
  239. | '(' R32 '*' absexp ')'
  240. { if ($4 == 1) {
  241. reg_2 = $2; sib_2 = 0; rm_2 = 0;
  242. }
  243. else {
  244. rm_2 = 04;
  245. sib_2 = checkscale($4) | regindex_ind[05][$2];
  246. reg_2 = 015;
  247. }
  248. }
  249. ;
  250. scale : /* empty */
  251. { sib_2 = 0;}
  252. | '*' absexp
  253. { sib_2 = checkscale($2);}
  254. ;
  255. ea_2 : mem
  256. | R8
  257. { reg_2 = ($1 | IS_R8) | (address_long ? 0 : 0300);
  258. rm_2 = 0;
  259. }
  260. | R32
  261. { reg_2 = ($1 | IS_R32) | (address_long ? 0 : 0310);
  262. rm_2 = 0;
  263. }
  264. | RSEG
  265. { reg_2 = ($1 | IS_RSEG) | (address_long ? 0 : 020);
  266. rm_2 = 0;
  267. }
  268. | expr
  269. { reg_2 = IS_EXPR | (address_long ? 0 : 040);
  270. exp_2 = $1; rm_2 = 0;
  271. RELOMOVE(rel_2, relonami);
  272. }
  273. ;
  274. reg : R8 { reg_1 = ($1 | IS_R8) | (address_long ? 0 : 0300);
  275. rm_1 = 0;
  276. $$ = $1;
  277. }
  278. | R32
  279. { reg_1 = ($1 | IS_R32) | (address_long ? 0 : 0310);
  280. rm_1 = 0;
  281. $$ = $1;
  282. }
  283. ;
  284. ea_1 : ea_2
  285. { op_1 = op_2;
  286. RELOMOVE(rel_1, rel_2);
  287. }
  288. ;
  289. ea_ea : ea_1 ',' ea_2
  290. ;