decode.c 31 KB

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