decode.c 34 KB

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