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

📄 decoder.h

📁 DOSBox emulates a full x86 pc with sound and dos. Its main use is to run old dosgames on platforms w
💻 H
📖 第 1 页 / 共 5 页
字号:
/* *  Copyright (C) 2002-2007  The DOSBox Team * *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#define X86_DYNFPU_DH_ENABLED#define X86_INLINED_MEMACCESSenum REP_Type {	REP_NONE=0,REP_NZ,REP_Z};static struct DynDecode {	PhysPt code;	PhysPt code_start;	PhysPt op_start;	bool big_op;	bool big_addr;	REP_Type rep;	Bitu cycles;	CacheBlock * block;	CacheBlock * active_block;	struct {		CodePageHandler * code;			Bitu index;		Bit8u * wmap;		Bit8u * invmap;		Bitu first;	} page;	struct {		Bitu val;		Bitu mod;		Bitu rm;		Bitu reg;	} modrm;	DynReg * segprefix;} decode;static bool MakeCodePage(Bitu lin_page,CodePageHandler * &cph) {	Bit8u rdval;	//Ensure page contains memory:	if (GCC_UNLIKELY(mem_readb_checked_x86(lin_page << 12,&rdval))) return true;	PageHandler * handler=paging.tlb.handler[lin_page];	if (handler->flags & PFLAG_HASCODE) {		cph=( CodePageHandler *)handler;		return false;	}	if (handler->flags & PFLAG_NOCODE) {		LOG_MSG("DYNX86:Can't run code in this page");		cph=0;		return false;	} 	Bitu phys_page=lin_page;	if (!PAGING_MakePhysPage(phys_page)) {		LOG_MSG("DYNX86:Can't find physpage");		cph=0;		return false;	}	/* Find a free CodePage */	if (!cache.free_pages) {		if (cache.used_pages!=decode.page.code) cache.used_pages->ClearRelease();		else {			if ((cache.used_pages->next) && (cache.used_pages->next!=decode.page.code))				cache.used_pages->next->ClearRelease();			else {				LOG_MSG("DYNX86:Invalid cache links");				cache.used_pages->ClearRelease();			}		}	}	CodePageHandler * cpagehandler=cache.free_pages;	cache.free_pages=cache.free_pages->next;	cpagehandler->prev=cache.last_page;	cpagehandler->next=0;	if (cache.last_page) cache.last_page->next=cpagehandler;	cache.last_page=cpagehandler;	if (!cache.used_pages) cache.used_pages=cpagehandler;	cpagehandler->SetupAt(phys_page,handler);	MEM_SetPageHandler(phys_page,1,cpagehandler);	PAGING_UnlinkPages(lin_page,1);	cph=cpagehandler;	return false;}static Bit8u decode_fetchb(void) {	if (GCC_UNLIKELY(decode.page.index>=4096)) {        /* Advance to the next page */		decode.active_block->page.end=4095;		/* trigger possible page fault here */		mem_readb((++decode.page.first) << 12);		MakeCodePage(decode.page.first,decode.page.code);		CacheBlock * newblock=cache_getblock();		decode.active_block->crossblock=newblock;		newblock->crossblock=decode.active_block;		decode.active_block=newblock;		decode.active_block->page.start=0;		decode.page.code->AddCrossBlock(decode.active_block);		decode.page.wmap=decode.page.code->write_map;		decode.page.invmap=decode.page.code->invalidation_map;		decode.page.index=0;	}	decode.page.wmap[decode.page.index]+=0x01;	decode.page.index++;	decode.code+=1;	return mem_readb(decode.code-1);}static Bit16u decode_fetchw(void) {	if (GCC_UNLIKELY(decode.page.index>=4095)) {   		Bit16u val=decode_fetchb();		val|=decode_fetchb() << 8;		return val;	}	*(Bit16u *)&decode.page.wmap[decode.page.index]+=0x0101;	decode.code+=2;decode.page.index+=2;	return mem_readw(decode.code-2);}static Bit32u decode_fetchd(void) {	if (GCC_UNLIKELY(decode.page.index>=4093)) {   		Bit32u val=decode_fetchb();		val|=decode_fetchb() << 8;		val|=decode_fetchb() << 16;		val|=decode_fetchb() << 24;		return val;        /* Advance to the next page */	}	*(Bit32u *)&decode.page.wmap[decode.page.index]+=0x01010101;	decode.code+=4;decode.page.index+=4;	return mem_readd(decode.code-4);}#define START_WMMEM 64static void INLINE decode_increase_wmapmask(Bitu size) {	Bitu mapidx;	CacheBlock* activecb=decode.active_block; 	if (GCC_UNLIKELY(!activecb->cache.wmapmask)) {		activecb->cache.wmapmask=(Bit8u*)malloc(START_WMMEM);		memset(activecb->cache.wmapmask,0,START_WMMEM);		activecb->cache.maskstart=decode.page.index;		activecb->cache.masklen=START_WMMEM;		mapidx=0;	} else {		mapidx=decode.page.index-activecb->cache.maskstart;		if (GCC_UNLIKELY(mapidx+size>=activecb->cache.masklen)) {			Bitu newmasklen=activecb->cache.masklen*4;			if (newmasklen<mapidx+size) newmasklen=((mapidx+size)&~3)*2;			Bit8u* tempmem=(Bit8u*)malloc(newmasklen);			memset(tempmem,0,newmasklen);			memcpy(tempmem,activecb->cache.wmapmask,activecb->cache.masklen);			free(activecb->cache.wmapmask);			activecb->cache.wmapmask=tempmem;			activecb->cache.masklen=newmasklen;		}	}	switch (size) {		case 1 : activecb->cache.wmapmask[mapidx]+=0x01; break;		case 2 : (*(Bit16u*)&activecb->cache.wmapmask[mapidx])+=0x0101; break;		case 4 : (*(Bit32u*)&activecb->cache.wmapmask[mapidx])+=0x01010101; break;	}}static bool decode_fetchb_imm(Bitu & val) {	if (decode.page.index<4096) {		Bitu index=(decode.code>>12);		if (paging.tlb.read[index]) {			val=(Bitu)(paging.tlb.read[index]+decode.code);			decode_increase_wmapmask(1);			decode.code++;			decode.page.index++;			return true;		}	}	val=(Bit32u)decode_fetchb();	return false;}static bool decode_fetchw_imm(Bitu & val) {	if (decode.page.index<4095) {		Bitu index=(decode.code>>12);		if (paging.tlb.read[index]) {			val=(Bitu)(paging.tlb.read[index]+decode.code);			decode_increase_wmapmask(2);			decode.code+=2;			decode.page.index+=2;			return true;		}	}	val=decode_fetchw();	return false;}static bool decode_fetchd_imm(Bitu & val) {	if (decode.page.index<4093) {		Bitu index=(decode.code>>12);		if (paging.tlb.read[index]) {			val=(Bitu)(paging.tlb.read[index]+decode.code);			decode_increase_wmapmask(4);			decode.code+=4;			decode.page.index+=4;			return true;		}	}	val=decode_fetchd();	return false;}static void dyn_reduce_cycles(void) {	gen_protectflags();	if (!decode.cycles) decode.cycles++;	gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles);}static void dyn_save_noncritical_regs(void) {	gen_releasereg(DREG(EAX));	gen_releasereg(DREG(ECX));	gen_releasereg(DREG(EDX));	gen_releasereg(DREG(EBX));	gen_releasereg(DREG(ESP));	gen_releasereg(DREG(EBP));	gen_releasereg(DREG(ESI));	gen_releasereg(DREG(EDI));}static void dyn_save_critical_regs(void) {	dyn_save_noncritical_regs();	gen_releasereg(DREG(FLAGS));	gen_releasereg(DREG(EIP));	gen_releasereg(DREG(CYCLES));}static void dyn_set_eip_last_end(DynReg * endreg) {	gen_protectflags();	gen_lea(endreg,DREG(EIP),0,0,decode.code-decode.code_start);	gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.op_start-decode.code_start);}static INLINE void dyn_set_eip_end(void) {	gen_protectflags();	gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.code-decode.code_start);}static INLINE void dyn_set_eip_end(DynReg * endreg) {	gen_protectflags();	gen_dop_word(DOP_MOV,cpu.code.big,DREG(TMPW),DREG(EIP));	gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(TMPW),decode.code-decode.code_start);}static INLINE void dyn_set_eip_last(void) {	gen_protectflags();	gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.op_start-decode.code_start);}enum save_info_type {exception, cycle_check, normal, fpu_restore};static struct {	save_info_type type;	DynState state;	Bit8u * branch_pos;	Bit32u eip_change;	Bitu cycles;	Bit8u * return_pos;} save_info[512];Bitu used_save_info=0;static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub,Bit32u dflags) {	reg_flags=(dflags&FMASK_TEST) | (reg_flags&(~FMASK_TEST));	reg_eip+=eip_add;	CPU_Cycles-=cycle_sub;	if (cpu.exception.which==SMC_CURRENT_BLOCK) return BR_SMCBlock;	CPU_Exception(cpu.exception.which,cpu.exception.error);	return BR_Normal;}static void dyn_check_bool_exception(DynReg * check) {	gen_dop_byte(DOP_OR,check,0,check,0);	save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);	dyn_savestate(&save_info[used_save_info].state);	if (!decode.cycles) decode.cycles++;	save_info[used_save_info].cycles=decode.cycles;	save_info[used_save_info].eip_change=decode.op_start-decode.code_start;	if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff;	save_info[used_save_info].type=exception;	used_save_info++;}static void dyn_check_bool_exception_al(void) {	cache_addw(0xc00a);		// or al, al	save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);	dyn_savestate(&save_info[used_save_info].state);	if (!decode.cycles) decode.cycles++;	save_info[used_save_info].cycles=decode.cycles;	save_info[used_save_info].eip_change=decode.op_start-decode.code_start;	if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff;	save_info[used_save_info].type=exception;	used_save_info++;}#include "pic.h"static void dyn_check_irqrequest(void) {	gen_load_host(&PIC_IRQCheck,DREG(TMPB),4);	gen_dop_word(DOP_OR,true,DREG(TMPB),DREG(TMPB));	save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);	gen_releasereg(DREG(TMPB));	dyn_savestate(&save_info[used_save_info].state);	if (!decode.cycles) decode.cycles++;	save_info[used_save_info].cycles=decode.cycles;	save_info[used_save_info].eip_change=decode.code-decode.code_start;	if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff;	save_info[used_save_info].type=normal;	used_save_info++;}static void dyn_check_bool_exception_ne(void) {	save_info[used_save_info].branch_pos=gen_create_branch_long(BR_Z);	dyn_savestate(&save_info[used_save_info].state);	if (!decode.cycles) decode.cycles++;	save_info[used_save_info].cycles=decode.cycles;	save_info[used_save_info].eip_change=decode.op_start-decode.code_start;	if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff;	save_info[used_save_info].type=exception;	used_save_info++;}static void dyn_fill_blocks(void) {	for (Bitu sct=0; sct<used_save_info; sct++) {		gen_fill_branch_long(save_info[sct].branch_pos);		switch (save_info[sct].type) {			case exception:				dyn_loadstate(&save_info[sct].state);				decode.cycles=save_info[sct].cycles;				dyn_save_critical_regs();				if (cpu.code.big) gen_call_function((void *)&DynRunException,"%Id%Id%F",save_info[sct].eip_change,save_info[sct].cycles);				else gen_call_function((void *)&DynRunException,"%Iw%Id%F",save_info[sct].eip_change,save_info[sct].cycles);				gen_return_fast(BR_Normal,true);				break;			case cycle_check:				gen_return(BR_Cycles);				break;			case normal:				dyn_loadstate(&save_info[sct].state);				gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),save_info[sct].eip_change);				dyn_save_critical_regs();				gen_return(BR_Cycles);				break;			case fpu_restore:				dyn_loadstate(&save_info[sct].state);				gen_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),4);				gen_sop_word(SOP_INC,true,DREG(TMPB));				GenReg * gr1=FindDynReg(DREG(TMPB));				cache_addb(0xdd);	// FRSTOR fpu.state (fpu_restore)				cache_addb(0x25);				cache_addd((Bit32u)(&(dyn_dh_fpu.state[0])));				cache_addb(0x89);	// mov fpu.state_used,1				cache_addb(0x05|(gr1->index<<3));				cache_addd((Bit32u)(&(dyn_dh_fpu.state_used)));				gen_releasereg(DREG(TMPB));				dyn_synchstate(&save_info[sct].state);				gen_create_jump(save_info[sct].return_pos);				break;		}	}	used_save_info=0;}#if !defined(X86_INLINED_MEMACCESS)static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) {	gen_protectflags();	gen_call_function((void *)&mem_readb_checked_x86,"%Dd%Id",addr,&core_dyn.readdata);	dyn_check_bool_exception_al();	gen_mov_host(&core_dyn.readdata,dst,1,high);}static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) {	gen_protectflags();	if (high) gen_call_function((void *)&mem_writeb_checked_x86,"%Dd%Dh",addr,val);	else gen_call_function((void *)&mem_writeb_checked_x86,"%Dd%Dd",addr,val);	dyn_check_bool_exception_al();}static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) {	gen_protectflags();	if (dword) gen_call_function((void *)&mem_readd_checked_x86,"%Dd%Id",addr,&core_dyn.readdata);	else gen_call_function((void *)&mem_readw_checked_x86,"%Dd%Id",addr,&core_dyn.readdata);	dyn_check_bool_exception_al();	gen_mov_host(&core_dyn.readdata,dst,dword?4:2);}static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) {	gen_protectflags();	if (dword) gen_call_function((void *)&mem_writed_checked_x86,"%Dd%Dd",addr,val);	else gen_call_function((void *)&mem_writew_checked_x86,"%Dd%Dd",addr,val);	dyn_check_bool_exception_al();}static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) {	gen_protectflags();	gen_call_function((void *)&mem_readb_checked_x86,"%Ddr%Id",addr,&core_dyn.readdata);	dyn_check_bool_exception_al();	gen_mov_host(&core_dyn.readdata,dst,1,high);}static void dyn_write_byte_release(DynReg * addr,DynReg * val,Bitu high) {	gen_protectflags();	if (high) gen_call_function((void *)&mem_writeb_checked_x86,"%Ddr%Dh",addr,val);	else gen_call_function((void *)&mem_writeb_checked_x86,"%Ddr%Dd",addr,val);	dyn_check_bool_exception_al();}

⌨️ 快捷键说明

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