I\'ve ported my library x86Lib to mbed. It fully emulates the 8086 processor, but a few things I\'m still working on. Notable missing things are interrupts. Previously I used exceptions for interrupts, but exceptions aren\'t supported with the mbed compiler. It is also quite slow
Revision 0:217a7931b41f, committed 2012-03-04
- Comitter:
- earlz
- Date:
- Sun Mar 04 08:15:47 2012 +0000
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/device_manager.cpp Sun Mar 04 08:15:47 2012 +0000 @@ -0,0 +1,252 @@ +/** +Copyright (c) 2007 - 2009 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This file is part of the x86Lib project. +**/ +#define X86LIB_BUILD +#include <iostream> +#include <list> +#include <stdlib.h> +#include <stdio.h> +#include <cstring> +#include <x86Lib.h> + + +namespace x86Lib{ +//The lack of indentation for namespaces is intentional... +using namespace std; + +MemorySystem::MemorySystem() +{ + locked=0; +} +/**Because we must resize the list with realloc, we use malloc through out this for safety.**/ +void MemorySystem::Add(uint32_t low,uint32_t high,MemoryDevice *memdev){ + DeviceRange_t device; + + /* Check For Overlapping Addresses */ + Serial pc(USBTX, USBRX); // tx, rx + pc.printf("memorysystem add\n"); + for(unsigned int i = 0; i < memorySystemVector.size(); i++) + { + device = memorySystemVector[i]; + + if( device.high <= high && + device.low >= low ) + { + pc.printf("System_excp\n"); + exit(1); + } + } + pc.printf("high: 0x%x low: 0x%x\n",high,low); + device.high = high; + device.low = low; + device.memdev = memdev; + + /* Place Device in Memory System Vector */ + memorySystemVector.push_back( device ); +} + +void MemorySystem::Remove(uint32_t low,uint32_t high) +{ + +} + +void MemorySystem::Remove(MemoryDevice *memdev) +{ +} +void MemorySystem::Read(uint32_t address,int size,void *b) +{ + uint32_t* buffer=(uint32_t*)b; + DeviceRange_t device; + + if(size == 0) + { + return; + } + + size--; + + for(unsigned int i = 0; i < memorySystemVector.size(); i++) + { + device = memorySystemVector[i]; + if(device.low <= address && + device.high >= address) + { + //we found a region matching. + if( (address + size) > device.high ) + { + //One device range will not cover the whole request. + device.memdev->Read(address, device.high - address + 1, buffer); + size -= device.high - address; + + buffer += device.high - address + 1; //bug? + + address += device.high - address + 1; + Read( address, size+1 , buffer ); + } + else + { + //correct absolute address to a relative one + address-=device.low; + device.memdev->Read(address, size + 1, buffer); + } + return; + } + } + Onx86LibError(); + //throw Mem_excp(address); +} + + + +void MemorySystem::Write(uint32_t address,int size,void *b) +{ + uint32_t *buffer=(uint32_t*)b; + DeviceRange_t device; + + if( size==0 ) + { + return; + } + + size--; + + for( unsigned int i = 0; i < memorySystemVector.size(); i++ ) + { + device = memorySystemVector[i]; + + if(device.low <= address && + device.high >= address) + { + //we found a region matching. + if( (address + size) > device.high) + { + //One device range will not cover the whole request. + device.memdev->Write(address, device.high - address + 1, buffer); + + size -= device.high - address; + + buffer += device.high - address; + + address += device.high - address + 1; + + Write(address , size + 1, buffer); + } + else + { + //correct absolute address to a relative one + address-=device.low; + device.memdev->Write(address,size+1,buffer); + } + return; + } + } + Onx86LibError(); + //throw Mem_excp(address); +} + +int MemorySystem::RangeFree(uint32_t low,uint32_t high) +{ + return 1; +} + + + +PortSystem::PortSystem(){ + count=0; + //list=NULL; +} +void PortSystem::Add(uint16_t low,uint16_t high,PortDevice *portdev){ + int i; + for(i=0;i<count;i++){ + if(list[i].high<=high && list[i].low>=low){ + Onx86LibError(); + //throw new System_excp(); + } + } + if(count==0){ + list=(DeviceRange_t*)malloc(sizeof(DeviceRange_t)*1); + //count++; + }else{ + void *t=list; + list=(DeviceRange_t*)realloc(list,sizeof(DeviceRange_t)*count+1); + if(list==NULL){ + list=(DeviceRange_t*)t; //restore old pointer so we can free it + Onx86LibError(); + //throw Default_excp(__FILE__,__FUNCTION__,__LINE__); + } + //count++; + } + list[count].high=high; + list[count].low=low; + list[count].portdev=portdev; + count++; +} + + + +void PortSystem::Read(uint16_t address,int size,void *buffer){ + int i; + if(size==0){return;} + size=size-1; + for(i=0;i<count;i++){ + if(list[i].low<=address && list[i].high>=address){ + //we found a region matching. + list[i].portdev->Read(address,size+1,buffer); + return; + } + } + Onx86LibError(); + //throw Mem_excp(address); +} + + + +void PortSystem::Write(uint16_t address,int size,void *buffer){ + int i; + if(size==0){return;} + size=size-1; + for(i=0;i<count;i++){ + if(list[i].low<=address && list[i].high>=address){ + list[i].portdev->Write(address,size+1,buffer); + return; + } + } + Onx86LibError(); + //throw Mem_excp(address); +} + +void Remove(uint16_t low,uint16_t high){} +void Remove(PortDevice *portdev){} +int RangeFree(uint32_t low,uint32_t high){return 1;} + + + + +}; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/config.h Sun Mar 04 08:15:47 2012 +0000 @@ -0,0 +1,85 @@ +/** +Copyright (c) 2007 - 2010 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This file is part of the x86Lib project. +**/ +#ifndef CONFIG_H +#define CONFIG_H + +//#define SAFE_MODE //This should be set if debugging, or if there are +//mysterious errors... This should be disabled in release builds so that it is faster +//static const bool Default_A20=1; + +//#define ENABLE_OPCODE_CALLBACK //warning! Bug when this is enabled and a callback is not assigned! +/**Define this for a callback to be available for EachOpcode. This callback will be called + after every opcode executed. This slows down the main loop so only enable if needed!**/ + +#ifdef __i386__ +//#define USE_NATIVE //This means to optimize by using native assembly when available... +#endif + +//#define STRICT_OPCODES //This should be defined if strict opcode errors should be used...this may slow down the CPU however + +//#define X86_MULTITHREADING //This should be defined to enable multi-threading optimizations(note, these will break most single thread implementations) + +//#define ENABLE_OPCODE_CALLBACK //provide a callback for each time an opcode is executed. Useful for debugging 8086 programs + +#define NEW_API_11 +/**This is the option to use the "new" API for version 1.1.x + This is for using the MemorySystem and MemoryDevice classes**/ + + + +#endif + +/**Locked Memory Access Description +Ok, for this new multi CPU capable branch, memory locking has been added. +The PhysMemory now has Lock, Unlock, and IsLocked member functions, and it has +a new variable in it called locked (of type uint32_t) +Also, at the end of Readxxxx and Writexxxx functions, there is now a new variable +named locked_access (with a default value of 0) If this value is 1, then memory +access should be granted, even though the memory is locked. This basically means +that the memory request is coming from the current CPU which holds the lock. + +In most implementations, (unless the X86_MULTITHREADING define is used) the CPU +will check IsLocked and if the memory is already locked(which in most cases, it +actually shouldn't be) then it will break from the currently executing instruction +so that if another CPU holds the lock, it will be able to get to the next CPU in +single threaded implementations. + +For PhysMemory preaccess lock checks, basically, what should be attached at the first of all +Readxxxx and Writexxxx functions is + if(locked_access==0){ + while(locked>0){} + } +so that if the busmaster is no trying to access memory, and the memory is locked, +then it will halt access until the lock is repelled. (note the infinite loop should never +be got to in single-threaded implementations +**/ + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/opcode_def.h Sun Mar 04 08:15:47 2012 +0000 @@ -0,0 +1,567 @@ +/** +Copyright (c) 2007 - 2010 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This file is part of the x86Lib project. +**/ + +/**This file contains the opcode function definitions and prototypes for x86CPU**/ + +/**NOTE! this is included INSIDE of a class, so this file is somewhat limited...**/ +uint8_t Add8(uint8_t,uint8_t); +uint16_t Add16(uint16_t,uint16_t); +uint8_t Sub8(uint8_t,uint8_t); +uint16_t Sub16(uint16_t,uint16_t); +uint8_t And8(uint8_t,uint8_t); +uint16_t And16(uint16_t,uint16_t); +uint8_t Or8(uint8_t,uint8_t); +uint16_t Or16(uint16_t,uint16_t); +uint8_t Xor8(uint8_t,uint8_t); +uint16_t Xor16(uint16_t,uint16_t); +uint8_t ShiftLogicalRight8(uint8_t,uint8_t); +uint16_t ShiftLogicalRight16(uint16_t,uint8_t); +uint8_t ShiftArithmeticRight8(uint8_t,uint8_t); +uint16_t ShiftArithmeticRight16(uint16_t,uint8_t); +uint8_t ShiftLogicalLeft8(uint8_t,uint8_t); +uint16_t ShiftLogicalLeft16(uint16_t,uint8_t); +uint8_t RotateRight8(uint8_t,uint8_t); +uint16_t RotateRight16(uint16_t,uint8_t); +uint8_t RotateLeft8(uint8_t,uint8_t); +uint16_t RotateLeft16(uint16_t,uint8_t); +uint8_t RotateCarryRight8(uint8_t,uint8_t); +uint16_t RotateCarryRight16(uint16_t,uint8_t); +uint8_t RotateCarryLeft8(uint8_t,uint8_t); +uint16_t RotateCarryLeft16(uint16_t,uint8_t); + + +void InstallOp(uint8_t,opcode,uint32_t=CPU086); +void InitOpcodes(); +/* +uint8_t ReadByte(uint8_t seg,uint32_t offset); +uint16_t ReadWord(uint8_t seg,uint32_t offset); +uint32_t ReadDword(uint8_t seg,uint32_t offset); + +void WriteByte(uint8_t seg,uint32_t offset,uint8_t data); +void WriteWord(uint8_t seg,uint32_t offset,uint16_t data); +void WriteDword(uint8_t seg,uint32_t offset,uint32_t data); +*/ + + + + + +void op16_unknown(); +void op16_mov_r8_imm8(); //Tested, pass #1; +void op16_hlt(); //Tested, pass #1; +void op16_nop(); //Tested, pass #1; +void op16_mov_r16_imm16(); //Tested, pass #1; +void op16_jmp_rel8(); //Tested, pass #1; +void op16_sub_al_imm8(); //Tested, pass #1; +void op16_sub_ax_imm16(); //Tested, pass #1; +void op16_ja_rel8(); +void op16_jnc_rel8(); +void op16_jbe_rel8(); +void op16_jc_rel8(); //Tested, pass #1; +void op16_jz_rel8(); //Tested, pass #1; +void op16_jnz_rel8(); //Tested, pass #1; +void op16_jp_rel8(); //Tested, pass #1; +void op16_jnp_rel8(); //Tested, pass #1; +void op16_jg_rel8(); //Tested, pass #1; +void op16_jge_rel8(); +void op16_jle_rel8(); +void op16_jl_rel8(); //Tested, pass #1; +void op16_jo_rel8(); +void op16_jno_rel8(); +void op16_js_rel8(); +void op16_jns_rel8(); +void op16_mov_sr_rm16(); //Tested, pass #1; +void op16_mov_rm16_sr(); //Tested, pass #1; +void op16_pop_r16(); //Tested, pass #1; +void op16_push_imm16(); //Tested, pass #1; +void op16_push_r16(); //Tested, pass #1; +void op16_push_es(); //Tested, pass #1; +void op16_push_cs(); //Tested, pass #1; +void op16_push_ss(); //Tested, pass #1; +void op16_push_ds(); //Tested, pass #1; +void op16_pop_es(); //Tested, pass #1; +void op16_pop_ss(); //Tested, pass #1; +void op16_pop_ds(); //Tested, pass #1; +void op16_mov_r16_rm16(); //Tested, pass #1; +void op16_mov_rm16_r16(); //Tested, pass #1; +void op16_call_rel16(); //Tested, pass #1; +void op16_retn(); //Tested, pass #1; +void op16_loop_rel8(); //Tested, pass #1; +void op16_pre_cs_override(); //Tested, pass #1; +void op16_pre_ds_override(); //Tested, pass #1; +void op16_pre_es_override(); //Tested, pass #1; +void op16_pre_ss_override(); //Tested, pass #1; +void op16_movsw(); //Tested, pass #1; +void op16_movsb(); //Tested, pass #1; +void op16_clc(); +void op16_cld(); //Tested, pass #1; +void op16_cli(); //Tested, pass #1; +void op16_stc(); +void op16_std(); //Tested, pass #1; +void op16_sti(); //Tested, pass #1; +void op16_rep(); //Tested, pass #1;(only rep, not conditionals) +void op16_out_imm8_al(); //Tested, pass #1; +void op16_out_imm8_ax(); //Tested, pass #1; +void op16_call_imm16_imm16(); //Tested, pass #1; +void op16_retf(); //Tested, pass #1; +void op16_int_imm8(); //Tested, pass #1; +void op16_iret(); //Tested, pass #1; +void op16_into(); +void op16_int3(); +void op16_in_al_imm8(); +void op16_in_ax_imm8(); +void op16_add_al_imm8(); //Tested, pass #1; +void op16_add_ax_imm8(); //Tested, pass #1; +void op16_sub_rm8_r8(); //Tested, pass #1; +void op16_group_80(); //Tested, pass #1; +void op16_sub_r8_rm8(); +void op16_sub_rm16_r16(); +void op16_sub_r16_rm16(); +void op16_group_81(); //Tested, pass #1; +void op16_add_rm8_r8(); +void op16_add_rm16_r16(); +void op16_add_r8_rm8(); +void op16_add_r16_rm16(); +void op16_mov_al_off8(); +void op16_mov_ax_off16(); +void op16_mov_rm8_r8(); +void op16_mov_r8_rm8(); +void op16_mov_off8_al(); //Tested, pass #1; +void op16_mov_off16_ax(); //Tested, pass #1; +void op16_mov_m8_imm8(); //Tested, pass #1; +void op16_mov_m16_imm16(); //Tested, pass #1;//currently have 85 instructions or prefixes implemented(actually more, not counting group instructions) +void op16_cmp_rm8_r8(); +void op16_cmp_rm16_r16(); +void op16_cmp_r8_rm8(); +void op16_cmp_r16_rm16(); +void op16_cmp_al_imm8(); //Tested, pass #1; +void op16_cmp_ax_imm16(); //Tested, pass #1; +void op16_group_83(); //Tested, pass #1; +void op16_jmp_rel16(); //Tested, pass #1 +void op16_jmp_imm16_imm16(); //Tested, pass #1 +void op16_group_FF(); +void op16_push_imm8(); +void op16_group_8F(); +void op16_salc(); //Undocumented -- Set AL on Carry +void op16_cmc(); +void op16_cbw(); +void op16_aaa(); +void op16_daa(); +void op16_das(); +void op16_aas(); +void op16_aad(); +void op16_aam(); +void op16_inc_r16(); +void op16_dec_r16(); +void op16_group_FE(); +void op16_group_F6(); +void op16_group_F7(); +void op16_cwd(); +void op16_and_rm8_r8(); +void op16_and_rm16_r16(); +void op16_and_r8_rm8(); +void op16_and_r16_rm16(); +void op16_and_al_imm8(); +void op16_and_ax_imm16(); +void op16_or_rm8_r8(); +void op16_or_rm16_r16(); +void op16_or_r8_rm8(); +void op16_or_r16_rm16(); +void op16_or_al_imm8(); +void op16_or_ax_imm16(); +void op16_escape(); +void op16_cmpsb(); //Tested, pass #1, full +void op16_cmpsw(); //tested, pass #1, full +void op16_jcxz_rel8(); +void op16_adc_al_imm8(); +void op16_adc_ax_imm8(); +void op16_adc_rm8_r8(); +void op16_adc_rm16_r16(); +void op16_adc_r8_rm8(); +void op16_adc_r16_rm16(); +void op16_lahf(); +void op16_sahf(); +void op16_loope_rel8(); +void op16_loopne_rel8(); +void op16_lds(); +void op16_les(); +void op16_lea(); +void op16_lock(); //funcitonally does nothing... +void op16_xor_rm8_r8(); +void op16_xor_rm16_r16(); +void op16_xor_r8_rm8(); +void op16_xor_r16_rm16(); +void op16_xor_al_imm8(); +void op16_xor_ax_imm16(); +void op16_sbb_rm8_r8(); +void op16_sbb_rm16_r16(); +void op16_sbb_r8_rm8(); +void op16_sbb_r16_rm16(); +void op16_sbb_al_imm8(); +void op16_sbb_ax_imm16(); +void op16_test_al_imm8(); +void op16_test_ax_imm16(); +void op16_test_rm8_r8(); +void op16_test_rm16_r16(); +void op16_xchg_rm8_r8(); +void op16_xchg_rm16_r16(); +void op16_xchg_ax_r16(); +void op16_group_D2(); +void op16_group_D3(); +void op16_group_D0(); +void op16_group_D1(); +void op16_lodsb(); +void op16_lodsw(); +void op16_scasb(); +void op16_scasw(); +void op16_stosb(); +void op16_stosw(); +void op16_wait(); +void op16_xlatb(); + +void op16_in_al_dx(); +void op16_in_ax_dx(); +void op16_out_dx_al(); +void op16_out_dx_ax(); + + + + +//Oh God how I hate prototyping and adding the opcodes to the master InstallOp list... + + + + +/**Group Include Functions(not direct opcodes)**/ +void op16_sub_rm8_imm8(ModRM16&); //group 0x80 /5 +void op16_sub_rm16_imm16(ModRM16&); +void op16_add_rm8_imm8(ModRM16&); +void op16_add_rm16_imm16(ModRM16&); +void op16_cmp_rm8_imm8(ModRM16&); //Tested, pass #1 +void op16_cmp_rm16_imm16(ModRM16&); +void op16_sub_rm16_imm8(ModRM16&); +void op16_add_rm16_imm8(ModRM16&); +void op16_cmp_rm16_imm8(ModRM16&); //Tested, pass #1 +void op16_jmp_rm16(ModRM16&); //Tested, pass #1 +void op16_jmp_m16_m16(ModRM16&); //Tested, pass #1 +void op16_push_m16(ModRM16&); +void op16_pop_m16(ModRM16&); +void op16_inc_rm8(ModRM16&); +void op16_inc_rm16(ModRM16&); +void op16_dec_rm8(ModRM16&); +void op16_dec_rm16(ModRM16&); +void op16_div_rm8(ModRM16 &rm);//Tested, pass #1 +void op16_div_rm16(ModRM16 &rm);//Tested, pass #1 +void op16_idiv_rm8(ModRM16 &rm);//Tested, pass #1 +void op16_idiv_rm16(ModRM16 &rm);//Tested, pass #1 +void op16_mul_rm8(ModRM16 &rm);//Tested, pass #1 +void op16_mul_rm16(ModRM16 &rm);//Tested, pass #1 +void op16_imul_rm8(ModRM16 &rm); +void op16_imul_rm16(ModRM16 &rm); +void op16_and_rm8_imm8(ModRM16 &rm); +void op16_and_rm16_imm16(ModRM16 &rm); +void op16_and_rm16_imm8(ModRM16 &rm); +void op16_or_rm8_imm8(ModRM16& rm); +void op16_or_rm16_imm16(ModRM16 &rm); +void op16_or_rm16_imm8(ModRM16 &rm); +void op16_adc_rm8_imm8(ModRM16&); +void op16_adc_rm16_imm16(ModRM16&); +void op16_adc_rm16_imm8(ModRM16&); +void op16_neg_rm16(ModRM16&); +void op16_neg_rm8(ModRM16&); +void op16_xor_rm8_imm8(ModRM16& rm); +void op16_xor_rm16_imm16(ModRM16 &rm); +void op16_xor_rm16_imm8(ModRM16 &rm); +void op16_sbb_rm8_imm8(ModRM16 &rm); +void op16_sbb_rm16_imm16(ModRM16 &rm); +void op16_sbb_rm16_imm8(ModRM16 &rm); +void op16_test_rm8_imm8(ModRM16 &rm); +void op16_test_rm16_imm16(ModRM16 &rm); +void op16_test_rm16_imm8(ModRM16 &rm); /**This needs to be added**/ +void op16_shr_rm8_cl(ModRM16 &rm); +void op16_shr_rm16_cl(ModRM16 &rm); +void op16_sar_rm8_cl(ModRM16 &rm); +void op16_sar_rm16_cl(ModRM16 &rm); +void op16_shl_rm8_cl(ModRM16 &rm); +void op16_shl_rm16_cl(ModRM16 &rm); +void op16_rol_rm8_cl(ModRM16 &rm); +void op16_rol_rm16_cl(ModRM16 &rm); +void op16_ror_rm8_cl(ModRM16 &rm); +void op16_ror_rm16_cl(ModRM16 &rm); +void op16_rcl_rm8_cl(ModRM16 &rm); +void op16_rcl_rm16_cl(ModRM16 &rm); +void op16_rcr_rm8_cl(ModRM16 &rm); +void op16_rcr_rm16_cl(ModRM16 &rm); +void op16_shr_rm8_1(ModRM16 &rm); +void op16_shr_rm16_1(ModRM16 &rm); +void op16_sar_rm8_1(ModRM16 &rm); +void op16_sar_rm16_1(ModRM16 &rm); +void op16_shl_rm8_1(ModRM16 &rm); +void op16_shl_rm16_1(ModRM16 &rm); +void op16_rol_rm8_1(ModRM16 &rm); +void op16_rol_rm16_1(ModRM16 &rm); +void op16_ror_rm8_1(ModRM16 &rm); +void op16_ror_rm16_1(ModRM16 &rm); +void op16_rcl_rm8_1(ModRM16 &rm); +void op16_rcl_rm16_1(ModRM16 &rm); +void op16_rcr_rm8_1(ModRM16 &rm); +void op16_rcr_rm16_1(ModRM16 &rm); +void op16_not_rm8(ModRM16 &rm); +void op16_not_rm16(ModRM16 &rm); +void op16_call_rm16(ModRM16 &rm); +void op16_call_rm16_rm16(ModRM16 &rm); + + + +void Push16(uint16_t val){ + *regs16[SP]-=2; + WriteWord(cSS,*regs16[SP],val); +} +uint16_t Pop16(){ + uint16_t register tmp; + tmp=ReadWord(cSS,*regs16[SP]); + *regs16[SP]+=2; + return tmp; +} + + +inline void SetIndex8(){ //this just makes my code look better... + if(freg.df==0){ + (*regs16[SI])++; + (*regs16[DI])++; + }else{ + (*regs16[SI])--; + (*regs16[DI])--; + } +} + +inline void SetIndex16(){ + if(freg.df==0){ + (*regs16[SI])+=2; + (*regs16[DI])+=2; + }else{ + (*regs16[SI])-=2; + (*regs16[DI])-=2; + } +} + +inline void CalculatePF8(uint8_t val){ + unsigned int i; + unsigned int count=0; + for(i=0;i<=7;i++){ + if((val&((1<<i)))!=0){count++;} + } + if((count%2)==0){freg.pf=1;}else{freg.pf=0;} + + + + +} + +inline void CalculatePF16(uint16_t val){ + #ifndef USE_NATIVE + unsigned int i; + unsigned int count=0; + for(i=0;i<=15;i++){ + /* TODO (Jordan#4#): speed this up! */ + if((val&((1<<i)))!=0){count++;} + } + if((count%2)==0){freg.pf=1;}else{freg.pf=0;} + #else + //x86 ASM optimization.. + __asm(".intel_syntax noprefix\n" + "cmp WORD PTR [ebp-10],0\n" + "jp .yes__\n" + ".att_syntax\n"); + val=0; + __asm(".intel_syntax noprefix\n" + "jmp .end__\n" + ".local .yes__:\n" + ".att_syntax\n"); + val=1; + __asm(".intel_syntax noprefix\n" + ".local .end__:\n" + ".att_syntax\n"); + freg.pf=val; + return; + #endif +} + +//these calculate SF for the given operand size +inline void CalculateSF8(uint8_t val){ + if((val&0x80)==0){freg.sf=0;}else{freg.sf=1;} +} + +inline void CalculateSF16(uint16_t val){ + if((val&0x8000)==0){freg.sf=0;}else{freg.sf=1;} +} + + + + +void Jmp16_near16(uint16_t off){ + + //I thought there would be a good way to do this, but I suppose this works.. + if((off&0x8000)==0){ //if unsigned + eip=eip+off; + }else{ + eip=eip-((uint16_t)-off); + } + +} + +void Jmp16_near8(uint8_t off){ + //I thought there would be a good way to do this, but I suppose this works.. + if((off&0x80)==0){ //if unsigned + eip=eip+off; + }else{ + eip=eip-((uint8_t)-off); + } + //eip++; + +} + +void Int16(uint8_t num){ + Push16(*(uint16_t*)&freg); + freg._if=0; + Push16(seg[cCS]); + Push16(eip); + seg[cIS]=0; + eip=ReadWord(cIS,num*4); + seg[cCS]=ReadWord(cIS,num*4+2); + +// cout << "0x" << hex << eip << "0x" << seg[cCS] << endl; + eip--; +} + +inline void ResetSegments(){ + ES=cES; + CS=cCS; + SS=cSS; + DS=cDS; + FS=cFS; + GS=cGS; +} + +inline void SetSegments(uint8_t segm){ + ES=segm; + CS=segm; + SS=segm; + DS=segm; + FS=segm; + GS=segm; +} + + + +inline uint8_t ReadByte(uint8_t segm,uint32_t off){ + Memory->WaitLock(busmaster); + uint8_t res=0; + Memory->Read((seg[segm]<<4)|off,1,&res); + return res; +} + +inline uint16_t ReadWord(uint8_t segm,uint32_t off){ + Memory->WaitLock(busmaster); + uint16_t res=0; + if(Opcodes==opcodes_16bit && off>=0xFFFE){ + + uint16_t offset=off; //for ease of rounding + uint32_t tmp=0; + Memory->Read((seg[segm]<<4)|offset,1,&tmp); + res=tmp; + Memory->Read((seg[segm]<<4)|(uint16_t)(offset+1),1,&tmp); + res|=tmp<<8; + return res; + }else{ + Memory->Read((seg[segm]<<4)|off,2,&res); + return res; + } +} + +inline uint32_t ReadDword(uint8_t segm,uint32_t off){ + Memory->WaitLock(busmaster); + uint32_t res=0; + if(Opcodes==opcodes_16bit && off>=0xFFFC){ + uint16_t offset=off; //for ease of rounding + uint32_t tmp=0; + Memory->Read((seg[segm]<<4)|offset,1,&tmp); + res=tmp; + Memory->Read((seg[segm]<<4)|(uint16_t)(offset+1),1,&tmp); + res|=tmp<<8; + Memory->Read((seg[segm]<<4)|(uint16_t)(offset+2),1,&tmp); + res|=tmp<<16; + Memory->Read((seg[segm]<<4)|(uint16_t)(offset+3),1,&tmp); + res|=tmp<<24; + return res; + }else{ + Memory->Read((seg[segm]<<4)|off,4,&res); + return res; + } +} + +inline void WriteByte(uint8_t segm,uint32_t off,uint8_t val){ + Memory->WaitLock(busmaster); + Memory->Write((seg[segm]<<4)|off,1,&val); +} + +inline void WriteWord(uint8_t segm,uint32_t off,uint16_t val){ + Memory->WaitLock(busmaster); + if(Opcodes==opcodes_16bit && off>=0xFFFE){ + uint16_t offset=off; //for ease of rounding + uint16_t tmp=val&0x00FF; + Memory->Write((seg[segm]<<4)|offset,1,&tmp); + tmp=(val&0xFF00)>>8; + Memory->Write((seg[segm]<<4)|(uint16_t)(offset+1),1,&tmp); + }else{ + Memory->Write((seg[segm]<<4)|off,2,&val); + } +} + +inline void WriteDword(uint8_t segm,uint32_t off,uint32_t val){ + Memory->WaitLock(busmaster); + if(Opcodes==opcodes_16bit && off>=0xFFFC){ + uint16_t offset=off; //for ease of rounding + uint32_t tmp=val&0x00FF; + Memory->Write((seg[segm]<<4)|offset,1,&tmp); + tmp=(val&0xFF00)>>8; + Memory->Write((seg[segm]<<4)|(uint16_t)(offset+1),1,&tmp); + tmp=(val&0xFF0000)>>16; + Memory->Write((seg[segm]<<4)|(uint16_t)(offset+2),1,&tmp); + tmp=(val&0xFF000000)>>24; + Memory->Write((seg[segm]<<4)|(uint16_t)(offset+3),1,&tmp); + }else{ + Memory->Write((seg[segm]<<4)|off,4,&val); + } +} + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/x86Lib.h Sun Mar 04 08:15:47 2012 +0000 @@ -0,0 +1,452 @@ +/** +Copyright (c) 2007 - 2010 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This file is part of the x86Lib project. +**/ + +#ifndef X86LIB +#define X86LIB +#include <iostream> +#include <vector> +#include <stdint.h> +#include <string> +#include "mbed.h" + +//! The main namespace of x86Lib +namespace x86Lib{ + +#ifdef X86LIB_BUILD +#include <config.h> +#endif + +//! 8086 CPU level +static const uint32_t CPU086=1; +//! 186 CPU level +static const uint32_t CPU186=2|CPU086; +//! 286 real mode only CPU level +static const uint32_t CPU286_REAL=4|CPU186; //Only support real mode instructions +//! 286 CPU level +static const uint32_t CPU286=8|CPU286_REAL; +//! 386 real mode only CPU level +static const uint32_t CPU386_REAL=16|CPU286_REAL; //Only Support real mode instructions +//! 386 CPU level +static const uint32_t CPU386=32|CPU386_REAL|CPU286; +//! 486 CPU level +static const uint32_t CPU486=64|CPU386; +//! Pentium(586) CPU level +static const uint32_t CPU_PENTIUM=128|CPU486; +//! Pentium Pro CPU level +static const uint32_t CPU_PPRO=256|CPU_PENTIUM; +//! Default CPU level +/*! CPU_DEFAULT will use the CPU with the most complete emulation +*/ +static const uint32_t CPU_DEFAULT=0; //this is actually changed internally.. + + + + + + +/**Exceptions...**/ +//! Exception code for an infinite halt +static const uint32_t CLIHLT_EXCP=1; //cli/hlt...nothing to do +//! Exception code for memory access exception +static const uint32_t MEM_ACCESS_EXCP=3; //Memory Access Error...(can actually be page fault, or GPF, or stack fault... +//! Exception code for triple fault +/*! This code is always OR'd with another code + so that you can tell what caused the triple fault. +*/ +static const uint32_t TRIPLE_FAULT_EXCP=0x10000; //Triple fault...This should be ORd with the last exception + + + +//! A debug exception +/*! This exception should really only be used when debugging. + It should be used as throw(Default_excp(__FILE__,__FUNCTION__,__LINE__)); +*/ +class Default_excp{ //Internal only...these should never happen when released... + + public: + /*! + \param file_ The file name in which the exception occured(use __FILE__) + \param func_ The function in which the exception occured(use __FUNCTION__) + \param line_ The line number which the excption occured on(use __LINE__) + */ + Default_excp(std::string file_,std::string func_,int line_){ + file=file_; + func=func_; + line=line_; + } + //! The file which the exception was thrown from + std::string file; + //! The function which the exception was thrown from + std::string func; + //! The line which the exception was thrown from + int line; +}; + +//! CPU Panic exception +/*! This exception is thrown out of x86CPU if a fatal CPU error occurs, + such as a triple fault. +*/ +class CpuPanic_excp{ //used for fatal CPU errors, such as triple fault.. + + public: + /*! + \param desc_ A text description of the error + \param code_ An exception code + */ + CpuPanic_excp(std::string desc_,uint32_t code_){ + desc=desc_; + code=code_; + } + //!A text description of the error + std::string desc; + //!An exception code + uint32_t code; +}; + +//! Memory error exception +/*! This should only be thrown out of the PhysMemory class + It is thrown out to tell x86CPU a memory exception has occured. + This does not always result in a triple fault. + /sa PhysMemory +*/ +class Mem_excp{ //Exclusively for the Memory Classes, these are caught and then a more appropriate excp is thrown + public: + /*! + \param address_ The address at which had problems being read or written + */ + Mem_excp(uint32_t address_){ + address=address_; + } + uint32_t address; +}; + +class System_excp{ + public: + System_excp(){} +}; + +class x86CPU; +/**This will be used for memory mapped devices(including memory itself)**/ +class MemoryDevice{ + public: + virtual void Read(uint32_t address,int count,void *buffer)=0; + virtual void Write(uint32_t address,int count,void *data)=0; + virtual int Readable(uint32_t address,int count){ + return 1; + //This is optional. It is currently not used in the CPU code + } + virtual int Writeable(uint32_t address,int count){ + return 1; + //This is optional. It is currently not used in the CPU code + } + virtual inline ~MemoryDevice()=0; +}; + +inline MemoryDevice::~MemoryDevice(){} +void Onx86LibError(); + +class PortDevice{ + public: + virtual void Read(uint16_t address,int count,void *buffer)=0; + virtual void Write(uint16_t address,int count,void *data)=0; + virtual inline ~PortDevice()=0; +}; + +inline PortDevice::~PortDevice(){} + +typedef struct DeviceRange +{ + union + { + class MemoryDevice *memdev; + class PortDevice *portdev; + }; + uint32_t high; + uint32_t low; +}DeviceRange_t; +/*Myk I hate you. This is going to be harder to implement than I thought. lol */ +class MemorySystem{ + std::vector<DeviceRange_t> memorySystemVector; + protected: + //! Intended to be used to mark if the address space is locked. + volatile uint32_t locked; + public: + MemorySystem(); + void Add(uint32_t low,uint32_t high,MemoryDevice *memdev); + void Remove(uint32_t low,uint32_t high); + void Remove(MemoryDevice *memdev); + int RangeFree(uint32_t low,uint32_t high); + void Read(uint32_t address,int count,void *buffer); + void Write(uint32_t address,int count,void *data); + //! Tells if memory is locked + /*! + \return 1 if memory is locked, 0 if not locked. + */ + bool IsLocked(){return locked;} + //! Locks the address space + void Lock(){ + while(locked==1){} + locked=1; + } + //! Unlocks the address space + void Unlock(){ + locked=0; + } + void WaitLock(int haslock){ + if(haslock==0){ + while(locked>0){} + } + } +}; + +class PortSystem{ + DeviceRange_t *list; + int count; + public: + PortSystem(); + + void Add(uint16_t low,uint16_t high,PortDevice *portdev); + void Remove(uint16_t low,uint16_t high); + void Remove(PortDevice *portdev); + int RangeFree(uint32_t low,uint32_t high); + void Read(uint16_t address,int count,void *buffer); + void Write(uint16_t address,int count,void *data); +}; + + + +//! The struct used to save the current state of x86CPU +struct x86SaveData{ + //! General registers + uint32_t reg32[8]; + //! Segment registers + uint16_t seg[7]; + //! Segment register routing(in case of segment overrides) + uint8_t seg_route[7]; + //! Instruction pointer + uint32_t eip; + //! Which opcode map is currently in use + uint32_t opcode_mode; + //! Flags register + uint16_t freg; + //! CPU level + uint32_t cpu_level; +}; + +}; + +#ifdef X86LIB_BUILD + +#include <x86Lib_internal.h> +#endif + + + +namespace x86Lib{ + +typedef void (x86Lib::x86CPU::*opcode)(); +typedef struct{ + unsigned char rm:3; + unsigned char extra:3; + unsigned char mod:2; +} +__attribute__((packed))mod_rm16; //this struct is a described mod r/m byte.. + +//Note, this will re-cache op_cache, so do not use op_cache afterward +//Also, eip should be on the modrm byte! +//On return, it is on the last byte of the modrm block, so no advancement needed unelss there is an immediate +//Also, this will advance EIP upon exiting the opcode(deconstruction) +class ModRM16{ //This is the best thing I have ever done... + //I love this class so much...am I cheating on her? lol + protected: + bool use_ss; + bool op_specific; + x86CPU *this_cpu; + private: + mod_rm16 modrm; + inline uint16_t GetRegD(); //This returns the register displacement value + inline uint16_t GetDisp(); + public: + inline ModRM16(x86CPU* this_cpu_); + inline ~ModRM16(); + //The r suffix means /r, which means for op_specific=1, use general registers + inline uint8_t ReadByter(); + inline uint16_t ReadWordr(); + inline uint32_t ReadDword(); + inline void WriteByter(uint8_t byte); + inline void WriteWordr(uint16_t word); + inline void WriteDword(uint32_t dword); + inline uint8_t GetLength(); //This returns how many total bytes the modrm block consumes + inline uint8_t GetExtra(); //Get the extra fied from mod_rm + inline uint16_t ReadOffset(); //This is only used by LEA. It will obtain the offset and not dereference it... + +}; //I hope that SIB and ModR/M32 will be this good! +//! The main CPU control class +/*! This class is the complete CPU. That being said, it is quite big + and has many functions. It completely emulates the x86 line of CPUs +*/ +class x86CPU{ + friend class ModRM16; + volatile uint32_t reg32[8]; + volatile uint16_t *regs16[8]; + volatile uint8_t *regs8[8]; + volatile uint16_t seg[7]; + volatile uint32_t eip; + #ifdef X86LIB_BUILD + volatile FLAGS freg; + #else + volatile uint16_t freg; + #endif + volatile uint8_t op_cache[4]; + volatile uint8_t ES; + volatile uint8_t CS; + volatile uint8_t SS; + volatile uint8_t DS; + volatile uint8_t FS; + volatile uint8_t GS; + volatile bool string_compares; + volatile uint8_t cli_count; //Whenever this is 1, an STI is done. + volatile bool int_pending; + volatile uint8_t int_number; + uint32_t cpu_level; + volatile bool busmaster; + void Init(); + protected: + //! Do one CPU opcode + /*! This should be put in the main loop, as this is what makes the CPU work. + */ + void Cycle(); + opcode opcodes_16bit[256]; + opcode *Opcodes; + + /*! + \return 0 if no interrupts are pending + */ + int CheckInterrupts(); + public: +#ifdef ENABLE_OPCODE_CALLBACK + void (*EachOpcodeCallback)(x86CPU *thiscpu); +#endif + MemorySystem *Memory; + PortSystem *Ports; + /*! + \param cpu_level The CPU level to use(default argument is default level) + \param flags special flags to control CPU (currently, there is none) + */ + x86CPU(uint32_t cpu_level=0 ,uint32_t flags=0); + /*! + \param save The x86SaveData class to restore the cpu to + \param flags special flags to control CPU (currently, there is none) + */ + x86CPU(x86SaveData &save,uint32_t flags=0); + + //!Runs the CPU for the specified cyclecount. + void Exec(int cyclecount); + + //! Dump CPU state + /*! This will dump cpu state to output. This is mainly used for debugging, as it is not flexible. + \param output output stream which to use. + */ + void DumpState(std::ostream &output); + //! Cause a CPU interrupt + /*! This will cause a CPU interrupt(unless interrupt flag is cleared) + Note! This does not resolve IRQs! This takes normal interrupt numbers(0-255) + \param num Interrupt number + */ + void Int(uint8_t num); + //! Saves CPU state + /*! This will completely save the CPU state of the current x86CPU class + \param save_data_buffer This should be a free memory area the size of x86SaveData + */ + void SaveState(x86SaveData *save_data_buffer); + //!Loads CPU state + /*! This will completely reset and reload the cpu state. + \param load_data where the x86SaveData is located + */ + void LoadState(x86SaveData &load_data); + + //!Completely resets the CPU + void Reset(); + //~x86CPU(); + //!Locks the PhysMemory in use, and declares this CPU as busmaster + void Lock(); + //!Unlocks the PhysMemory in use + void Unlock(); + //! Tells if PhysMemory in use is locked + /*! + \return 1 if PhysMemory in use is locked, otherwise returns 0 + */ + bool IsLocked(); + /*Added after inital multi-branch switch over*/ + //!Checks if an interrupt is on the stack waiting to be answered. + /*! + \return 1 if an interrupt is waiting to be answered by the CPU, else, 0. + */ + bool IntPending(); + + /*End public interface*/ + #ifdef X86LIB_BUILD + private: + #include <opcode_def.h> + #endif + +}; + + + +#ifdef X86LIB_BUILD +#define X86_POST_CPU +#include "x86Lib_internal.h" +#undef X86_POST_CPU +#endif + + + + + + + + + + + + + + + + + + + +} + + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/x86Lib_internal.h Sun Mar 04 08:15:47 2012 +0000 @@ -0,0 +1,452 @@ +/** +Copyright (c) 2007 - 2010 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This file is part of the x86Lib project. +**/ + + +#ifndef X86LIB_INTERNAL_H +#define X86LIB_INTERNAL_H + + +namespace x86Lib{ + //32 bit register macros +static const int EAX=0; +static const int ECX=1; +static const int EDX=2; +static const int EBX=3; +static const int ESP=4; +static const int EBP=5; +static const int ESI=6; +static const int EDI=7; + + +//16 bit register macros +static const int AX=0; +static const int CX=1; +static const int DX=2; +static const int BX=3; +static const int SP=4; +static const int BP=5; +static const int SI=6; +static const int DI=7; + +//8 bit register macros +static const int AL=0; +static const int CL=1; +static const int DL=2; +static const int BL=3; +static const int AH=4; +static const int CH=5; +static const int DH=6; +static const int BH=7; + + +//segment registers constants(the defaults) +static const int cES=0; +static const int cCS=1; +static const int cSS=2; +static const int cDS=3; +static const int cFS=4; +static const int cGS=5; +static const int cIS=6; //this is an imaginary segment only used for direct segment overrides +//for instance it would be used in mov [1000:bx],ax + + + +typedef struct{ + unsigned char cf:1; + unsigned char r0:1; + unsigned char pf:1; + unsigned char r1:1; + unsigned char af:1; + unsigned char r2:1; + unsigned char zf:1; + unsigned char sf:1; + unsigned char tf:1; + unsigned char _if:1; + unsigned char df:1; + unsigned char of:1; + unsigned char iopl:2; //not yet used + unsigned char nt:1; + unsigned char r3:1; +}__attribute__((packed))FLAGS; //this is a better representation of flags(much easier to use) + + + + + +typedef void (x86Lib::x86CPU::*opcode)(); /**You have no idea how hard it was to figure out how to do that!**/ + + +static const uint32_t OPCODE_REAL_16=1; + + +//CPU Exceptions(interrupt handled) +static const uint32_t DIV0_IEXCP=0xF000; //Divide by zero exception +static const uint32_t DEBUG_IEXCP=0xF001; //Debug exception +static const uint32_t NMI_IEXCP=0xF002; //NMI +static const uint32_t BREAK_IEXCP=0xF003; //Breakpoint/int 3 +static const uint32_t OVERFLOW_IEXCP=0xF004; //Overflow/into +static const uint32_t BOUNDS_IEXCP=0xF005; //Bounds Check +static const uint32_t UNK_IEXCP=0xF006; //unknown opcode +static const uint32_t UNDEV_IEXCP=0xF007; //Unknown device +static const uint32_t DOUBLE_FAULT_IEXCP=0xF008; +static const uint32_t SEG_OVERRUN_IEXCP=0xF009; //Co-processor segment overrun..(not used after i486 +static const uint32_t ITSS_IEXCP=0xF00A; //Invalid TSS +static const uint32_t ISEG_IEXCP=0xF00B; //Invalid/non-existent segment +static const uint32_t STACK_IEXCP=0xF00C; //Stack Exception +static const uint32_t GPF_IEXCP=0xF00D; //GPF +static const uint32_t PAGE_FAULT_IEXCP=0xF00E; +static const uint32_t RESERVED_IEXCP=0xF00F; //Reserved by intel, so internal use? +static const uint32_t FLOAT_ERROR_IEXCP=0xF010; //Floating Point Error.. +static const uint32_t ALIGN_IEXCP=0xF011; //Alignment Check... + +class CpuInt_excp{ //Used internally for handling interrupt exceptions... + public: + CpuInt_excp(uint32_t code_){ + code=code_; + } + uint32_t code; +}; + + + + + + + + + + + + + + + + +/**Random support functions that are static inline'd**/ + +static inline uint16_t SignExtend8(uint8_t val){ //sign extend a byte to a word + if((val&0x80)!=0){ + return 0xFF00|val; + }else{ + return val; + } +} + +//convert signed integer into unsigned, and store top bit in store +static inline uint32_t Unsign32(uint32_t val,bool &store){ + + if(val>=0x80000000){ + store=1; + //cout << hex << "0x" << (int) ~(-2) << endl; + return (~(val))+1; + }else{ + store=0; + return val; + } + +} + +static inline uint16_t Unsign16(uint16_t val,bool &store){ + if(val>=0x8000){ + store=1; + //cout << hex << "0x" << (int) ~(-2) << endl; + return (~(val))+1; + }else{ + store=0; + return val; + } + +} + +static inline uint8_t Unsign8(uint8_t val,bool &store){ + if(val>=0x80){ + store=1; + return (~(val))+1; + }else{ + store=0; + return val; + } + +} + +/**Resign an unsigned integer using the store as the sign bit. +--Note, in order to combine two sign bits, just bitwise XOR(^) them!*/ +static inline uint32_t Resign32(uint32_t val,bool store1){ + if((store1)==1){ + return (~(val))+1; + }else{ + return val; + } +} + +static inline uint16_t Resign16(uint16_t val,bool store1){ + if((store1)==1){ + return (~(val))+1; + }else{ + return val; + } +} + +static inline uint8_t Resign8(uint8_t val,bool store1){ + if((store1)==1){ + return (~(val))+1; + }else{ + return val; + } +} + + +}; + + +#endif + + +#ifdef X86_POST_CPU + +#ifndef X86LIB_INTERNAL_H_POST_CPU +#define X86LIB_INTERNAL_H_POST_CPU +//namespace x86Lib{ + + + + + + +inline uint16_t ModRM16::GetRegD(){ //This returns the register displacement value + switch(modrm.rm){ + case 0: + return *this_cpu->regs16[BX]+*this_cpu->regs16[SI]; + case 1: + return *this_cpu->regs16[BX]+*this_cpu->regs16[DI]; + case 2: + use_ss=1; + return *this_cpu->regs16[BP]+*this_cpu->regs16[SI]; + case 3: + use_ss=1; + return *this_cpu->regs16[BP]+*this_cpu->regs16[DI]; + case 4: + return *this_cpu->regs16[SI]; + case 5: + return *this_cpu->regs16[DI]; + case 6: //immediate Displacement only, so no register displace.. + return 0; + case 7: + return *this_cpu->regs16[BX]; + } + return 0; +} + +inline uint16_t ModRM16::GetDisp(){ + uint16_t reg; + reg=GetRegD(); + if(modrm.rm==6){ //Don't worry, it's safe... + use_ss=1; + reg=*this_cpu->regs16[BP]; + } + switch(modrm.mod){ + case 0: //no displacement + + if(modrm.rm==6){ //if only word displacement... + use_ss=0; + //eip++; + //eip++; + return *(uint16_t*)&this_cpu->op_cache[1]; + }else{ + return reg; + } + case 1: //byte displacement(signed) + //eip++; + return (signed)reg+(signed)this_cpu->op_cache[1]; + case 2: //word displacement(signed) + return (signed)reg+(signed)(*(uint16_t*)&this_cpu->op_cache[1]); + case 3: //opcode specific... + op_specific=1; + return 0; + } + return 0; +} + + +inline ModRM16::ModRM16(x86CPU *this_cpu_){ + use_ss=0; + op_specific=0; + this_cpu=this_cpu_; + *(uint32_t*)&this_cpu->op_cache=this_cpu->ReadDword(cCS,this_cpu->eip); + *(uint8_t*)&modrm=this_cpu->op_cache[0]; + //cout << hex << (int)modrm.rm << endl; + //knowing how to do type casting owns! +} + +inline ModRM16::~ModRM16(){ + this_cpu->eip+=GetLength()-1; + //eip--; +} + +//The r suffix means /r, which means for op_specific=1, use general registers +inline uint8_t ModRM16::ReadByter(){ + use_ss=0; + op_specific=0; + uint16_t disp=GetDisp(); + if(op_specific==1){ + return *this_cpu->regs8[modrm.rm]; + }else{ + if(use_ss==1){ + return this_cpu->ReadByte(this_cpu->SS,disp); + }else{ + return this_cpu->ReadByte(this_cpu->DS,disp); + } + } +} + +inline uint16_t ModRM16::ReadWordr(){ + use_ss=0; + op_specific=0; + uint16_t disp=GetDisp(); + if(op_specific==1){ + //cout << "h" << endl; + return *this_cpu->regs16[modrm.rm]; + }else{ + + if(use_ss==1){ + return this_cpu->ReadWord(this_cpu->SS,disp); + }else{ + return this_cpu->ReadWord(this_cpu->DS,disp); + } + } +} +inline uint32_t ModRM16::ReadDword(){ + use_ss=0; + op_specific=0; + uint16_t disp=GetDisp(); + if(op_specific==1){ + //cout << "h" << endl; + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + //We can't return regs16 because it needs 32bits! + //return *regs16[modrm.rm]; + }else{ + + if(use_ss==1){ + return this_cpu->ReadDword(this_cpu->SS,disp); + }else{ + return this_cpu->ReadDword(this_cpu->DS,disp); + } + } + return 0; +} + +inline void ModRM16::WriteByter(uint8_t byte){ + use_ss=0; + op_specific=0; + uint16_t disp=GetDisp(); + if(op_specific==1){ + *this_cpu->regs8[modrm.rm]=byte; + }else{ + + if(use_ss==1){ + this_cpu->WriteByte(this_cpu->SS,disp,byte); + }else{ + this_cpu->WriteByte(this_cpu->DS,disp,byte); + } + } +} +inline void ModRM16::WriteWordr(uint16_t word){ + use_ss=0; + op_specific=0; + uint16_t disp=GetDisp(); + if(op_specific==1){ + *this_cpu->regs16[modrm.rm]=word; + }else{ + + if(use_ss==1){ + this_cpu->WriteWord(this_cpu->SS,disp,word); + }else{ + this_cpu->WriteWord(this_cpu->DS,disp,word); + } + } +} +inline void ModRM16::WriteDword(uint32_t dword){ + use_ss=0; + op_specific=0; + uint16_t disp=GetDisp(); + if(op_specific==1){ + //*regs16[modrm.rm]=word; + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + }else{ + + if(use_ss==1){ + this_cpu->WriteDword(this_cpu->SS,disp,dword); + }else{ + this_cpu->WriteDword(this_cpu->DS,disp,dword); + } + } +} + +inline uint8_t ModRM16::GetLength(){ //This returns how many total bytes the modrm block consumes + if((modrm.mod==0) && (modrm.rm==6)){ + return 3; + } + switch(modrm.mod){ + case 0: + return 1; + case 1: + return 2; + case 2: + return 3; + case 3: + return 1; + } + return 1; //should never reach here, but to avoid warnings... +} //that was easier than I first thought it would be... +inline uint8_t ModRM16::GetExtra(){ //Get the extra fied from mod_rm + return modrm.extra; +} + +inline uint16_t ModRM16::ReadOffset(){ //This is only used by LEA. It will obtain the offset and not dereference it... + use_ss=0; + op_specific=0; + uint16_t disp=GetDisp(); + if(op_specific==1){ + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + //We can't return regs16 because it can't get address of a register! + //return *regs16[modrm.rm]; + }else{ + return disp; + } + return 0; +} +//} + + +#endif +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ops/etc.cpp Sun Mar 04 08:15:47 2012 +0000 @@ -0,0 +1,214 @@ +/** +Copyright (c) 2007 - 2009 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This file is part of the x86Lib project. +**/ +#define X86LIB_BUILD +#include <x86Lib.h> + + +namespace x86Lib{ + +void x86CPU::op16_nop(){ //0x90 + //do nothing +} + +void x86CPU::op16_hlt(){ //0xF4 + if(freg._if==0){ + Onx86LibError(); + //throw CpuPanic_excp("HLT With IF=0; Nothing to do",CLIHLT_EXCP); + } +} + +void x86CPU::op16_unknown(){ + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); +} + + + + +//Segment overrides... +void x86CPU::op16_pre_es_override(){ //0x26 + SetSegments(cES); + eip++; + *(uint32_t*)&op_cache=ReadDword(cCS,eip); + (this->*Opcodes[op_cache[0]])(); + + ResetSegments(); +} + +void x86CPU::op16_pre_ds_override(){ //0x3E + SetSegments(cDS); + eip++; + *(uint32_t*)&op_cache=ReadDword(cCS,eip); + (this->*Opcodes[op_cache[0]])(); + + ResetSegments(); +} + +void x86CPU::op16_pre_ss_override(){ //0x36 + SetSegments(cSS); + eip++; + *(uint32_t*)&op_cache=ReadDword(cCS,eip); + (this->*Opcodes[op_cache[0]])(); + + ResetSegments(); +} + +void x86CPU::op16_pre_cs_override(){ //0x2E + SetSegments(cCS); + eip++; + *(uint32_t*)&op_cache=ReadDword(cCS,eip); + (this->*Opcodes[op_cache[0]])(); + + ResetSegments(); +} + +void x86CPU::op16_rep(){ //repe and repne..(different opcodes, but I make them possible to use the same function) + //use a string_compares variable... + if(*regs16[CX]==0){ //for this, not executing the instruction is almost as expensive... + *(uint16_t*)&op_cache=ReadWord(cCS,eip+1); + int i=0; + //get size of opcode and prefixes.... + for(i=0;i<4;i++){ + switch(op_cache[i]){ + case 0x67: + case 0x66: + case 0x2E: + case 0x36: + case 0x3E: + case 0x26: + case 0x64: + case 0x65: + eip++; + break; + default: + eip++; + return; + } + } + return; + }else{ + uint32_t tmp=eip; + uint8_t t2=op_cache[0]; + eip++; + *(uint32_t*)&op_cache=ReadDword(cCS,eip); + (this->*Opcodes[op_cache[0]])(); + (*regs16[CX])--; + eip=tmp-1; + if(string_compares==1){ + string_compares=0; + if(t2==0xF2){ //repNE + if(freg.zf==1){ //exit... + eip+=2; + return; + } + }else{ + if((volatile uint8_t)freg.zf==0){ //exit... + eip+=2; + return; + } + } + } + } +} + +void x86CPU::op16_lock(){ //0xF0 prefix + #ifndef X86_MULTITHREADING + if(IsLocked()==1){ + eip--; + return; + } + #endif + Lock(); + eip++; + *(uint32_t*)&op_cache=ReadDword(cCS,eip); + //Add strict opcode testing for 386+ + (this->*Opcodes[op_cache[0]])(); + Unlock(); +} + + + +void x86CPU::op16_cbw(){ + if((*regs8[AL]&0x80)==0){ + *regs8[AH]=0; + }else{ + *regs8[AH]=0xFF; + } +} + + + +void x86CPU::op16_cwd(){ + if(*regs16[AX]>=0x8000){ + *regs16[DX]=0xFFFF; + }else{ + *regs16[DX]=0; + } +} + +void x86CPU::op16_escape(){ + /**This is for FPU escape opcodes + this uses 0xD8 to 0xDF + **/ + Onx86LibError(); + //throw CpuInt_excp(UNDEV_IEXCP); //throw unknown device exception +} +void x86CPU::op16_wait(){ + /**Does nothing...**/ + Onx86LibError(); + //throw CpuInt_excp(UNDEV_IEXCP); +} + + + +/**so-called undocumented opcodes:**/ + +/**salc -0xD6- this is will set al on carry -no arguments +log: if cf=0 then al=0 else al=FF +**/ +void x86CPU::op16_salc(){ //set al on carry + if(freg.cf==0){*regs8[AL]=0; + }else{*regs8[AL]=0xFF; + } + +} + + + + + + + + +}; + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ops/flags.cpp Sun Mar 04 08:15:47 2012 +0000 @@ -0,0 +1,205 @@ +/** +Copyright (c) 2007 - 2009 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This file is part of the x86Lib project. +**/ +#define X86LIB_BUILD +#include <x86Lib.h> +namespace x86Lib{ +using namespace std; + +//jmp rel8 jcc stuff +void x86CPU::op16_ja_rel8(){ //is also jnbe + eip++; + if(freg.cf==0 && freg.zf==0){ + Jmp16_near8(op_cache[1]); + } +} + +void x86CPU::op16_jnc_rel8(){ //is also jae and jnb + eip++; + if(freg.cf==0){ + Jmp16_near8(op_cache[1]); + } +} + + +void x86CPU::op16_jbe_rel8(){ //is also jna + eip++; + if(freg.cf==1 || freg.zf==1){ + Jmp16_near8(op_cache[1]); + }else{ + eip++; + } +} + +void x86CPU::op16_jc_rel8(){ //is also jb and jnae + eip++; + if(freg.cf==1){ + Jmp16_near8(op_cache[1]); + } +} + +void x86CPU::op16_jz_rel8(){ //is also je + eip++; + if(freg.zf==1){ + Jmp16_near8(op_cache[1]); + } +} + +void x86CPU::op16_jnz_rel8(){ //is also jne + eip++; + if(freg.zf==0){ + Jmp16_near8(op_cache[1]); + } +} + + +void x86CPU::op16_jp_rel8(){ //also jpe + eip++; + if(freg.pf==1){ + Jmp16_near8(op_cache[1]); + } +} + +void x86CPU::op16_jnp_rel8(){ //is also jpo + eip++; + if(freg.pf==0){ + Jmp16_near8(op_cache[1]); + } +} + +void x86CPU::op16_jg_rel8(){ //is also jnle + eip++; + if(freg.sf==freg.of && freg.zf==0){ + Jmp16_near8(op_cache[1]); + } +} + + +void x86CPU::op16_jge_rel8(){ //is also jnl + eip++; + if(freg.sf==freg.of){ + Jmp16_near8(op_cache[1]); + } +} + +void x86CPU::op16_jle_rel8(){ //is also jng + eip++; + if(freg.sf!=freg.of || freg.zf==1){ + Jmp16_near8(op_cache[1]); + } +} + +void x86CPU::op16_jl_rel8(){ //is also jnge + eip++; + if(freg.sf!=freg.of){ + Jmp16_near8(op_cache[1]); + } +} + + +void x86CPU::op16_jo_rel8(){ + eip++; + if(freg.of==1){ + Jmp16_near8(op_cache[1]); + } +} + +void x86CPU::op16_jno_rel8(){ + eip++; + if(freg.of==0){ + Jmp16_near8(op_cache[1]); + } +} + +void x86CPU::op16_js_rel8(){ //is negative + eip++; + if(freg.sf==1){ + Jmp16_near8(op_cache[1]); + } +} + +void x86CPU::op16_jns_rel8(){ //is positive + eip++; + if(freg.sf==0){ + Jmp16_near8(op_cache[1]); + } +} + + + +void x86CPU::op16_clc(){ + freg.cf=0; +} + +void x86CPU::op16_cld(){ + freg.df=0; +} + +void x86CPU::op16_cli(){ + freg._if=0; +} + +void x86CPU::op16_stc(){ + freg.cf=1; +} + +void x86CPU::op16_std(){ + freg.df=1; +} + +void x86CPU::op16_sti(){ + freg._if=1; +} + + +void x86CPU::op16_cmc(){ + freg.cf=freg.cf^1; +} + +void x86CPU::op16_lahf(){ + *regs8[AL]=*(uint8_t*)&freg; +} +void x86CPU::op16_sahf(){ + *(uint8_t*)&freg=*regs8[AL]; +} + + + + + + + + + + + +}; + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ops/flow.cpp Sun Mar 04 08:15:47 2012 +0000 @@ -0,0 +1,178 @@ +/** +Copyright (c) 2007 - 2009 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This file is part of the x86Lib project. +**/ +#define X86LIB_BUILD +#include <x86Lib.h> +namespace x86Lib{ +using namespace std; + + + + + + + + + + +void x86CPU::op16_jmp_rel8(){ + eip++; + Jmp16_near8(op_cache[1]); +} + +void x86CPU::op16_jmp_rel16(){ + eip+=2; //get to last byte of address so jmp works right + Jmp16_near16(*(uint16_t*)&op_cache[1]); +} + +void x86CPU::op16_jmp_imm16_imm16(){ //far jmp + *(uint32_t*)&op_cache=ReadDword(cCS,eip+1); + seg[cCS]=*(uint16_t*)&op_cache[2]; //I always forget that they are reversed... + eip=*(uint16_t*)&op_cache[0]; + eip--; //eip will be incremented in Cycle +} + +void x86CPU::op16_jmp_rm16(ModRM16 &rm){ + eip=rm.ReadWordr(); //absolute address... + eip--; +} + +void x86CPU::op16_jmp_m16_m16(ModRM16 &rm){ + *(uint32_t*)&op_cache=rm.ReadDword(); //quicker to use op_cache, than dynamic variables... + seg[cCS]=*(uint16_t*)&op_cache[2]; + eip=*(uint16_t*)&op_cache[0]; + eip--; +} + + + +void x86CPU::op16_jcxz_rel8(){ + if(*regs16[CX]==0){ + Jmp16_near8(op_cache[1]); + } +} + + + + + + +void x86CPU::op16_call_rel16(){ + + Push16(eip+2); + if(*(uint16_t*)&op_cache[1]<0x8000){ + //eip++; + } + eip+=2; + Jmp16_near16(*(uint16_t*)&op_cache[1]); +} +void x86CPU::op16_retn(){ + eip=Pop16(); + //eip--; //because in Cycle, we increment.. +} + +void x86CPU::op16_loop_rel8(){ + (*regs16[CX])--; + eip++; + if(*regs16[CX]!=0){ + Jmp16_near8(op_cache[1]); + } +} + +void x86CPU::op16_loope_rel8(){ + (*regs16[CX])--; + eip++; + if((*regs16[CX]!=0) && (freg.zf==1)){ + Jmp16_near8(op_cache[1]); + } +} + +void x86CPU::op16_loopne_rel8(){ + (*regs16[CX])--; + eip++; + if((*regs16[CX]!=0) && (freg.zf==0)){ + Jmp16_near8(op_cache[1]); + } +} + + +void x86CPU::op16_call_imm16_imm16(){ //far call + Push16(seg[cCS]); + Push16(eip+4); + *(uint32_t*)&op_cache=ReadDword(cCS,eip+1); + seg[cCS]=*(uint16_t*)&op_cache[2]; //I always forget that they are reversed... + eip=*(uint16_t*)&op_cache[0]; + eip--; //eip will be incremented in Cycle +} + +void x86CPU::op16_retf(){ + eip=Pop16(); + seg[cCS]=Pop16(); +} + +void x86CPU::op16_int_imm8(){ + eip++; + Int16(op_cache[1]); +} + +void x86CPU::op16_iret(){ + eip=Pop16(); + seg[cCS]=Pop16(); + *(uint16_t*)&freg=Pop16(); +} + +void x86CPU::op16_int3(){ + Int16(3); +} + +void x86CPU::op16_into(){ + if(freg.of==1){ + Int16(4); + } +} +void x86CPU::op16_call_rm16(ModRM16 &rm){ //far call + Push16(eip+rm.GetLength()+1); + eip=rm.ReadWordr(); + eip--; //eip will be incremented in Cycle +} + +void x86CPU::op16_call_rm16_rm16(ModRM16 &rm){ //far call + Push16(seg[cCS]); + Push16(eip+rm.GetLength()+1); + *(uint32_t*)&op_cache=ReadDword(DS,rm.ReadDword()); + seg[cCS]=*(uint16_t*)&op_cache[2]; //I always forget that they are reversed... + eip=*(uint16_t*)&op_cache[0]; + eip--; //eip will be incremented in Cycle +} + + + +}; + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ops/groups.cpp Sun Mar 04 08:15:47 2012 +0000 @@ -0,0 +1,437 @@ +/** +Copyright (c) 2007 - 2009 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This file is part of the x86Lib project. +**/ +#define X86LIB_BUILD +#include <x86Lib.h> +namespace x86Lib{ +using namespace std; + + +void x86CPU::op16_group_80(){ + eip++; + ModRM16 rm(this); + switch(rm.GetExtra()){ + case 5: + op16_sub_rm8_imm8(rm); + break; + case 0: + op16_add_rm8_imm8(rm); + break; + case 2: + op16_adc_rm8_imm8(rm); + break; + case 7: + op16_cmp_rm8_imm8(rm); + break; + case 1: + op16_or_rm8_imm8(rm); + break; + case 6: + op16_xor_rm8_imm8(rm); + break; + case 3: + op16_sbb_rm8_imm8(rm); + break; + case 4: + op16_and_rm8_imm8(rm); + break; + + default: + eip--; //to get actual opcode + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + break; + } + eip++; //for imm8 + +} + +void x86CPU::op16_group_81(){ + eip++; + ModRM16 rm(this); + switch(rm.GetExtra()){ + case 5: + op16_sub_rm16_imm16(rm); + break; + case 0: + op16_add_rm16_imm16(rm); + break; + case 2: + op16_adc_rm16_imm16(rm); + break; + case 7: + op16_cmp_rm16_imm16(rm); + break; + case 1: + op16_or_rm16_imm16(rm); + break; + case 6: + op16_xor_rm16_imm16(rm); + break; + case 3: + op16_sbb_rm16_imm16(rm); + break; + case 4: + op16_and_rm16_imm16(rm); + break; + + default: + eip--; + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + break; + } + eip+=2; //these each have imm16 +} + +void x86CPU::op16_group_83(){ + eip++; + ModRM16 rm(this); + switch(rm.GetExtra()){ + case 0: + op16_add_rm16_imm8(rm); + break; + case 2: + op16_adc_rm16_imm8(rm); + break; + case 5: + op16_sub_rm16_imm8(rm); + break; + case 7: + op16_cmp_rm16_imm8(rm); + break; + case 1: + op16_or_rm16_imm8(rm); + break; + case 6: + op16_xor_rm16_imm8(rm); + break; + case 3: + op16_sbb_rm16_imm8(rm); + break; + case 4: + op16_and_rm16_imm8(rm); + break; + + default: + eip--; + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + break; + } + eip++; +} + +void x86CPU::op16_group_8F(){ + eip++; + ModRM16 rm(this); + switch(rm.GetExtra()){ + case 0: + op16_pop_m16(rm); + break; + + default: + eip--; + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + break; + } +} + +void x86CPU::op16_group_F6(){ + eip++; + ModRM16 rm(this); + switch(rm.GetExtra()){ + case 6: + op16_div_rm8(rm); + break; + case 7: + op16_idiv_rm8(rm); + break; + case 4: + op16_mul_rm8(rm); + break; + case 5: + op16_imul_rm8(rm); + break; + case 3: + op16_neg_rm8(rm); + break; + case 0: + op16_test_rm8_imm8(rm); + eip++; + break; + case 2: + op16_not_rm8(rm); + break; + + default: + eip--; + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + break; + } +} + +void x86CPU::op16_group_F7(){ + eip++; + ModRM16 rm(this); + switch(rm.GetExtra()){ + case 6: + op16_div_rm16(rm); + break; + case 7: + op16_idiv_rm16(rm); + break; + case 4: + op16_mul_rm16(rm); + break; + case 5: + op16_imul_rm16(rm); + break; + case 3: + op16_neg_rm16(rm); + break; + case 0: + op16_test_rm16_imm16(rm); + eip+=2; + break; + case 2: + op16_not_rm16(rm); + break; + + default: + eip--; + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + break; + } +} + + +void x86CPU::op16_group_FF(){ + eip++; + ModRM16 rm(this); + switch(rm.GetExtra()){ + case 4: + op16_jmp_rm16(rm); + break; + case 5: + op16_jmp_m16_m16(rm); + break; + case 6: + op16_push_m16(rm); + break; + case 0: + op16_inc_rm16(rm); + break; + case 1: + op16_dec_rm16(rm); + break; + case 2: + op16_call_rm16(rm); + break; + case 3: + op16_call_rm16_rm16(rm); + break; + + default: + eip--; + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + break; + } +} + +void x86CPU::op16_group_FE(){ + eip++; + ModRM16 rm(this); + switch(rm.GetExtra()){ + case 0: + op16_inc_rm8(rm); + break; + case 1: + op16_dec_rm8(rm); + break; + + default: + eip--; + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + break; + } +} + +void x86CPU::op16_group_D0(){ + eip++; + ModRM16 rm(this); + switch(rm.GetExtra()){ + case 7: + op16_sar_rm8_1(rm); + break; + case 4: + op16_shl_rm8_1(rm); + break; + case 5: + op16_shr_rm8_1(rm); + break; + case 0: + op16_rol_rm8_1(rm); + break; + case 1: + op16_ror_rm8_1(rm); + break; + case 3: + op16_rcr_rm8_1(rm); + break; + case 2: + op16_rcl_rm8_1(rm); + break; + default: + eip--; + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + break; + } +} + +void x86CPU::op16_group_D1(){ + eip++; + ModRM16 rm(this); + switch(rm.GetExtra()){ + case 7: + op16_sar_rm16_1(rm); + break; + case 4: + op16_shl_rm16_1(rm); + break; + case 5: + op16_shr_rm16_1(rm); + break; + case 0: + op16_rol_rm16_1(rm); + break; + case 1: + op16_ror_rm16_1(rm); + break; + case 3: + op16_rcr_rm16_1(rm); + break; + case 2: + op16_rcl_rm16_1(rm); + break; + + + default: + eip--; + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + break; + } +} + +void x86CPU::op16_group_D2(){ + eip++; + ModRM16 rm(this); + switch(rm.GetExtra()){ + case 7: + op16_sar_rm8_cl(rm); + break; + case 4: + op16_shl_rm8_cl(rm); + break; + case 5: + op16_shr_rm8_cl(rm); + break; + case 0: + op16_rol_rm8_cl(rm); + break; + case 1: + op16_ror_rm8_cl(rm); + break; + case 3: + op16_rcr_rm8_cl(rm); + break; + case 2: + op16_rcl_rm8_cl(rm); + break; + + + default: + eip--; + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + break; + } +} + +void x86CPU::op16_group_D3(){ + eip++; + ModRM16 rm(this); + switch(rm.GetExtra()){ + case 7: + op16_sar_rm16_cl(rm); + break; + case 4: + op16_shl_rm16_cl(rm); + break; + case 5: + op16_shr_rm16_cl(rm); + break; + case 0: + op16_rol_rm16_cl(rm); + break; + case 1: + op16_ror_rm16_cl(rm); + break; + case 3: + op16_rcr_rm16_cl(rm); + break; + case 2: + op16_rcl_rm16_cl(rm); + break; + + + default: + eip--; + Onx86LibError(); + //throw CpuInt_excp(UNK_IEXCP); + break; + } +} + + + + + + +}; + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ops/maths.cpp Sun Mar 04 08:15:47 2012 +0000 @@ -0,0 +1,1287 @@ +/** +Copyright (c) 2007 - 2009 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This file is part of the x86Lib project. +**/ +#define X86LIB_BUILD +#include <x86Lib.h> +namespace x86Lib{ +using namespace std; + + + + +// TODO (Jordan#4#): Get AF stuff working in this!! +uint8_t x86CPU::Sub8(uint8_t base,uint8_t subt){ + int8_t result; + if(subt>base){freg.cf=1;}else{freg.cf=0;} + if((int16_t)base-subt>127 || (int16_t)base-subt<-127){ + freg.of=1; + }else{ + freg.of=0; + } + result=base-subt; + if(result==0){freg.zf=1;}else{freg.zf=0;} + CalculatePF8(result); //do pf + CalculateSF8(result); //do sf + base&=0xF; + subt&=0xF; + freg.af = (((base-subt) & ~0xf) != 0); //thank you http://stackoverflow.com/questions/4513746/explain-how-the-af-flag-works-in-an-x86-instructions + return result; +} + +uint16_t x86CPU::Sub16(uint16_t base,uint16_t subt){ + int16_t result; + uint16_t mirror; + if(subt>base){freg.cf=1;}else{freg.cf=0;} + if((int32_t)base-subt>32767 || (int32_t)base-subt<-32767){ + freg.of=1; + }else{ + freg.of=0; + } + mirror=base-subt; + result=mirror; + if(result==0){freg.zf=1;}else{freg.zf=0;} + CalculatePF16(result); //do pf + CalculateSF16(result); //do sf + base&=0xF; + subt&=0xF; + freg.af = (((base-subt) & ~0xf) != 0); + return mirror; +} + +uint8_t x86CPU::Add8(uint8_t base,uint8_t adder){ + int8_t result; + if(adder+base>255){freg.cf=1;}else{freg.cf=0;} + if((int16_t)base+adder>127 || (int16_t)base+adder<-127){ + freg.of=1; + }else{ + freg.of=0; + } + result=base+adder; + if(result==0){freg.zf=1;}else{freg.zf=0;} + CalculatePF8(result); //do pf + CalculateSF8(result); //do sf + base&=0x0F; + adder&=0x0F; + freg.af = ((int16_t)base+adder > 15); + return result; +} + +uint16_t x86CPU::Add16(uint16_t base,uint16_t adder){ + int16_t result; + if((uint32_t)adder+base>(uint32_t)65535){freg.cf=1;}else{freg.cf=0;} + if((int32_t)base+adder>32767 || (int32_t)base+adder<-32767){ + freg.of=1; + }else{ + freg.of=0; + } + result=base+adder; + if(result==0){freg.zf=1;}else{freg.zf=0;} + CalculatePF16(result); //do pf + CalculateSF16(result); //do sf + base&=0x0F; + adder&=0x0F; + freg.af = ((int16_t)base+adder > 15); + return result; +} + + + + +uint8_t x86CPU::And8(uint8_t base,uint8_t mask){ + freg.of=0; + freg.cf=0; + base=base&mask; + CalculatePF8(base); + CalculateSF8(base); + if(base==0){ + freg.zf=1; + }else{ + freg.zf=0; + } + return base; +} + +uint16_t x86CPU::And16(uint16_t base,uint16_t mask){ + freg.of=0; + freg.cf=0; + base=base&mask; + CalculatePF16(base); + CalculateSF16(base); + if(base==0){ + freg.zf=1; + }else{ + freg.zf=0; + } + return base; +} + +//Not affects no flags, so just use ~ + + +uint8_t x86CPU::Or8(uint8_t base,uint8_t mask){ + freg.of=0; + freg.cf=0; + base=base|mask; + CalculatePF8(base); + CalculateSF8(base); + if(base==0){ + freg.zf=1; + }else{ + freg.zf=0; + } + return base; +} + +uint16_t x86CPU::Or16(uint16_t base,uint16_t mask){ + freg.of=0; + freg.cf=0; + base=base|mask; + CalculatePF16(base); + CalculateSF16(base); + if(base==0){ + freg.zf=1; + }else{ + freg.zf=0; + } + return base; +} + +uint8_t x86CPU::Xor8(uint8_t base,uint8_t mask){ + freg.of=0; + freg.cf=0; + base=base^mask; + CalculatePF8(base); + CalculateSF8(base); + if(base==0){ + freg.zf=1; + }else{ + freg.zf=0; + } + return base; +} + +uint16_t x86CPU::Xor16(uint16_t base,uint16_t mask){ + freg.of=0; + freg.cf=0; + base=base^mask; + CalculatePF16(base); + CalculateSF16(base); + if(base==0){ + freg.zf=1; + }else{ + freg.zf=0; + } + return base; +} + +uint8_t x86CPU::ShiftLogicalRight8(uint8_t base,uint8_t count){ + count&=0x1F; //only use bottom 5 bits + if(count==0){ + CalculatePF8(base); + CalculateSF8(base); + freg.zf=1; + return base; + } + freg.of=(base&0x80)>>7; + freg.cf=(base>>(count-1))&1; + base=base>>count; + freg.of=freg.of^((base&0x80)>>7); //if the sign bit changed, then set it to 1 + CalculatePF8(base); + CalculateSF8(base); + if(base==0){ + freg.zf=1; + }else{ + freg.zf=0; + } + freg.of=0; + return base; +} + +uint16_t x86CPU::ShiftLogicalRight16(uint16_t base,uint8_t count){ + count&=0x1F; //only use bottom 5 bits + if(count==0){ + CalculatePF16(base); + CalculateSF16(base); + freg.zf=1; + return base; + } + freg.of=(base&0x8000)>>15; + freg.cf=(base>>(count-1))&1; + base=base>>count; + freg.of=freg.of^((base&0x8000)>>15); //if the sign bit changed, then set it to 1 + CalculatePF16(base); + CalculateSF16(base); + if(base==0){ + freg.zf=1; + }else{ + freg.zf=0; + } + freg.of=0; + return base; +} +uint8_t x86CPU::ShiftArithmeticRight8(uint8_t base,uint8_t count){ + count&=0x1F; //only use bottom 5 bits + if(count==0){ + CalculatePF8(base); + CalculateSF8(base); + freg.zf=1; + return base; + } + freg.cf=(base>>(count-1))&1; + if((base&0x80)!=0){ + base=(base>>count)|(~(0xFF>>count)); //this replaces displaced zero bits with the sign bit + }else{ + base=(base>>count); + } + freg.of=0; + CalculatePF8(base); + CalculateSF8(base); + if(base==0){ + freg.zf=1; + }else{ + freg.zf=0; + } + freg.of=0; + return base; +} +uint16_t x86CPU::ShiftArithmeticRight16(uint16_t base,uint8_t count){ + count&=0x1F; //only use bottom 5 bits + if(count==0){ + CalculatePF16(base); + CalculateSF16(base); + freg.zf=1; + return base; + } + freg.cf=(base>>(count-1))&1; + if((base&0x8000)!=0){ + base=(base>>count)|(~(0xFFFF>>count)); //this replaces displaced zero bits with the sign bit + }else{ + base=(base>>count); + } + freg.of=0; + CalculatePF16(base); + CalculateSF16(base); + if(base==0){ + freg.zf=1; + }else{ + freg.zf=0; + } + freg.of=0; + return base; +} + +uint8_t x86CPU::ShiftLogicalLeft8(uint8_t base,uint8_t count){ + count&=0x1F; //only use bottom 5 bits + if(count==0){ + CalculatePF8(base); + CalculateSF8(base); + freg.zf=1; + return base; + } + freg.of=(base&0x80)>>7; + freg.cf=((base<<(count-1))&0x80)>>7; + base=base<<count; + freg.of=freg.of^((base&0x80)>>7); //if the sign bit changed, then set it to 1 + CalculatePF8(base); + CalculateSF8(base); + if(base==0){ + freg.zf=1; + }else{ + freg.zf=0; + } + freg.of=0; + return base; +} + +uint16_t x86CPU::ShiftLogicalLeft16(uint16_t base,uint8_t count){ + count&=0x1F; //only use bottom 5 bits + if(count==0){ + CalculatePF16(base); + CalculateSF16(base); + freg.zf=1; + return base; + } + freg.of=(base&0x8000)>>15; + freg.cf=((base<<(count-1))&0x8000)>>15; + base=base<<count; + freg.of=freg.of^((base&0x8000)>>15); //if the sign bit changed, then set it to 1 + CalculatePF16(base); + CalculateSF16(base); + if(base==0){ + freg.zf=1; + }else{ + freg.zf=0; + } + return base; +} + +/**ToDo: Possibly adapt BOCHS source so that we avoid this loop crap...**/ +uint8_t x86CPU::RotateRight8(uint8_t base,uint8_t count){ + freg.of=(base&0x80)>>7; + while(count>0){ + freg.cf=(base&0x01); + base=(freg.cf<<7)|(base>>1); + count--; + } + freg.of=freg.of^((base&0x80)>>7); + return base; +} + +uint16_t x86CPU::RotateRight16(uint16_t base,uint8_t count){ + freg.of=(base&0x8000)>>15; + while(count>0){ + freg.cf=(base&0x01); + base=(freg.cf<<15)|(base>>1); + count--; + } + freg.of=freg.of^((base&0x80)>>15); + return base; +} + +uint8_t x86CPU::RotateLeft8(uint8_t base,uint8_t count){ + freg.of=(base&0x80)>>7; + while(count>0){ + freg.cf=(base&0x80)>>7; + base=(freg.cf)|(base<<1); + count--; + } + freg.of=freg.of^((base&0x80)>>7); + return base; +} + +uint16_t x86CPU::RotateLeft16(uint16_t base,uint8_t count){ + freg.of=(base&0x8000)>>15; + while(count>0){ + freg.cf=(base&0x8000)>>15; + base=(freg.cf)|(base<<1); + count--; + } + freg.of=freg.of^((base&0x8000)>>15); + return base; +} + +uint8_t x86CPU::RotateCarryLeft8(uint8_t base,uint8_t count){ + freg.of=(base&0x80)>>7; + while(count>0){ + freg.r0=freg.cf; //reserved bit as a temp variable... + freg.cf=(base&0x80)>>7; + base=(base<<1); + base|=freg.r0; //puts (old)CF in it's place + count--; + } + freg.of=freg.of^((base&0x80)>>7); + return base; +} + +uint16_t x86CPU::RotateCarryLeft16(uint16_t base,uint8_t count){ + freg.of=(base&0x8000)>>15; + while(count>0){ + freg.r0=freg.cf; //reserved bit as a temp variable... + freg.cf=(base&0x8000)>>15; + base=(base<<1); + base=(base&0xFFFE)|freg.r0; //zeros the 0 bit and puts (old)CF in it's place + count--; + } + freg.of=freg.of^((base&0x8000)>>15); + return base; +} + +uint8_t x86CPU::RotateCarryRight8(uint8_t base,uint8_t count){ + freg.of=(base&0x80)>>7; + while(count>0){ + freg.r0=freg.cf; + freg.cf=(base&0x01); + base=(freg.r0<<7)|(base>>1); + count--; + } + freg.of=freg.of^((base&0x80)>>7); + return base; +} + +uint16_t x86CPU::RotateCarryRight16(uint16_t base,uint8_t count){ + freg.of=(base&0x8000)>>15; + while(count>0){ + freg.r0=freg.cf; + freg.cf=(base&0x01); + base=(freg.r0<<15)|(base>>1); + count--; + } + freg.of=freg.of^((base&0x8000)>>15); + return base; +} + + + + + + + + + +void x86CPU::op16_sub_al_imm8(){ //0x2C + *regs8[AL]=Sub8(*regs8[AL],op_cache[1]); + eip++; +} + +void x86CPU::op16_sub_ax_imm16(){ //0x2D..yay! 2D and not 3! + *regs16[AX]=Sub16(*regs16[AX],*(uint16_t*)&op_cache[1]); + eip+=2; +} + +void x86CPU::op16_sub_rm8_r8(){ + eip++; + ModRM16 rm8(this); + rm8.WriteByter(Sub8(rm8.ReadByter(),*regs8[rm8.GetExtra()])); + //finally learning the power of deconstructors! +} + +void x86CPU::op16_sub_rm16_r16(){ + eip++; + ModRM16 rm16(this); + rm16.WriteWordr(Sub16(rm16.ReadWordr(),*regs16[rm16.GetExtra()])); +} +void x86CPU::op16_sub_r8_rm8(){ + eip++; + ModRM16 rm8(this); + *regs8[rm8.GetExtra()]=Sub8(*regs8[rm8.GetExtra()],rm8.ReadByter()); +} + +void x86CPU::op16_sub_r16_rm16(){ + eip++; + ModRM16 rm16(this); + *regs16[rm16.GetExtra()]=Sub16(*regs16[rm16.GetExtra()],rm16.ReadWordr()); +} + +void x86CPU::op16_sub_rm8_imm8(ModRM16 &rm8){ //group 0x80 /5 + rm8.WriteByter(Sub8(rm8.ReadByter(),ReadByte(cCS,eip+rm8.GetLength()))); +} + +void x86CPU::op16_sub_rm16_imm16(ModRM16 &rm){ //Group 0x81 /5 + rm.WriteWordr(Sub16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength()))); +} + +void x86CPU::op16_sub_rm16_imm8(ModRM16 &rm){ //group 0x83 /5 + rm.WriteWordr(Sub16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength())))); +} + +/****/ +void x86CPU::op16_sbb_al_imm8(){ + *regs8[AL]=Sub8(*regs8[AL],op_cache[1]-freg.cf); + eip++; +} + +void x86CPU::op16_sbb_ax_imm16(){ + *regs16[AX]=Sub16(*regs16[AX],*(uint16_t*)&op_cache[1]-freg.cf); + eip++; + eip++; +} + +void x86CPU::op16_sbb_rm8_r8(){ + eip++; + ModRM16 rm8(this); + rm8.WriteByter(Sub8(rm8.ReadByter(),*regs8[rm8.GetExtra()]-freg.cf)); +} + +void x86CPU::op16_sbb_rm16_r16(){ + eip++; + ModRM16 rm16(this); + rm16.WriteWordr(Sub16(rm16.ReadWordr(),*regs16[rm16.GetExtra()]-freg.cf)); +} +void x86CPU::op16_sbb_r8_rm8(){ + eip++; + ModRM16 rm8(this); + *regs8[rm8.GetExtra()]=Sub8(*regs8[rm8.GetExtra()],rm8.ReadByter()-freg.cf); +} + +void x86CPU::op16_sbb_r16_rm16(){ + eip++; + ModRM16 rm16(this); + *regs16[rm16.GetExtra()]=Sub16(*regs16[rm16.GetExtra()],rm16.ReadWordr()-freg.cf); +} + +void x86CPU::op16_sbb_rm8_imm8(ModRM16 &rm8){ //group 0x80 + rm8.WriteByter(Sub8(rm8.ReadByter(),ReadByte(cCS,eip+rm8.GetLength())-freg.cf)); +} + +void x86CPU::op16_sbb_rm16_imm16(ModRM16 &rm){ //Group 0x81 + rm.WriteWordr(Sub16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength())-freg.cf)); +} + +void x86CPU::op16_sbb_rm16_imm8(ModRM16 &rm){ //group 0x83 + rm.WriteWordr(Sub16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength())-freg.cf))); +} + + +void x86CPU::op16_dec_r16(){ //0x48+r + freg.r0=freg.cf; + *regs16[(op_cache[0]-0x48)]=Sub16(*regs16[(op_cache[0]-0x48)],1); + freg.cf=freg.r0; +} + +void x86CPU::op16_dec_rm8(ModRM16& rm){ + freg.r0=freg.cf; + rm.WriteByter(Sub8(rm.ReadByter(),1)); + freg.cf=freg.r0; +} + +void x86CPU::op16_dec_rm16(ModRM16& rm){ + freg.r0=freg.cf; + rm.WriteWordr(Sub16(rm.ReadWordr(),1)); + freg.cf=freg.r0; +} + + + + + + +//cmp and sub are so similar, that they are both going in here... +void x86CPU::op16_cmp_al_imm8(){ + Sub8(*regs8[AL],op_cache[1]); + eip++; +} + +void x86CPU::op16_cmp_ax_imm16(){ + Sub16(*regs16[AX],*(uint16_t*)&op_cache[1]); + eip+=2; +} + +void x86CPU::op16_cmp_rm8_r8(){ + eip++; + ModRM16 rm(this); + Sub8(rm.ReadByter(),*regs8[rm.GetExtra()]); +} + +void x86CPU::op16_cmp_rm16_r16(){ + eip++; + ModRM16 rm(this); + Sub16(rm.ReadWordr(),*regs16[rm.GetExtra()]); +} + +void x86CPU::op16_cmp_r8_rm8(){ + eip++; + ModRM16 rm(this); + Sub8(*regs16[rm.GetExtra()],rm.ReadByter()); +} + +void x86CPU::op16_cmp_r16_rm16(){ + eip++; + ModRM16 rm(this); + Sub16(*regs16[rm.GetExtra()],rm.ReadWordr()); +} + +void x86CPU::op16_cmp_rm8_imm8(ModRM16 &rm){ //group 80 /7 + Sub8(rm.ReadByter(),ReadByte(cCS,eip+rm.GetLength())); +} + +void x86CPU::op16_cmp_rm16_imm16(ModRM16 &rm){ //group 81 /7 + Sub16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength())); +} + +void x86CPU::op16_cmp_rm16_imm8(ModRM16 &rm){ //group 83 /7 + Sub16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength()))); +} + + + + + + +void x86CPU::op16_add_al_imm8(){ + *regs8[AL]=Add8(*regs8[AL],op_cache[1]); + eip++; +} + +void x86CPU::op16_add_ax_imm8(){ + *regs16[AX]=Add16(*regs16[AX],*(uint16_t*)&op_cache[1]); + eip++; + eip++; +} + +void x86CPU::op16_add_rm8_r8(){ + eip++; + ModRM16 rm8(this); + rm8.WriteByter(Add8(rm8.ReadByter(),*regs8[rm8.GetExtra()])); +} + +void x86CPU::op16_add_rm16_r16(){ + eip++; + ModRM16 rm16(this); + rm16.WriteWordr(Add16(rm16.ReadWordr(),*regs16[rm16.GetExtra()])); +} + +void x86CPU::op16_add_r8_rm8(){ + eip++; + ModRM16 rm(this); + *regs8[rm.GetExtra()]=Add8(*regs8[rm.GetExtra()],rm.ReadByter()); +} + +void x86CPU::op16_add_r16_rm16(){ + eip++; + ModRM16 rm(this); + *regs16[rm.GetExtra()]=Add16(*regs16[rm.GetExtra()],rm.ReadWordr()); +} + +void x86CPU::op16_add_rm8_imm8(ModRM16 &rm){ //Group 0x80 /0 + rm.WriteByter(Add8(rm.ReadWordr(),ReadByte(cCS,eip+rm.GetLength()))); +} + +void x86CPU::op16_add_rm16_imm16(ModRM16 &rm){ //Group 0x81 /0 + rm.WriteWordr(Add16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength()))); +} + +void x86CPU::op16_add_rm16_imm8(ModRM16 &rm){ //group 0x83 /0 + rm.WriteWordr(Add16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength())))); +} + + +/****/ +void x86CPU::op16_adc_al_imm8(){ + *regs8[AL]=Add8(*regs8[AL],op_cache[1]+freg.cf); + eip++; +} + +void x86CPU::op16_adc_ax_imm8(){ + *regs16[AX]=Add16(*regs16[AX],*(uint16_t*)&op_cache[1]+freg.cf); + eip++; + eip++; +} + +void x86CPU::op16_adc_rm8_r8(){ + eip++; + ModRM16 rm8(this); + rm8.WriteByter(Add8(rm8.ReadByter(),*regs8[rm8.GetExtra()]+freg.cf)); +} + +void x86CPU::op16_adc_rm16_r16(){ + eip++; + ModRM16 rm16(this); + rm16.WriteWordr(Add16(rm16.ReadWordr(),*regs16[rm16.GetExtra()]+freg.cf)); +} + +void x86CPU::op16_adc_r8_rm8(){ + eip++; + ModRM16 rm(this); + *regs8[rm.GetExtra()]=Add8(*regs8[rm.GetExtra()],rm.ReadByter()+freg.cf); +} + +void x86CPU::op16_adc_r16_rm16(){ + eip++; + ModRM16 rm(this); + *regs16[rm.GetExtra()]=Add16(*regs16[rm.GetExtra()],rm.ReadWordr()+freg.cf); +} + +void x86CPU::op16_adc_rm8_imm8(ModRM16 &rm){ //Group 0x80 /2 + rm.WriteByter(Add8(rm.ReadWordr(),ReadByte(cCS,eip+rm.GetLength())+freg.cf)); +} + +void x86CPU::op16_adc_rm16_imm16(ModRM16 &rm){ //Group 0x81 /2 + rm.WriteWordr(Add16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength())+freg.cf)); +} + +void x86CPU::op16_adc_rm16_imm8(ModRM16 &rm){ //group 0x83 /2 + rm.WriteWordr(Add16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength()))+freg.cf)); +} + + + +void x86CPU::op16_inc_r16(){ //0x40+r + freg.r0=freg.cf; + *regs16[(op_cache[0]-0x40)]=Add16(*regs16[(op_cache[0]-0x40)],1); + freg.cf=freg.r0; +} + +void x86CPU::op16_inc_rm8(ModRM16 &rm){ + freg.r0=freg.cf; //yay for reserved flags! + rm.WriteByter(Add8(rm.ReadByter(),1)); + freg.cf=freg.r0; +} + +void x86CPU::op16_inc_rm16(ModRM16 &rm){ + freg.r0=freg.cf; + rm.WriteWordr(Add16(rm.ReadWordr(),1)); + freg.cf=freg.r0; +} + +void x86CPU::op16_neg_rm8(ModRM16 &rm){ + uint8_t tmp=rm.ReadByter(); + if(tmp==0xFF){ + freg.of=1; + return; + } + rm.WriteByter(Sub8(0,tmp)); + if(tmp==0){ + freg.cf=0; + }else{ + freg.cf=1; + } +} +void x86CPU::op16_neg_rm16(ModRM16 &rm){ + uint16_t tmp=rm.ReadWordr(); + if(tmp==0xFFFF){ + freg.of=1; + return; + } + rm.WriteWordr(Sub16(0,tmp)); + if(tmp==0){ + freg.cf=0; + }else{ + freg.cf=1; + } +} + + + +void x86CPU::op16_div_rm8(ModRM16 &rm){ + if(rm.ReadByter()==0){ + Onx86LibError(); + //throw CpuInt_excp(DIV0_IEXCP); + } + if(((*regs16[AX])/rm.ReadByter())>0xFF){ + Onx86LibError(); + //throw CpuInt_excp(DIV0_IEXCP); + } + *regs8[AL]=(*regs16[AX])/rm.ReadByter(); + *regs8[AH]=(*regs16[AX])%rm.ReadByter(); +} + +void x86CPU::op16_div_rm16(ModRM16 &rm){ + if(rm.ReadWordr()==0){ + Onx86LibError(); + //throw CpuInt_excp(DIV0_IEXCP); + } + if((((*regs16[DX]<<16)|(*regs16[AX]))/rm.ReadWordr())>0xFFFF){ + Onx86LibError(); + //throw CpuInt_excp(DIV0_IEXCP); + } + *regs8[AX]=((*regs16[DX]<<16)|(*regs16[AX]))/rm.ReadWordr(); + *regs8[DX]=((*regs16[DX]<<16)|(*regs16[AX]))%rm.ReadWordr(); +} + + +void x86CPU::op16_idiv_rm8(ModRM16 &rm){ //This WORKS! both signed, and unsigned! + //grrr...who the crap does signed division anyway!? + if(rm.ReadByter()==0){ + Onx86LibError(); + //throw CpuInt_excp(DIV0_IEXCP); + } + uint8_t tmp=rm.ReadByter(); + bool store1,store2; + + tmp=Unsign8(tmp,store1); + *regs16[AX]=Unsign16(*regs16[AX],store2); + if(((*regs16[AX])/tmp)>0xFF){ + Onx86LibError(); + //throw CpuInt_excp(DIV0_IEXCP); + } + + *regs8[AL]=(*regs16[AX])/tmp; + *regs8[AH]=(*regs16[AX])%tmp; + + *regs8[AL]=Resign8(*regs8[AL],store1^store2); +} + +void x86CPU::op16_idiv_rm16(ModRM16 &rm){ + if(rm.ReadWordr()==0){ + Onx86LibError(); + //throw CpuInt_excp(DIV0_IEXCP); + } + uint16_t tmp=rm.ReadWordr(); + bool store1,store2; + tmp=Unsign16(tmp,store1); + static uint32_t tmp2=Unsign32(((*regs16[DX])<<16)|(*regs16[AX]),store2); + + if((tmp2/tmp)>0xFFFF){ + Onx86LibError(); + //throw CpuInt_excp(DIV0_IEXCP); + } + *regs16[AX]=tmp2/tmp; + *regs16[DX]=tmp2%tmp; + + *regs16[AX]=Resign16(*regs16[AX],store1^store2); +} + + + +void x86CPU::op16_mul_rm8(ModRM16 &rm){ + *regs16[AX]=(*regs8[AL])*rm.ReadByter(); + if((*regs8[AH])>0){ //if tophalf of result has anything in it + freg.cf=1; + freg.of=1; + }else{ + freg.cf=0; + freg.of=0; + } +} + + +void x86CPU::op16_mul_rm16(ModRM16 &rm){ + uint32_t result; + result=(*regs16[AX])*rm.ReadWordr(); + *regs16[AX]=result&0x0000FFFF; + *regs16[DX]=(result&0xFFFF0000)>>16; + if((*regs16[DX])>0){ //if tophalf of result has anything in it + freg.cf=1; + freg.of=1; + }else{ + freg.cf=0; + freg.of=0; + } +} + +void x86CPU::op16_imul_rm8(ModRM16 &rm){ + bool store1,store2; + *regs16[AX]=Unsign8(*regs8[AL],store1)*Unsign8(rm.ReadByter(),store2); + if(*regs8[AX]>0){ + freg.of=1; + freg.cf=1; + }else{ + freg.of=0; + freg.cf=0; + } + *regs16[AX]=Resign16(*regs16[AX],store1^store2); +} + +void x86CPU::op16_imul_rm16(ModRM16 &rm){ + bool store1,store2; + uint32_t result=Unsign16(*regs16[AX],store1)*Unsign16(rm.ReadWordr(),store2); + if((result&0xFFFF0000)>0){ + freg.of=1; + freg.cf=1; + }else{ + freg.of=0; + freg.cf=0; + } + result=Resign32(result,store1^store2); + *regs16[DX]=(result&0xFFFF0000)>>16; + *regs16[AX]=(result&0xFFFF); +} + + + +void x86CPU::op16_and_rm8_r8(){ + eip++; + ModRM16 rm(this); + rm.WriteByter(And8(rm.ReadByter(),*regs8[rm.GetExtra()])); +} + +void x86CPU::op16_and_rm16_r16(){ + eip++; + ModRM16 rm(this); + rm.WriteWordr(And16(rm.ReadWordr(),*regs16[rm.GetExtra()])); +} + +void x86CPU::op16_and_r8_rm8(){ + eip++; + ModRM16 rm(this); + *regs8[rm.GetExtra()]=And8(*regs8[rm.GetExtra()],rm.ReadByter()); +} + +void x86CPU::op16_and_r16_rm16(){ + eip++; + ModRM16 rm(this); + *regs16[rm.GetExtra()]=And16(*regs16[rm.GetExtra()],rm.ReadWordr()); +} + +void x86CPU::op16_and_al_imm8(){ + eip++; + *regs8[AL]=And8(*regs8[AL],op_cache[1]); +} + +void x86CPU::op16_and_ax_imm16(){ + eip++; + eip++; + *regs16[AX]=And16(*regs16[AX],*(uint16_t*)&op_cache[1]); +} + +void x86CPU::op16_and_rm8_imm8(ModRM16& rm){ + rm.WriteByter(And8(rm.ReadByter(),ReadByte(cCS,eip+rm.GetLength()))); +} + +void x86CPU::op16_and_rm16_imm16(ModRM16& rm){ + rm.WriteWordr(And16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength()))); +} + +void x86CPU::op16_and_rm16_imm8(ModRM16& rm){ + rm.WriteWordr(And16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength())))); + //gotta love parentheses... +} + +void x86CPU::op16_or_rm8_r8(){ + eip++; + ModRM16 rm(this); + rm.WriteByter(Or8(rm.ReadByter(),*regs8[rm.GetExtra()])); +} + +void x86CPU::op16_or_rm16_r16(){ + eip++; + ModRM16 rm(this); + rm.WriteWordr(Or16(rm.ReadWordr(),*regs16[rm.GetExtra()])); +} + +void x86CPU::op16_or_r8_rm8(){ + eip++; + ModRM16 rm(this); + *regs8[rm.GetExtra()]=Or8(*regs8[rm.GetExtra()],rm.ReadByter()); +} + +void x86CPU::op16_or_r16_rm16(){ + eip++; + ModRM16 rm(this); + *regs16[rm.GetExtra()]=Or16(*regs16[rm.GetExtra()],rm.ReadWordr()); +} + +void x86CPU::op16_or_al_imm8(){ + eip++; + *regs8[AL]=Or8(*regs8[AL],op_cache[1]); +} + +void x86CPU::op16_or_ax_imm16(){ + eip++; + eip++; + *regs16[AX]=Or16(*regs16[AX],*(uint16_t*)&op_cache[1]); +} + +void x86CPU::op16_or_rm8_imm8(ModRM16& rm){ + rm.WriteByter(Or8(rm.ReadByter(),ReadByte(cCS,eip+rm.GetLength()))); +} + +void x86CPU::op16_or_rm16_imm16(ModRM16& rm){ + rm.WriteWordr(Or16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength()))); +} + +void x86CPU::op16_or_rm16_imm8(ModRM16& rm){ + rm.WriteWordr(Or16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength())))); + //gotta love parentheses... +} + + + +void x86CPU::op16_xor_rm8_r8(){ + eip++; + ModRM16 rm(this); + rm.WriteByter(Xor8(rm.ReadByter(),*regs8[rm.GetExtra()])); +} + +void x86CPU::op16_xor_rm16_r16(){ + eip++; + ModRM16 rm(this); + rm.WriteWordr(Xor16(rm.ReadWordr(),*regs16[rm.GetExtra()])); +} + +void x86CPU::op16_xor_r8_rm8(){ + eip++; + ModRM16 rm(this); + *regs8[rm.GetExtra()]=Xor8(*regs8[rm.GetExtra()],rm.ReadByter()); +} + +void x86CPU::op16_xor_r16_rm16(){ + eip++; + ModRM16 rm(this); + *regs16[rm.GetExtra()]=Xor16(*regs16[rm.GetExtra()],rm.ReadWordr()); +} + +void x86CPU::op16_xor_al_imm8(){ + eip++; + *regs8[AL]=Xor8(*regs8[AL],op_cache[1]); +} + +void x86CPU::op16_xor_ax_imm16(){ + eip++; + eip++; + *regs16[AX]=Xor16(*regs16[AX],*(uint16_t*)&op_cache[1]); +} + +void x86CPU::op16_xor_rm8_imm8(ModRM16& rm){ + rm.WriteByter(Xor8(rm.ReadByter(),ReadByte(cCS,eip+rm.GetLength()))); +} + +void x86CPU::op16_xor_rm16_imm16(ModRM16& rm){ + rm.WriteWordr(Xor16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength()))); +} + +void x86CPU::op16_xor_rm16_imm8(ModRM16& rm){ + rm.WriteWordr(Xor16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength())))); + //gotta love parentheses... +} + +void x86CPU::op16_test_rm8_r8(){ + eip++; + ModRM16 rm(this); + And8(rm.ReadByter(),*regs8[rm.GetExtra()]); +} + +void x86CPU::op16_test_rm16_r16(){ + eip++; + ModRM16 rm(this); + And16(rm.ReadWordr(),*regs16[rm.GetExtra()]); +} +void x86CPU::op16_test_al_imm8(){ + eip++; + And8(*regs8[AL],op_cache[1]); +} +void x86CPU::op16_test_ax_imm16(){ + eip++; + eip++; + And16(*regs16[AX],*(uint16_t*)&op_cache[1]); +} + +void x86CPU::op16_test_rm8_imm8(ModRM16& rm){ + And8(rm.ReadByter(),ReadByte(cCS,eip+rm.GetLength())); +} + +void x86CPU::op16_test_rm16_imm16(ModRM16& rm){ + And16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength())); +} + +void x86CPU::op16_test_rm16_imm8(ModRM16& rm){ + And16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength()))); + //gotta love parentheses... +} + + +void x86CPU::op16_shr_rm8_cl(ModRM16 &rm){ + rm.WriteByter(ShiftLogicalRight8(rm.ReadByter(),*regs8[CL])); +} +void x86CPU::op16_shr_rm16_cl(ModRM16 &rm){ + rm.WriteWordr(ShiftLogicalRight16(rm.ReadWordr(),*regs8[CL])); +} + +void x86CPU::op16_shl_rm8_cl(ModRM16 &rm){ + rm.WriteByter(ShiftLogicalLeft8(rm.ReadByter(),*regs8[CL])); +} +void x86CPU::op16_shl_rm16_cl(ModRM16 &rm){ + rm.WriteWordr(ShiftLogicalLeft16(rm.ReadWordr(),*regs8[CL])); +} + +void x86CPU::op16_sar_rm8_cl(ModRM16 &rm){ + rm.WriteByter(ShiftArithmeticRight8(rm.ReadByter(),*regs8[CL])); +} +void x86CPU::op16_sar_rm16_cl(ModRM16 &rm){ + rm.WriteWordr(ShiftArithmeticRight16(rm.ReadWordr(),*regs8[CL])); +} + +void x86CPU::op16_rol_rm8_cl(ModRM16 &rm){ + rm.WriteByter(RotateLeft8(rm.ReadByter(),*regs8[CL])); +} +void x86CPU::op16_rol_rm16_cl(ModRM16 &rm){ + rm.WriteWordr(RotateLeft16(rm.ReadWordr(),*regs8[CL])); +} + +void x86CPU::op16_ror_rm8_cl(ModRM16 &rm){ + rm.WriteByter(RotateRight8(rm.ReadByter(),*regs8[CL])); +} +void x86CPU::op16_ror_rm16_cl(ModRM16 &rm){ + rm.WriteWordr(RotateRight16(rm.ReadWordr(),*regs8[CL])); +} + + +void x86CPU::op16_rcl_rm8_cl(ModRM16 &rm){ + rm.WriteByter(RotateCarryLeft8(rm.ReadByter(),*regs8[CL])); +} +void x86CPU::op16_rcl_rm16_cl(ModRM16 &rm){ + rm.WriteWordr(RotateCarryLeft16(rm.ReadWordr(),*regs8[CL])); +} + +void x86CPU::op16_rcr_rm8_cl(ModRM16 &rm){ + rm.WriteByter(RotateCarryRight8(rm.ReadByter(),*regs8[CL])); +} +void x86CPU::op16_rcr_rm16_cl(ModRM16 &rm){ + rm.WriteWordr(RotateCarryRight16(rm.ReadWordr(),*regs8[CL])); +} + + +/****/ +void x86CPU::op16_shr_rm8_1(ModRM16 &rm){ + rm.WriteByter(ShiftLogicalRight8(rm.ReadByter(),1)); +} +void x86CPU::op16_shr_rm16_1(ModRM16 &rm){ + rm.WriteWordr(ShiftLogicalRight16(rm.ReadWordr(),1)); +} + +void x86CPU::op16_shl_rm8_1(ModRM16 &rm){ + rm.WriteByter(ShiftLogicalLeft8(rm.ReadByter(),1)); +} +void x86CPU::op16_shl_rm16_1(ModRM16 &rm){ + rm.WriteWordr(ShiftLogicalLeft16(rm.ReadWordr(),1)); +} + +void x86CPU::op16_sar_rm8_1(ModRM16 &rm){ + rm.WriteByter(ShiftArithmeticRight8(rm.ReadByter(),1)); +} +void x86CPU::op16_sar_rm16_1(ModRM16 &rm){ + rm.WriteWordr(ShiftArithmeticRight16(rm.ReadWordr(),1)); +} + +void x86CPU::op16_rol_rm8_1(ModRM16 &rm){ + rm.WriteByter(RotateLeft8(rm.ReadByter(),1)); +} +void x86CPU::op16_rol_rm16_1(ModRM16 &rm){ + rm.WriteWordr(RotateLeft16(rm.ReadWordr(),1)); +} + +void x86CPU::op16_ror_rm8_1(ModRM16 &rm){ + rm.WriteByter(RotateRight8(rm.ReadByter(),1)); +} +void x86CPU::op16_ror_rm16_1(ModRM16 &rm){ + rm.WriteWordr(RotateRight16(rm.ReadWordr(),1)); +} + + +void x86CPU::op16_rcl_rm8_1(ModRM16 &rm){ + rm.WriteByter(RotateCarryLeft8(rm.ReadByter(),1)); +} +void x86CPU::op16_rcl_rm16_1(ModRM16 &rm){ + rm.WriteWordr(RotateCarryLeft16(rm.ReadWordr(),1)); +} + +void x86CPU::op16_rcr_rm8_1(ModRM16 &rm){ + rm.WriteByter(RotateCarryRight8(rm.ReadByter(),1)); +} +void x86CPU::op16_rcr_rm16_1(ModRM16 &rm){ + rm.WriteWordr(RotateCarryRight16(rm.ReadWordr(),1)); +} + +void x86CPU::op16_not_rm8(ModRM16 &rm){ + rm.WriteByter(~(rm.ReadByter())); +} + +void x86CPU::op16_not_rm16(ModRM16 &rm){ + rm.WriteWordr(~(rm.ReadWordr())); +} + + + + +/** +BCD Opcodes for Open86 +By: Alboin, 3-16-07 +Modified to work with x86Lib by Jordan(hckr83) +**/ + + +/* Opcode: 0x37 */ +void x86CPU::op16_aaa() { + if((*regs8[AL] & 0x0f) > 9 || freg.af == 1) { + *regs8[AL] += 6; + *regs8[AH]++; + freg.af = 1; + freg.cf = 1; + } + else { + freg.af = 0; + freg.cf = 0; + } + *regs8[AL] = *regs8[AL] & 0x0f; +} + + +/* Opcode: 0x27 */ +void x86CPU::op16_daa() { + if((*regs8[AL] & 0x0f) > 9 || freg.af == 1) { + *regs8[AL] += 6; + *regs8[AH]++; + } + else + freg.af = 0; + + if(*regs8[AL] > 0x9f || freg.cf == 1) { + *regs8[AL] = *regs8[AL] + 0x60; + freg.cf = 1; + } + else + freg.cf = 0; +} + +/* Opcode: 0x2F */ +void x86CPU::op16_das() { + if((*regs8[AL] & 0x0f) > 9 || freg.af == 1) { + *regs8[AL] -= 6; + freg.af = 1; + } + else + freg.af = 0; + + if(*regs8[AL] > 0x9f || freg.cf == 1) { + *regs8[AL] -= 0x60; + freg.cf = 1; + } + else + freg.cf = 0; +} + +/* Opcode: 0x3F */ +void x86CPU::op16_aas() { + if((*regs8[AL] & 0x0f) > 9 || freg.af == 1) { + *regs8[AL] -= 6; + *regs8[AH]--; + freg.af = 1; + freg.cf = 1; + } + else { + freg.af = 0; + freg.cf = 0; + } + *regs8[AL] = *regs8[AL] & 0x0f; +} + + + +void x86CPU::op16_aad(){ + //AAD is a weird opcode because it is two bytes + //for "apparently" no reason. But really, it is just + //undocumented... the 0x0A in the second byte is for + //multiplecation...but it can be changed... + *regs8[AL]=(*regs8[AH])*(op_cache[1])+*regs8[AL]; + *regs8[AH]=0; +} + +void x86CPU::op16_aam(){ + //same wiht the 0x0A operand as above.. + if(op_cache[1]==0){ + Onx86LibError(); + //throw CpuInt_excp(DIV0_IEXCP); + } + *regs8[AH]=(*regs8[AL])/op_cache[1]; + *regs8[AL]=(*regs8[AL])%op_cache[1]; +} + + + + + + + + + + +}; + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ops/store.cpp Sun Mar 04 08:15:47 2012 +0000 @@ -0,0 +1,307 @@ +/** +Copyright (c) 2007 - 2010 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This file is part of the x86Lib project. +**/ +#define X86LIB_BUILD +#include <x86Lib.h> +namespace x86Lib{ +using namespace std; + + + + + + +void x86CPU::op16_mov_r8_imm8(){ //0xB0+r + //I suppose the first real instruction is the hardest... + *regs8[op_cache[0]-0xB0]=op_cache[1]; + eip++; +} + +void x86CPU::op16_mov_r16_imm16(){ //0xB8+r + *regs16[op_cache[0]-0xB8]=*(uint16_t*)&op_cache[1]; + eip+=2; +} + +void x86CPU::op16_mov_sr_rm16(){ //0x8E + eip++; + ModRM16 rm16(this); + if(rm16.GetExtra()==cSS){ //if a mov into SS, then disable interrupts for 1 instruction. + cli_count=2; + freg._if=0; + } + seg[rm16.GetExtra()]=rm16.ReadWordr(); +} + +void x86CPU::op16_mov_rm16_sr(){ //0x8C + eip++; + ModRM16 rm16(this); + rm16.WriteWordr(seg[rm16.GetExtra()]); +} + + + +void x86CPU::op16_mov_r16_rm16(){ + eip++; + ModRM16 rm16(this); + *regs16[rm16.GetExtra()]=rm16.ReadWordr(); +} + +void x86CPU::op16_mov_rm16_r16(){ + eip++; + ModRM16 rm16(this); + rm16.WriteWordr(*regs16[rm16.GetExtra()]); +} + +void x86CPU::op16_mov_al_off8(){ + *regs8[AL]=ReadByte(DS,*(uint16_t*)&op_cache[1]); + eip++; + eip++; +} +void x86CPU::op16_mov_ax_off16(){ + *regs16[AX]=ReadWord(DS,*(uint16_t*)&op_cache[1]); + eip++; + eip++; +} + +void x86CPU::op16_mov_rm8_r8(){ + eip++; + ModRM16 rm(this); + rm.WriteByter(*regs8[rm.GetExtra()]); +} + +void x86CPU::op16_mov_r8_rm8(){ + eip++; + ModRM16 rm(this); + *regs8[rm.GetExtra()]=rm.ReadByter(); +} +void x86CPU::op16_mov_off8_al(){ + WriteByte(DS,*(uint16_t*)&op_cache[1],*regs8[AL]); + eip++; + eip++; +} + +void x86CPU::op16_mov_off16_ax(){ + WriteWord(DS,*(uint16_t*)&op_cache[1],*regs16[AX]); + eip++;eip++; +} + +void x86CPU::op16_mov_m8_imm8(){ + eip++; + ModRM16 rm(this); + + //eventually fix this so that if r is used, then invalid opcode... + rm.WriteByter(ReadByte(cCS,eip+rm.GetLength())); + eip++; +} + +void x86CPU::op16_mov_m16_imm16(){ + eip++; + ModRM16 rm(this); + rm.WriteWordr(ReadWord(cCS,eip+rm.GetLength())); + eip++; + eip++; +} + +void x86CPU::op16_lds(){ + eip++; + ModRM16 rm(this); + uint32_t tmp=rm.ReadDword(); + seg[cDS]=(tmp&0xFFFF0000)>>16; + *regs16[rm.GetExtra()]=(tmp&0xFFFF); +} + +void x86CPU::op16_les(){ + eip++; + ModRM16 rm(this); + uint32_t tmp=rm.ReadDword(); + seg[cES]=(tmp&0xFFFF0000)>>16; + *regs16[rm.GetExtra()]=(tmp&0xFFFF); +} + +void x86CPU::op16_lea(){ //wtf is the point of this instruction! why not just mov reg,immediate! seriously frikkin crazy designers of x86 + eip++; + ModRM16 rm(this); + *regs16[rm.GetExtra()]=rm.ReadOffset(); +} + + + +void x86CPU::op16_push_imm8(){ + eip++; + Push16(op_cache[1]); +} +void x86CPU::op16_push_m16(ModRM16 &rm){ + Push16(rm.ReadWordr()); +} + +void x86CPU::op16_push_imm16(){ //0x68 + eip++; + Push16(*(uint16_t*)&op_cache[1]); + eip++; +} + + +void x86CPU::op16_push_r16(){ //0x50+reg + Push16(*regs16[op_cache[0]-0x50]); +} + +void x86CPU::op16_push_es(){ + Push16(seg[ES]); +} + +void x86CPU::op16_push_cs(){ + Push16(seg[CS]); +} + +void x86CPU::op16_push_ds(){ + Push16(seg[DS]); +} + + +void x86CPU::op16_push_ss(){ + Push16(seg[SS]); +} + + + +void x86CPU::op16_pop_m16(ModRM16 &rm){ + rm.WriteWordr(Pop16()); +} + +void x86CPU::op16_pop_r16(){ //0x58+reg + *regs16[op_cache[0]-0x58]=Pop16(); +} + + +void x86CPU::op16_pop_es(){ + seg[ES]=Pop16(); +} + +void x86CPU::op16_pop_ss(){ + cli_count=2; + freg._if=0; + seg[SS]=Pop16(); +} + +void x86CPU::op16_pop_ds(){ + seg[DS]=Pop16(); +} + + + +void x86CPU::op16_out_imm8_al(){ + Ports->Write(op_cache[1],1,(void*)regs8[AL]); + eip++; +} + +void x86CPU::op16_out_imm8_ax(){ + Ports->Write(op_cache[1],2,(void*)regs16[AX]); + eip++; +} + +void x86CPU::op16_out_dx_al(){ + Ports->Write(*regs16[DX],1,(void*)regs8[AL]); +} + +void x86CPU::op16_out_dx_ax(){ + Ports->Write(*regs16[DX],2,(void*)regs16[AX]); +} + + +void x86CPU::op16_in_al_imm8(){ + Ports->Read(op_cache[1],1,(void*)regs8[AL]); + eip++; +} + +void x86CPU::op16_in_ax_imm8(){ + Ports->Read(op_cache[1],2,(void*)regs16[AX]); + eip++; +} + +void x86CPU::op16_in_al_dx(){ + Ports->Read(*regs16[DX],1,(void*)regs8[AL]); +} + +void x86CPU::op16_in_ax_dx(){ + Ports->Read(*regs16[DX],2,(void*)regs16[AX]); +} + + + +void x86CPU::op16_xchg_rm8_r8(){ + #ifndef X86_MULTITHREADING + if(IsLocked()==1){ + eip--; + return; + } + #endif + Lock(); + eip++; + ModRM16 rm(this); + uint8_t tmp=*regs8[rm.GetExtra()]; + *regs8[rm.GetExtra()]=rm.ReadByter(); + rm.WriteByter(tmp); + Unlock(); +} +void x86CPU::op16_xchg_rm16_r16(){ + #ifndef X86_MULTITHREADING + if(IsLocked()==1){ + eip--; + return; + } + #endif + Lock(); + eip++; + ModRM16 rm(this); + uint16_t tmp=*regs16[rm.GetExtra()]; + *regs16[rm.GetExtra()]=rm.ReadWordr(); + rm.WriteWordr(tmp); + Unlock(); +} + +void x86CPU::op16_xchg_ax_r16(){ //0x90+r + uint16_t tmp=*regs16[AX]; + *regs16[AX]=*regs16[op_cache[0]-0x90]; + *regs16[op_cache[0]-0x90]=tmp; +} + + +void x86CPU::op16_xlatb(){ + *regs8[AL]=ReadByte(DS,(*regs16[BX])+(*regs8[AL])); +} + + + + + + +}; + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ops/strings.cpp Sun Mar 04 08:15:47 2012 +0000 @@ -0,0 +1,92 @@ +/** +Copyright (c) 2007 - 2009 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This file is part of the x86Lib project. +**/ +#define X86LIB_BUILD +#include <x86Lib.h> +namespace x86Lib{ +using namespace std; + + + +void x86CPU::op16_movsb(){ + WriteByte(cES,*regs16[DI],ReadByte(DS,*regs16[SI])); + SetIndex8(); +} + +void x86CPU::op16_movsw(){ + WriteWord(cES,*regs16[DI],ReadWord(DS,*regs16[SI])); + SetIndex16(); +} + +void x86CPU::op16_cmpsb(){ + string_compares=1; + Sub8(ReadByte(DS,*regs16[SI]),ReadByte(cES,*regs16[DI])); + SetIndex8(); +} + +void x86CPU::op16_cmpsw(){ + string_compares=1; + Sub16(ReadWord(DS,*regs16[SI]),ReadWord(cES,*regs16[DI])); + SetIndex16(); +} + +void x86CPU::op16_lodsb(){ + *regs8[AL]=ReadByte(DS,*regs16[SI]); + SetIndex8(); +} +void x86CPU::op16_lodsw(){ + *regs16[AX]=ReadWord(DS,*regs16[SI]); + SetIndex16(); +} + +void x86CPU::op16_scasb(){ + string_compares=1; + Sub8(*regs8[AL],ReadByte(cES,*regs16[DI])); + SetIndex8(); +} +void x86CPU::op16_scasw(){ + string_compares=1; + Sub16(*regs16[AX],ReadWord(cES,*regs16[DI])); + SetIndex16(); +} +void x86CPU::op16_stosb(){ + WriteByte(ES,*regs16[DI],*regs8[AL]); + SetIndex8(); +} +void x86CPU::op16_stosw(){ + WriteWord(ES,*regs16[DI],*regs16[AX]); + SetIndex16(); +} + + + +}; + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/x86Lib.cpp Sun Mar 04 08:15:47 2012 +0000 @@ -0,0 +1,542 @@ +/** +Copyright (c) 2007 - 2010 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This file is part of the x86Lib project. +**/ +#define X86LIB_BUILD +#include <iostream> +#include "include/x86Lib.h" + + +namespace x86Lib{ +//The lack of indentation for namespaces is intentional... +using namespace std; + + +x86CPU::x86CPU(uint32_t cpu_level_,uint32_t flags){ + if(cpu_level_==0){ + cpu_level=CPU286_REAL; //The default CPU right now.. + }else{ + cpu_level=cpu_level_; + } + Init(); +} +x86CPU::x86CPU(x86SaveData &load_data,uint32_t flags){ + Init(); + LoadState(load_data); +} + +void x86CPU::Init(){ + //ports=new x86Ports(); +#ifdef ENABLE_OPCODE_CALLBACK + EachOpcodeCallback=NULL; +#endif + Reset(); +} + +void Onx86LibError() +{ + Serial pc(USBTX, USBRX); // tx, rx + pc.printf("x86lib error\n"); + exit(1); +} + +void x86CPU::Reset(){ + /**Initialize register pointers**/ + regs16[0]=&((volatile uint16_t*)reg32)[0]; + regs16[1]=&((volatile uint16_t*)reg32)[2]; + regs16[2]=&((volatile uint16_t*)reg32)[4]; + regs16[3]=&((volatile uint16_t*)reg32)[6]; + regs16[4]=&((volatile uint16_t*)reg32)[8]; + regs16[5]=&((volatile uint16_t*)reg32)[10]; + regs16[6]=&((volatile uint16_t*)reg32)[12]; + regs16[7]=&((volatile uint16_t*)reg32)[14]; + regs8[0]=&((volatile uint8_t*)reg32)[0]; + regs8[1]=&((volatile uint8_t*)reg32)[4]; + regs8[2]=&((volatile uint8_t*)reg32)[8]; + regs8[3]=&((volatile uint8_t*)reg32)[12], //now do all the highs + regs8[4]=&((volatile uint8_t*)reg32)[1]; + regs8[5]=&((volatile uint8_t*)reg32)[5]; + regs8[6]=&((volatile uint8_t*)reg32)[9]; + regs8[7]=&((volatile uint8_t*)reg32)[13]; + busmaster=0; + //assumes pmem and ports are still the same... + InitOpcodes(); + uint32_t i; + for(i=0;i<8;i++){ + reg32[i]=0; + } + for(i=0;i<7;i++){ + seg[i]=0; + } + ResetSegments(); + //eip=0xFFFE; + eip=0x0; + seg[cCS]=0xF000; + *(uint16_t*)&freg=0; + string_compares=0; + int_pending=0; + cli_count=0; +} + + +void x86CPU::SaveState(x86SaveData *save){ + uint32_t i; + for(i=0;i<8;i++){ + save->reg32[i]=reg32[i]; + } + for(i=0;i<7;i++){ + save->seg[i]=seg[i]; + } + save->freg=*(uint16_t*)&freg; + save->eip=eip; + save->seg_route[cES]=ES; + save->seg_route[cCS]=CS; + save->seg_route[cDS]=DS; + save->seg_route[cSS]=SS; + save->seg_route[cFS]=FS; + save->seg_route[cGS]=GS; + save->cpu_level=cpu_level; + if(Opcodes==opcodes_16bit){ + save->opcode_mode=OPCODE_REAL_16; + }else{ + Onx86LibError(); + //throw Default_excp(__FILE__,__FUNCTION__,__LINE__); + } +} + +void x86CPU::LoadState(x86SaveData &load){ + uint32_t i; + cpu_level=load.cpu_level; + Reset(); + for(i=0;i<8;i++){ + reg32[i]=load.reg32[i]; + } + for(i=0;i<7;i++){ + seg[i]=load.seg[i]; + } + *(uint16_t*)&freg=load.freg; + eip=load.eip; + ES=load.seg_route[cES]; + CS=load.seg_route[cCS]; + DS=load.seg_route[cDS]; + SS=load.seg_route[cSS]; + GS=load.seg_route[cGS]; + FS=load.seg_route[cFS]; + if(load.opcode_mode==OPCODE_REAL_16){ + Opcodes=opcodes_16bit; + }else{ + Onx86LibError(); + //throw Default_excp(__FILE__,__FUNCTION__,__LINE__); + } +} + + + + +void x86CPU::DumpState(ostream &output){ + output << "EAX: "<< hex << reg32[EAX] <<endl; + output << "ECX: "<< hex << reg32[ECX] <<endl; + output << "EDX: "<< hex << reg32[EDX] <<endl; + output << "EBX: "<< hex << reg32[EBX] <<endl; + output << "ESP: "<< hex << reg32[ESP] <<endl; + output << "EBP: "<< hex << reg32[EBP] <<endl; + output << "ESI: "<< hex << reg32[ESI] <<endl; + output << "EDI: "<< hex << reg32[EDI] <<endl; + + output << "CS: " << hex << seg[cCS] << endl; + output << "SS: " << hex << seg[cSS] << endl; + output << "DS: " << hex << seg[cDS] << endl; + output << "ES: " << hex << seg[cES] << endl; + output << "FS: " << hex << seg[cFS] << endl; + output << "GS: " << hex << seg[cGS] << endl; + output << "EIP: " << hex << eip << endl; + + output << "--Flags:" <<hex << *(uint16_t*)&freg<< endl; + output << "CF: " << (int)freg.cf << endl; + output << "PF: " << (int)freg.pf << endl; + output << "AF: " << (int)freg.af << endl; + output << "ZF: " << (int)freg.zf << endl; + output << "SF: " << (int)freg.sf << endl; + output << "TF: " << (int)freg.tf << endl; + output << "IF: " << (int)freg._if << endl; + output << "DF: " << (int)freg.df << endl; + output << "OF: " << (int)freg.of << endl; +} + +void x86CPU::Int(uint8_t num){ //external interrupt + int_pending=1; + int_number=num; +} + +bool x86CPU::IntPending(){ + return int_pending; +} + + + +int x86CPU::CheckInterrupts(){ + //possible bug here. What if we have a pop SS without an interrupt waiting? Won't interrupts be forever ignored? + if(int_pending==0){return 0;} //quickly get out of this, this is in the main Cycle loop, so needs to be very speedy... + if((int_pending==1) && (int_number==2)){ //NMI + eip--; + Int16(2); + eip++; + int_pending=0; + return 1; + } + if(freg._if==0){ + if(cli_count>1){ + cli_count--; + }else{ + if(cli_count!=0){ + freg._if=1; + } + } + }else{ + if(int_pending==1){ + eip--; + Int16(int_number); + eip++; + int_pending=0; + return 1; + } + } + return 0; +} + +void x86CPU::Exec(int cyclecount){ + int i=0; + bool done=false; + while(!done){ + //try{ + for(;i<cyclecount;i++){ + Cycle(); + } + //} + /*catch(CpuInt_excp err){ + err.code&=0x00FF; + switch(err.code){ + case 0: //division by zero + case 1: //debug exception + case 2: //NMI + case 3: //breakpoint + case 4: //overflow + + case 7: //device unavailable + Int16(err.code); + eip++; //undo the decrement by Int + break; + case 5: //(186+ bounds check) + if(cpu_level >= CPU186){ + Int16(err.code); + eip++; + break; + } + default: + throw CpuPanic_excp("16bit Faults",(err.code|0xF000)|TRIPLE_FAULT_EXCP); + break; + } + } + catch(Mem_excp err){ + throw CpuPanic_excp("Mem Error--16bit Faults",TRIPLE_FAULT_EXCP); + } + */ + if(i>=cyclecount){ + done=true; + } + } +} + + +void x86CPU::Cycle(){ +#ifdef ENABLE_OPCODE_CALLBACK + if(EachOpcodeCallback!=NULL){ + (*EachOpcodeCallback)(this); + } +#endif + CheckInterrupts(); + *(uint32_t*)&op_cache=ReadDword(cCS,eip); + (this->*Opcodes[op_cache[0]])(); + //operate on the this class with the opcode functions in this class + eip=(uint16_t)eip+1; +} + + + + + + + +void x86CPU::InstallOp(uint8_t num,opcode func,uint32_t level){ + if((cpu_level&level)>0){ + Opcodes[num]=func; + } +} + + +void x86CPU::InitOpcodes(){ + Opcodes=opcodes_16bit; + int i; + for(i=0;i<256;i++){ + InstallOp(i,&x86CPU::op16_unknown); + } + for(i=0;i<=7;i++){ + InstallOp(0xB0+i,&x86CPU::op16_mov_r8_imm8); + InstallOp(0x58+i,&x86CPU::op16_pop_r16); + InstallOp(0x50+i,&x86CPU::op16_push_r16); + InstallOp(0x40+i,&x86CPU::op16_inc_r16); + InstallOp(0x48+i,&x86CPU::op16_dec_r16); + InstallOp(0xD8+i,&x86CPU::op16_escape); + InstallOp(0x90+i,&x86CPU::op16_xchg_ax_r16); + InstallOp(0xB8+i,&x86CPU::op16_mov_r16_imm16); + } + InstallOp(0xF4,&x86CPU::op16_hlt); + InstallOp(0x90,&x86CPU::op16_nop); + InstallOp(0xEB,&x86CPU::op16_jmp_rel8); + InstallOp(0x2C,&x86CPU::op16_sub_al_imm8); + InstallOp(0x2D,&x86CPU::op16_sub_ax_imm16); + InstallOp(0x77,&x86CPU::op16_ja_rel8); + InstallOp(0x70,&x86CPU::op16_jo_rel8); + InstallOp(0x71,&x86CPU::op16_jno_rel8); + InstallOp(0x72,&x86CPU::op16_jc_rel8); + InstallOp(0x73,&x86CPU::op16_jnc_rel8); + InstallOp(0x74,&x86CPU::op16_jz_rel8); + InstallOp(0x75,&x86CPU::op16_jnz_rel8); + InstallOp(0x77,&x86CPU::op16_jbe_rel8); + InstallOp(0x78,&x86CPU::op16_js_rel8); + InstallOp(0x79,&x86CPU::op16_jns_rel8); + InstallOp(0x7A,&x86CPU::op16_jp_rel8); + InstallOp(0x7B,&x86CPU::op16_jnp_rel8); + InstallOp(0x7C,&x86CPU::op16_jl_rel8); + InstallOp(0x7D,&x86CPU::op16_jge_rel8); + InstallOp(0x7E,&x86CPU::op16_jle_rel8); + InstallOp(0x7F,&x86CPU::op16_jg_rel8); + InstallOp(0x8E,&x86CPU::op16_mov_sr_rm16); + InstallOp(0x8C,&x86CPU::op16_mov_rm16_sr); + InstallOp(0x68,&x86CPU::op16_push_imm16,CPU286_REAL); + InstallOp(0x07,&x86CPU::op16_pop_es); + InstallOp(0x17,&x86CPU::op16_pop_ss); + InstallOp(0x1F,&x86CPU::op16_pop_ds); + InstallOp(0x06,&x86CPU::op16_push_es); + InstallOp(0x0E,&x86CPU::op16_push_cs); + InstallOp(0x16,&x86CPU::op16_push_ss); + InstallOp(0x1E,&x86CPU::op16_push_ds); + InstallOp(0x89,&x86CPU::op16_mov_rm16_r16); + InstallOp(0x8B,&x86CPU::op16_mov_r16_rm16); + InstallOp(0xE8,&x86CPU::op16_call_rel16); + InstallOp(0xC3,&x86CPU::op16_retn); + InstallOp(0xE2,&x86CPU::op16_loop_rel8); + InstallOp(0x26,&x86CPU::op16_pre_es_override); + InstallOp(0x3E,&x86CPU::op16_pre_ds_override); + InstallOp(0x36,&x86CPU::op16_pre_ss_override); + InstallOp(0x2E,&x86CPU::op16_pre_cs_override); + InstallOp(0xA5,&x86CPU::op16_movsw); + InstallOp(0xA4,&x86CPU::op16_movsb); + InstallOp(0xF8,&x86CPU::op16_clc); + InstallOp(0xFC,&x86CPU::op16_cld); + InstallOp(0xFA,&x86CPU::op16_cli); + InstallOp(0xF9,&x86CPU::op16_stc); + InstallOp(0xFD,&x86CPU::op16_std); + InstallOp(0xFB,&x86CPU::op16_sti); + InstallOp(0xF2,&x86CPU::op16_rep); + InstallOp(0xF3,&x86CPU::op16_rep); //different, but handled by the same function... + InstallOp(0xE6,&x86CPU::op16_out_imm8_al); + InstallOp(0xE7,&x86CPU::op16_out_imm8_ax); + InstallOp(0x9A,&x86CPU::op16_call_imm16_imm16); + InstallOp(0xCB,&x86CPU::op16_retf); //lol...CB...<inside joke> + InstallOp(0xCD,&x86CPU::op16_int_imm8); + InstallOp(0xCF,&x86CPU::op16_iret); + InstallOp(0xCC,&x86CPU::op16_int3); + InstallOp(0xCE,&x86CPU::op16_into); + InstallOp(0xE4,&x86CPU::op16_in_al_imm8); + InstallOp(0xE5,&x86CPU::op16_in_ax_imm8); + InstallOp(0x04,&x86CPU::op16_add_al_imm8); + InstallOp(0x05,&x86CPU::op16_add_ax_imm8); + InstallOp(0x28,&x86CPU::op16_sub_rm8_r8); + InstallOp(0x80,&x86CPU::op16_group_80); + InstallOp(0x29,&x86CPU::op16_sub_rm16_r16); + InstallOp(0x2A,&x86CPU::op16_sub_r8_rm8); + InstallOp(0x2B,&x86CPU::op16_sub_r16_rm16); + InstallOp(0x81,&x86CPU::op16_group_81); + InstallOp(0x00,&x86CPU::op16_add_rm8_r8); + InstallOp(0x01,&x86CPU::op16_add_rm16_r16); + InstallOp(0x02,&x86CPU::op16_add_r8_rm8); + InstallOp(0x03,&x86CPU::op16_add_r16_rm16); + InstallOp(0xA0,&x86CPU::op16_mov_al_off8); + InstallOp(0xA1,&x86CPU::op16_mov_ax_off16); + InstallOp(0x88,&x86CPU::op16_mov_rm8_r8); + InstallOp(0x8A,&x86CPU::op16_mov_r8_rm8); + InstallOp(0xA2,&x86CPU::op16_mov_off8_al); + InstallOp(0xA3,&x86CPU::op16_mov_off16_ax); + InstallOp(0xC6,&x86CPU::op16_mov_m8_imm8); + InstallOp(0xC7,&x86CPU::op16_mov_m16_imm16); + InstallOp(0x38,&x86CPU::op16_cmp_rm8_r8); + InstallOp(0x39,&x86CPU::op16_cmp_rm16_r16); + InstallOp(0x3A,&x86CPU::op16_cmp_r8_rm8); + InstallOp(0x3B,&x86CPU::op16_cmp_r16_rm16); + InstallOp(0x3C,&x86CPU::op16_cmp_al_imm8); + InstallOp(0x3D,&x86CPU::op16_cmp_ax_imm16); //3D TimD Tim Vision TV!!! Yay!!! + InstallOp(0x83,&x86CPU::op16_group_83); //83 is my lucky number btw... + InstallOp(0xFF,&x86CPU::op16_group_FF); + InstallOp(0xE9,&x86CPU::op16_jmp_rel16); + InstallOp(0xEA,&x86CPU::op16_jmp_imm16_imm16); + InstallOp(0x6A,&x86CPU::op16_push_imm8); + InstallOp(0x8F,&x86CPU::op16_group_8F); + InstallOp(0xD6,&x86CPU::op16_salc); + InstallOp(0xF5,&x86CPU::op16_cmc); + InstallOp(0x98,&x86CPU::op16_cbw); + InstallOp(0x37,&x86CPU::op16_aaa); + InstallOp(0x27,&x86CPU::op16_daa); + InstallOp(0x2F,&x86CPU::op16_das); + InstallOp(0x3F,&x86CPU::op16_aas); + InstallOp(0xD5,&x86CPU::op16_aad); + InstallOp(0xD4,&x86CPU::op16_aam); + InstallOp(0xFE,&x86CPU::op16_group_FE); + InstallOp(0xF6,&x86CPU::op16_group_F6); + InstallOp(0xF7,&x86CPU::op16_group_F7); + InstallOp(0x99,&x86CPU::op16_cwd); + InstallOp(0x20,&x86CPU::op16_and_rm8_r8); + InstallOp(0x21,&x86CPU::op16_and_rm16_r16); + InstallOp(0x22,&x86CPU::op16_and_r8_rm8); + InstallOp(0x23,&x86CPU::op16_and_r16_rm16); + InstallOp(0x24,&x86CPU::op16_and_al_imm8); + InstallOp(0x25,&x86CPU::op16_and_ax_imm16); + InstallOp(0x08,&x86CPU::op16_or_rm8_r8); + InstallOp(0x09,&x86CPU::op16_or_rm16_r16); + InstallOp(0x0A,&x86CPU::op16_or_r8_rm8); + InstallOp(0x0B,&x86CPU::op16_or_r16_rm16); + InstallOp(0x0C,&x86CPU::op16_or_al_imm8); + InstallOp(0x0D,&x86CPU::op16_or_ax_imm16); + InstallOp(0xA6,&x86CPU::op16_cmpsb); + InstallOp(0xA7,&x86CPU::op16_cmpsw); + InstallOp(0xE3,&x86CPU::op16_jcxz_rel8); + InstallOp(0x14,&x86CPU::op16_adc_al_imm8); + InstallOp(0x15,&x86CPU::op16_adc_ax_imm8); + InstallOp(0x10,&x86CPU::op16_adc_rm8_r8); + InstallOp(0x11,&x86CPU::op16_adc_rm16_r16); + InstallOp(0x12,&x86CPU::op16_adc_r8_rm8); + InstallOp(0x13,&x86CPU::op16_adc_r16_rm16); + InstallOp(0x9E,&x86CPU::op16_sahf); + InstallOp(0x9F,&x86CPU::op16_lahf); + InstallOp(0xE1,&x86CPU::op16_loope_rel8); + InstallOp(0xE0,&x86CPU::op16_loopne_rel8); + InstallOp(0xC5,&x86CPU::op16_lds); + InstallOp(0xC4,&x86CPU::op16_les); + InstallOp(0x8D,&x86CPU::op16_lea); + InstallOp(0xF0,&x86CPU::op16_lock); + InstallOp(0x30,&x86CPU::op16_xor_rm8_r8); + InstallOp(0x31,&x86CPU::op16_xor_rm16_r16); + InstallOp(0x32,&x86CPU::op16_xor_r8_rm8); + InstallOp(0x33,&x86CPU::op16_xor_r16_rm16); + InstallOp(0x34,&x86CPU::op16_xor_al_imm8); + InstallOp(0x35,&x86CPU::op16_xor_ax_imm16); + InstallOp(0x1C,&x86CPU::op16_sbb_al_imm8); + InstallOp(0x1D,&x86CPU::op16_sbb_ax_imm16); + InstallOp(0x19,&x86CPU::op16_sbb_rm16_r16); + InstallOp(0x1A,&x86CPU::op16_sbb_r8_rm8); + InstallOp(0x1B,&x86CPU::op16_sbb_r16_rm16); + InstallOp(0x18,&x86CPU::op16_sub_rm8_r8); + InstallOp(0x84,&x86CPU::op16_test_rm8_r8); + InstallOp(0x85,&x86CPU::op16_test_rm16_r16); + InstallOp(0xA8,&x86CPU::op16_test_al_imm8); + InstallOp(0xA9,&x86CPU::op16_test_ax_imm16); + InstallOp(0x86,&x86CPU::op16_xchg_rm8_r8); + InstallOp(0x87,&x86CPU::op16_xchg_rm16_r16); + InstallOp(0xD2,&x86CPU::op16_group_D2); + InstallOp(0xD3,&x86CPU::op16_group_D3); + InstallOp(0xD0,&x86CPU::op16_group_D0); + InstallOp(0xD1,&x86CPU::op16_group_D1); + InstallOp(0xAC,&x86CPU::op16_lodsb); + InstallOp(0xAD,&x86CPU::op16_lodsw); + InstallOp(0xAE,&x86CPU::op16_scasb); + InstallOp(0xAF,&x86CPU::op16_scasw); + InstallOp(0x9B,&x86CPU::op16_wait); + InstallOp(0xD7,&x86CPU::op16_xlatb); + InstallOp(0xEC,&x86CPU::op16_in_al_dx); + InstallOp(0xED,&x86CPU::op16_in_ax_dx); + InstallOp(0xEE,&x86CPU::op16_out_dx_al); + InstallOp(0xEF,&x86CPU::op16_out_dx_ax); + InstallOp(0xAA,&x86CPU::op16_stosb); + InstallOp(0xAB,&x86CPU::op16_stosw); + + + +} + + + +//void unknown(); + +bool x86CPU::IsLocked(){ + return Memory->IsLocked(); +} + +void x86CPU::Lock(){ + //nothing... + Memory->Lock(); + busmaster=1; +} + +void x86CPU::Unlock(){ + //still nothing... + Memory->Unlock(); + busmaster=0; +} + + + + + + + + + + + + + + + + + + + + + + + + + + +}; + + + + + +