mach5.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. */
  5. #define RCSID5 "$Id$"
  6. /*
  7. * INTEL 80386 special routines
  8. */
  9. ea_1_16(param)
  10. {
  11. reg_1 &= 0377;
  12. if ((reg_1 & 070) || (param & ~070)) {
  13. serror("bad operand");
  14. }
  15. emit1(reg_1 | param);
  16. switch(reg_1 >> 6) {
  17. case 0:
  18. if (reg_1 == 6 || (reg_1 & 040)) {
  19. #ifdef RELOCATION
  20. RELOMOVE(relonami, rel_1);
  21. newrelo(exp_1.typ, RELO2);
  22. #endif
  23. emit2(exp_1.val);
  24. }
  25. break;
  26. case 1:
  27. emit1(exp_1.val);
  28. break;
  29. case 2:
  30. #ifdef RELOCATION
  31. RELOMOVE(relonami, rel_1);
  32. newrelo(exp_1.typ, RELO2);
  33. #endif
  34. emit2(exp_1.val);
  35. break;
  36. }
  37. }
  38. ea_1(param) {
  39. if (! address_long) {
  40. ea_1_16(param);
  41. return;
  42. }
  43. if (is_expr(reg_1)) {
  44. serror("bad operand");
  45. return;
  46. }
  47. if (is_reg(reg_1)) {
  48. emit1(0300 | param | (reg_1&07));
  49. return;
  50. }
  51. if (rm_1 == 04) {
  52. /* sib field use here */
  53. emit1(mod_1 << 6 | param | 04);
  54. emit1(sib_1 | reg_1);
  55. }
  56. else emit1(mod_1<<6 | param | (reg_1&07));
  57. if ((mod_1 == 0 && reg_1 == 5) || mod_1 == 2) {
  58. /* ??? should this be protected by a call to "small" ??? */
  59. #ifdef RELOCATION
  60. RELOMOVE(relonami, rel_1);
  61. newrelo(exp_1.typ, RELO4);
  62. #endif
  63. emit4((long)(exp_1.val));
  64. }
  65. else if (mod_1 == 1) {
  66. emit1((int)(exp_1.val));
  67. }
  68. }
  69. ea_2(param) {
  70. op_1 = op_2;
  71. RELOMOVE(rel_1, rel_2);
  72. ea_1(param);
  73. }
  74. int
  75. checkscale(val)
  76. valu_t val;
  77. {
  78. int v = val;
  79. if (! address_long) {
  80. serror("scaling not allowed in 16-bit mode");
  81. return 0;
  82. }
  83. if (v != val) v = 0;
  84. switch(v) {
  85. case 1:
  86. return 0;
  87. case 2:
  88. return 1 << 6;
  89. case 4:
  90. return 2 << 6;
  91. case 8:
  92. return 3 << 6;
  93. default:
  94. serror("bad scale");
  95. return 0;
  96. }
  97. /*NOTREACHED*/
  98. }
  99. reverse() {
  100. struct operand op;
  101. #ifdef RELOCATION
  102. int r = rel_1;
  103. rel_1 = rel_2; rel_2 = r;
  104. #endif
  105. op = op_1; op_1 = op_2; op_2 = op;
  106. }
  107. badsyntax() {
  108. serror("bad operands");
  109. }
  110. regsize(sz)
  111. int sz;
  112. {
  113. register int bit;
  114. bit = (sz&1) ? 0 : IS_R8;
  115. if ((is_reg(reg_1) && (reg_1 & IS_R8) != bit) ||
  116. (is_reg(reg_2) && (reg_2 & IS_R8) != bit))
  117. serror("register error");
  118. if (! address_long) {
  119. reg_1 &= ~010;
  120. reg_2 &= ~010;
  121. }
  122. }
  123. indexed() {
  124. if (address_long) {
  125. mod_2 = 0;
  126. if (sib_2 == -1)
  127. serror("register error");
  128. if (rm_2 == 0 && reg_2 == 4) {
  129. /* base register sp, no index register; use
  130. indexed mode without index register
  131. */
  132. rm_2 = 04;
  133. sib_2 = 044;
  134. }
  135. if (reg_2 == 015) {
  136. reg_2 = 05;
  137. return;
  138. }
  139. if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 3)) {
  140. if (small(exp_2.val == 0 && reg_2 != 5, 1)) {
  141. }
  142. else mod_2 = 01;
  143. }
  144. else if (small(0, 1)) {
  145. }
  146. else mod_2 = 02;
  147. }
  148. else {
  149. if (reg_2 & ~7)
  150. serror("register error");
  151. if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 1)) {
  152. if (small(exp_2.val == 0 && reg_2 != 6, 1)) {
  153. }
  154. else reg_2 |= 0100;
  155. }
  156. else if (small(0, 1)) {
  157. }
  158. else reg_2 |= 0200;
  159. }
  160. }
  161. ebranch(opc,exp)
  162. register int opc;
  163. expr_t exp;
  164. {
  165. /* Conditional branching; Full displacements are available
  166. on the 80386, so the welknown trick with the reverse branch
  167. over a jump is not needed here.
  168. The only complication here is with the address size, which
  169. can be set with a prefix. In this case, the user gets what
  170. he asked for.
  171. */
  172. register int sm;
  173. register long dist;
  174. int saving = address_long ? 4 : 2;
  175. if (opc == 0353) saving--;
  176. dist = exp.val - (DOTVAL + 2);
  177. if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
  178. dist -= DOTGAIN;
  179. sm = dist > 0 ? fitb(dist-saving) : fitb(dist);
  180. if ((exp.typ & ~S_DOT) != DOTTYP)
  181. sm = 0;
  182. if ((sm = small(sm,saving)) == 0) {
  183. if (opc == 0353) {
  184. emit1(0xe9);
  185. }
  186. else {
  187. emit1(0xF);
  188. emit1(opc | 0x80);
  189. }
  190. dist -= saving;
  191. exp.val = dist;
  192. adsize_exp(exp, RELPC);
  193. }
  194. else {
  195. if (opc == 0353) {
  196. emit1(opc);
  197. }
  198. else {
  199. emit1(opc | 0x70);
  200. }
  201. emit1((int)dist);
  202. }
  203. }
  204. branch(opc,exp)
  205. register int opc;
  206. expr_t exp;
  207. {
  208. /* LOOP, JCXZ, etc. branch instructions.
  209. Here, the offset just must fit in a byte.
  210. */
  211. register long dist;
  212. dist = exp.val - (DOTVAL + 2);
  213. if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
  214. dist -= DOTGAIN;
  215. fit((exp.typ & ~S_DOT) == DOTTYP && fitb(dist));
  216. emit1(opc);
  217. emit1((int)dist);
  218. }
  219. pushop(opc)
  220. register int opc;
  221. {
  222. regsize(1);
  223. if (is_segreg(reg_1)) {
  224. /* segment register */
  225. if ((reg_1 & 07) <= 3)
  226. emit1(6 | opc | (reg_1&7)<<3);
  227. else {
  228. emit1(0xF);
  229. emit1(0200 | opc | ((reg_1&7)<<3));
  230. }
  231. } else if (is_reg(reg_1)) {
  232. /* normal register */
  233. emit1(0120 | opc<<3 | (reg_1&7));
  234. } else if (opc == 0) {
  235. if (is_expr(reg_1)) {
  236. if (small(exp_1.typ == S_ABS && fitb(exp_1.val),
  237. operand_long ? 3 : 1)) {
  238. emit1(0152);
  239. emit1((int)(exp_1.val));
  240. }
  241. else {
  242. emit1(0150);
  243. RELOMOVE(relonami, rel_1);
  244. opsize_exp(exp_1, 1);
  245. }
  246. }
  247. else {
  248. emit1(0377); ea_1(6<<3);
  249. }
  250. } else {
  251. emit1(0217); ea_1(0<<3);
  252. }
  253. }
  254. opsize_exp(exp, nobyte)
  255. expr_t exp;
  256. {
  257. if (! nobyte) {
  258. #ifdef RELOCATION
  259. newrelo(exp.typ, RELO1);
  260. #endif
  261. emit1((int)(exp.val));
  262. }
  263. else if (operand_long) {
  264. #ifdef RELOCATION
  265. newrelo(exp.typ, RELO4);
  266. #endif
  267. emit4((long)(exp.val));
  268. }
  269. else {
  270. #ifdef RELOCATION
  271. newrelo(exp.typ, RELO2);
  272. #endif
  273. emit2((int)(exp.val));
  274. }
  275. }
  276. adsize_exp(exp, relpc)
  277. expr_t exp;
  278. {
  279. if (address_long) {
  280. #ifdef RELOCATION
  281. newrelo(exp.typ, RELO4 | relpc);
  282. #endif
  283. emit4((long)(exp.val));
  284. }
  285. else {
  286. #ifdef RELOCATION
  287. newrelo(exp.typ, RELO2 | relpc);
  288. #endif
  289. emit2((int)(exp.val));
  290. }
  291. }
  292. addop(opc)
  293. register int opc;
  294. {
  295. regsize(opc);
  296. if (is_reg(reg_2)) {
  297. /* Add register to register or memory */
  298. emit1(opc); ea_1((reg_2&7)<<3);
  299. } else if (is_acc(reg_1) && is_expr(reg_2)) {
  300. /* Add immediate to accumulator */
  301. emit1(opc | 4);
  302. RELOMOVE(relonami, rel_2);
  303. opsize_exp(exp_2, (opc&1));
  304. } else if (is_expr(reg_2)) {
  305. /* Add immediate to register or memory */
  306. if ((opc&1) == 0) {
  307. emit1(0200);
  308. } else if (! small(exp_2.typ == S_ABS && fitb(exp_2.val),
  309. operand_long ? 3 : 1)) {
  310. emit1(0201);
  311. } else {
  312. emit1(0203); opc &= ~1;
  313. }
  314. ea_1(opc & 070);
  315. RELOMOVE(relonami, rel_2);
  316. opsize_exp(exp_2, (opc&1));
  317. } else if (is_reg(reg_1)) {
  318. /* Add register or memory to register */
  319. emit1(opc | 2);
  320. ea_2((reg_1&7)<<3);
  321. } else
  322. badsyntax();
  323. }
  324. rolop(opc)
  325. register int opc;
  326. {
  327. register int oreg;
  328. oreg = reg_2;
  329. reg_2 = reg_1;
  330. regsize(opc);
  331. if (oreg == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
  332. /* cl register */
  333. emit1(0322 | (opc&1)); ea_1(opc&070);
  334. } else if (is_expr(oreg)) {
  335. if (small(exp_2.typ == S_ABS && exp_2.val == 1, 1)) {
  336. /* shift by 1 */
  337. emit1(0320 | (opc&1)); ea_1(opc&070);
  338. } else {
  339. /* shift by byte count */
  340. emit1(0300 | (opc & 1));
  341. ea_1(opc & 070);
  342. #ifdef RELOCATION
  343. RELOMOVE(relonami, rel_2);
  344. newrelo(exp_2.typ, RELO1);
  345. #endif
  346. emit1((int)(exp_2.val));
  347. }
  348. }
  349. else
  350. badsyntax();
  351. }
  352. incop(opc)
  353. register int opc;
  354. {
  355. regsize(opc);
  356. if ((opc&1) && is_reg(reg_1)) {
  357. /* word register */
  358. emit1(0100 | (opc&010) | (reg_1&7));
  359. } else {
  360. emit1(0376 | (opc&1));
  361. ea_1(opc & 010);
  362. }
  363. }
  364. callop(opc)
  365. register int opc;
  366. {
  367. regsize(1);
  368. if (is_expr(reg_1)) {
  369. if (opc == (040+(0351<<8))) {
  370. RELOMOVE(relonami, rel_1);
  371. ebranch(0353,exp_1);
  372. } else {
  373. exp_1.val -= (DOTVAL+3 + (address_long ? 2 : 0));
  374. emit1(opc>>8);
  375. RELOMOVE(relonami, rel_1);
  376. adsize_exp(exp_1, RELPC);
  377. }
  378. } else {
  379. emit1(0377); ea_1(opc&070);
  380. }
  381. }
  382. xchg(opc)
  383. register int opc;
  384. {
  385. regsize(opc);
  386. if (! is_reg(reg_1) || is_acc(reg_2)) {
  387. reverse();
  388. }
  389. if (opc == 1 && is_acc(reg_1) && is_reg(reg_2)) {
  390. emit1(0220 | (reg_2&7));
  391. } else if (is_reg(reg_1)) {
  392. emit1(0206 | opc); ea_2((reg_1&7)<<3);
  393. } else
  394. badsyntax();
  395. }
  396. test(opc)
  397. register int opc;
  398. {
  399. regsize(opc);
  400. if (is_reg(reg_2) || is_expr(reg_1))
  401. reverse();
  402. if (is_expr(reg_2)) {
  403. if (is_acc(reg_1)) {
  404. emit1(0250 | opc);
  405. RELOMOVE(relonami, rel_2);
  406. opsize_exp(exp_2, (opc&1));
  407. }
  408. else {
  409. emit1(0366 | opc);
  410. ea_1(0<<3);
  411. RELOMOVE(relonami, rel_2);
  412. opsize_exp(exp_2, (opc&1));
  413. }
  414. } else if (is_reg(reg_1)) {
  415. emit1(0204 | opc); ea_2((reg_1&7)<<3);
  416. } else
  417. badsyntax();
  418. }
  419. mov(opc)
  420. register int opc;
  421. {
  422. regsize(opc);
  423. if (is_segreg(reg_1)) {
  424. /* to segment register */
  425. emit1(0216); ea_2((reg_1&07)<<3);
  426. } else if (is_segreg(reg_2)) {
  427. /* from segment register */
  428. emit1(0214); ea_1((reg_2&07)<<3);
  429. } else if (is_expr(reg_2)) {
  430. /* from immediate */
  431. if (is_reg(reg_1)) {
  432. /* to register */
  433. emit1(0260 | opc<<3 | (reg_1&7));
  434. } else {
  435. /* to memory */
  436. emit1(0306 | opc); ea_1(0<<3);
  437. }
  438. RELOMOVE(relonami, rel_2);
  439. opsize_exp(exp_2, (opc&1));
  440. } else if (rm_1 == 05 && is_acc(reg_2)) {
  441. /* from accumulator to memory (displacement) */
  442. emit1(0242 | opc);
  443. RELOMOVE(relonami, rel_1);
  444. adsize_exp(exp_1, 0);
  445. } else if (rm_2 == 05 && is_acc(reg_1)) {
  446. /* from memory (displacement) to accumulator */
  447. emit1(0240 | opc);
  448. RELOMOVE(relonami, rel_2);
  449. adsize_exp(exp_2, 0);
  450. } else if (is_reg(reg_2)) {
  451. /* from register to memory or register */
  452. emit1(0210 | opc); ea_1((reg_2&07)<<3);
  453. } else if (is_reg(reg_1)) {
  454. /* from memory or register to register */
  455. emit1(0212 | opc); ea_2((reg_1&07)<<3);
  456. } else
  457. badsyntax();
  458. }
  459. extshft(opc, reg)
  460. int opc;
  461. {
  462. int oreg2 = reg_2;
  463. reg_2 = reg_1;
  464. regsize(1);
  465. emit1(0xF);
  466. if (oreg2 == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
  467. /* cl register */
  468. emit1(opc|1);
  469. ea_1(reg << 3);
  470. }
  471. else if (is_expr(oreg2)) {
  472. emit1(opc);
  473. ea_1(reg << 3);
  474. #ifdef RELOCATION
  475. RELOMOVE(relonami, rel_2);
  476. newrelo(exp_2.typ, RELO1);
  477. #endif
  478. emit1((int)(exp_2.val));
  479. }
  480. else badsyntax();
  481. }
  482. bittestop(opc)
  483. int opc;
  484. {
  485. regsize(1);
  486. emit1(0xF);
  487. if (is_expr(reg_2)) {
  488. emit1(0272);
  489. ea_1(opc << 3);
  490. #ifdef RELOCATION
  491. RELOMOVE(relonami, rel_2);
  492. newrelo(exp_2.typ, RELO1);
  493. #endif
  494. emit1((int)(exp_2.val));
  495. }
  496. else if (is_reg(reg_2)) {
  497. emit1(0203 | (opc<<3));
  498. ea_1((reg_2&7)<<3);
  499. }
  500. else badsyntax();
  501. }
  502. imul(reg)
  503. int reg;
  504. {
  505. /* This instruction is more elaborate on the 80386. Its most
  506. general form is:
  507. imul reg, reg_or_mem, immediate.
  508. This is the form processed here.
  509. */
  510. regsize(1);
  511. if (is_expr(reg_1)) {
  512. /* To also handle
  513. imul reg, immediate, reg_or_mem
  514. */
  515. reverse();
  516. }
  517. if (is_expr(reg_2)) {
  518. /* The immediate form; two cases: */
  519. if (small(exp_2.typ == S_ABS && fitb(exp_2.val),
  520. operand_long ? 3 : 1)) {
  521. /* case 1: 1 byte encoding of immediate */
  522. emit1(0153);
  523. ea_1((reg & 07) << 3);
  524. emit1((int)(exp_2.val));
  525. }
  526. else {
  527. /* case 2: WORD or DWORD encoding of immediate */
  528. emit1(0151);
  529. ea_1((reg & 07) << 3);
  530. RELOMOVE(relonami, rel_2);
  531. opsize_exp(exp_2, 1);
  532. }
  533. }
  534. else if (is_reg(reg_1) && ((reg_1&7) == (reg & 07))) {
  535. /* the "reg" field and the "reg_or_mem" field are the same,
  536. and the 3rd operand is not an immediate ...
  537. */
  538. if (reg == 0) {
  539. /* how lucky we are, the target is the ax register */
  540. /* However, we cannot make an optimization for f.i.
  541. imul eax, blablabla
  542. because the latter does not affect edx, whereas
  543. imul blablabla
  544. does! Therefore, "reg" is or-ed with 0x10 in the
  545. former case, so that the test above fails.
  546. */
  547. emit1(0367);
  548. ea_2(050);
  549. }
  550. else {
  551. /* another register ... */
  552. emit1(0xF);
  553. emit1(0257);
  554. ea_2((reg & 07) << 3);
  555. }
  556. }
  557. else badsyntax();
  558. }