;    GRDB - debugger for dos with 32-bit extensions
;    Copyright (C) 1997-2006  David Lindauer
;
;    This program is free software; you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation; either version 2 of the License, or
;    (at your option) any later version.
;
;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.
;
;    You should have received a copy of the GNU General Public License
;    along with this program; if not, write to the Free Software
;    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
;
;    (for GNU General public license see file COPYING)
;
;    you may contact the author at:  mailto::camille@bluegrass.net
; 
;    or by snail mail at:
;
;    David Lindauer
;    850 Washburn Ave.  Apt #99
;    Louisville, KY 40222
;
;
; operands.asm
;
; Function: Handle 386 operands as dictated by the opcode table
;   Handle formatting output
;
; Sorry, I didn't have time to document this one yet
;
; years later:
;
; sorry, I STILL didn't have time to document this one yet :)
;
	;MASM MODE
	.386
	.MODEL use32 SMALL

include	dispatch.ase
include	opcodes.asi
include	operands.asi
include	opcom.ase
include mtrap.ase

	PUBLIC TabTo, ReadOverrides, DispatchOperands
	PUBLIC	FormatDisassembly, FormatValue, code_address
        PUBLIC  PutDword, PutWord,PutByte, source,dest, segs
        PUBLIC  put2,put3,put4, strlen, GetSeg, PutWordox,PutByte

	extrn x86pfx : byte
SZ_QWORD	=	2
SZ_TBYTE	=	4

	.DATA
code_address	dd	0		;disassembly address within segment
dest2		dd	0		;temps to aid decoding
source2		dd	0
segs		dw	0		
extraoperand	operand <>		;third operand
source		operand	<>		;second operand
dest		operand	<>		;first operand
nmmnemonic      db      20 DUP (?)      ;mnemonic (may be modified here)
reqsPtrSizeOvride	db	0	;flag set if xxx ptr required
realopsize      db      0               ;flag set if 0x66 byte detected
unksse          db      "???SSE???",0
hasputoverride  db      0               ; flag set if an override has been displayed
	.code

;Find the length of a string in a buffer pointed to by esi, and return that
;length in AX.  This is a strange way to do this. I think I'll change it
;just a little.
;  If SI comes in pointing to a 0, we return a string length of 0

strlen	PROC	
	push	edi
	push	esi
	push	ecx
	mov	edi,esi
	mov	ecx,-1
	sub	al,al
	repnz	scasb
	mov	eax,ecx
	not	eax
	dec	eax
	pop	ecx
	pop	esi
	pop	edi
	ret
strlen	ENDP	




strcpy	PROC	
strcpylp:
	lodsb
	stosb
	or	al,al
	jnz	strcpylp
	ret
strcpy	ENDP	


strcat	PROC	
	mov	al,[edi]
	inc	edi
	or	al,al
	jnz	strcat
	dec	edi
	jmp	strcpy
strcat	ENDP	


CopyExtra	PROC	
	push	esi
	push	edi
	mov	esi,offset extraoperand
	xchg	esi,edi
	mov	ecx,OPERANDSIZE
	rep	movsb
	pop	edi
	pop	esi
	ret
CopyExtra	ENDP	



put2	PROC	
	mov	[esi],ah
	inc	esi
	mov	[esi],al
	inc	esi
	mov	BYTE PTR [esi],0
	ret
put2	ENDP	


put3	PROC	
	push	eax
	shr	eax,8
	mov	[esi],ah
	inc	esi
	pop	eax
	call	put2
	ret
put3	ENDP	


put4	PROC	
	push	eax
	shr	eax,16
	call	put2
	pop	eax
	call	put2
	ret
put4	ENDP	


setseg	PROC	
        mov     [reqsPtrSizeOvride],FALSE
	mov	[edi+operand.code],OM_SEGMENT
	mov	[edi+operand.thereg],al
	ret
setseg	ENDP	


setreg	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	mov	[edi+operand.code],OM_REG
	mov	[edi+operand.thereg],al
	ret
setreg	ENDP	


readrm	PROC	
	push	ecx
	sub	ecx,ecx
	mov	cl,2
	RM	esi
	mov	[edi+operand.thereg],al
	MODX	esi
	mov	ch,al
	cmp	ch,MOD_REG
	jnz	short notregreg
	mov	[edi+operand.code],OM_REG
	mov	[reqsPtrSizeOvride],FALSE
	sub	eax,eax
	pop	ecx
	ret
notregreg:
	bt	[edi+operand.oeflags],OMF_ADR32
	jnc	adr16
	cmp	[edi+operand.thereg],RM_32_SCALED
	jnz	notscaled
	inc	cl
	RM	esi+1
	mov	[edi+operand.thereg],al
	REG	esi+1
	mov	[edi+operand.scalereg],al
	MODX	esi+1
	mov	[edi+operand.scale],al
	cmp	[edi+operand.scalereg],RM_32_STACKINDEX
	jz	hassp
	bts	[edi+operand.oeflags],OMF_SCALED
hassp:
	cmp	[edi+operand.thereg],RM_32_ABSOLUTE
	jnz	basedAndscaled
	cmp	ch,MOD_NOOFS
	jnz	short basedAndscaled
	mov	[edi+operand.code],OM_ABSOLUTE
	LONG	esi+3
	mov	[edi+operand.address],eax
	sub	eax,eax
	mov	al,5
	pop	ecx
	ret
notscaled:
	
	cmp	ch,MOD_NOOFS
	jnz	basedAndscaled
	cmp	[edi+operand.thereg], RM_32_ABSOLUTE
	jnz	basedAndscaled
	mov	[edi+operand.code], OM_ABSOLUTE
	LONG	esi+2
	mov	[edi+operand.address],eax
	sub	eax,eax
	sub	eax,eax
	mov	al,4
	pop	ecx
	ret
adr16:
	cmp	ch,MOD_NOOFS
	jnz	basedAndscaled
	cmp	[edi+operand.thereg], RM_16_ABSOLUTE
	jnz	basedAndscaled
	mov	[edi+operand.code], OM_ABSOLUTE
	UINT	esi+2
	mov	[edi+operand.address],eax
	sub	eax,eax
	mov	al,2
	pop	ecx
	ret
basedAndscaled:
	mov	[edi+operand.code], OM_BASED
	cmp	ch,MOD_ADDR
	jnz	short checksigned
	bts	[edi+operand.oeflags], OMF_WORD_OFFSET
	push	ecx
	sub	ch,ch
	movzx	ecx,cl
	mov	eax,[esi+ecx]
	pop	ecx
	bt	[edi+operand.oeflags], OMF_ADR32
	jc	dwordx
	and	eax,0ffffh
	sub	cl,2
dwordx:
	mov	[edi+operand.address],eax
	add	cl,4
	jmp	short readrmdone
checksigned:
	cmp	ch, MOD_SIGNED
	jnz	short readrmdone
	bts	[edi+operand.oeflags],OMF_SIGNED_OFFSET
	movzx	ecx,cl
        movsx   eax,byte ptr [esi+ecx]
	mov	[edi+operand.address],eax
	inc	cl
readrmdone:
	movzx	eax,cl
	sub	al,2
	pop	ecx
	ret
readrm	ENDP	


RegRM	PROC	
	mov	edi,[dest2]
	REG	esi
	call	setreg
	mov	edi,[source2]
	call	readrm
	ret
RegRM	ENDP	


Immediate	PROC	
	push	ecx
	sub	ecx,ecx
	mov	[edi+operand.code],OM_IMMEDIATE
	bt	[edi+operand.oeflags],OMF_BYTE
	jnc	short inotbyte
	inc	cl
	sub	eax,eax
	mov	al,[esi]
	jmp	short i_ret
inotbyte:
	bt	[edi+operand.oeflags], OMF_OP32
	jnc	iword
	add	cl,4
	LONG	esi
	jmp	short i_ret
iword:
	add	cl,2
	UINT	esi
i_ret:
	mov	[edi+operand.address],eax
	mov	eax,ecx
	pop	ecx
	ret
Immediate	ENDP	

;Find a binary 0, stick whatever is in AL there, and put a 0 after that.

MnemonicChar	PROC	
	push	edi
	mov	edi,offset nmmnemonic
mc2:
	inc	edi
	cmp	BYTE PTR [edi-1],0
	jnz	mc2
	mov	[edi-1],al
	mov	BYTE PTR [edi],0
	pop	edi
	ret
MnemonicChar	ENDP	

issse PROC
        test    [realopsize],1
        jz      notsse
        push    esi
        push    edi
        mov     esi,offset unksse
        mov     edi,offset nmmnemonic
        call    strcpy
        pop     edi
        pop     esi
notsse:
        ret
issse ENDP

;/* op 1- word reg from bits 0 - 2 of opcode */

op1	PROC	
	btr	[edi+operand.oeflags],OMF_BYTE
	mov	al,[esi]
	B02
	call	setreg
	sub	eax,eax
	ret
op1	ENDP	


;/* Op2 acc, reg bits 0-2 of opcode */
op2	PROC	
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[ebx+operand.oeflags],OMF_BYTE
	mov	al,REG_EAX
	call	setreg
	mov	edi,ebx
	mov	al,[esi]
	and	al,7
	call	setreg
	sub	eax,eax
	ret
op2	ENDP	


;/* op3 - seg from b3-5 of opcode */
op3	PROC	
	mov	al,[esi]
	B35
	call	setseg
	sub	eax,eax
	ret
op3	ENDP	


;/* op4 - REGRM with b1 of opcode set reg is dest else source */
op4	PROC	
	bt	DWORD PTR [esi],1
	jc	short op4nox
	xchg	ebx,edi
op4nox:
	mov	[dest2],edi
	mov	[source2],ebx
	call	RegRM
	ret
op4	ENDP	


;/* op5 - use RM only */
op5	PROC	
	call	readrm
	ret
op5	ENDP	


;/* op6 readrm for shift */
op6	PROC	
	call	readrm
	sub	ecx,ecx
	mov	cl,al
	mov	edi,ebx
	mov	[edi+operand.code],OM_SHIFT
	bt	DWORD PTR [esi],4
	jnc	short op6cnt
	bt	DWORD PTR [esi],1
        jnc     short op61a
	bts	[edi+operand.oeflags],OMF_CL
	jmp	short op6done
op61a:
	mov	[edi+operand.address],1
	jmp	short op6done
op6cnt:
	movzx	eax,BYTE PTR [esi+ecx+2]
	inc	cl
	mov	[edi+operand.address],eax
op6done:
	mov	eax,ecx
	ret
op6	ENDP	


;/* op 7 regrm with reg dest */
op7	PROC	
	mov	[dest2],edi
	mov	[source2],ebx
	call	RegRM
	ret
op7	ENDP	


;/* OP8 - word regrm with reg dest */
op8	PROC	
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[ebx+operand.oeflags],OMF_BYTE
	jmp	op7
op8	ENDP	


;/* op 9 - interrupts */
op9	PROC	
        btr     [edi+operand.oeflags],OMF_ADR32
        btr     [edi+operand.oeflags],OMF_OP32
	mov	[reqsPtrSizeOvride],FALSE
	sub	eax,eax
	mov	al,3
	bt	DWORD PTR [esi],0
	jnc	short op9int3
	mov	al,[esi+1]
op9int3:
	mov	[edi+operand.address],eax
	mov	BYTE PTR [edi+operand.code],OM_INT
	sub	al,al
	ret
op9	ENDP	


;/* op 10, short relative branch */
op10	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	mov	[edi+operand.code],OM_SHORTBRANCH
	movsx	eax,BYTE PTR [esi+1]
        inc     eax
        inc     eax
        mov     edx,[code_address]
        add     eax,edx
	mov	[edi+operand.address],eax
	bt	[edi+operand.oeflags],OMF_OP32
	jc	short op10notword
	and	[edi+operand.address],0ffffh
op10notword:
	sub	eax,eax
	ret
op10	ENDP	


;/* op 11 RM, immediate */
op11	PROC	
	call	readrm
	movzx	ecx,al
	mov	edi,ebx
	push	esi
	add	esi,ecx
	add	esi,2
	call	Immediate
	add	cl,al
	pop	esi
	mov	eax,ecx
	ret
op11	ENDP	


;/* op 12 - acc, immediate */
op12	PROC	
	mov	al,REG_EAX
	call	setreg
	mov	edi,ebx
	inc	esi
	call	Immediate
	dec	esi
	ret
op12	ENDP	


;/* op 13 absolute, acc*/
op13	PROC	
	sub	ecx,ecx
	mov	[edi+operand.code],OM_ABSOLUTE
	bt	[edi+operand.oeflags],OMF_ADR32
	jnc	short op13word
	LONG	esi+1
	inc	cl
	inc	cl
	jmp	short op13fin
op13word:
	UINT	esi+1
op13fin:
	mov	[edi+operand.address],eax
	mov	edi,ebx
	mov	al,REG_EAX
	call	setreg
	mov	eax,ecx
	ret
op13	ENDP	


;/* op 14 - RM, immediate, b01 of opcode != 1 for byte */
op14	PROC	
	call	readrm
	movzx	ecx,al
	mov	al,[esi]
	B01
        test    al,1
	jnz	short op14checkbyte
	bts	[ebx+operand.oeflags],OMF_BYTE
	bts	[edi+operand.oeflags],OMF_BYTE
	jmp	short op14source
op14checkbyte:
	btr	[ebx+operand.oeflags],OMF_BYTE
	cmp	al,1
	jz	short op14check2
	bts	[ebx+operand.oeflags],OMF_BYTE
op14check2:
	btr	[edi+operand.oeflags],OMF_BYTE
op14source:
	mov	edi,ebx
	push	esi
	add	esi,ecx
	add	esi,2
	call	Immediate
	pop	esi
	add	cl,al
	mov	al,[esi]
	B01
	cmp	al,3
	jnz	op14done
	bt	[edi+operand.oeflags],OMF_BYTE
	jnc	op14done
	bts	[edi+operand.oeflags],OMF_SIGNED
	movzx	eax,byte ptr [edi+operand.address]
	mov	[edi+operand.address],eax
op14done:
	mov	eax,ecx
	ret
op14	ENDP	


;/* op 15 - acc, immediate, B3 of opcode clear for byte */
op15	PROC	
	mov	al,[esi]
	B02
	call	setreg
	bt	DWORD PTR [esi],3
	jnc	op15byte
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[ebx+operand.oeflags],OMF_BYTE
	jmp	short op15source
op15byte:
	bts	[edi+operand.oeflags],OMF_BYTE
	bts	[ebx+operand.oeflags],OMF_BYTE
op15source:
	mov	edi,ebx
	inc	esi
	call	Immediate
	dec	esi
	ret
op15	ENDP	


;/* op 16 - seg,readrm, if B1 of opcode seg is dest else source */
op16	PROC	
	bt	DWORD PTR [esi],1
	jc	noswap
	xchg	ebx,edi
noswap:
	REG	esi
	call	setseg
	mov	edi,ebx
	btr	[edi+operand.oeflags],OMF_BYTE
	call	readrm
	ret
op16	ENDP	


;/* op 17, far return */
op17	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	mov	[edi+operand.code],OM_RETURN
	btr	[edi+operand.oeflags],OMF_ADR32
	btr	[edi+operand.oeflags],OMF_OP32
	btr	[edi+operand.oeflags],OMF_BYTE
	UINT	esi+1
	mov	[edi+operand.address],eax
	sub	eax,eax
	ret
op17	ENDP	


;/* op 18, far branch/call */
op18	PROC	
	sub	ecx,ecx
	mov	[reqsPtrSizeOvride],FALSE
	mov	[edi+operand.code],OM_FARBRANCH
	btr	[edi+operand.oeflags],OMF_BYTE
	bt	[edi+operand.oeflags],OMF_OP32
	jnc	short op18word
	inc	cl
	inc	cl
	LONG	esi+1
	jmp	short	op18fin
op18word:
	UINT	esi+1
op18fin:
	mov	[edi+operand.address],eax
	movzx	ecx,cx
	UINT	esi+ecx+3
	mov	[edi+operand.oeseg],ax
	mov	eax,ecx
	ret
op18	ENDP	


;/* op 19 - ESC, mnem of bits 0-2 of opcode, imm,readrm */
op19	PROC	
	mov	[edi+operand.code],OM_IMMEDIATE
	bts	[edi+operand.oeflags],OMF_BYTE
	mov	al,[esi]
	and	al,7
	shl	al,3
	mov	ah,[esi+1]
	shr	ah,3
	and	ah,7
	or	al,ah
	sub	ah,ah
	cwde
	mov	[edi+ operand.address],eax
	mov	edi,ebx
	call	readrm
	ret
op19	ENDP	


;/* op 20 - long branch */
op20	PROC	
	sub	eax,eax
	mov	[reqsPtrSizeOvride],FALSE
	sub	ecx,ecx
	mov	[edi+operand.code],OM_LONGBRANCH
	bt	[edi+operand.oeflags],OMF_OP32
	jnc	short op20word
	LONG	esi+1
	inc	cl
	inc	cl
	jmp	short op20fin
op20word:
	UINT	esi+1
op20fin:

        mov   edx,[code_address]
        add     eax,edx
	test	[segs],SG_TWOBYTEOP
	jz	op20xx
	inc	ax
op20xx:
        test    [segs],SG_OPSIZ
        jz      op20xy
        inc     eax
op20xy:
	add	eax,ecx
	add	eax,3
	bt	[edi+operand.oeflags],OMF_OP32
	jc	op20done
	and	eax,0ffffh
op20done:
	mov	[edi+operand.address],eax
	mov	eax,ecx
	ret
op20	ENDP	


;/* op21 acc,dx */
op21	PROC	
	mov	al,REG_EAX
	call	setreg
	mov	edi,ebx
	btr	[edi+operand.oeflags],OMF_OP32
	btr	[edi+operand.oeflags],OMF_BYTE
	mov	al,REG_DX
	call	setreg
	sub	eax,eax
	ret
op21	ENDP	


;/* op22 - dx,acc */
op22	PROC	
	btr	[edi+operand.oeflags],OMF_OP32
	btr	[edi+operand.oeflags],OMF_BYTE
	mov	al,REG_DX
	call	setreg
	mov	edi,ebx
	mov	al,REG_EAX
	call	setreg
	sub	eax,eax
	ret
op22	ENDP	


;/* op23 - port,acc where B1 of opcode set is port dest */
op23	PROC	
	bt	DWORD PTR [esi],1
	jc	short op20noswap
	xchg	ebx,edi
op20noswap:
	bts	[edi+operand.oeflags],OMF_BYTE
	mov	[edi+operand.code],OM_PORT
	movzx	eax,BYTE PTR [esi+1]
	mov	[edi+operand.address],eax
	mov	edi,ebx
	mov	al,REG_EAX
	call	setreg
	sub	eax,eax
	ret
op23	ENDP	


;/* op 24 acc, absolute */
op24	PROC	
	sub	ecx,ecx
	mov	al,REG_EAX
	call	setreg
	mov	edi,ebx
	mov	[edi+operand.code],OM_ABSOLUTE
	bt	[edi+operand.oeflags],OMF_ADR32
	jnc	short op24word
	inc	cl
	inc	cl
	LONG	esi+1
	jmp	short op24done
op24word:
	UINT	esi+1
op24done:
	mov	[edi+operand.address],eax
	mov	ax,cx
	ret
op24	ENDP	


;/* op 25 - immediate byte or word */
op25	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	bts	[edi+operand.oeflags],OMF_BYTE
	bt	DWORD PTR [esi],1
	jc	short op25fin
	btr	[edi+operand.oeflags],OMF_BYTE
op25fin:
	push	esi
	inc	esi
        call    Immediate
	pop	esi
        bts     [edi+operand.oeflags],OMF_SIGNED
	ret
op25	ENDP	


;/* op 26, immediate 2byte,byte */
op26	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[edi+operand.oeflags],OMF_OP32
	push	esi
	inc	esi
	call	Immediate
	mov	edi,ebx
	bts	[edi+operand.oeflags],OMF_BYTE
	btr	[edi+operand.oeflags],OMF_OP32
	inc	esi
	inc	esi
	call	Immediate
	pop	esi
	sub	eax,eax
	ret
op26	ENDP	


;/* op 27 - string */
op27	PROC	
	mov	al,'d'
	bt	[edi+operand.oeflags],OMF_OP32
	jc	short op27pc
	mov	al,'w'
op27pc:
	call	MnemonicChar
	sub	eax,eax
	ret
op27	ENDP	


;/* op 28 - source = REG, dest = RM */
op28	PROC	
	xchg	edi,ebx
	jmp	op7
op28	ENDP	


;/* op 29 - rm, size don't care */
op29	PROC	
	btr	[edi+operand.oeflags],OMF_OP32
	btr	[edi+operand.oeflags],OMF_BYTE
        mov     [reqsPtrSizeOvride],FALSE
	call	readrm
	ret
op29	ENDP	


;/* op30 - RM, shift with B3 of stream selecting COUNT or CL*/
op30	PROC	
	call	readrm
        movzx   ecx,al
	mov	edi,ebx
	mov	[edi+operand.code],OM_SHIFT
	bt	DWORD PTR [esi],3
	jnc	op30cl
	movzx	ecx,cx
	movzx	eax,byte ptr [esi+ecx+2]
	mov	[edi+operand.address],eax
	inc	ecx
	jmp	short op30done
op30cl:
	bts	[edi+operand.oeflags],OMF_CL
op30done:
	mov	eax,ecx
	ret
op30	ENDP	


;/* op 31- reg, rm, count where B1 of opcode = byte/word */
op31	PROC	
	call	CopyExtra
	REG	esi
	call	setreg
	mov	edi,ebx
	call	readrm
        movzx   ecx,al
	mov	edi,offset extraoperand
	btr	[edi+operand.oeflags],OMF_BYTE
	bt	DWORD PTR [esi],1
        jnc     short op31byte
	bts	[edi+operand.oeflags],OMF_BYTE
        bts     [edi+operand.oeflags],OMF_SIGNED
op31byte:
	push	esi
	inc	esi
        inc     esi
        add     esi,ecx
	call	Immediate
	pop	esi
	add	eax,ecx
	ret
op31	ENDP	


;/* op32 - 386 special regs */
op32	PROC	
	mov	cx,WORD PTR [esi]
	and	cx,0c005h
	cmp	cx,0c000h
	mov	al,OM_CRX
	jz	short op32gotype
	cmp	cx,0c001h
	mov	al,OM_DRX
	jz	short op32gotype
	cmp	cx,0c004h
	mov	al,OM_TRX
	jz	short op32gotype
	mov	al,OM_SUD
op32gotype:
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[ebx+operand.oeflags],OMF_BYTE
        btr     [edi+operand.oeflags],OMF_ADR32
        btr     [ebx+operand.oeflags],OMF_ADR32
	bts	[edi+operand.oeflags],OMF_OP32
	bts	[ebx+operand.oeflags],OMF_OP32
	bt	DWORD PTR [esi],1
	jc	op32noswap
	xchg	ebx,edi
op32noswap:
	mov	[edi+operand.code],al
	REG	esi
	mov	[edi+operand.thereg],al
	mov	edi,ebx
	RM	esi
	call	setreg
	sub	eax,eax
	ret
op32	ENDP	


;/* op33 - reg,rm,shiftcnt where B3 = reg source, b0 = shift cl */
op33	PROC	
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[ebx+operand.oeflags],OMF_BYTE
	call	CopyExtra
	call	readrm
        movzx   ecx,al
	REG	esi
	mov	edi,ebx
	call	setreg
	mov	edi,offset extraoperand
	mov	[edi+operand.code],OM_SHIFT
	bt	DWORD PTR [esi],0
	jnc	short getofs
	bts	[edi+operand.oeflags],OMF_CL
	jmp	short op33done
getofs:
	movzx	ecx,cx
	movzx	eax,BYTE PTR [esi+ecx+2]
	mov	[edi+operand.address],eax
op33done:
	mov	eax,ecx
	ret
op33	ENDP	


;/* op 34 - push & pop word, also no reqsPtrSizeOvride single args */
op34	PROC	
	call	readrm
	ret
op34	ENDP	


;/* op 35 -floating RM */
op35	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	MODX	esi
	cmp	al,3
	jnz	short op35fsttab
	bts	[edi+operand.oeflags],OMF_FST
	call	readrm
	ret
op35	endp



op35fsttab	proc
	bts	[edi+operand.oeflags],OMF_FSTTAB
	movzx	eax,BYTE PTR [esi]
	B12
	shl	eax, OM_FTAB
        or      [edi+operand.oeflags],eax
	call	readrm
	ret
op35fsttab	endp


;/* op 36 - floating math & pop */

op36	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	mov	al,[esi+1]
	and	al,0c7h
	cmp	al,0c1h
	jz	op36noarg
	bts	[edi+operand.oeflags],OMF_FST
	and	al,7
	call	setreg
	sub	al,al
	xchg	ebx,edi
	bts	[edi+operand.oeflags],OMF_FST
	call	setreg
op36noarg:
	sub	eax,eax
	ret
op36	ENDP	


;/* OP 37 - floating MATH */
op37	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	MODX	esi
	cmp	al,3
	jc	op35fsttab
	test	byte ptr [esi],4
	jnz	op37noflop
	xchg	edi,ebx
op37noflop:
	bts	[edi+operand.oeflags],OMF_FST
	RM	esi
	call	setreg
	sub	al,al
	xchg	ebx,edi
	bts	[edi+operand.oeflags],OMF_FST
	call	setreg
	sub	eax,eax
	ret
op37	ENDP	


;/* op38 - FAR RM */
op38	PROC	
;        mov     [reqsPtrSizeOvride],FALSE
;        bts     [edi+operand.oeflags],OMF_FSTTAB
        bts     [edi+operand.oeflags],OMF_FARPTR
	call	readrm
	ret
op38	ENDP	


;/* OP39 - word regrm with reg source */
op39	PROC	
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[ebx+operand.oeflags],OMF_BYTE
	call	op40
	ret
op39	ENDP	


;/* op 40 regrm with reg source */
op40	PROC	
	mov	[dest2],ebx
	mov	[source2],edi
	call	RegRM
	ret
op40	ENDP	


;/* op 41 reg, bitnum */
op41	PROC	
	btr	[edi+operand.oeflags],OMF_BYTE
	call	readrm
        movzx   ecx,al
	mov	edi,ebx
	bts	[edi+operand.oeflags],OMF_BYTE
	push	esi
	add	esi,ecx
	add	esi,2
	call	Immediate
	pop	esi
	mov	eax,ecx
	ret
op41	ENDP	


;/* op 42 mixed regrm with reg dest & reqsPtrSizeOvrideness enforced */

op42	PROC	
	mov	[dest2],edi
	mov	[source2],ebx
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[ebx+operand.oeflags],OMF_OP32
	call	RegRM
	mov	[reqsPtrSizeOvride],TRUE
	ret
op42	ENDP	



;/* op 43 CWDE

op43	PROC	
	bt	[edi+operand.oeflags],OMF_OP32	
	jnc	short op43nochng		
	push	esi				
	mov	esi,offset nmmnemonic+1		
	mov	eax,"wde"			
	call	put3				
	mov	BYTE PTR [esi],0			
	pop	esi				
	sub	eax,eax				
op43nochng:
	ret
op43	ENDP	


;/* op 44 BSWAP

op44	PROC
	btr	[edi+operand.oeflags],OMF_BYTE
	mov	al,[esi]
	and	al,7
	call	setreg
	sub	eax,eax
	ret
op44	ENDP


;/* OP45 - any regrm with reg source */

op45	PROC	
	bt	word ptr [esi-1],0
	jc	op45nb
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[ebx+operand.oeflags],OMF_BYTE
op45nb:
        mov     [dest2],ebx
        mov     [source2],edi
        call    RegRM
;        XCHG    BX,DI
;        REG     si
;        call    setreg
;        XCHG    bx,di
;        call    readrm
        ret
op45	ENDP	


;/* op 46 - floating R/M, pointers to mem */
op46	PROC	
	jmp	op29
op46	ENDP	


;/* op47 - AX */
op47	PROC
	btr	[edi+operand.oeflags],OMF_OP32
	btr	[edi+operand.oeflags],OMF_BYTE
	sub	al,al
	call	setreg
	sub	eax,eax
	ret
op47	ENDP


;/* op48 - 32-bit reg to r02, no prefix (bswap) */
op48	PROC
	bts	[edi+operand.oeflags],OMF_OP32
	btr	[edi+operand.oeflags],OMF_BYTE
	mov	al,[esi]
	B02
	call	setreg
	sub	eax,eax
	ret
op48	ENDP


;/* op 49, FST */
op49	PROC
	mov	[reqsPtrSizeOvride],FALSE
	MODX	esi
	cmp	al,3
	jnz	op49noreg
	bts	[edi+operand.oeflags],OMF_FST
	jmp	short op49fin
op49noreg:
	bts	[edi+operand.oeflags],OMF_FSTTAB
	movzx	eax,BYTE PTR [esi]
	and	al,6
	jz	op49nxor
	xor	al,6
op49nxor:
	shl	eax, OM_FTAB
        or      [edi+operand.oeflags],eax
op49fin:
	call	readrm
	ret
op49	ENDP


;/* op 50, FLD & FSTP */
op50	PROC
	jmp	op49
op50	ENDP


;/* op 51, FBLD/FBSTP */
op51	PROC
	mov	[reqsPtrSizeOvride],FALSE
	bts	[edi+operand.oeflags],OMF_FSTTAB
	or	[edi+operand.oeflags],4 SHL OM_FTAB
	call	readrm
	ret
op51	ENDP


;/* op 52, FILD & FISTP */
op52	PROC
	mov	[reqsPtrSizeOvride],FALSE
	mov	ah,1		; assume dword
	mov	al,[esi]
	cmp	al,0dfh
	jnz	op52dw
	mov	ah,2		; assume qword
	test	byte ptr [esi+1],20h
	jnz	op52dw
	mov	ah,3
op52dw:
	mov	al,ah
	sub	ah,ah
	bts	[edi+operand.oeflags],OMF_FSTTAB
	shl	eax,OM_FTAB
        or      [edi+operand.oeflags],eax
	call	readrm
	ret
op52	ENDP


;/* op 53, FIST & FISTP */
op53	PROC
	jmp	op52
op53	ENDP


;/* op 54, FREG */
op54	PROC
	mov	[reqsPtrSizeOvride],0
	bts	[edi+operand.oeflags],OMF_FST
	call	readrm
	ret
op54	ENDP


;/* op 55, FREG if not one */
op55	PROC
	mov	al,[esi+1]
	and	al,7
	cmp	al,1
	jnz	op54
	sub	eax,eax
	ret
op55	ENDP


;/* op 56, FIMATH */
op56	PROC
	mov	[reqsPtrSizeOvride],FALSE
	mov	eax,1
	test	byte ptr [esi],4
	jz	op56go
	mov	al,3
op56go:
	bts	[edi+operand.oeflags],OMF_FSTTAB
	shl	eax,OM_FTAB
        or      [edi+operand.oeflags],eax
	call	readrm
	ret
op56	ENDP

;/* op 59 MMXREG,RM */
op59    PROC
        call    issse
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[ebx+operand.oeflags],OMF_BYTE
        bts     [edi+operand.oeflags],OMF_MMXTAB
        bts     [ebx+operand.oeflags],OMF_MMXTAB
        mov     [dest2],edi
        mov     [source2],ebx
        call    RegRM
	ret
op59    ENDP

;/* op60 MMXMOVDLD */
op60    PROC
        call    issse
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[ebx+operand.oeflags],OMF_BYTE
        bts     [edi+operand.oeflags],OMF_MMXTAB
        bts     [ebx+operand.oeflags],OMF_OP32
        mov     [dest2],edi
        mov     [source2],ebx
        call    RegRM
	ret
op60    ENDP

;/* op61 MMXMOVDST */
op61    PROC
        call    issse
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[ebx+operand.oeflags],OMF_BYTE
        bts     [ebx+operand.oeflags],OMF_MMXTAB
        bts     [edi+operand.oeflags],OMF_OP32
        mov     [dest2],ebx
        mov     [source2],edi
        call    RegRM
	ret
op61    ENDP

;/* op62 MMXMOVQLD */
op62    PROC
        call    issse
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[ebx+operand.oeflags],OMF_BYTE
        bts     [edi+operand.oeflags],OMF_MMXTAB
        bts     [ebx+operand.oeflags],OMF_MMXTAB
        mov     [dest2],edi
        mov     [source2],ebx
        call    RegRM
	ret
op62    ENDP

;/* op63 MMXMOVQST */
op63    PROC
        call    issse
	btr	[edi+operand.oeflags],OMF_BYTE
	btr	[ebx+operand.oeflags],OMF_BYTE
        bts     [ebx+operand.oeflags],OMF_MMXTAB
        bts     [edi+operand.oeflags],OMF_MMXTAB
        mov     [dest2],ebx
        mov     [source2],edi
        call    RegRM
	ret
op63    ENDP

;/* op64 MMXSHIFT */
op64    PROC
        call    issse
        bts     [edi+operand.oeflags],OMF_MMXTAB
        bts     [ebx+operand.oeflags],OMF_MMXTAB
        call    readrm
	sub	ecx,ecx
	mov	cl,al
	mov	edi,ebx
	mov	[edi+operand.code],OM_SHIFT
	movzx	ecx,cx
	movzx	eax,BYTE PTR [esi+ecx+2]
	inc	cl
	mov	[edi+operand.address],eax
	mov	eax,ecx
	ret
op64    ENDP

;/* loop */
op65    proc
	mov	al,'d'
        bt      [edi+operand.oeflags],OMF_ADR32
        jc      short op65pc
	mov	al,'w'
op65pc:
	call	MnemonicChar
	sub	eax,eax
	mov	[reqsPtrSizeOvride],FALSE
        mov     [edi+operand.code],OM_SHORTBRANCH
        movsx   eax,byte ptr [esi+1]

        mov   edx,[code_address]
        add     eax,edx
        add     eax,2
        sub     edx,edx
        bt      [edi+operand.oeflags],OMF_ADR32
        jnc     op65notas
        inc     edx
op65notas:
;        test    [optass32],255
;        jz      op65t2
        neg     edx
        inc     edx
op65t2:
        add     eax,edx
	bt	[edi+operand.oeflags],OMF_OP32
        jc      op65done
	and	eax,0ffffh
op65done:
	mov	[edi+operand.address],eax
        sub     eax,eax
        clc
	ret
op65    endp

; CDW/CDQ

op66    PROC    
	bt	[edi+operand.oeflags],OMF_OP32	
        jnc     short op66nochng                
	push	esi				
	mov	esi,offset nmmnemonic+1		
        mov     eax,"dq"                       
        call    put2                            
	mov	BYTE PTR [esi],0			
	pop	esi				
	sub	eax,eax				
op66nochng:
	ret
op66    ENDP    

;
; AAM
;
op67    PROC
        inc     esi
        mov     al,[esi]
        bts     [edi+operand.oeflags],OMF_BYTE
        call    Immediate
        sub     eax,eax
        ret
op67    ENDP

;
; XLAT
;
op68    PROC
        mov     [reqsPtrSizeOvride],FALSE
        mov     [edi.operand.code],OM_BASED
        mov     [edi.operand.thereg],3 ; [ebx]
        bt      [edi.operand.oeflags],OMF_ADR32
        jc      op68n32
        mov     [edi.operand.thereg],7 ; [ebx]
op68n32:
        sub     eax,eax  
        ret
op68    ENDP

;
; set xx
;
op69    PROC
	bts	[edi+operand.oeflags],OMF_BYTE
	bts	[ebx+operand.oeflags],OMF_BYTE
        jmp     op29
op69    endp
;
; lgdt/sgdt
;
op70    PROC
        btr     [edi+operand.oeflags],OMF_BYTE
        bt      [edi+operand.oeflags],OMF_OP32
        jc      op70_fword
        bts     [edi+operand.oeflags],OMF_PBYTE
        jmp     op70_cont
op70_fword:
        bts     [edi+operand.oeflags],OMF_FWORD
op70_cont:
	call	readrm
	ret
op70    ENDP

ReadOverrides   PROC    
        mov     [segs],0
      	
ro_lp:
	sub	eax,eax
	lods	BYTE PTR [esi]
;	test	[disassemble32Bit],1
;	jz	testseg
	cmp	al,64h
	jc	short testseg
	cmp	al,68h
	jnc	short testseg
	sub	al,64h
	mov	bx,SG_FS
ro_found:
	mov	cl,al
	shl	ebx,cl
	or	[segs],bx
	jmp	short ro_lp
testseg:
	push	ax
	and	al,0e7h
	cmp	al,026h
	pop	ax
	jnz	testrep
	mov	ebx,1
	shr	ax,3
	and	al,3
	jmp	ro_found
testrep:
        sub     al,0f0h         ; lock
        mov     bx,SG_LOCK
        jz      short ro_found
        sub     al,02h
	cmp	al,2
	jnc	ro_done
	mov	ebx,SG_REPNZ
	jmp	short ro_found
ro_done:
	dec	si
	ret
ReadOverrides	ENDP	


DispatchOperands	PROC	
	mov	edx,eax
	push	ebx
	mov	edi,offset nmmnemonic
	push	esi
	mov	esi,[ebx+opcode.mnemonic]
	call	strcpy
	pop	esi
	mov	[reqsPtrSizeOvride],TRUE
	movzx	eax,[ebx+opcode.operands]
	push	eax
	mov	edi,offset dest
	mov	ebx,offset source
	test	[x86pfx],1
	jz	short notwobyte
	or	[segs],SG_TWOBYTEOP
notwobyte:
	mov	eax,offset extraoperand
	mov	[eax+operand.code],0
	mov	[edi+operand.code],0
	mov	[ebx+operand.code],0
	mov	[edi+operand.oeflags],0
	mov	[ebx+operand.oeflags],0
        mov     [edi+operand.address],0
        mov     [ebx+operand.address],0

	
	bt	DWORD PTR [esi],0
	jc	notbyte
	bts	[edi+operand.oeflags],OMF_BYTE
	bts	[ebx+operand.oeflags],OMF_BYTE
notbyte:
	or	edx,edx
	jz	short xadr16
	bts	[edi+operand.oeflags],OMF_ADR32
	bts	[ebx+operand.oeflags],OMF_ADR32
	bts	[edi+operand.oeflags],OMF_OP32
	bts	[ebx+operand.oeflags],OMF_OP32
xadr16:
	test	[segs],SG_ADRSIZ
	jz	do_word1
	btc	[edi+operand.oeflags],OMF_ADR32
	btc	[ebx+operand.oeflags],OMF_ADR32
do_word1:
        mov     [realopsize],FALSE
	test	[segs],SG_OPSIZ
	jz	do_word2
        mov     [realopsize],TRUE
	btc	[edi+operand.oeflags],OMF_OP32
	btc	[ebx+operand.oeflags],OMF_OP32
do_word2:
	pop	eax
	or	eax,eax
	jz	nodispatch
	dec	al
	push	0
	call	TableDispatch
        dd      69
	dd	op1,  op2,  op3,  op4,  op5,  op6,  op7,  op8,  op9,  op10
	dd	op11, op12, op13, op14, op15, op16, op17, op18, op19, op20
	dd	op21, op22, op23, op24, op25, op26, op27, op28, op29, op30
	dd	op31, op32, op33, op34, op35, op36, op37, op38, op39, op40
	dd	op41, op42, op43, op44, op45, op46, op47, op48, op49, op50
        dd      op51, op52, op53, op54, op55, op56, op59, op59, op59, op60
        dd      op61, op62, op63, op64, op65, op66, op67, op68, op69, op70
	movzx	eax,al
	add	esi,eax
joindispatch:
	pop	ebx
	movzx	eax,[ebx+opcode.oclength]
	add	esi,eax
	ret
nodispatch:
        btr     [edi+operand.oeflags],OMF_ADR32
        btr     [ebx+operand.oeflags],OMF_ADR32
        btr     [edi+operand.oeflags],OMF_OP32
        btr     [ebx+operand.oeflags],OMF_OP32
        jmp     joindispatch
DispatchOperands	ENDP	


DoReqsPtrSizeOvride	PROC	
;	mov BYTE PTR [esi],C_RESERVEDWORD
;	inc esi
	mov byte ptr [esi],0
	push	edi
	push	esi
	test	[reqsPtrSizeOvride],-1
	jz	short floatreqsPtrSizeOvride
        bt      [edi+operand.oeflags],OMF_FARPTR
        jnc     drpso_nofar
        push    esi
        push    edi
        mov     edi,esi
        mov     esi,offset opn_farptr
        call    strcat
        pop     edi
        pop     esi
drpso_nofar:

	bt	[edi+operand.oeflags],OMF_BYTE
        jnc     chkfwptr
	mov	edi,esi
	mov	esi,offset byptr
	jmp	short reqsPtrSizeOvrideend
chkfwptr:
        bt      [edi+operand.oeflags],OMF_FWORD
        jnc     chkpbyteptr
	mov	edi,esi
        mov     esi,offset fwptr
	jmp	short reqsPtrSizeOvrideend
chkpbyteptr:
        bt      [edi+operand.oeflags],OMF_PBYTE
        jnc     chkdwptr
	mov	edi,esi
        mov     esi,offset pbptr
	jmp	short reqsPtrSizeOvrideend
chkdwptr:
	bt	[edi+operand.oeflags],OMF_OP32
	mov	edi,esi
        jnc     mkwordptr
	mov	esi,offset dwptr
	jmp	short reqsPtrSizeOvrideend
mkwordptr:
	mov	esi,offset woptr
  	jmp	short reqsPtrSizeOvrideend
floatreqsPtrSizeOvride:
	bt	[edi+operand.oeflags],OMF_FSTTAB
	jnc	reqsPtrSizeOvridedone
        mov     eax,[edi+operand.oeflags]
	shr	eax,OM_FTAB
	and	eax,7
	mov	edi,esi
	push	edi
	mov	esi,offset sts
	movzx	eax,ax
	mov	esi,[esi+eax * 4]
	call	strcat
	mov	esi,offset theptr
	pop	edi
reqsPtrSizeOvrideend:
	call	strcat
reqsPtrSizeOvridedone:
	pop	esi
	call	strlen
	add	esi,eax
;	mov BYTE PTR [esi],C_DEFAULT
;	inc esi
;	mov BYTE PTR [esi],0
	pop	edi
	ret
DoReqsPtrSizeOvride	ENDP	

;Tab over to the next location on the display
; INPUT: AL contains the number of positions to move 
;	SI points to a buffer aparently containing display strings?
; If the buffer contains a string whose length exceeds the passed tab
; position, we just add the requested tab position to esi, which now points
; into the middle of that string somewhere.  Otherwise, we stuff spaces into
; the buffer up to the requested tab position.

TabTo	PROC	
	movzx	ecx,al		;convert length to dword
ttl:
	lodsb
	cmp	al,20h
	jae	notabcnt
	inc	ecx
notabcnt:
	or	al,al
	loopne	ttl
	jecxz	ttns
	dec		esi
	push	es
	push	ds
	pop		es
	mov		al,' '
	xchg	esi,edi
	cld
	rep		stosb
	xchg	esi,edi
	pop		es
ttns:
	mov		byte ptr [esi], 0
	ret
TabTo	ENDP	


GetST	PROC	
;	mov byte ptr [esi],C_REGISTER
;	inc esi
	push	edi
	mov	al,[edi+operand.thereg]
	push	eax
	xchg	esi,edi
	mov	esi,offset stsreg
	call	strcpy
	pop	eax
	add	al,'0'
	dec	di
	stosb
	mov	al,')'
	stosb
	sub	al,al
	stosb
	dec	edi
	xchg	esi,edi
	pop	edi
;	mov byte ptr [esi],C_DEFAULT
;	inc si
	mov byte ptr [esi], 0
	ret
GetST	ENDP	

GetMMX   PROC    
;	mov byte ptr [esi],C_REGISTER
;	inc esi
	push	edi
	mov	al,[edi+operand.thereg]
	push	eax
	xchg	esi,edi
        mov     esi,offset mmxreg
	call	strcpy
	pop	eax
	add	al,'0'
	dec	edi
	stosb
	sub	al,al
	stosb
	dec	edi
	xchg	esi,edi
	pop	edi
;	mov byte ptr [esi],C_DEFAULT
;	inc	si
	mov byte ptr [esi],0
	ret
GetMMX   ENDP    

GetStdReg	PROC	
;	mov byte ptr[esi],C_REGISTER
;	inc esi
	push	edi
	or	al,al
	jnz	short gsrnoe
	mov	BYTE PTR [esi],'e'
	inc	esi
gsrnoe:
	mov	edi,offset regs
	movzx	ecx,cx
	mov	ax,[edi+ecx *2]
	mov	[esi],al
	inc	esi
	mov	[esi],ah
	inc	esi
;	mov byte ptr [esi],C_DEFAULT
;	inc esi
	mov	BYTE PTR [esi],0
	pop	edi
	ret
GetStdReg	ENDP	


GetReg	PROC	
	movzx	ecx,al
	sub	al,al
	inc	al
	bt	[edi+operand.oeflags],OMF_BYTE
	jc	short grno32
	bt	[edi+operand.oeflags],OMF_OP32
	jnc	short grno32
	dec	al
grno32:
	bt	[edi+operand.oeflags],OMF_BYTE
	jc	short isbyte
	or	cl,8
isbyte:
	call	GetStdReg
	ret
GetReg	ENDP	


GetSpecial	PROC	
;	mov byte ptr [esi],C_REGISTER
;	inc esi
	mov	al,[ebx]
	mov	[esi],al
	inc	esi
	inc	ebx
	mov	al,[ebx]
	mov	[esi],al
	inc	esi
	inc	ebx
	movzx	eax,[edi+operand.thereg]
	movzx	ebx,bx
	mov	al,[ebx +eax]
	mov	[esi],al
	inc	esi
;	mov byte ptr [esi],C_DEFAULT
;	inc esi
	mov	BYTE PTR [esi],0
	ret
GetSpecial	ENDP	


GetSeg	PROC	
;	mov byte ptr [esi],C_RESERVEDWORD
;	inc esi
	push	edi
	push	eax
	mov	edi,offset psegs
	movzx	ecx,cx
	mov	ax,[edi+ecx *2]
	mov	[esi],al
	inc	esi
	mov	[esi],ah
	inc	esi
;	mov BYTE PTR [esi],C_DEFAULT
;	inc esi
	pop	eax
	or	al,al
	mov	al,':'
	jz	short nocolon
	mov	[esi],al
	inc	esi
nocolon:
	mov	BYTE PTR [esi],0
	pop	edi
	ret
GetSeg	ENDP	


SegOverride	PROC	
	mov	al,1
        mov     [hasputoverride],al
	sub	ecx,ecx
	test	[segs],SG_ES
	jz	short so_testcs
	call	GetSeg
so_testcs:
	inc	ecx
	test	[segs],SG_CS
	jz	short so_testss
	call	GetSeg
so_testss:
	inc	ecx
	test	[segs],SG_SS
	jz	short so_testds
	call	GetSeg
so_testds:
	inc	ecx
	test	[segs],SG_DS
	jz	short so_testfs
	call	GetSeg
so_testfs:
	inc	ecx
	test	[segs],SG_FS
	jz	short so_testgs
	call	GetSeg
so_testgs:
	inc	ecx
	test	[segs],SG_GS
	jz	short so_done
	call	GetSeg
so_done:
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
SegOverride	ENDP	


scaled	PROC	
	push	DWORD PTR [edi+operand.oeflags]
	btr	[edi+operand.oeflags],OMF_BYTE
	bts	[edi+operand.oeflags],OMF_OP32
	or	al,al
	jz	short notbased
	sub	al,al
	mov	al,[edi+operand.thereg]
	call	GetReg
notbased:
	bt	[edi+operand.oeflags],OMF_SCALED
	jnc	short notscaled2
	mov	byte ptr [esi],'+'
	inc	esi
	mov	al,[edi+operand.scalereg]
	call	GetReg
	movzx	cx,[edi+operand.scale]
;        or      cx,cx
;        jz      notscaled2
	add	ecx,ecx
;	mov byte ptr [esi],C_NUMBER
;	inc	esi

	lea	ecx,[ecx + offset scales]
	mov	ax,[ecx]
	call	put2
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
notscaled2:
	pop	DWORD PTR [edi+operand.oeflags]
	ret
scaled	ENDP	


FOM_FSTREG	PROC	
	mov	edi,offset stalone
	call	strcat
	ret
FOM_FSTREG	ENDP	


FOM_CRX	PROC	
	mov	ebx,offset crreg
	call	GetSpecial
	ret
FOM_CRX	ENDP	


FOM_DRX	PROC	
	mov	ebx,offset drreg
	call	GetSpecial
	ret
FOM_DRX	ENDP	


FOM_TRX	PROC	
	mov	ebx,offset trreg
	call	GetSpecial
	ret
FOM_TRX	ENDP	


FOM_SUD	PROC	
	mov	ebx,offset sudreg
	call	GetSpecial
	ret
FOM_SUD	ENDP	


FOM_PORT	PROC	
	mov	al,SY_PORT
	jmp	FormatValue
FOM_PORT	ENDP	


FOM_INT	PROC	
	mov	al,SY_INTR
	jmp	FormatValue
FOM_INT	ENDP	


FOM_SHIFT	PROC	
	bt	[edi+operand.oeflags],OMF_CL
	jnc	fos_notcl
;	mov byte ptr [esi],C_REGISTER
;	inc	esi
	mov	ax,"cl"
	call	put2
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
fos_notcl:
	cmp	[edi+operand.address],1
	mov	al,SY_SHIFT
	jnz	FormatValue
	mov	BYTE PTR [esi],'1'
	inc	esi
	mov	BYTE PTR [esi],0
	ret
FOM_SHIFT	ENDP	


FOM_RETURN	PROC	
	mov	al,SY_RETURN
	jmp	FormatValue
FOM_RETURN	ENDP	


FOM_SHORTBRANCH	PROC	
	mov	al,SY_SHORTBRANCH
	jmp	FormatValue
FOM_SHORTBRANCH	ENDP	


FOM_LONGBRANCH	PROC	
	mov	al,SY_LONGBRANCH
	jmp	FormatValue
FOM_LONGBRANCH	ENDP	


FOM_FARBRANCH	PROC	
;        push    ebx
        mov     dx,[edi+operand.oeseg]
;        mov     ebx,[edi + operand.address]
;        push    es
;        push    edi
;        call    symLookupByValue
;        jc      psa_fb
;	mov byte ptr [esi],C_SYMBOL
;	inc	esi
;        call    putsyms
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
;        pop     edi
;        pop     es
;        pop     ebx
;        mov     byte ptr [esi],'('
;        inc     si
;	mov	al,SY_SEGMENT
;	call	FormatValue
;	mov	BYTE PTR [esi],':'
;	inc	esi
;        mov     eax,[edi + operand.address]
;        call    PutWordox
;        mov     byte ptr [esi],')'
;        inc     esi
;	mov	byte ptr [esi],0
;        ret
;psa_fb:
;        pop     edi
;        pop     es
;        pop     ebx
	mov	al,SY_SEGMENT
	call	FormatValue
	mov	BYTE PTR [esi],':'
	inc	esi
	mov	al,SY_ABSBRANCH
        jmp     FormatValue
FOM_FARBRANCH	ENDP	


FOM_ABSOLUTE	PROC	
	call	DoReqsPtrSizeOvride
	call	SegOverride
	mov	BYTE PTR [esi],'['
	inc	esi
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov	BYTE PTR [esi],0
	bt	[edi+operand.oeflags],OMF_SCALED
	jnc	foa_notscaled
	mov	al,SY_WORDOFS
	call	FormatValue
	sub	eax,eax
	call	scaled
	jmp	short foa_finish
foa_notscaled:
	mov	al,SY_ABSOLUTE
	call	FormatValue
foa_finish:
	mov	BYTE PTR [esi],']'
	inc	esi
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov	BYTE PTR [esi],0
	ret
FOM_ABSOLUTE	ENDP	


FOM_IMMEDIATE	PROC	
	bt	[edi+operand.oeflags],OMF_BYTE
	mov	al,SY_WORDIMM
	jnc	short absformat
;	test	[optsignedimm],1
;	jnz	fi_signed
	push	ebx
	movzx	ebx,byte ptr [edi + operand.address]
        bt      [edi + operand.oeflags],OMF_SIGNED
        jnc     fi_nsi
        movsx   ebx,bl
fi_nsi:
	mov	[edi + operand.address],ebx
	pop	ebx
	jmp	FormatValue
;fi_signed:
;	mov	al,SY_BYTEOFS
;	bt	[edi+operand.oeflags],OMF_SIGNED
;	jnc	short absformat
;	mov	al,SY_SIGNEDIMM
;	test	[optsignedimm],1
;	jnz	absformat
;        movsx   eax,byte ptr [edi + operand.address]
;	mov	[edi + operand.address],eax
;	mov	al,SY_WORDIMM
absformat:
	jmp	FormatValue
FOM_IMMEDIATE	ENDP	


FOM_REG	PROC	
        bt      [edi+operand.oeflags],OMF_MMXTAB
        jnc     isfst
        call    GetMMX
        ret
isfst:
	bt	[edi+operand.oeflags],OMF_FST
	jnc	short foreg
	call	GetST
	ret
foreg:
	mov	al,[edi+operand.thereg]
	call	GetReg
	ret
FOM_REG	ENDP	


FOM_BASED	PROC	
	call	DoReqsPtrSizeOvride
	call	SegOverride
	mov	BYTE PTR [esi],'['
	inc	esi
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov	BYTE PTR [esi],0
	bt	[edi+operand.oeflags],OMF_ADR32
	jnc	fob_notscaled
	mov	al,1
	call	scaled
	jmp	short fob2
fob_notscaled:
;	mov 	byte ptr [esi],C_REGISTER
;	inc		esi
	push	edi
	push	esi
	movzx	eax,BYTE PTR [edi+operand.thereg]
	xchg	esi,edi
	mov	esi,offset based
	movzx	ecx,cx
	mov	esi,[esi+eax * 4]
	call	strcpy
	pop	esi
	pop	edi
	call	strlen
	add	esi,eax
;	mov		byte ptr [esi],C_DEFAULT
;	inc esi
	mov		byte ptr [esi],0
fob2:
	test	[edi+operand.oeflags],OMF_OFFSET
	jz	short fob_noofs
	bt	[edi+operand.oeflags],OMF_SIGNED_OFFSET
	mov	al,SY_SIGNEDOFS
	jc	fob_format
	mov	al,SY_WORDOFS
	bt	[edi+operand.oeflags],OMF_WORD_OFFSET
	jc	fob_format
	mov	al,SY_BYTEOFS
fob_format:
	call	FormatValue
fob_noofs:
	mov	BYTE PTR [esi],']'
	inc	esi
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov	BYTE PTR [esi],0
	ret
FOM_BASED	ENDP	


FOM_SEGMENT	PROC	
	movzx	cx,[edi+operand.thereg]
	sub	ax,ax
	call	GetSeg
	ret
FOM_SEGMENT	ENDP	


Putoperand	PROC	
	call	strlen
	add	esi,eax
	mov	al,[edi+operand.code]
	dec	al
	js	short po_none
	push	0
	call	TableDispatch
	dd	17
	dd	FOM_BASED
	dd	FOM_SEGMENT
	dd	FOM_REG
	dd	FOM_IMMEDIATE
	dd	FOM_ABSOLUTE
	dd	FOM_FARBRANCH
	dd	FOM_LONGBRANCH
	dd	FOM_SHORTBRANCH
	dd	FOM_RETURN
	dd	FOM_SHIFT
	dd	FOM_INT
	dd	FOM_PORT
	dd	FOM_SUD
	dd	0
	dd	FOM_TRX
	dd	FOM_DRX
	dd	FOM_CRX
	dd	FOM_FSTREG
po_none:
	ret
Putoperand	ENDP	


FormatDisassembly	PROC	
	ENTER	256,0
        mov     [hasputoverride],0
	push	esi
	lea	edi,[ebp-256]
	push	edi
	mov	BYTE PTR [edi],0
        test    [segs],SG_LOCK
        jz      fd_notlock
        mov     esi,offset st_lock
        call    strcpy
fd_notlock:
	test	[segs],SG_REPZ
	jz	fd_notrepz
	mov	esi,offset st_repz
        call    strcat
fd_notrepz:
	test	[segs],SG_REPNZ
	jz	fd_notrepnz
		mov	esi,offset st_repnz
        call    strcat
fd_notrepnz:
	pop	edi
	xchg	esi,edi
	call	strlen
	add	esi,eax
;	mov	byte ptr [esi], C_INSTRUCTION
;	inc esi
	mov	byte ptr [esi], 0
	xchg	esi,edi
	mov	esi,offset nmmnemonic
	call	strcat
	lea	esi,[ebp-256]
	sub	eax,eax
	mov	al,TAB_ARGPOS
	call	TabTo
;	mov	byte ptr [esi], C_DEFAULT
;	inc esi
	mov	byte ptr [esi], 0
	mov	edi,offset dest
	call	Putoperand
	mov	edi,offset source
	test	[edi+operand.code],-1
	jz	short nosource
	mov	BYTE PTR [esi],','
	inc	esi
	mov	BYTE PTR [esi],0
	call	Putoperand
nosource:
	mov	edi,offset extraoperand
	test	[edi+operand.code],-1
	jz	short noextra
	mov	BYTE PTR [esi],','
	inc	esi
	mov	BYTE PTR [esi],0
	call	Putoperand
noextra:
	pop	esi	
	mov	BYTE PTR [esi],0
        test    [hasputoverride],255
        jnz     nonewover
	call	SegOverride
nonewover:
	mov	edi,esi
	lea	esi,[ebp-256]
	call	strcat
	LEAVE
	ret
FormatDisassembly	ENDP	


PutDword:
	push	eax		; To print a dword
	shr	eax,16		; Print the high 16 bits
	call	PutWord
	pop	eax		; And the low 16 bits
PutWord:
	push	eax		; To print a word
	mov	al,ah		; Print the high byte
	call	PutByte
	pop	eax		; And the low byte
PutByte:
	push	eax		; To print a byte
	shr	eax,4		; Print the high nibble
	call	putnibble
	pop	eax		; And the low nibble
putnibble:
	and	al,0fh		; Get a nibble
	add	al,'0'		; Make it numeric
	cmp	al,'9'		; If supposed to be alphabetic
	jle	onib
	add	al,7		; Add 7
onib:
	mov	[esi],al
	inc	esi
	ret

PutWordox:
;	mov byte ptr [esi],C_NUMBER
;	inc	esi
	bt	[edi+operand.oeflags],OMF_OP32
	jnc	PutWord
	jmp	PutDword
PutWordax:
;	mov byte ptr [esi],C_NUMBER
;	inc	esi
	bt	[edi+operand.oeflags],OMF_ADR32
	jnc	PutWord
	jmp	PutDword

;putsyms PROC
;        push    ecx
;        xchg    esi,edi
;        push    ds
;        push    es
;        push    ds
;        push    es
;        pop     ds
;        pop     es
;        add     esi,6
;        lodsb
;        movzx   ecx,al
;        rep     movsb
;        xchg    esi,edi
;        pop     es
;        pop     ds
;        pop     ecx
;        ret
;putsyms ENDP
defseg PROC
        test    [segs],SG_ES
        jnz     defes
        test    [segs],SG_DS
        jnz     defds
        test    [segs],SG_CS
        jnz     defcs
        test    [segs],SG_SS
        jnz     defss
        test    [segs],SG_FS
        jnz     deffs
        test    [segs],SG_GS
        jnz     defgs
defds:
        mov     dx,[drds]
        ret
defes:
        mov     dx,[dres]
        ret
defcs:
        mov     dx,[drcs]
        ret
defss:
        mov     dx,[drss]
        ret
deffs:
        mov     dx,[drfs]
        ret
defgs:
        mov     dx,[drgs]
        ret
        
defseg ENDP
putsymax PROC
;        push    ebx
;        mov     ebx,eax
;        call    defseg
;        push    es
;        push    edi
;        call    symLookupByValue
;        jc      psa_n
;		mov byte ptr [esi],C_SYMBOL
;		inc	esi
;        call    putsyms
;        pop     edi
;        pop     es
;		mov byte ptr [esi],C_NUMBER
;		inc	esi
;        mov     byte ptr [esi],'('
;        inc     esi
;        mov     eax,ebx
;        pop     ebx
;        call    PutWordax
;        mov     byte ptr [esi],')'
;        inc     esi
;;		mov byte ptr [esi],C_DEFAULT
;;		inc	esi
;		mov byte ptr [esi],0
;        ret
;psa_n:
;        pop     edi
;        pop     es
;        mov     eax,ebx
;        pop     ebx
        jmp     PutWordax
putsymax ENDP
putsymox PROC
;        push    ebx
;        mov     ebx,eax
;        call    defseg
;        push    es
;        push    edi
;        call    symLookupByValue
;        jc      pso_n
;		mov byte ptr [esi],C_SYMBOL
;		inc	esi
;        call    putsyms
;        pop     edi
;        pop     es
;		mov byte ptr [esi],C_NUMBER
;		inc	esi
;        mov     byte ptr [esi],'('
;        inc     esi
;        mov     eax,ebx
;        pop     ebx
;        call    PutWordox
;        mov     byte ptr [esi],')'
;        inc     esi
;		mov byte ptr [esi],C_DEFAULT
;		inc	esi
;		mov byte ptr [esi],0
;        ret
;pso_n:
;        pop     edi
;        pop     es
;        mov     eax,ebx
;        pop     ebx
        jmp     PutWordox
putsymox ENDP
putsymbr PROC
;        push    ebx
;        mov     ebx,eax
;        mov     dx,[drCS]
;        push    es
;        push    edi
;        call    symLookupByValue
;        jc      pso_b
;		mov byte ptr [esi],C_SYMBOL
;		inc	esi
;        call    putsyms
;        pop     edi
;        pop     es
;		mov byte ptr [esi],C_NUMBER
;		inc	esi
;        mov     byte ptr [esi],'('
;        inc     esi
;        mov     eax,ebx
;        pop     ebx
;        call    PutWordox
;        mov     byte ptr [esi],')'
;        inc     esi
;		mov byte ptr [esi],C_DEFAULT
;		inc	esi
;		mov byte ptr [esi],0
;        ret
;pso_b:
;        pop     edi
;        pop     es
;        mov     eax,ebx
;        pop     ebx
        jmp     PutWordox
putsymbr ENDP
FSY_SIGNEDOFS   PROC    
	push	ebx
	mov	eax,[edi+operand.address]
	bt	eax,7
	mov	bl,'+'
	jnc	fso_pos
	mov	bl,'-'
	neg	al
fso_pos:
	mov	byte ptr [esi],bl
	inc esi
;	mov byte ptr [esi],C_NUMBER
;	inc	esi
	call	PutByte
	pop	ebx
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
FSY_SIGNEDOFS	ENDP	


FSY_WORDOFS	PROC	
	push	ebx
	mov	eax,[edi+operand.address]
        bt      [edi + operand.oeflags],OMF_ADR32
        jnc     wordchk
        cmp     eax,-40000000h
        jmp     fwo_join
wordchk:
	cmp	ax,-4000h
fwo_join:
	mov	bl,'+'
	jc	fsy_wouseplus
        neg     eax
	mov	bl,'-'
fsy_wouseplus:
	mov	byte ptr [esi],bl
	inc esi
;	mov byte ptr [esi],C_NUMBER
;	inc	esi
    call    putsymax
	pop	ebx
	ret
FSY_WORDOFS	ENDP	


FSY_BYTEOFS	PROC	
;	mov byte ptr [esi],C_NUMBER
;	inc	esi
	mov	eax,[edi+operand.address]
	call	PutByte
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
FSY_BYTEOFS	ENDP	


FSY_ABSOLUTE	PROC	
	mov	eax,[edi+operand.address]
        call    putsymax
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
FSY_ABSOLUTE	ENDP	


FSY_SIGNEDIMM	PROC	
	jmp	FSY_SIGNEDOFS
FSY_SIGNEDIMM	ENDP	


FSY_WORDIMM	PROC	
	mov	eax,[edi+operand.address]
        call    putsymox
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
FSY_WORDIMM	ENDP	


FSY_BYTEIMM	PROC	
;	mov byte ptr [esi],C_NUMBER
;	inc	esi
	mov	eax,[edi+operand.address]
	call	PutByte
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
FSY_BYTEIMM	ENDP	


FSY_PORT	PROC	
;	mov byte ptr [esi],C_NUMBER
;	inc	esi
	mov	eax,[edi+operand.address]
	call	PutByte
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
FSY_PORT	ENDP	


FSY_INTR	PROC	
;	mov byte ptr [esi],C_NUMBER
;	inc	esi
	mov	eax,[edi+operand.address]
	call	PutByte
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
FSY_INTR	ENDP	


FSY_RETURN	PROC	
;	mov byte ptr [esi],C_NUMBER
;	inc	esi
	mov	eax,[edi+operand.address]
	call	PutWord
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
FSY_RETURN	ENDP	


FSY_ABSBRANCH	PROC	
	mov	eax,[edi+operand.address]
        call    putsymbr
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
FSY_ABSBRANCH	ENDP	


FSY_LONGBRANCH	PROC	
	mov	eax,[edi+operand.address]
        call    putsymbr
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
FSY_LONGBRANCH	ENDP	


FSY_SHORTBRANCH	PROC	
	mov	eax,[edi+operand.address]
        call    putsymbr
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
FSY_SHORTBRANCH	ENDP	


FSY_SHIFT	PROC	
;	mov byte ptr [esi],C_NUMBER
;	inc	esi
	mov	eax,[edi+operand.address]
	call	PutByte
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
FSY_SHIFT	ENDP	


FSY_SEGMENT	PROC	
;	mov byte ptr [esi],C_NUMBER
;	inc	esi
	mov	ax,[edi+operand.oeseg]
	call	PutWord
;	mov byte ptr [esi],C_DEFAULT
;	inc	esi
	mov byte ptr [esi],0
	ret
FSY_SEGMENT	ENDP	


FormatValue	PROC	
	dec	al
	push	0
	call	TableDispatch
	dd	14
	dd	FSY_SIGNEDOFS,FSY_WORDOFS,FSY_BYTEOFS,FSY_ABSOLUTE
	dd	FSY_SIGNEDIMM,FSY_WORDIMM,FSY_BYTEIMM,FSY_PORT
	dd	FSY_INTR,FSY_RETURN,FSY_ABSBRANCH,FSY_LONGBRANCH
	dd	FSY_SHORTBRANCH,FSY_SHIFT,FSY_SEGMENT
	mov	byte ptr [esi],0
	ret
FormatValue	ENDP	

END
