⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 em86real.s

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 S
📖 第 1 页 / 共 5 页
字号:
#define CL	4#define CX	4#define ECX	4#define DX	8#define EDX	8#define BX	12#define EBX	12#define SP	16#define ESP	16#define BP	20#define EBP	20#define SI	24#define ESI	24#define DI	28#define EDI	28/* than the rest of the machine state, big endian !offset     name       32       essel     segment register selectors (values)  36	   cssel  40       sssel  44       dssel  48       fssel  52       gssel  56       eipimg    true eip (register named eip is csbase+eip)  60       eflags    eip and eflags only valid when C code running !  64       esbase    segment registers bases  68       csbase  72       ssbase  76       dsbase  80       fsbase  84       gsbase  88       iobase    For I/O instructions, I/O space virtual base  92       ioperm    I/O permission bitmap pointer  96       reason    Reason code when calling external emulator 100       nexteip   eip past instruction for external emulator 104       parm1     parameter for external emulator 108       parm2     parameter for external emulator 112       _opcode   current opcode register for external emulator 116       _base     segment register base for external emulator 120       _offset   intruction operand offset More internal state was dumped here for debugging in first versions 128       vbase     where the 1Mb memory is mapped 132       cntimg    instruction counter 136                 scratch          192       eipstat   array of 32k unsigned long pairs for eip stats*/#define essel	32#define cssel	36#define sssel	40#define dssel	44#define fssel	48#define gssel	52#define eipimg	56#define eflags	60#define esbase	64#define csbase	68#define ssbase	72#define dsbase	76#define fsbase	80#define gsbase	84#define iobase	88#define ioperm	92#define reason	96#define nexteip	100#define parm1	104#define parm2	108#define _opcode	112#define _base	116#define _offset 120#define vbase	128#define cntimg	132#ifdef EIP_STATS#define eipstat	192#endif/* Global registers *//* Some segment register bases are permanently kept in registers since they are often used: these are csb, esb and ssb because they arerequired for jumps, string instructions, and pushes/pops/calls/rets.dsbase is not kept in a register but loaded from memory to allow somewhatmore parallelism in the main emulation loop. */#define one	30		/* Constant one, so pervasive */#define ssb	29#define csb	28#define esb	27#define eip	26		/* That one is indeed csbase+(e)ip-1 */	#define result	25		/* For the use of result, op1, op2 */#define op1	24		/* see the section on flag emulation */#define op2	23#define opbase	22		/* default opcode table */#define flags	21		/* See earlier description */#define opcode	20		/* Opcode */#define opreg	19		/* Opcode extension/register number *//* base is reloaded with the base of the ds segment at the beginning ofevery instruction, it is modified by segment override prefixes, whenthe default base segment is ss, or when the modrm byte specifies aregister operand */#define base	18		/* Instruction's operand segment base */#define offset	17		/* Instruction's memory operand offset *//* used to address a table telling how to decode the addressing modespecified by the modrm byte */#define adbase	16		/* addressing mode table *//* Following registers are used only as dedicated temporaries during decoding,they are free for use during emulation *//*  * ceip (current eip) is only in use when we call the external emulator for  * instructions that fault. Note that it is forbidden to change flags before  * the check for the fault happens (divide by zero...) ! ceip is also used  * when measuring timing.  */#define ceip 15/* A register used to measure timing information (when enabled) */#ifdef EIP_STATS#define tstamp 14#endif#define count 12		/* Instruction counter. */#define r0 0#define r1 1			/* PPC Stack pointer. */#define r3 3#define r4 4#define r5 5#define r6 6#define r7 7/* Macros to read code stream */#define NEXTBYTE(dest) lbzu dest,1(eip)#define NEXTWORD(dest) lhbrx dest,eip,one; la eip,2(eip)#define NEXTDWORD(dest) lwbrx dest,eip,one; la eip,4(eip)#define NEXT	b nop#define GOTNEXT b gotopcode#ifdef __BOOT__		START_GOT		GOT_ENTRY(_jtables)		GOT_ENTRY(jtab_www)		GOT_ENTRY(adtable)		END_GOT#else			.text#endif		.align 2		.global em86_enter		.type em86_enter,@functionem86_enter:	stwu r1,-96(r1)			# allocate stack		mflr r0		stmw 14,24(r1)		mfcr r4		stw r0,100(r1)		mr state,r3		stw r4,20(r1)#ifdef __BOOT__/* We need this since r30 is the default GOT pointer */#define	r30 30		GET_GOT/* The relocation of these tables is explicit, this could be done * automatically with fixups but would add more than 8kb in the fixup tables. */		lwz r3,GOT(_jtables)		lwz r4,_endjtables-_jtables(r3)		sub. r4,r3,r4		beq+ 1f		li r0,((_endjtables-_jtables)>>2)+1		addi r3,r3,-4		mtctr r00:		lwzu r5,4(r3)		add r5,r5,r4		stw r5,0(r3)		bdnz 0b1:		lwz adbase,GOT(adtable)		lwz opbase,GOT(jtab_www)/* Now r30 is only used as constant 1 */#undef r30		li one,1			# pervasive constant#else		lis opbase,jtab_www@ha		lis adbase,adtable@ha		li one,1			# pervasive constant		addi opbase,opbase,jtab_www@l		addi adbase,adbase,adtable@l#ifdef EIP_STATS		li ceip,0		mftb tstamp#endif#endif/* We branch back here when calling an external function tells us to resume */restart:	lwz r3,eflags(state)		lis flags,(OF_EXPLICIT|ZF_IN_CR|ZF_PROTECT|SF_IN_CR)>>16		lwz csb,csbase(state)		extsb result,r3			# SF/PF		rlwinm op1,r3,31,0x08		# AF		lwz eip,eipimg(state)		ZF862ZF(r3)			# cr6		addi op2,op1,0			# AF		lwz ssb,ssbase(state)		rlwimi flags,r3,15,OF_VALUE	# OF		rlwimi r3,r3,32+RF86-RF,RF,RF	# RF		lwz esb,esbase(state)		ori result,result,0xfb		# PF		mtcrf 0x06,r3			# RF/DF/IF/TF/SF/ZF		lbzux opcode,eip,csb		rlwimi flags,r3,27,CF_VALUE	# CF		xori result,result,0xff		# PF		lwz count,cntimg(state)		GOTNEXT				# start the emulator/* Now return */exit:		lwz r0,100(r1)		lwz r4,20(r1)		mtlr r0		lmw 14,24(r1)		mtcr r4		addi r1,r1,96		blr	trap:		crmove 0,RF		crclr RF		bt- 0,resume		sub ceip,eip,csb		li r3,code_trapcomplex:	addi eip,eip,1		stw r3,reason(state)		sub eip,eip,csb		stw op1,240(state)		stw op2,244(state)		stw result,248(state)		stw flags,252(state)		stw r4,parm1(state)		stw r5,parm2(state)		stw opcode,_opcode(state)		bl _eval_flags		stw base,_base(state)		stw eip,nexteip(state)		stw r3,eflags(state)		mr r3,state		stw offset,_offset(state)		stw ceip,eipimg(state)		stw count,cntimg(state)		bl em86_trap		cmpwi r3,0		bne exit		b restart	/* Main loop *//*  * The two LSB of each entry in the main table mean the following: * 00: indirect opcode: modrm follows and the three middle bits are an  *     opcode extension. The entry points to another jump table. * 01: direct instruction, branch directly to the routine. * 10: modrm specifies byte size memory and register operands. * 11: modrm specifies word/long memory and register operands. *	 *  The modrm byte, if present, is always loaded in r7. * * Note: most "mr x,y" instructions have been replaced by "addi x,y,0" since * the latter can be executed in the second integer unit on 603e.  *//*  * This code is very good example of absolutely unmaintainable code. * It was actually much easier to write than it is to understand ! * If my computations are right, the maximum path length from fetching * the opcode to exiting to the actual instruction execution is * 46 instructions (for non-prefixed, single byte opcode instructions). * */		.align 5	#ifdef EIP_STATSnop:		NEXTBYTE(opcode)gotopcode:	slwi r3,opcode,2		bt- TF,trapresume:		lwzx r4,opbase,r3		addi r5,state,eipstat+4		clrlslwi r6,ceip,17,3		mtctr r4		lwzux r7,r5,r6		slwi. r0,r4,30		# two lsb of table entry		sub r7,r7,tstamp		lwz r6,-4(r5)		mftb tstamp		addi r6,r6,1		sub ceip,eip,csb		stw r6,-4(r5)		add r7,r7,tstamp		lwz base,dsbase(state)		stw r7,0(r5)#elsenop:		NEXTBYTE(opcode)gotopcode:	slwi r3,opcode,2		bt- TF,trapresume:		lwzx r4,opbase,r3		sub ceip,eip,csb		mtctr r4		slwi. r0,r4,30		# two lsb of table entry		lwz base,dsbase(state)		addi count,count,1#endif		bgtctr-			# for instructions without modrm/* modrm byte present */		NEXTBYTE(r7)		# modrm byte		cmplwi cr1,r7,192		rlwinm opreg,r7,31,0x1c		beq- cr0,8f		# extended opcode/* modrm with middle 3 bits specifying a register (non prefixed) */		rlwinm r0,r4,3,0x8		li r4,0x1c0d		rlwimi opreg,r7,27,0x01		srw r4,r4,r0		and opreg,opreg,r4		blt cr1,9f/* modrm with 2 register operands */1:		rlwinm offset,r7,2,0x1c		addi base,state,0		rlwimi offset,r7,30,0x01		and offset,offset,r4		bctr/* Prefixes: first segment overrides */		.align 4_es:		NEXTBYTE(r7); addi base,esb,0		oris opcode,opcode,0x8000; b 2f_cs:		NEXTBYTE(r7); addi base,csb,0		oris opcode,opcode,0x8000; b 2f_fs:		NEXTBYTE(r7); lwz base,fsbase(state)		oris opcode,opcode,0x8000; b 2f_gs:		NEXTBYTE(r7); lwz base,gsbase(state)		oris opcode,opcode,0x8000; b 2f_ss:		NEXTBYTE(r7); addi base,ssb,0		oris opcode,opcode,0x8000; b 2f_ds:		NEXTBYTE(r7)		oris opcode,opcode,0x8000; b 2f/* Lock (unimplemented) and repeat prefixes */_lock:		li r3,code_lock; b complex_repnz:		NEXTBYTE(r7); rlwimi opcode,one,12,0x1800; b 2f	_repz:		NEXTBYTE(r7); rlwimi opcode,one,11,0x1800; b 2f			/* Operand and address size prefixes */		.align 4_opsize:	NEXTBYTE(r7); ori opcode,opcode,0x200		rlwinm r3,opcode,2,0x1ffc; b 2f_adsize:	NEXTBYTE(r7); ori opcode,opcode,0x400		rlwinm r3,opcode,2,0x1ffc; b 2f_twobytes:	NEXTBYTE(r7); addi r3,r3,0x4002:		rlwimi r3,r7,2,0x3fc		lwzx r4,opbase,r3		rlwimi opcode,r7,0,0xff		mtctr r4		slwi. r0,r4,30		bgtctr-				# direct instruction/* modrm byte in a prefixed instruction */		NEXTBYTE(r7)			# modrm byte		cmpwi cr1,r7,192		rlwinm opreg,r7,31,0x1c		beq- 6f	/* modrm with middle 3 bits specifying a register (prefixed) */		rlwinm r0,r4,3,0x8		li r4,0x1c0d		rlwimi opreg,r7,27,0x01		srw r4,r4,r0		and opreg,opreg,r4		bnl cr1,1b			# 2 register operands/* modrm specifying memory with prefix */3:		rlwinm r3,r3,27,0xff80		rlwimi adbase,r7,2,0x1c		extsh r3,r3		rlwimi r3,r7,31,0x60		lwzx r4,r3,adbase		cmpwi cr1,r4,0x3090		bnl+ cr1,10f	/* displacement only addressing modes */4:		cmpwi r4,0x2000		bne 5f		NEXTWORD(offset)		bctr5:		NEXTDWORD(offset)		bctr/* modrm with opcode extension (prefixed) */ 6:		lwzx r4,r4,opreg		mtctr r4		blt cr1,3b/* modrm with opcode extension and register operand */7:		rlwinm offset,r7,2,0x1c		addi base,state,0		rlwinm r0,r4,3,0x8		li r4,0x1c0d		rlwimi offset,r7,30,0x01		srw r4,r4,r0		and offset,offset,r4		bctr/* modrm with opcode extension (non prefixed) */8:		lwzx r4,r4,opreg		mtctr r4/* FIXME ? We continue fetching even if the opcode extension is undefined. * It shouldn't do any harm on real mode emulation anyway, and for ROM * BIOS emulation, we are supposed to read valid code. */		bnl cr1,7b/* modrm specifying memory without prefix */9:		rlwimi adbase,r7,2,0x1c	# memory addressing mode computation		rlwinm r3,r7,31,0x60		lwzx r4,r3,adbase		cmplwi cr1,r4,0x3090		blt- cr1,4b		# displacement only addressing mode10:		rlwinm. r0,r7,24,0,1	# three cases distinguished		beq- cr1,15f		# an sib follows		rlwinm r3,r4,30,0x1c	# 16bit/32bit/%si index/%di index		cmpwi cr1,r3,8		# set cr1 as early as possible		rlwinm r6,r4,26,0x1c	# base register		lwbrx offset,state,r6	# load the base register 		beq cr0,14f		# no displacement		cmpw cr2,r4,opcode	# check for ss as default base		bgt cr0,12f		# byte offset		beq cr1,11f		# 32 bit displacement		NEXTWORD(r5)		# 16 bit displacement		bgt cr1,13f		# d16(base,index)/* d16(base) */		add offset,offset,r5		clrlwi offset,offset,16		bgtctr cr2		addi base,ssb,0		bctr/* d32(base) */11:		NEXTDWORD(r5)		add offset,offset,r5		bgtctr cr2		addi base,ssb,0		bctr/* 8 bit displacement */	12:		NEXTBYTE(r5)		extsb r5,r5		bgt cr1,13f/* d8(base) */		extsb r6,r4		add offset,offset,r5		ori r6,r6,0xffff		and offset,offset,r6		bgtctr cr2		addi base,ssb,0		bctr/* d8(base,index) and d16(base,index) share this code ! */13:		lhbrx r3,state,r3		add offset,offset,r5		add offset,offset,r3		clrlwi offset,offset,16		bgtctr cr2		addi base,ssb,0		bctr/* no displacement: only indexed modes may use ss as default base */ 14:		beqctr cr1		# 32 bit register indirect		clrlwi offset,offset,16		bltctr cr1		# 16 bit register indirect/* (base,index) */		lhbrx r3,state,r3	# 16 bit [{bp,bx}+{si,di}]		cmpw cr2,r4,opcode	# check for ss as default base		add offset,offset,r3		clrlwi offset,offset,r3		bgtctr+ cr2		addi base,ssb,0		bctr/* sib modes, note that the size of the offset can be known from cr0 */15:		NEXTBYTE(r7)			# get sib		rlwinm r3,r7,31,0x1c		# index		rlwinm offset,r7,2,0x1c		# base		cmpwi cr1,r3,ESP		# has index ?		bne cr0,18f			# base+d8/d32			cmpwi offset,EBP		beq 17f				# d32(,index,scale)		xori r4,one,0xcc01		# build 0x0000cc00		rlwnm r4,r4,offset,0,1		# 0 or 0xc0000000		lwbrx offset,state,offset		cmpw cr2,r4,opcode		# use ss ?		beq- cr1,16f			# no index/* (base,index,scale) */		lwbrx r3,state,r3		srwi r6,r7,6		slw r3,r3,r6		add offset,offset,r3		bgtctr cr2		addi base,ssb,0		bctr/* (base), in practice only (%esp) is coded this way */16:		bgtctr cr2

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -