decode.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149
  1. /****************************************************************************
  2. *
  3. * Realmode X86 Emulator Library
  4. *
  5. * Copyright (C) 1991-2004 SciTech Software, Inc.
  6. * Copyright (C) David Mosberger-Tang
  7. * Copyright (C) 1999 Egbert Eich
  8. *
  9. * ========================================================================
  10. *
  11. * Permission to use, copy, modify, distribute, and sell this software and
  12. * its documentation for any purpose is hereby granted without fee,
  13. * provided that the above copyright notice appear in all copies and that
  14. * both that copyright notice and this permission notice appear in
  15. * supporting documentation, and that the name of the authors not be used
  16. * in advertising or publicity pertaining to distribution of the software
  17. * without specific, written prior permission. The authors makes no
  18. * representations about the suitability of this software for any purpose.
  19. * It is provided "as is" without express or implied warranty.
  20. *
  21. * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  22. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  23. * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  24. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  25. * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  26. * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  27. * PERFORMANCE OF THIS SOFTWARE.
  28. *
  29. * ========================================================================
  30. *
  31. * Language: ANSI C
  32. * Environment: Any
  33. * Developer: Kendall Bennett
  34. *
  35. * Description: This file includes subroutines which are related to
  36. * instruction decoding and accessess of immediate data via IP. etc.
  37. *
  38. ****************************************************************************/
  39. #include <common.h>
  40. #if defined(CONFIG_BIOSEMU)
  41. #include "x86emu/x86emui.h"
  42. /*----------------------------- Implementation ----------------------------*/
  43. /****************************************************************************
  44. REMARKS:
  45. Handles any pending asychronous interrupts.
  46. ****************************************************************************/
  47. static void x86emu_intr_handle(void)
  48. {
  49. u8 intno;
  50. if (M.x86.intr & INTR_SYNCH) {
  51. intno = M.x86.intno;
  52. if (_X86EMU_intrTab[intno]) {
  53. (*_X86EMU_intrTab[intno])(intno);
  54. } else {
  55. push_word((u16)M.x86.R_FLG);
  56. CLEAR_FLAG(F_IF);
  57. CLEAR_FLAG(F_TF);
  58. push_word(M.x86.R_CS);
  59. M.x86.R_CS = mem_access_word(intno * 4 + 2);
  60. push_word(M.x86.R_IP);
  61. M.x86.R_IP = mem_access_word(intno * 4);
  62. M.x86.intr = 0;
  63. }
  64. }
  65. }
  66. /****************************************************************************
  67. PARAMETERS:
  68. intrnum - Interrupt number to raise
  69. REMARKS:
  70. Raise the specified interrupt to be handled before the execution of the
  71. next instruction.
  72. ****************************************************************************/
  73. void x86emu_intr_raise(
  74. u8 intrnum)
  75. {
  76. M.x86.intno = intrnum;
  77. M.x86.intr |= INTR_SYNCH;
  78. }
  79. /****************************************************************************
  80. REMARKS:
  81. Main execution loop for the emulator. We return from here when the system
  82. halts, which is normally caused by a stack fault when we return from the
  83. original real mode call.
  84. ****************************************************************************/
  85. void X86EMU_exec(void)
  86. {
  87. u8 op1;
  88. M.x86.intr = 0;
  89. DB(x86emu_end_instr();)
  90. for (;;) {
  91. DB( if (CHECK_IP_FETCH())
  92. x86emu_check_ip_access();)
  93. /* If debugging, save the IP and CS values. */
  94. SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
  95. INC_DECODED_INST_LEN(1);
  96. if (M.x86.intr) {
  97. if (M.x86.intr & INTR_HALTED) {
  98. DB( if (M.x86.R_SP != 0) {
  99. printk("halted\n");
  100. X86EMU_trace_regs();
  101. }
  102. else {
  103. if (M.x86.debug)
  104. printk("Service completed successfully\n");
  105. })
  106. return;
  107. }
  108. if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) ||
  109. !ACCESS_FLAG(F_IF)) {
  110. x86emu_intr_handle();
  111. }
  112. }
  113. op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
  114. (*x86emu_optab[op1])(op1);
  115. if (M.x86.debug & DEBUG_EXIT) {
  116. M.x86.debug &= ~DEBUG_EXIT;
  117. return;
  118. }
  119. }
  120. }
  121. /****************************************************************************
  122. REMARKS:
  123. Halts the system by setting the halted system flag.
  124. ****************************************************************************/
  125. void X86EMU_halt_sys(void)
  126. {
  127. M.x86.intr |= INTR_HALTED;
  128. }
  129. /****************************************************************************
  130. PARAMETERS:
  131. mod - Mod value from decoded byte
  132. regh - Reg h value from decoded byte
  133. regl - Reg l value from decoded byte
  134. REMARKS:
  135. Raise the specified interrupt to be handled before the execution of the
  136. next instruction.
  137. NOTE: Do not inline this function, as (*sys_rdb) is already inline!
  138. ****************************************************************************/
  139. void fetch_decode_modrm(
  140. int *mod,
  141. int *regh,
  142. int *regl)
  143. {
  144. int fetched;
  145. DB( if (CHECK_IP_FETCH())
  146. x86emu_check_ip_access();)
  147. fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
  148. INC_DECODED_INST_LEN(1);
  149. *mod = (fetched >> 6) & 0x03;
  150. *regh = (fetched >> 3) & 0x07;
  151. *regl = (fetched >> 0) & 0x07;
  152. }
  153. /****************************************************************************
  154. RETURNS:
  155. Immediate byte value read from instruction queue
  156. REMARKS:
  157. This function returns the immediate byte from the instruction queue, and
  158. moves the instruction pointer to the next value.
  159. NOTE: Do not inline this function, as (*sys_rdb) is already inline!
  160. ****************************************************************************/
  161. u8 fetch_byte_imm(void)
  162. {
  163. u8 fetched;
  164. DB( if (CHECK_IP_FETCH())
  165. x86emu_check_ip_access();)
  166. fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
  167. INC_DECODED_INST_LEN(1);
  168. return fetched;
  169. }
  170. /****************************************************************************
  171. RETURNS:
  172. Immediate word value read from instruction queue
  173. REMARKS:
  174. This function returns the immediate byte from the instruction queue, and
  175. moves the instruction pointer to the next value.
  176. NOTE: Do not inline this function, as (*sys_rdw) is already inline!
  177. ****************************************************************************/
  178. u16 fetch_word_imm(void)
  179. {
  180. u16 fetched;
  181. DB( if (CHECK_IP_FETCH())
  182. x86emu_check_ip_access();)
  183. fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
  184. M.x86.R_IP += 2;
  185. INC_DECODED_INST_LEN(2);
  186. return fetched;
  187. }
  188. /****************************************************************************
  189. RETURNS:
  190. Immediate lone value read from instruction queue
  191. REMARKS:
  192. This function returns the immediate byte from the instruction queue, and
  193. moves the instruction pointer to the next value.
  194. NOTE: Do not inline this function, as (*sys_rdw) is already inline!
  195. ****************************************************************************/
  196. u32 fetch_long_imm(void)
  197. {
  198. u32 fetched;
  199. DB( if (CHECK_IP_FETCH())
  200. x86emu_check_ip_access();)
  201. fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
  202. M.x86.R_IP += 4;
  203. INC_DECODED_INST_LEN(4);
  204. return fetched;
  205. }
  206. /****************************************************************************
  207. RETURNS:
  208. Value of the default data segment
  209. REMARKS:
  210. Inline function that returns the default data segment for the current
  211. instruction.
  212. On the x86 processor, the default segment is not always DS if there is
  213. no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
  214. addresses relative to SS (ie: on the stack). So, at the minimum, all
  215. decodings of addressing modes would have to set/clear a bit describing
  216. whether the access is relative to DS or SS. That is the function of the
  217. cpu-state-varible M.x86.mode. There are several potential states:
  218. repe prefix seen (handled elsewhere)
  219. repne prefix seen (ditto)
  220. cs segment override
  221. ds segment override
  222. es segment override
  223. fs segment override
  224. gs segment override
  225. ss segment override
  226. ds/ss select (in absense of override)
  227. Each of the above 7 items are handled with a bit in the mode field.
  228. ****************************************************************************/
  229. _INLINE u32 get_data_segment(void)
  230. {
  231. #define GET_SEGMENT(segment)
  232. switch (M.x86.mode & SYSMODE_SEGMASK) {
  233. case 0: /* default case: use ds register */
  234. case SYSMODE_SEGOVR_DS:
  235. case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
  236. return M.x86.R_DS;
  237. case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */
  238. return M.x86.R_SS;
  239. case SYSMODE_SEGOVR_CS:
  240. case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
  241. return M.x86.R_CS;
  242. case SYSMODE_SEGOVR_ES:
  243. case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
  244. return M.x86.R_ES;
  245. case SYSMODE_SEGOVR_FS:
  246. case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
  247. return M.x86.R_FS;
  248. case SYSMODE_SEGOVR_GS:
  249. case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
  250. return M.x86.R_GS;
  251. case SYSMODE_SEGOVR_SS:
  252. case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
  253. return M.x86.R_SS;
  254. default:
  255. #ifdef DEBUG
  256. printk("error: should not happen: multiple overrides.\n");
  257. #endif
  258. HALT_SYS();
  259. return 0;
  260. }
  261. }
  262. /****************************************************************************
  263. PARAMETERS:
  264. offset - Offset to load data from
  265. RETURNS:
  266. Byte value read from the absolute memory location.
  267. NOTE: Do not inline this function as (*sys_rdX) is already inline!
  268. ****************************************************************************/
  269. u8 fetch_data_byte(
  270. uint offset)
  271. {
  272. #ifdef DEBUG
  273. if (CHECK_DATA_ACCESS())
  274. x86emu_check_data_access((u16)get_data_segment(), offset);
  275. #endif
  276. return (*sys_rdb)((get_data_segment() << 4) + offset);
  277. }
  278. /****************************************************************************
  279. PARAMETERS:
  280. offset - Offset to load data from
  281. RETURNS:
  282. Word value read from the absolute memory location.
  283. NOTE: Do not inline this function as (*sys_rdX) is already inline!
  284. ****************************************************************************/
  285. u16 fetch_data_word(
  286. uint offset)
  287. {
  288. #ifdef DEBUG
  289. if (CHECK_DATA_ACCESS())
  290. x86emu_check_data_access((u16)get_data_segment(), offset);
  291. #endif
  292. return (*sys_rdw)((get_data_segment() << 4) + offset);
  293. }
  294. /****************************************************************************
  295. PARAMETERS:
  296. offset - Offset to load data from
  297. RETURNS:
  298. Long value read from the absolute memory location.
  299. NOTE: Do not inline this function as (*sys_rdX) is already inline!
  300. ****************************************************************************/
  301. u32 fetch_data_long(
  302. uint offset)
  303. {
  304. #ifdef DEBUG
  305. if (CHECK_DATA_ACCESS())
  306. x86emu_check_data_access((u16)get_data_segment(), offset);
  307. #endif
  308. return (*sys_rdl)((get_data_segment() << 4) + offset);
  309. }
  310. /****************************************************************************
  311. PARAMETERS:
  312. segment - Segment to load data from
  313. offset - Offset to load data from
  314. RETURNS:
  315. Byte value read from the absolute memory location.
  316. NOTE: Do not inline this function as (*sys_rdX) is already inline!
  317. ****************************************************************************/
  318. u8 fetch_data_byte_abs(
  319. uint segment,
  320. uint offset)
  321. {
  322. #ifdef DEBUG
  323. if (CHECK_DATA_ACCESS())
  324. x86emu_check_data_access(segment, offset);
  325. #endif
  326. return (*sys_rdb)(((u32)segment << 4) + offset);
  327. }
  328. /****************************************************************************
  329. PARAMETERS:
  330. segment - Segment to load data from
  331. offset - Offset to load data from
  332. RETURNS:
  333. Word value read from the absolute memory location.
  334. NOTE: Do not inline this function as (*sys_rdX) is already inline!
  335. ****************************************************************************/
  336. u16 fetch_data_word_abs(
  337. uint segment,
  338. uint offset)
  339. {
  340. #ifdef DEBUG
  341. if (CHECK_DATA_ACCESS())
  342. x86emu_check_data_access(segment, offset);
  343. #endif
  344. return (*sys_rdw)(((u32)segment << 4) + offset);
  345. }
  346. /****************************************************************************
  347. PARAMETERS:
  348. segment - Segment to load data from
  349. offset - Offset to load data from
  350. RETURNS:
  351. Long value read from the absolute memory location.
  352. NOTE: Do not inline this function as (*sys_rdX) is already inline!
  353. ****************************************************************************/
  354. u32 fetch_data_long_abs(
  355. uint segment,
  356. uint offset)
  357. {
  358. #ifdef DEBUG
  359. if (CHECK_DATA_ACCESS())
  360. x86emu_check_data_access(segment, offset);
  361. #endif
  362. return (*sys_rdl)(((u32)segment << 4) + offset);
  363. }
  364. /****************************************************************************
  365. PARAMETERS:
  366. offset - Offset to store data at
  367. val - Value to store
  368. REMARKS:
  369. Writes a word value to an segmented memory location. The segment used is
  370. the current 'default' segment, which may have been overridden.
  371. NOTE: Do not inline this function as (*sys_wrX) is already inline!
  372. ****************************************************************************/
  373. void store_data_byte(
  374. uint offset,
  375. u8 val)
  376. {
  377. #ifdef DEBUG
  378. if (CHECK_DATA_ACCESS())
  379. x86emu_check_data_access((u16)get_data_segment(), offset);
  380. #endif
  381. (*sys_wrb)((get_data_segment() << 4) + offset, val);
  382. }
  383. /****************************************************************************
  384. PARAMETERS:
  385. offset - Offset to store data at
  386. val - Value to store
  387. REMARKS:
  388. Writes a word value to an segmented memory location. The segment used is
  389. the current 'default' segment, which may have been overridden.
  390. NOTE: Do not inline this function as (*sys_wrX) is already inline!
  391. ****************************************************************************/
  392. void store_data_word(
  393. uint offset,
  394. u16 val)
  395. {
  396. #ifdef DEBUG
  397. if (CHECK_DATA_ACCESS())
  398. x86emu_check_data_access((u16)get_data_segment(), offset);
  399. #endif
  400. (*sys_wrw)((get_data_segment() << 4) + offset, val);
  401. }
  402. /****************************************************************************
  403. PARAMETERS:
  404. offset - Offset to store data at
  405. val - Value to store
  406. REMARKS:
  407. Writes a long value to an segmented memory location. The segment used is
  408. the current 'default' segment, which may have been overridden.
  409. NOTE: Do not inline this function as (*sys_wrX) is already inline!
  410. ****************************************************************************/
  411. void store_data_long(
  412. uint offset,
  413. u32 val)
  414. {
  415. #ifdef DEBUG
  416. if (CHECK_DATA_ACCESS())
  417. x86emu_check_data_access((u16)get_data_segment(), offset);
  418. #endif
  419. (*sys_wrl)((get_data_segment() << 4) + offset, val);
  420. }
  421. /****************************************************************************
  422. PARAMETERS:
  423. segment - Segment to store data at
  424. offset - Offset to store data at
  425. val - Value to store
  426. REMARKS:
  427. Writes a byte value to an absolute memory location.
  428. NOTE: Do not inline this function as (*sys_wrX) is already inline!
  429. ****************************************************************************/
  430. void store_data_byte_abs(
  431. uint segment,
  432. uint offset,
  433. u8 val)
  434. {
  435. #ifdef DEBUG
  436. if (CHECK_DATA_ACCESS())
  437. x86emu_check_data_access(segment, offset);
  438. #endif
  439. (*sys_wrb)(((u32)segment << 4) + offset, val);
  440. }
  441. /****************************************************************************
  442. PARAMETERS:
  443. segment - Segment to store data at
  444. offset - Offset to store data at
  445. val - Value to store
  446. REMARKS:
  447. Writes a word value to an absolute memory location.
  448. NOTE: Do not inline this function as (*sys_wrX) is already inline!
  449. ****************************************************************************/
  450. void store_data_word_abs(
  451. uint segment,
  452. uint offset,
  453. u16 val)
  454. {
  455. #ifdef DEBUG
  456. if (CHECK_DATA_ACCESS())
  457. x86emu_check_data_access(segment, offset);
  458. #endif
  459. (*sys_wrw)(((u32)segment << 4) + offset, val);
  460. }
  461. /****************************************************************************
  462. PARAMETERS:
  463. segment - Segment to store data at
  464. offset - Offset to store data at
  465. val - Value to store
  466. REMARKS:
  467. Writes a long value to an absolute memory location.
  468. NOTE: Do not inline this function as (*sys_wrX) is already inline!
  469. ****************************************************************************/
  470. void store_data_long_abs(
  471. uint segment,
  472. uint offset,
  473. u32 val)
  474. {
  475. #ifdef DEBUG
  476. if (CHECK_DATA_ACCESS())
  477. x86emu_check_data_access(segment, offset);
  478. #endif
  479. (*sys_wrl)(((u32)segment << 4) + offset, val);
  480. }
  481. /****************************************************************************
  482. PARAMETERS:
  483. reg - Register to decode
  484. RETURNS:
  485. Pointer to the appropriate register
  486. REMARKS:
  487. Return a pointer to the register given by the R/RM field of the
  488. modrm byte, for byte operands. Also enables the decoding of instructions.
  489. ****************************************************************************/
  490. u8* decode_rm_byte_register(
  491. int reg)
  492. {
  493. switch (reg) {
  494. case 0:
  495. DECODE_PRINTF("AL");
  496. return &M.x86.R_AL;
  497. case 1:
  498. DECODE_PRINTF("CL");
  499. return &M.x86.R_CL;
  500. case 2:
  501. DECODE_PRINTF("DL");
  502. return &M.x86.R_DL;
  503. case 3:
  504. DECODE_PRINTF("BL");
  505. return &M.x86.R_BL;
  506. case 4:
  507. DECODE_PRINTF("AH");
  508. return &M.x86.R_AH;
  509. case 5:
  510. DECODE_PRINTF("CH");
  511. return &M.x86.R_CH;
  512. case 6:
  513. DECODE_PRINTF("DH");
  514. return &M.x86.R_DH;
  515. case 7:
  516. DECODE_PRINTF("BH");
  517. return &M.x86.R_BH;
  518. }
  519. HALT_SYS();
  520. return NULL; /* NOT REACHED OR REACHED ON ERROR */
  521. }
  522. /****************************************************************************
  523. PARAMETERS:
  524. reg - Register to decode
  525. RETURNS:
  526. Pointer to the appropriate register
  527. REMARKS:
  528. Return a pointer to the register given by the R/RM field of the
  529. modrm byte, for word operands. Also enables the decoding of instructions.
  530. ****************************************************************************/
  531. u16* decode_rm_word_register(
  532. int reg)
  533. {
  534. switch (reg) {
  535. case 0:
  536. DECODE_PRINTF("AX");
  537. return &M.x86.R_AX;
  538. case 1:
  539. DECODE_PRINTF("CX");
  540. return &M.x86.R_CX;
  541. case 2:
  542. DECODE_PRINTF("DX");
  543. return &M.x86.R_DX;
  544. case 3:
  545. DECODE_PRINTF("BX");
  546. return &M.x86.R_BX;
  547. case 4:
  548. DECODE_PRINTF("SP");
  549. return &M.x86.R_SP;
  550. case 5:
  551. DECODE_PRINTF("BP");
  552. return &M.x86.R_BP;
  553. case 6:
  554. DECODE_PRINTF("SI");
  555. return &M.x86.R_SI;
  556. case 7:
  557. DECODE_PRINTF("DI");
  558. return &M.x86.R_DI;
  559. }
  560. HALT_SYS();
  561. return NULL; /* NOTREACHED OR REACHED ON ERROR */
  562. }
  563. /****************************************************************************
  564. PARAMETERS:
  565. reg - Register to decode
  566. RETURNS:
  567. Pointer to the appropriate register
  568. REMARKS:
  569. Return a pointer to the register given by the R/RM field of the
  570. modrm byte, for dword operands. Also enables the decoding of instructions.
  571. ****************************************************************************/
  572. u32* decode_rm_long_register(
  573. int reg)
  574. {
  575. switch (reg) {
  576. case 0:
  577. DECODE_PRINTF("EAX");
  578. return &M.x86.R_EAX;
  579. case 1:
  580. DECODE_PRINTF("ECX");
  581. return &M.x86.R_ECX;
  582. case 2:
  583. DECODE_PRINTF("EDX");
  584. return &M.x86.R_EDX;
  585. case 3:
  586. DECODE_PRINTF("EBX");
  587. return &M.x86.R_EBX;
  588. case 4:
  589. DECODE_PRINTF("ESP");
  590. return &M.x86.R_ESP;
  591. case 5:
  592. DECODE_PRINTF("EBP");
  593. return &M.x86.R_EBP;
  594. case 6:
  595. DECODE_PRINTF("ESI");
  596. return &M.x86.R_ESI;
  597. case 7:
  598. DECODE_PRINTF("EDI");
  599. return &M.x86.R_EDI;
  600. }
  601. HALT_SYS();
  602. return NULL; /* NOTREACHED OR REACHED ON ERROR */
  603. }
  604. /****************************************************************************
  605. PARAMETERS:
  606. reg - Register to decode
  607. RETURNS:
  608. Pointer to the appropriate register
  609. REMARKS:
  610. Return a pointer to the register given by the R/RM field of the
  611. modrm byte, for word operands, modified from above for the weirdo
  612. special case of segreg operands. Also enables the decoding of instructions.
  613. ****************************************************************************/
  614. u16* decode_rm_seg_register(
  615. int reg)
  616. {
  617. switch (reg) {
  618. case 0:
  619. DECODE_PRINTF("ES");
  620. return &M.x86.R_ES;
  621. case 1:
  622. DECODE_PRINTF("CS");
  623. return &M.x86.R_CS;
  624. case 2:
  625. DECODE_PRINTF("SS");
  626. return &M.x86.R_SS;
  627. case 3:
  628. DECODE_PRINTF("DS");
  629. return &M.x86.R_DS;
  630. case 4:
  631. DECODE_PRINTF("FS");
  632. return &M.x86.R_FS;
  633. case 5:
  634. DECODE_PRINTF("GS");
  635. return &M.x86.R_GS;
  636. case 6:
  637. case 7:
  638. DECODE_PRINTF("ILLEGAL SEGREG");
  639. break;
  640. }
  641. HALT_SYS();
  642. return NULL; /* NOT REACHED OR REACHED ON ERROR */
  643. }
  644. /****************************************************************************
  645. PARAMETERS:
  646. scale - scale value of SIB byte
  647. index - index value of SIB byte
  648. RETURNS:
  649. Value of scale * index
  650. REMARKS:
  651. Decodes scale/index of SIB byte and returns relevant offset part of
  652. effective address.
  653. ****************************************************************************/
  654. unsigned decode_sib_si(
  655. int scale,
  656. int index)
  657. {
  658. scale = 1 << scale;
  659. if (scale > 1) {
  660. DECODE_PRINTF2("[%d*", scale);
  661. } else {
  662. DECODE_PRINTF("[");
  663. }
  664. switch (index) {
  665. case 0:
  666. DECODE_PRINTF("EAX]");
  667. return M.x86.R_EAX * index;
  668. case 1:
  669. DECODE_PRINTF("ECX]");
  670. return M.x86.R_ECX * index;
  671. case 2:
  672. DECODE_PRINTF("EDX]");
  673. return M.x86.R_EDX * index;
  674. case 3:
  675. DECODE_PRINTF("EBX]");
  676. return M.x86.R_EBX * index;
  677. case 4:
  678. DECODE_PRINTF("0]");
  679. return 0;
  680. case 5:
  681. DECODE_PRINTF("EBP]");
  682. return M.x86.R_EBP * index;
  683. case 6:
  684. DECODE_PRINTF("ESI]");
  685. return M.x86.R_ESI * index;
  686. case 7:
  687. DECODE_PRINTF("EDI]");
  688. return M.x86.R_EDI * index;
  689. }
  690. HALT_SYS();
  691. return 0; /* NOT REACHED OR REACHED ON ERROR */
  692. }
  693. /****************************************************************************
  694. PARAMETERS:
  695. mod - MOD value of preceding ModR/M byte
  696. RETURNS:
  697. Offset in memory for the address decoding
  698. REMARKS:
  699. Decodes SIB addressing byte and returns calculated effective address.
  700. ****************************************************************************/
  701. unsigned decode_sib_address(
  702. int mod)
  703. {
  704. int sib = fetch_byte_imm();
  705. int ss = (sib >> 6) & 0x03;
  706. int index = (sib >> 3) & 0x07;
  707. int base = sib & 0x07;
  708. int offset = 0;
  709. int displacement;
  710. switch (base) {
  711. case 0:
  712. DECODE_PRINTF("[EAX]");
  713. offset = M.x86.R_EAX;
  714. break;
  715. case 1:
  716. DECODE_PRINTF("[ECX]");
  717. offset = M.x86.R_ECX;
  718. break;
  719. case 2:
  720. DECODE_PRINTF("[EDX]");
  721. offset = M.x86.R_EDX;
  722. break;
  723. case 3:
  724. DECODE_PRINTF("[EBX]");
  725. offset = M.x86.R_EBX;
  726. break;
  727. case 4:
  728. DECODE_PRINTF("[ESP]");
  729. offset = M.x86.R_ESP;
  730. break;
  731. case 5:
  732. switch (mod) {
  733. case 0:
  734. displacement = (s32)fetch_long_imm();
  735. DECODE_PRINTF2("[%d]", displacement);
  736. offset = displacement;
  737. break;
  738. case 1:
  739. displacement = (s8)fetch_byte_imm();
  740. DECODE_PRINTF2("[%d][EBP]", displacement);
  741. offset = M.x86.R_EBP + displacement;
  742. break;
  743. case 2:
  744. displacement = (s32)fetch_long_imm();
  745. DECODE_PRINTF2("[%d][EBP]", displacement);
  746. offset = M.x86.R_EBP + displacement;
  747. break;
  748. default:
  749. HALT_SYS();
  750. }
  751. DECODE_PRINTF("[EAX]");
  752. offset = M.x86.R_EAX;
  753. break;
  754. case 6:
  755. DECODE_PRINTF("[ESI]");
  756. offset = M.x86.R_ESI;
  757. break;
  758. case 7:
  759. DECODE_PRINTF("[EDI]");
  760. offset = M.x86.R_EDI;
  761. break;
  762. default:
  763. HALT_SYS();
  764. }
  765. offset += decode_sib_si(ss, index);
  766. return offset;
  767. }
  768. /****************************************************************************
  769. PARAMETERS:
  770. rm - RM value to decode
  771. RETURNS:
  772. Offset in memory for the address decoding
  773. REMARKS:
  774. Return the offset given by mod=00 addressing. Also enables the
  775. decoding of instructions.
  776. NOTE: The code which specifies the corresponding segment (ds vs ss)
  777. below in the case of [BP+..]. The assumption here is that at the
  778. point that this subroutine is called, the bit corresponding to
  779. SYSMODE_SEG_DS_SS will be zero. After every instruction
  780. except the segment override instructions, this bit (as well
  781. as any bits indicating segment overrides) will be clear. So
  782. if a SS access is needed, set this bit. Otherwise, DS access
  783. occurs (unless any of the segment override bits are set).
  784. ****************************************************************************/
  785. unsigned decode_rm00_address(
  786. int rm)
  787. {
  788. unsigned offset;
  789. if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
  790. /* 32-bit addressing */
  791. switch (rm) {
  792. case 0:
  793. DECODE_PRINTF("[EAX]");
  794. return M.x86.R_EAX;
  795. case 1:
  796. DECODE_PRINTF("[ECX]");
  797. return M.x86.R_ECX;
  798. case 2:
  799. DECODE_PRINTF("[EDX]");
  800. return M.x86.R_EDX;
  801. case 3:
  802. DECODE_PRINTF("[EBX]");
  803. return M.x86.R_EBX;
  804. case 4:
  805. return decode_sib_address(0);
  806. case 5:
  807. offset = fetch_long_imm();
  808. DECODE_PRINTF2("[%08x]", offset);
  809. return offset;
  810. case 6:
  811. DECODE_PRINTF("[ESI]");
  812. return M.x86.R_ESI;
  813. case 7:
  814. DECODE_PRINTF("[EDI]");
  815. return M.x86.R_EDI;
  816. }
  817. } else {
  818. /* 16-bit addressing */
  819. switch (rm) {
  820. case 0:
  821. DECODE_PRINTF("[BX+SI]");
  822. return (M.x86.R_BX + M.x86.R_SI) & 0xffff;
  823. case 1:
  824. DECODE_PRINTF("[BX+DI]");
  825. return (M.x86.R_BX + M.x86.R_DI) & 0xffff;
  826. case 2:
  827. DECODE_PRINTF("[BP+SI]");
  828. M.x86.mode |= SYSMODE_SEG_DS_SS;
  829. return (M.x86.R_BP + M.x86.R_SI) & 0xffff;
  830. case 3:
  831. DECODE_PRINTF("[BP+DI]");
  832. M.x86.mode |= SYSMODE_SEG_DS_SS;
  833. return (M.x86.R_BP + M.x86.R_DI) & 0xffff;
  834. case 4:
  835. DECODE_PRINTF("[SI]");
  836. return M.x86.R_SI;
  837. case 5:
  838. DECODE_PRINTF("[DI]");
  839. return M.x86.R_DI;
  840. case 6:
  841. offset = fetch_word_imm();
  842. DECODE_PRINTF2("[%04x]", offset);
  843. return offset;
  844. case 7:
  845. DECODE_PRINTF("[BX]");
  846. return M.x86.R_BX;
  847. }
  848. }
  849. HALT_SYS();
  850. return 0;
  851. }
  852. /****************************************************************************
  853. PARAMETERS:
  854. rm - RM value to decode
  855. RETURNS:
  856. Offset in memory for the address decoding
  857. REMARKS:
  858. Return the offset given by mod=01 addressing. Also enables the
  859. decoding of instructions.
  860. ****************************************************************************/
  861. unsigned decode_rm01_address(
  862. int rm)
  863. {
  864. int displacement;
  865. if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
  866. /* 32-bit addressing */
  867. if (rm != 4)
  868. displacement = (s8)fetch_byte_imm();
  869. else
  870. displacement = 0;
  871. switch (rm) {
  872. case 0:
  873. DECODE_PRINTF2("%d[EAX]", displacement);
  874. return M.x86.R_EAX + displacement;
  875. case 1:
  876. DECODE_PRINTF2("%d[ECX]", displacement);
  877. return M.x86.R_ECX + displacement;
  878. case 2:
  879. DECODE_PRINTF2("%d[EDX]", displacement);
  880. return M.x86.R_EDX + displacement;
  881. case 3:
  882. DECODE_PRINTF2("%d[EBX]", displacement);
  883. return M.x86.R_EBX + displacement;
  884. case 4: {
  885. int offset = decode_sib_address(1);
  886. displacement = (s8)fetch_byte_imm();
  887. DECODE_PRINTF2("[%d]", displacement);
  888. return offset + displacement;
  889. }
  890. case 5:
  891. DECODE_PRINTF2("%d[EBP]", displacement);
  892. return M.x86.R_EBP + displacement;
  893. case 6:
  894. DECODE_PRINTF2("%d[ESI]", displacement);
  895. return M.x86.R_ESI + displacement;
  896. case 7:
  897. DECODE_PRINTF2("%d[EDI]", displacement);
  898. return M.x86.R_EDI + displacement;
  899. }
  900. } else {
  901. /* 16-bit addressing */
  902. displacement = (s8)fetch_byte_imm();
  903. switch (rm) {
  904. case 0:
  905. DECODE_PRINTF2("%d[BX+SI]", displacement);
  906. return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
  907. case 1:
  908. DECODE_PRINTF2("%d[BX+DI]", displacement);
  909. return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
  910. case 2:
  911. DECODE_PRINTF2("%d[BP+SI]", displacement);
  912. M.x86.mode |= SYSMODE_SEG_DS_SS;
  913. return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
  914. case 3:
  915. DECODE_PRINTF2("%d[BP+DI]", displacement);
  916. M.x86.mode |= SYSMODE_SEG_DS_SS;
  917. return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
  918. case 4:
  919. DECODE_PRINTF2("%d[SI]", displacement);
  920. return (M.x86.R_SI + displacement) & 0xffff;
  921. case 5:
  922. DECODE_PRINTF2("%d[DI]", displacement);
  923. return (M.x86.R_DI + displacement) & 0xffff;
  924. case 6:
  925. DECODE_PRINTF2("%d[BP]", displacement);
  926. M.x86.mode |= SYSMODE_SEG_DS_SS;
  927. return (M.x86.R_BP + displacement) & 0xffff;
  928. case 7:
  929. DECODE_PRINTF2("%d[BX]", displacement);
  930. return (M.x86.R_BX + displacement) & 0xffff;
  931. }
  932. }
  933. HALT_SYS();
  934. return 0; /* SHOULD NOT HAPPEN */
  935. }
  936. /****************************************************************************
  937. PARAMETERS:
  938. rm - RM value to decode
  939. RETURNS:
  940. Offset in memory for the address decoding
  941. REMARKS:
  942. Return the offset given by mod=10 addressing. Also enables the
  943. decoding of instructions.
  944. ****************************************************************************/
  945. unsigned decode_rm10_address(
  946. int rm)
  947. {
  948. if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
  949. int displacement;
  950. /* 32-bit addressing */
  951. if (rm != 4)
  952. displacement = (s32)fetch_long_imm();
  953. else
  954. displacement = 0;
  955. switch (rm) {
  956. case 0:
  957. DECODE_PRINTF2("%d[EAX]", displacement);
  958. return M.x86.R_EAX + displacement;
  959. case 1:
  960. DECODE_PRINTF2("%d[ECX]", displacement);
  961. return M.x86.R_ECX + displacement;
  962. case 2:
  963. DECODE_PRINTF2("%d[EDX]", displacement);
  964. return M.x86.R_EDX + displacement;
  965. case 3:
  966. DECODE_PRINTF2("%d[EBX]", displacement);
  967. return M.x86.R_EBX + displacement;
  968. case 4: {
  969. int offset = decode_sib_address(2);
  970. displacement = (s32)fetch_long_imm();
  971. DECODE_PRINTF2("[%d]", displacement);
  972. return offset + displacement;
  973. }
  974. case 5:
  975. DECODE_PRINTF2("%d[EBP]", displacement);
  976. return M.x86.R_EBP + displacement;
  977. case 6:
  978. DECODE_PRINTF2("%d[ESI]", displacement);
  979. return M.x86.R_ESI + displacement;
  980. case 7:
  981. DECODE_PRINTF2("%d[EDI]", displacement);
  982. return M.x86.R_EDI + displacement;
  983. }
  984. } else {
  985. int displacement = (s16)fetch_word_imm();
  986. /* 16-bit addressing */
  987. switch (rm) {
  988. case 0:
  989. DECODE_PRINTF2("%d[BX+SI]", displacement);
  990. return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
  991. case 1:
  992. DECODE_PRINTF2("%d[BX+DI]", displacement);
  993. return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
  994. case 2:
  995. DECODE_PRINTF2("%d[BP+SI]", displacement);
  996. M.x86.mode |= SYSMODE_SEG_DS_SS;
  997. return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
  998. case 3:
  999. DECODE_PRINTF2("%d[BP+DI]", displacement);
  1000. M.x86.mode |= SYSMODE_SEG_DS_SS;
  1001. return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
  1002. case 4:
  1003. DECODE_PRINTF2("%d[SI]", displacement);
  1004. return (M.x86.R_SI + displacement) & 0xffff;
  1005. case 5:
  1006. DECODE_PRINTF2("%d[DI]", displacement);
  1007. return (M.x86.R_DI + displacement) & 0xffff;
  1008. case 6:
  1009. DECODE_PRINTF2("%d[BP]", displacement);
  1010. M.x86.mode |= SYSMODE_SEG_DS_SS;
  1011. return (M.x86.R_BP + displacement) & 0xffff;
  1012. case 7:
  1013. DECODE_PRINTF2("%d[BX]", displacement);
  1014. return (M.x86.R_BX + displacement) & 0xffff;
  1015. }
  1016. }
  1017. HALT_SYS();
  1018. return 0; /* SHOULD NOT HAPPEN */
  1019. }
  1020. /****************************************************************************
  1021. PARAMETERS:
  1022. mod - modifier
  1023. rm - RM value to decode
  1024. RETURNS:
  1025. Offset in memory for the address decoding, multiplexing calls to
  1026. the decode_rmXX_address functions
  1027. REMARKS:
  1028. Return the offset given by "mod" addressing.
  1029. ****************************************************************************/
  1030. unsigned decode_rmXX_address(int mod, int rm)
  1031. {
  1032. if(mod == 0)
  1033. return decode_rm00_address(rm);
  1034. if(mod == 1)
  1035. return decode_rm01_address(rm);
  1036. return decode_rm10_address(rm);
  1037. }
  1038. #endif