Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

608 lines
16 KiB

  1. title "Operand Decoding"
  2. ;++
  3. ;
  4. ;Copyright (c) 1991 Microsoft Corporation
  5. ;
  6. ;Module Name:
  7. ;
  8. ; vdmoprnd.asm
  9. ;
  10. ;Abstract:
  11. ;
  12. ; This module contains support for decoding 386/486 instruction operands.
  13. ; This is used by the opcode 0f emulation.
  14. ;
  15. ;
  16. ;Author:
  17. ;
  18. ; Dave Hastings (daveh) 20-Feb-1992
  19. ;
  20. ;Notes:
  21. ;
  22. ; The only instruction which uses the operand decodeing (3/10/92) is
  23. ; LMSW. This instruction only has 16 bit operands, so only the 16 bit
  24. ; operand decode has been tested. The 32 bit decode will be tested
  25. ; (or removed?) during clean up, after code freeze.
  26. ;
  27. ;Revision History:
  28. ;
  29. ;--
  30. .386p
  31. .xlist
  32. include ks386.inc
  33. include callconv.inc ; calling convention macros
  34. include mi386.inc
  35. include vdm.inc
  36. include vdmtib.inc
  37. page ,132
  38. _PAGE SEGMENT DWORD PUBLIC 'CODE'
  39. ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING
  40. EXTRNP _Ki386GetSelectorParameters,4
  41. extrn CheckEip:proc
  42. _PAGE ENDS
  43. PAGEDATA SEGMENT DWORD PUBLIC 'DATA'
  44. ;
  45. ; This table is used to dispatch base on the mod code for 16 bit address size.
  46. ; When these locations are dispatched to,
  47. ; edi = linear address of next byte of instruction
  48. ; esi = pointer to register info
  49. ; ecx = R/M value for the instruction
  50. modtab16 dd offset FLAT:do20 ; no displacement
  51. dd offset FLAT:do40 ; 8 bit displacement
  52. dd offset FLAT:do50 ; 16 bit displacement
  53. dd offset FLAT:do60 ; Register operand
  54. ;
  55. ; This table is used to dispatch based on the RM code for 16 bit address size.
  56. ; When these locations are dispatched to,
  57. ; edi = pointer to trap frame
  58. ; esi = pointer to register info
  59. ; ebx = partial linear address of operand
  60. rmtab16 dd offset FLAT:do70 ; [bx + si]
  61. dd offset FLAT:do80 ; [bx + di]
  62. dd offset FLAT:do90 ; [bp + si]
  63. dd offset FLAT:do100 ; [bp + di]
  64. dd offset FLAT:do95 ; [si]
  65. dd offset FLAT:do85 ; [di]
  66. dd offset FLAT:do105 ; [bp]
  67. dd offset FLAT:do75 ; [bx]
  68. ;
  69. ; This table is used to dispatch base on the mod code for 32 bit address size.
  70. ; When these locations are dispatched to,
  71. ; edi = linear address of next byte of instruction
  72. ; esi = pointer to register info
  73. ; ecx = R/M value for the instruction
  74. modtab32 dd offset FLAT:do220 ; no displacement
  75. dd offset FLAT:do240 ; 8 bit displacement
  76. dd offset FLAT:do250 ; 32 bit displacement
  77. dd offset FLAT:do260 ; Register operand
  78. ;
  79. ; This table is used to pick up register offsets in the trap frame.
  80. ; N.B. This table cannot be used to find byte registers!!
  81. ;
  82. public RegTab
  83. RegTab dd TsEax
  84. dd TsEcx
  85. dd TsEdx
  86. dd TsEbx
  87. dd TsHardwareEsp
  88. dd TsEbp
  89. dd TsEsi
  90. dd TsEdi
  91. PAGEDATA ENDS
  92. _PAGE SEGMENT DWORD PUBLIC 'CODE'
  93. ASSUME DS:FLAT, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
  94. page ,132
  95. subttl "Decode Operands"
  96. ;++
  97. ;
  98. ; Routine Description:
  99. ;
  100. ; This routine decodes the operands for 386/486 instructions. It returns
  101. ; the linear address of the operand. For register operands, this is
  102. ; an address in the stack frame. The read/write flag is used for
  103. ; operand verification.
  104. ;
  105. ; Arguments:
  106. ;
  107. ; esi = address of reg info
  108. ; eax = 1 -- Read of operand
  109. ; 0 -- Write of operand
  110. ;
  111. ; Returns:
  112. ;
  113. ; eax = True -- operand ok, and reg info operand field filled in
  114. ; eax = False -- operand not ok.
  115. ; reg info eip updated
  116. ;
  117. ; Notes:
  118. ;
  119. ; This routine DOES NOT decode the reg field of the mod r/m byte of the
  120. ; opcode. This is not a problem because it will only return one operand
  121. ; address anyway. It does not decode byte registers correctly!!.
  122. ;
  123. ; check grow down ss handling
  124. public VdmDecodeOperand
  125. VdmDecodeOperand proc
  126. SegBase equ [ebp] - 04h
  127. SegLimit equ [ebp] - 08h
  128. SegFlags equ [ebp] - 0ch
  129. SelLookupResult equ [ebp] - 010h
  130. ReadWrite equ [ebp] - 014h
  131. ModRm equ [ebp] - 018h
  132. SIB equ [ebp] - 01ch
  133. push ebp
  134. mov ebp,esp
  135. sub esp,01ch
  136. push edi
  137. push ecx
  138. push ebx
  139. mov ReadWrite,eax
  140. ;
  141. ; Get the info on DS (assumed default selector)
  142. ;
  143. lea edx,SegLimit
  144. push edx
  145. lea edx,SegBase
  146. push edx
  147. lea edx,SegFlags
  148. push edx
  149. mov edi,[esi].RiTrapFrame
  150. push [edi].TsSegDs
  151. call VdmSegParams
  152. add esp,010h
  153. mov SelLookupResult,eax ; check result after override check
  154. mov edi,[esi].RiEip
  155. add edi,[esi].RiCsBase
  156. call CheckEip
  157. test al,0fh
  158. jz do200 ; Gp fault, report error
  159. movzx edx,byte ptr [edi] ; get mod r/m byte
  160. inc [esi].RiEip
  161. inc edi
  162. mov ecx,edx
  163. mov ModRm,edx
  164. and edx,MI_MODMASK
  165. shr edx,MI_MODSHIFT ; form jump table index from mod
  166. and ecx,MI_RMMASK ; form index for RM jump table
  167. test [esi].RiPrefixFlags,PREFIX_ADDR32
  168. ; 32 bit segments.
  169. jnz do210 ; 32 bit instructions have diff form
  170. jmp modtab16[edx * 4]
  171. do20:
  172. ;
  173. ; These forms have no displacement, except for the "bp" form, which
  174. ; is just a 16 bit immediate displacement
  175. ;
  176. mov ebx,0 ; assume no displacement
  177. cmp ecx,MI_RMBP
  178. jne do30 ; dispatch through jmp table
  179. call CheckEip
  180. test al,0fh
  181. jz do200 ; Gp fault, report error
  182. movzx ebx,word ptr [edi] ; get displacement
  183. inc [esi].RiEip ; update eip
  184. inc [esi].RiEip
  185. jmp do120 ; go add in seg
  186. do30: mov edi,[esi].RiTrapFrame
  187. jmp rmtab16[ecx * 4] ; go get register info.
  188. do40:
  189. ;
  190. ; These forms have an 8 bit displacement
  191. ;
  192. call CheckEip
  193. test al,0fh
  194. jz do200 ; Gp fault, report error
  195. movsx ebx,byte ptr [edi]
  196. inc [esi].RiEip
  197. mov edi,[esi].RiTrapFrame
  198. jmp rmtab16[ecx * 4]
  199. do50:
  200. ;
  201. ; These forms have an 16 bit displacement
  202. ;
  203. call CheckEip
  204. test al,0fh
  205. jz do200 ; Gp fault, report error
  206. movzx ebx,word ptr [edi]
  207. inc [esi].RiEip
  208. inc [esi].RiEip
  209. mov edi,[esi].RiTrapFrame
  210. jmp rmtab16[ecx * 4]
  211. do60:
  212. ;
  213. ; These forms are register operands
  214. ;
  215. mov ebx,RegTab[ecx * 4] ; get offset into stackframe
  216. add ebx,[esi].RiTrapFrame ; form linear address
  217. jmp do194 ; return success
  218. do70:
  219. ;
  220. ; This is the [bx + si] operand
  221. ;
  222. movzx edx,word ptr [edi].TsEsi
  223. add ebx,edx
  224. do75:
  225. ;
  226. ; This is the [bx] operand, and a fall through to finish forming [bx + si]
  227. ;
  228. movzx edx,word ptr [edi].TsEbx
  229. add ebx,edx
  230. jmp do120 ; go add seg info
  231. do80:
  232. ;
  233. ; This is the [bx + di] operand
  234. ;
  235. movzx edx,word ptr [edi].TsEbx
  236. add ebx,edx
  237. do85:
  238. ;
  239. ; This is the [di] operand, and the fall through to finish [bx + di]
  240. ;
  241. movzx edx,word ptr [edi].TsEdi
  242. add ebx,edx
  243. jmp do120 ; go add seg info
  244. do90:
  245. ;
  246. ; This is the [bp + si] operand
  247. ;
  248. movzx edx,word ptr [edi].TsEbp
  249. add ebx,edx
  250. ;
  251. ; Change default segment to be ss
  252. ;
  253. lea edx,SegLimit
  254. push edx
  255. lea edx,SegBase
  256. push edx
  257. lea edx,SegFlags
  258. push edx
  259. mov edi,[esi].RiTrapFrame
  260. push [edi].TsHardwareSegSs
  261. call VdmSegParams
  262. add esp,010h
  263. mov SelLookupResult,eax
  264. do95:
  265. ;
  266. ; This is the [si] operand, and the fall through for forming [bp + si]
  267. ;
  268. movzx edx,word ptr [edi].TsEsi
  269. add ebx,edx
  270. jmp do120 ; go add seg info
  271. do100:
  272. ;
  273. ; This is the [bp + di] operand
  274. ;
  275. movzx edx,word ptr [edi].TsEdi
  276. add ebx,edx
  277. do105:
  278. ;
  279. ; This is the [bp] operand, and the fall through for forming [bp + di]
  280. ;
  281. movzx edx,word ptr [edi].TsEbp
  282. add ebx,edx
  283. ;
  284. ; Change default segment to be SS
  285. ;
  286. lea edx,SegLimit
  287. push edx
  288. lea edx,SegBase
  289. push edx
  290. lea edx,SegFlags
  291. push edx
  292. mov edi,[esi].RiTrapFrame
  293. push [edi].TsHardwareSegSs
  294. call VdmSegParams
  295. add esp,010h
  296. mov SelLookupResult,eax
  297. do120: test [esi].RiPrefixFlags,PREFIX_SEG_ALL ; check for seg prefixes
  298. jz do190 ; no prefixes, use default.
  299. ; Note: we could use a bsr instruction here, but it has a high
  300. ; overhead relative to a test and a jump, and I expect that
  301. ; es overrides will be by far the most common
  302. mov edi,[esi].RiTrapFrame
  303. test [esi].RiPrefixFlags,PREFIX_ES
  304. jz do130
  305. movzx edx,word ptr [edi].TsSegEs
  306. jmp do180
  307. do130: test [esi].RiPrefixFlags,PREFIX_CS
  308. jz do140
  309. movzx edx,word ptr [edi].TsSegCs
  310. jmp do180
  311. do140: test [esi].RiPrefixFlags,PREFIX_SS
  312. jz do150
  313. movzx edx,word ptr [edi].TsHardwareSegSs
  314. jmp do180
  315. do150: test [esi].RiPrefixFlags,PREFIX_DS
  316. jz do160
  317. movzx edx,word ptr [edi].TsSegDs
  318. jmp do180
  319. do160: test [esi].RiPrefixFlags,PREFIX_FS
  320. jz do170
  321. movzx edx,word ptr [edi].TsSegFs
  322. jmp do180
  323. do170: ; assert that seg gs bit is set
  324. movzx edx,word ptr [edi].TsSegGs
  325. ;
  326. ; Get information on new default segment
  327. ;
  328. do180: lea ecx,SegLimit
  329. push ecx
  330. lea ecx,SegBase
  331. push ecx
  332. lea ecx,SegFlags
  333. push ecx
  334. push edx
  335. call VdmSegParams
  336. add esp,010h
  337. mov SelLookupResult,eax
  338. test byte ptr SelLookupResult,0fh
  339. jz do200 ; return error
  340. cmp dword ptr ReadWrite,0
  341. jnz do190 ; we can read all sels
  342. test dword ptr SegFlags,SEL_TYPE_WRITE
  343. jz do200 ; return error.
  344. cmp ebx,SegLimit
  345. jae do200 ; gp fault
  346. do190: add ebx,SegBase
  347. do194: mov [esi].RiOperand,ebx ; update op pointer
  348. mov eax,1
  349. do195: pop ebx
  350. pop ecx
  351. pop edi
  352. mov esp,ebp
  353. pop ebp
  354. ret
  355. do200: xor eax,eax
  356. jmp do195
  357. ;
  358. ; Get the SIB if there is one, and save it for later.
  359. ;
  360. do210: cmp ecx,MI_RMSIB
  361. jne do215 ; no Sib, dispatch for displacement
  362. call CheckEip
  363. test al,0fh
  364. jz do200 ; report GP fault
  365. movzx eax,byte ptr [edi]
  366. mov Sib,eax
  367. inc edi
  368. inc [esi].RiEip
  369. do215: jmp modtab32[edx * 4]
  370. do220:
  371. ;
  372. ; These forms have no displacement, except for the "bp" form, which
  373. ; is just a 32 bit immediate displacement
  374. ;
  375. mov ebx,0 ; assume no displacement
  376. cmp ecx,MI_RMBP
  377. jne do270
  378. call CheckEip
  379. test al,0fh
  380. jz do200 ; Gp fault, report error
  381. mov ebx,[edi] ; get displacement
  382. add [esi].RiEip,4 ; update eip
  383. jmp do120 ; go add in seg
  384. do240:
  385. ;
  386. ; These forms have an 8 bit displacement
  387. ;
  388. call CheckEip
  389. test al,0fh
  390. jz do200 ; Gp fault, report error
  391. movsx ebx,byte ptr [edi]
  392. inc [esi].RiEip
  393. jmp do270
  394. do250:
  395. ;
  396. ; These forms have an 32 bit displacement
  397. ;
  398. call CheckEip
  399. test al,0fh
  400. jz do200 ; Gp fault, report error
  401. mov ebx, [edi]
  402. add [esi].RiEip,4
  403. jmp do270
  404. do260:
  405. ;
  406. ; These forms are register operands
  407. ;
  408. mov ebx,RegTab[ecx * 4] ; get offset into stackframe
  409. add ebx,[esi].RiTrapFrame ; form linear address
  410. jmp do195 ; return success
  411. do270:
  412. ;
  413. ; Add in the RM portion of the effective address.
  414. ;
  415. cmp ecx,MI_RMSIB
  416. je do290 ; handle SIB specially
  417. mov edi,[esi].RiTrapFrame
  418. mov edx,RegTab[ecx * 4] ; get offset of register
  419. add ebx,[edx+edi] ; add register to displacement
  420. cmp ecx,MI_RMBP ; bp is base?
  421. je do280 ; set up ss as default
  422. jmp do120 ; get segment info.
  423. do280:
  424. ;
  425. ; Change default segment to be SS
  426. ;
  427. lea edx,SegLimit
  428. push edx
  429. lea edx,SegBase
  430. push edx
  431. lea edx,SegFlags
  432. push edx
  433. mov edi,[esi].RiTrapFrame
  434. push [edi].TsHardwareSegSs
  435. call VdmSegParams
  436. add esp,010h
  437. mov SelLookupResult,eax
  438. jmp do120
  439. do290:
  440. ;
  441. ; Decode the Sib
  442. ;
  443. mov edx,Sib
  444. mov edi,[esi].RiTrapFrame
  445. and edx,MI_SIB_BASEMASK ; isolate base
  446. cmp edx,MI_SIB_BASENONE ; no base
  447. je do300
  448. mov eax,RegTab[edx * 4]
  449. add ebx,[edi+eax] ; get register contents, and add
  450. do300: mov edx,Sib
  451. and ecx,MI_SIB_INDEXMASK
  452. shr ecx,MI_SIB_INDEXSHIFT ; make index out of "index" field
  453. cmp ecx,MI_SIB_INDEXNONE
  454. je do310 ; no index
  455. mov eax,RegTab[ecx * 4]
  456. mov eax,[eax+edi] ; get reg contents for multiply.
  457. mov ecx,Sib
  458. and ecx,MI_SIB_SSMASK
  459. shr ecx,MI_SIB_SSSHIFT ; for shift count
  460. shl eax,cl
  461. add ebx,eax
  462. do310: cmp edx,MI_SIB_BASENONE
  463. jne do120
  464. ;
  465. ; If mod != 0, then we have to add in EBP, and make ss the default seg
  466. ;
  467. mov edx,ModRm
  468. and edx,MI_MODMASK
  469. shr edx,MI_MODSHIFT
  470. cmp edx,MI_MODNONE
  471. jne do120
  472. ;
  473. ; Add in Ebp, and change default segment to ss
  474. ;
  475. add ebx,[edi].TsEbp
  476. lea edx,SegLimit
  477. push edx
  478. lea edx,SegBase
  479. push edx
  480. lea edx,SegFlags
  481. push edx
  482. mov edi,[esi].RiTrapFrame
  483. push [edi].TsHardwareSegSs
  484. call VdmSegParams
  485. add esp,010h
  486. mov SelLookupResult,eax
  487. jmp do120 ; add in segment info
  488. VdmDecodeOperand endp
  489. public VdmSegParams
  490. VdmSegParams proc
  491. push edi
  492. mov edi,[esi].RiTrapFrame
  493. test dword ptr [edi].TsEFlags,EFLAGS_V86_MASK
  494. jz vsp20
  495. Segmt equ word ptr [ebp + 8]
  496. SegFlags equ [ebp + 0Ch]
  497. SegBase equ [ebp + 010h]
  498. SegLimit equ [ebp + 014h]
  499. pop edi
  500. push ebp
  501. mov ebp,esp
  502. push edi
  503. movzx eax,Segmt
  504. shl eax,4
  505. mov edi,SegBase
  506. mov [edi],eax
  507. mov edi,SegLimit
  508. mov dword ptr [edi],0FFFFh
  509. mov edi,SegFlags
  510. mov [edi],dword ptr SEL_TYPE_WRITE
  511. mov eax,1
  512. pop edi
  513. mov esp,ebp
  514. pop ebp
  515. ret
  516. vsp20: pop edi
  517. jmp _Ki386GetSelectorParameters@16
  518. VdmSegParams endp
  519. _PAGE ENDS
  520. end