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
include/x86Lib.h@0:217a7931b41f, 2012-03-04 (annotated)
- Committer:
- earlz
- Date:
- Sun Mar 04 08:15:47 2012 +0000
- Revision:
- 0:217a7931b41f
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
earlz | 0:217a7931b41f | 1 | /** |
earlz | 0:217a7931b41f | 2 | Copyright (c) 2007 - 2010 Jordan "Earlz/hckr83" Earls <http://www.Earlz.biz.tm> |
earlz | 0:217a7931b41f | 3 | All rights reserved. |
earlz | 0:217a7931b41f | 4 | |
earlz | 0:217a7931b41f | 5 | Redistribution and use in source and binary forms, with or without |
earlz | 0:217a7931b41f | 6 | modification, are permitted provided that the following conditions |
earlz | 0:217a7931b41f | 7 | are met: |
earlz | 0:217a7931b41f | 8 | |
earlz | 0:217a7931b41f | 9 | 1. Redistributions of source code must retain the above copyright |
earlz | 0:217a7931b41f | 10 | notice, this list of conditions and the following disclaimer. |
earlz | 0:217a7931b41f | 11 | 2. Redistributions in binary form must reproduce the above copyright |
earlz | 0:217a7931b41f | 12 | notice, this list of conditions and the following disclaimer in the |
earlz | 0:217a7931b41f | 13 | documentation and/or other materials provided with the distribution. |
earlz | 0:217a7931b41f | 14 | 3. The name of the author may not be used to endorse or promote products |
earlz | 0:217a7931b41f | 15 | derived from this software without specific prior written permission. |
earlz | 0:217a7931b41f | 16 | |
earlz | 0:217a7931b41f | 17 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, |
earlz | 0:217a7931b41f | 18 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
earlz | 0:217a7931b41f | 19 | AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
earlz | 0:217a7931b41f | 20 | THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
earlz | 0:217a7931b41f | 21 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
earlz | 0:217a7931b41f | 22 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
earlz | 0:217a7931b41f | 23 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
earlz | 0:217a7931b41f | 24 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
earlz | 0:217a7931b41f | 25 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
earlz | 0:217a7931b41f | 26 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
earlz | 0:217a7931b41f | 27 | |
earlz | 0:217a7931b41f | 28 | This file is part of the x86Lib project. |
earlz | 0:217a7931b41f | 29 | **/ |
earlz | 0:217a7931b41f | 30 | |
earlz | 0:217a7931b41f | 31 | #ifndef X86LIB |
earlz | 0:217a7931b41f | 32 | #define X86LIB |
earlz | 0:217a7931b41f | 33 | #include <iostream> |
earlz | 0:217a7931b41f | 34 | #include <vector> |
earlz | 0:217a7931b41f | 35 | #include <stdint.h> |
earlz | 0:217a7931b41f | 36 | #include <string> |
earlz | 0:217a7931b41f | 37 | #include "mbed.h" |
earlz | 0:217a7931b41f | 38 | |
earlz | 0:217a7931b41f | 39 | //! The main namespace of x86Lib |
earlz | 0:217a7931b41f | 40 | namespace x86Lib{ |
earlz | 0:217a7931b41f | 41 | |
earlz | 0:217a7931b41f | 42 | #ifdef X86LIB_BUILD |
earlz | 0:217a7931b41f | 43 | #include <config.h> |
earlz | 0:217a7931b41f | 44 | #endif |
earlz | 0:217a7931b41f | 45 | |
earlz | 0:217a7931b41f | 46 | //! 8086 CPU level |
earlz | 0:217a7931b41f | 47 | static const uint32_t CPU086=1; |
earlz | 0:217a7931b41f | 48 | //! 186 CPU level |
earlz | 0:217a7931b41f | 49 | static const uint32_t CPU186=2|CPU086; |
earlz | 0:217a7931b41f | 50 | //! 286 real mode only CPU level |
earlz | 0:217a7931b41f | 51 | static const uint32_t CPU286_REAL=4|CPU186; //Only support real mode instructions |
earlz | 0:217a7931b41f | 52 | //! 286 CPU level |
earlz | 0:217a7931b41f | 53 | static const uint32_t CPU286=8|CPU286_REAL; |
earlz | 0:217a7931b41f | 54 | //! 386 real mode only CPU level |
earlz | 0:217a7931b41f | 55 | static const uint32_t CPU386_REAL=16|CPU286_REAL; //Only Support real mode instructions |
earlz | 0:217a7931b41f | 56 | //! 386 CPU level |
earlz | 0:217a7931b41f | 57 | static const uint32_t CPU386=32|CPU386_REAL|CPU286; |
earlz | 0:217a7931b41f | 58 | //! 486 CPU level |
earlz | 0:217a7931b41f | 59 | static const uint32_t CPU486=64|CPU386; |
earlz | 0:217a7931b41f | 60 | //! Pentium(586) CPU level |
earlz | 0:217a7931b41f | 61 | static const uint32_t CPU_PENTIUM=128|CPU486; |
earlz | 0:217a7931b41f | 62 | //! Pentium Pro CPU level |
earlz | 0:217a7931b41f | 63 | static const uint32_t CPU_PPRO=256|CPU_PENTIUM; |
earlz | 0:217a7931b41f | 64 | //! Default CPU level |
earlz | 0:217a7931b41f | 65 | /*! CPU_DEFAULT will use the CPU with the most complete emulation |
earlz | 0:217a7931b41f | 66 | */ |
earlz | 0:217a7931b41f | 67 | static const uint32_t CPU_DEFAULT=0; //this is actually changed internally.. |
earlz | 0:217a7931b41f | 68 | |
earlz | 0:217a7931b41f | 69 | |
earlz | 0:217a7931b41f | 70 | |
earlz | 0:217a7931b41f | 71 | |
earlz | 0:217a7931b41f | 72 | |
earlz | 0:217a7931b41f | 73 | |
earlz | 0:217a7931b41f | 74 | /**Exceptions...**/ |
earlz | 0:217a7931b41f | 75 | //! Exception code for an infinite halt |
earlz | 0:217a7931b41f | 76 | static const uint32_t CLIHLT_EXCP=1; //cli/hlt...nothing to do |
earlz | 0:217a7931b41f | 77 | //! Exception code for memory access exception |
earlz | 0:217a7931b41f | 78 | static const uint32_t MEM_ACCESS_EXCP=3; //Memory Access Error...(can actually be page fault, or GPF, or stack fault... |
earlz | 0:217a7931b41f | 79 | //! Exception code for triple fault |
earlz | 0:217a7931b41f | 80 | /*! This code is always OR'd with another code |
earlz | 0:217a7931b41f | 81 | so that you can tell what caused the triple fault. |
earlz | 0:217a7931b41f | 82 | */ |
earlz | 0:217a7931b41f | 83 | static const uint32_t TRIPLE_FAULT_EXCP=0x10000; //Triple fault...This should be ORd with the last exception |
earlz | 0:217a7931b41f | 84 | |
earlz | 0:217a7931b41f | 85 | |
earlz | 0:217a7931b41f | 86 | |
earlz | 0:217a7931b41f | 87 | //! A debug exception |
earlz | 0:217a7931b41f | 88 | /*! This exception should really only be used when debugging. |
earlz | 0:217a7931b41f | 89 | It should be used as throw(Default_excp(__FILE__,__FUNCTION__,__LINE__)); |
earlz | 0:217a7931b41f | 90 | */ |
earlz | 0:217a7931b41f | 91 | class Default_excp{ //Internal only...these should never happen when released... |
earlz | 0:217a7931b41f | 92 | |
earlz | 0:217a7931b41f | 93 | public: |
earlz | 0:217a7931b41f | 94 | /*! |
earlz | 0:217a7931b41f | 95 | \param file_ The file name in which the exception occured(use __FILE__) |
earlz | 0:217a7931b41f | 96 | \param func_ The function in which the exception occured(use __FUNCTION__) |
earlz | 0:217a7931b41f | 97 | \param line_ The line number which the excption occured on(use __LINE__) |
earlz | 0:217a7931b41f | 98 | */ |
earlz | 0:217a7931b41f | 99 | Default_excp(std::string file_,std::string func_,int line_){ |
earlz | 0:217a7931b41f | 100 | file=file_; |
earlz | 0:217a7931b41f | 101 | func=func_; |
earlz | 0:217a7931b41f | 102 | line=line_; |
earlz | 0:217a7931b41f | 103 | } |
earlz | 0:217a7931b41f | 104 | //! The file which the exception was thrown from |
earlz | 0:217a7931b41f | 105 | std::string file; |
earlz | 0:217a7931b41f | 106 | //! The function which the exception was thrown from |
earlz | 0:217a7931b41f | 107 | std::string func; |
earlz | 0:217a7931b41f | 108 | //! The line which the exception was thrown from |
earlz | 0:217a7931b41f | 109 | int line; |
earlz | 0:217a7931b41f | 110 | }; |
earlz | 0:217a7931b41f | 111 | |
earlz | 0:217a7931b41f | 112 | //! CPU Panic exception |
earlz | 0:217a7931b41f | 113 | /*! This exception is thrown out of x86CPU if a fatal CPU error occurs, |
earlz | 0:217a7931b41f | 114 | such as a triple fault. |
earlz | 0:217a7931b41f | 115 | */ |
earlz | 0:217a7931b41f | 116 | class CpuPanic_excp{ //used for fatal CPU errors, such as triple fault.. |
earlz | 0:217a7931b41f | 117 | |
earlz | 0:217a7931b41f | 118 | public: |
earlz | 0:217a7931b41f | 119 | /*! |
earlz | 0:217a7931b41f | 120 | \param desc_ A text description of the error |
earlz | 0:217a7931b41f | 121 | \param code_ An exception code |
earlz | 0:217a7931b41f | 122 | */ |
earlz | 0:217a7931b41f | 123 | CpuPanic_excp(std::string desc_,uint32_t code_){ |
earlz | 0:217a7931b41f | 124 | desc=desc_; |
earlz | 0:217a7931b41f | 125 | code=code_; |
earlz | 0:217a7931b41f | 126 | } |
earlz | 0:217a7931b41f | 127 | //!A text description of the error |
earlz | 0:217a7931b41f | 128 | std::string desc; |
earlz | 0:217a7931b41f | 129 | //!An exception code |
earlz | 0:217a7931b41f | 130 | uint32_t code; |
earlz | 0:217a7931b41f | 131 | }; |
earlz | 0:217a7931b41f | 132 | |
earlz | 0:217a7931b41f | 133 | //! Memory error exception |
earlz | 0:217a7931b41f | 134 | /*! This should only be thrown out of the PhysMemory class |
earlz | 0:217a7931b41f | 135 | It is thrown out to tell x86CPU a memory exception has occured. |
earlz | 0:217a7931b41f | 136 | This does not always result in a triple fault. |
earlz | 0:217a7931b41f | 137 | /sa PhysMemory |
earlz | 0:217a7931b41f | 138 | */ |
earlz | 0:217a7931b41f | 139 | class Mem_excp{ //Exclusively for the Memory Classes, these are caught and then a more appropriate excp is thrown |
earlz | 0:217a7931b41f | 140 | public: |
earlz | 0:217a7931b41f | 141 | /*! |
earlz | 0:217a7931b41f | 142 | \param address_ The address at which had problems being read or written |
earlz | 0:217a7931b41f | 143 | */ |
earlz | 0:217a7931b41f | 144 | Mem_excp(uint32_t address_){ |
earlz | 0:217a7931b41f | 145 | address=address_; |
earlz | 0:217a7931b41f | 146 | } |
earlz | 0:217a7931b41f | 147 | uint32_t address; |
earlz | 0:217a7931b41f | 148 | }; |
earlz | 0:217a7931b41f | 149 | |
earlz | 0:217a7931b41f | 150 | class System_excp{ |
earlz | 0:217a7931b41f | 151 | public: |
earlz | 0:217a7931b41f | 152 | System_excp(){} |
earlz | 0:217a7931b41f | 153 | }; |
earlz | 0:217a7931b41f | 154 | |
earlz | 0:217a7931b41f | 155 | class x86CPU; |
earlz | 0:217a7931b41f | 156 | /**This will be used for memory mapped devices(including memory itself)**/ |
earlz | 0:217a7931b41f | 157 | class MemoryDevice{ |
earlz | 0:217a7931b41f | 158 | public: |
earlz | 0:217a7931b41f | 159 | virtual void Read(uint32_t address,int count,void *buffer)=0; |
earlz | 0:217a7931b41f | 160 | virtual void Write(uint32_t address,int count,void *data)=0; |
earlz | 0:217a7931b41f | 161 | virtual int Readable(uint32_t address,int count){ |
earlz | 0:217a7931b41f | 162 | return 1; |
earlz | 0:217a7931b41f | 163 | //This is optional. It is currently not used in the CPU code |
earlz | 0:217a7931b41f | 164 | } |
earlz | 0:217a7931b41f | 165 | virtual int Writeable(uint32_t address,int count){ |
earlz | 0:217a7931b41f | 166 | return 1; |
earlz | 0:217a7931b41f | 167 | //This is optional. It is currently not used in the CPU code |
earlz | 0:217a7931b41f | 168 | } |
earlz | 0:217a7931b41f | 169 | virtual inline ~MemoryDevice()=0; |
earlz | 0:217a7931b41f | 170 | }; |
earlz | 0:217a7931b41f | 171 | |
earlz | 0:217a7931b41f | 172 | inline MemoryDevice::~MemoryDevice(){} |
earlz | 0:217a7931b41f | 173 | void Onx86LibError(); |
earlz | 0:217a7931b41f | 174 | |
earlz | 0:217a7931b41f | 175 | class PortDevice{ |
earlz | 0:217a7931b41f | 176 | public: |
earlz | 0:217a7931b41f | 177 | virtual void Read(uint16_t address,int count,void *buffer)=0; |
earlz | 0:217a7931b41f | 178 | virtual void Write(uint16_t address,int count,void *data)=0; |
earlz | 0:217a7931b41f | 179 | virtual inline ~PortDevice()=0; |
earlz | 0:217a7931b41f | 180 | }; |
earlz | 0:217a7931b41f | 181 | |
earlz | 0:217a7931b41f | 182 | inline PortDevice::~PortDevice(){} |
earlz | 0:217a7931b41f | 183 | |
earlz | 0:217a7931b41f | 184 | typedef struct DeviceRange |
earlz | 0:217a7931b41f | 185 | { |
earlz | 0:217a7931b41f | 186 | union |
earlz | 0:217a7931b41f | 187 | { |
earlz | 0:217a7931b41f | 188 | class MemoryDevice *memdev; |
earlz | 0:217a7931b41f | 189 | class PortDevice *portdev; |
earlz | 0:217a7931b41f | 190 | }; |
earlz | 0:217a7931b41f | 191 | uint32_t high; |
earlz | 0:217a7931b41f | 192 | uint32_t low; |
earlz | 0:217a7931b41f | 193 | }DeviceRange_t; |
earlz | 0:217a7931b41f | 194 | /*Myk I hate you. This is going to be harder to implement than I thought. lol */ |
earlz | 0:217a7931b41f | 195 | class MemorySystem{ |
earlz | 0:217a7931b41f | 196 | std::vector<DeviceRange_t> memorySystemVector; |
earlz | 0:217a7931b41f | 197 | protected: |
earlz | 0:217a7931b41f | 198 | //! Intended to be used to mark if the address space is locked. |
earlz | 0:217a7931b41f | 199 | volatile uint32_t locked; |
earlz | 0:217a7931b41f | 200 | public: |
earlz | 0:217a7931b41f | 201 | MemorySystem(); |
earlz | 0:217a7931b41f | 202 | void Add(uint32_t low,uint32_t high,MemoryDevice *memdev); |
earlz | 0:217a7931b41f | 203 | void Remove(uint32_t low,uint32_t high); |
earlz | 0:217a7931b41f | 204 | void Remove(MemoryDevice *memdev); |
earlz | 0:217a7931b41f | 205 | int RangeFree(uint32_t low,uint32_t high); |
earlz | 0:217a7931b41f | 206 | void Read(uint32_t address,int count,void *buffer); |
earlz | 0:217a7931b41f | 207 | void Write(uint32_t address,int count,void *data); |
earlz | 0:217a7931b41f | 208 | //! Tells if memory is locked |
earlz | 0:217a7931b41f | 209 | /*! |
earlz | 0:217a7931b41f | 210 | \return 1 if memory is locked, 0 if not locked. |
earlz | 0:217a7931b41f | 211 | */ |
earlz | 0:217a7931b41f | 212 | bool IsLocked(){return locked;} |
earlz | 0:217a7931b41f | 213 | //! Locks the address space |
earlz | 0:217a7931b41f | 214 | void Lock(){ |
earlz | 0:217a7931b41f | 215 | while(locked==1){} |
earlz | 0:217a7931b41f | 216 | locked=1; |
earlz | 0:217a7931b41f | 217 | } |
earlz | 0:217a7931b41f | 218 | //! Unlocks the address space |
earlz | 0:217a7931b41f | 219 | void Unlock(){ |
earlz | 0:217a7931b41f | 220 | locked=0; |
earlz | 0:217a7931b41f | 221 | } |
earlz | 0:217a7931b41f | 222 | void WaitLock(int haslock){ |
earlz | 0:217a7931b41f | 223 | if(haslock==0){ |
earlz | 0:217a7931b41f | 224 | while(locked>0){} |
earlz | 0:217a7931b41f | 225 | } |
earlz | 0:217a7931b41f | 226 | } |
earlz | 0:217a7931b41f | 227 | }; |
earlz | 0:217a7931b41f | 228 | |
earlz | 0:217a7931b41f | 229 | class PortSystem{ |
earlz | 0:217a7931b41f | 230 | DeviceRange_t *list; |
earlz | 0:217a7931b41f | 231 | int count; |
earlz | 0:217a7931b41f | 232 | public: |
earlz | 0:217a7931b41f | 233 | PortSystem(); |
earlz | 0:217a7931b41f | 234 | |
earlz | 0:217a7931b41f | 235 | void Add(uint16_t low,uint16_t high,PortDevice *portdev); |
earlz | 0:217a7931b41f | 236 | void Remove(uint16_t low,uint16_t high); |
earlz | 0:217a7931b41f | 237 | void Remove(PortDevice *portdev); |
earlz | 0:217a7931b41f | 238 | int RangeFree(uint32_t low,uint32_t high); |
earlz | 0:217a7931b41f | 239 | void Read(uint16_t address,int count,void *buffer); |
earlz | 0:217a7931b41f | 240 | void Write(uint16_t address,int count,void *data); |
earlz | 0:217a7931b41f | 241 | }; |
earlz | 0:217a7931b41f | 242 | |
earlz | 0:217a7931b41f | 243 | |
earlz | 0:217a7931b41f | 244 | |
earlz | 0:217a7931b41f | 245 | //! The struct used to save the current state of x86CPU |
earlz | 0:217a7931b41f | 246 | struct x86SaveData{ |
earlz | 0:217a7931b41f | 247 | //! General registers |
earlz | 0:217a7931b41f | 248 | uint32_t reg32[8]; |
earlz | 0:217a7931b41f | 249 | //! Segment registers |
earlz | 0:217a7931b41f | 250 | uint16_t seg[7]; |
earlz | 0:217a7931b41f | 251 | //! Segment register routing(in case of segment overrides) |
earlz | 0:217a7931b41f | 252 | uint8_t seg_route[7]; |
earlz | 0:217a7931b41f | 253 | //! Instruction pointer |
earlz | 0:217a7931b41f | 254 | uint32_t eip; |
earlz | 0:217a7931b41f | 255 | //! Which opcode map is currently in use |
earlz | 0:217a7931b41f | 256 | uint32_t opcode_mode; |
earlz | 0:217a7931b41f | 257 | //! Flags register |
earlz | 0:217a7931b41f | 258 | uint16_t freg; |
earlz | 0:217a7931b41f | 259 | //! CPU level |
earlz | 0:217a7931b41f | 260 | uint32_t cpu_level; |
earlz | 0:217a7931b41f | 261 | }; |
earlz | 0:217a7931b41f | 262 | |
earlz | 0:217a7931b41f | 263 | }; |
earlz | 0:217a7931b41f | 264 | |
earlz | 0:217a7931b41f | 265 | #ifdef X86LIB_BUILD |
earlz | 0:217a7931b41f | 266 | |
earlz | 0:217a7931b41f | 267 | #include <x86Lib_internal.h> |
earlz | 0:217a7931b41f | 268 | #endif |
earlz | 0:217a7931b41f | 269 | |
earlz | 0:217a7931b41f | 270 | |
earlz | 0:217a7931b41f | 271 | |
earlz | 0:217a7931b41f | 272 | namespace x86Lib{ |
earlz | 0:217a7931b41f | 273 | |
earlz | 0:217a7931b41f | 274 | typedef void (x86Lib::x86CPU::*opcode)(); |
earlz | 0:217a7931b41f | 275 | typedef struct{ |
earlz | 0:217a7931b41f | 276 | unsigned char rm:3; |
earlz | 0:217a7931b41f | 277 | unsigned char extra:3; |
earlz | 0:217a7931b41f | 278 | unsigned char mod:2; |
earlz | 0:217a7931b41f | 279 | } |
earlz | 0:217a7931b41f | 280 | __attribute__((packed))mod_rm16; //this struct is a described mod r/m byte.. |
earlz | 0:217a7931b41f | 281 | |
earlz | 0:217a7931b41f | 282 | //Note, this will re-cache op_cache, so do not use op_cache afterward |
earlz | 0:217a7931b41f | 283 | //Also, eip should be on the modrm byte! |
earlz | 0:217a7931b41f | 284 | //On return, it is on the last byte of the modrm block, so no advancement needed unelss there is an immediate |
earlz | 0:217a7931b41f | 285 | //Also, this will advance EIP upon exiting the opcode(deconstruction) |
earlz | 0:217a7931b41f | 286 | class ModRM16{ //This is the best thing I have ever done... |
earlz | 0:217a7931b41f | 287 | //I love this class so much...am I cheating on her? lol |
earlz | 0:217a7931b41f | 288 | protected: |
earlz | 0:217a7931b41f | 289 | bool use_ss; |
earlz | 0:217a7931b41f | 290 | bool op_specific; |
earlz | 0:217a7931b41f | 291 | x86CPU *this_cpu; |
earlz | 0:217a7931b41f | 292 | private: |
earlz | 0:217a7931b41f | 293 | mod_rm16 modrm; |
earlz | 0:217a7931b41f | 294 | inline uint16_t GetRegD(); //This returns the register displacement value |
earlz | 0:217a7931b41f | 295 | inline uint16_t GetDisp(); |
earlz | 0:217a7931b41f | 296 | public: |
earlz | 0:217a7931b41f | 297 | inline ModRM16(x86CPU* this_cpu_); |
earlz | 0:217a7931b41f | 298 | inline ~ModRM16(); |
earlz | 0:217a7931b41f | 299 | //The r suffix means /r, which means for op_specific=1, use general registers |
earlz | 0:217a7931b41f | 300 | inline uint8_t ReadByter(); |
earlz | 0:217a7931b41f | 301 | inline uint16_t ReadWordr(); |
earlz | 0:217a7931b41f | 302 | inline uint32_t ReadDword(); |
earlz | 0:217a7931b41f | 303 | inline void WriteByter(uint8_t byte); |
earlz | 0:217a7931b41f | 304 | inline void WriteWordr(uint16_t word); |
earlz | 0:217a7931b41f | 305 | inline void WriteDword(uint32_t dword); |
earlz | 0:217a7931b41f | 306 | inline uint8_t GetLength(); //This returns how many total bytes the modrm block consumes |
earlz | 0:217a7931b41f | 307 | inline uint8_t GetExtra(); //Get the extra fied from mod_rm |
earlz | 0:217a7931b41f | 308 | inline uint16_t ReadOffset(); //This is only used by LEA. It will obtain the offset and not dereference it... |
earlz | 0:217a7931b41f | 309 | |
earlz | 0:217a7931b41f | 310 | }; //I hope that SIB and ModR/M32 will be this good! |
earlz | 0:217a7931b41f | 311 | //! The main CPU control class |
earlz | 0:217a7931b41f | 312 | /*! This class is the complete CPU. That being said, it is quite big |
earlz | 0:217a7931b41f | 313 | and has many functions. It completely emulates the x86 line of CPUs |
earlz | 0:217a7931b41f | 314 | */ |
earlz | 0:217a7931b41f | 315 | class x86CPU{ |
earlz | 0:217a7931b41f | 316 | friend class ModRM16; |
earlz | 0:217a7931b41f | 317 | volatile uint32_t reg32[8]; |
earlz | 0:217a7931b41f | 318 | volatile uint16_t *regs16[8]; |
earlz | 0:217a7931b41f | 319 | volatile uint8_t *regs8[8]; |
earlz | 0:217a7931b41f | 320 | volatile uint16_t seg[7]; |
earlz | 0:217a7931b41f | 321 | volatile uint32_t eip; |
earlz | 0:217a7931b41f | 322 | #ifdef X86LIB_BUILD |
earlz | 0:217a7931b41f | 323 | volatile FLAGS freg; |
earlz | 0:217a7931b41f | 324 | #else |
earlz | 0:217a7931b41f | 325 | volatile uint16_t freg; |
earlz | 0:217a7931b41f | 326 | #endif |
earlz | 0:217a7931b41f | 327 | volatile uint8_t op_cache[4]; |
earlz | 0:217a7931b41f | 328 | volatile uint8_t ES; |
earlz | 0:217a7931b41f | 329 | volatile uint8_t CS; |
earlz | 0:217a7931b41f | 330 | volatile uint8_t SS; |
earlz | 0:217a7931b41f | 331 | volatile uint8_t DS; |
earlz | 0:217a7931b41f | 332 | volatile uint8_t FS; |
earlz | 0:217a7931b41f | 333 | volatile uint8_t GS; |
earlz | 0:217a7931b41f | 334 | volatile bool string_compares; |
earlz | 0:217a7931b41f | 335 | volatile uint8_t cli_count; //Whenever this is 1, an STI is done. |
earlz | 0:217a7931b41f | 336 | volatile bool int_pending; |
earlz | 0:217a7931b41f | 337 | volatile uint8_t int_number; |
earlz | 0:217a7931b41f | 338 | uint32_t cpu_level; |
earlz | 0:217a7931b41f | 339 | volatile bool busmaster; |
earlz | 0:217a7931b41f | 340 | void Init(); |
earlz | 0:217a7931b41f | 341 | protected: |
earlz | 0:217a7931b41f | 342 | //! Do one CPU opcode |
earlz | 0:217a7931b41f | 343 | /*! This should be put in the main loop, as this is what makes the CPU work. |
earlz | 0:217a7931b41f | 344 | */ |
earlz | 0:217a7931b41f | 345 | void Cycle(); |
earlz | 0:217a7931b41f | 346 | opcode opcodes_16bit[256]; |
earlz | 0:217a7931b41f | 347 | opcode *Opcodes; |
earlz | 0:217a7931b41f | 348 | |
earlz | 0:217a7931b41f | 349 | /*! |
earlz | 0:217a7931b41f | 350 | \return 0 if no interrupts are pending |
earlz | 0:217a7931b41f | 351 | */ |
earlz | 0:217a7931b41f | 352 | int CheckInterrupts(); |
earlz | 0:217a7931b41f | 353 | public: |
earlz | 0:217a7931b41f | 354 | #ifdef ENABLE_OPCODE_CALLBACK |
earlz | 0:217a7931b41f | 355 | void (*EachOpcodeCallback)(x86CPU *thiscpu); |
earlz | 0:217a7931b41f | 356 | #endif |
earlz | 0:217a7931b41f | 357 | MemorySystem *Memory; |
earlz | 0:217a7931b41f | 358 | PortSystem *Ports; |
earlz | 0:217a7931b41f | 359 | /*! |
earlz | 0:217a7931b41f | 360 | \param cpu_level The CPU level to use(default argument is default level) |
earlz | 0:217a7931b41f | 361 | \param flags special flags to control CPU (currently, there is none) |
earlz | 0:217a7931b41f | 362 | */ |
earlz | 0:217a7931b41f | 363 | x86CPU(uint32_t cpu_level=0 ,uint32_t flags=0); |
earlz | 0:217a7931b41f | 364 | /*! |
earlz | 0:217a7931b41f | 365 | \param save The x86SaveData class to restore the cpu to |
earlz | 0:217a7931b41f | 366 | \param flags special flags to control CPU (currently, there is none) |
earlz | 0:217a7931b41f | 367 | */ |
earlz | 0:217a7931b41f | 368 | x86CPU(x86SaveData &save,uint32_t flags=0); |
earlz | 0:217a7931b41f | 369 | |
earlz | 0:217a7931b41f | 370 | //!Runs the CPU for the specified cyclecount. |
earlz | 0:217a7931b41f | 371 | void Exec(int cyclecount); |
earlz | 0:217a7931b41f | 372 | |
earlz | 0:217a7931b41f | 373 | //! Dump CPU state |
earlz | 0:217a7931b41f | 374 | /*! This will dump cpu state to output. This is mainly used for debugging, as it is not flexible. |
earlz | 0:217a7931b41f | 375 | \param output output stream which to use. |
earlz | 0:217a7931b41f | 376 | */ |
earlz | 0:217a7931b41f | 377 | void DumpState(std::ostream &output); |
earlz | 0:217a7931b41f | 378 | //! Cause a CPU interrupt |
earlz | 0:217a7931b41f | 379 | /*! This will cause a CPU interrupt(unless interrupt flag is cleared) |
earlz | 0:217a7931b41f | 380 | Note! This does not resolve IRQs! This takes normal interrupt numbers(0-255) |
earlz | 0:217a7931b41f | 381 | \param num Interrupt number |
earlz | 0:217a7931b41f | 382 | */ |
earlz | 0:217a7931b41f | 383 | void Int(uint8_t num); |
earlz | 0:217a7931b41f | 384 | //! Saves CPU state |
earlz | 0:217a7931b41f | 385 | /*! This will completely save the CPU state of the current x86CPU class |
earlz | 0:217a7931b41f | 386 | \param save_data_buffer This should be a free memory area the size of x86SaveData |
earlz | 0:217a7931b41f | 387 | */ |
earlz | 0:217a7931b41f | 388 | void SaveState(x86SaveData *save_data_buffer); |
earlz | 0:217a7931b41f | 389 | //!Loads CPU state |
earlz | 0:217a7931b41f | 390 | /*! This will completely reset and reload the cpu state. |
earlz | 0:217a7931b41f | 391 | \param load_data where the x86SaveData is located |
earlz | 0:217a7931b41f | 392 | */ |
earlz | 0:217a7931b41f | 393 | void LoadState(x86SaveData &load_data); |
earlz | 0:217a7931b41f | 394 | |
earlz | 0:217a7931b41f | 395 | //!Completely resets the CPU |
earlz | 0:217a7931b41f | 396 | void Reset(); |
earlz | 0:217a7931b41f | 397 | //~x86CPU(); |
earlz | 0:217a7931b41f | 398 | //!Locks the PhysMemory in use, and declares this CPU as busmaster |
earlz | 0:217a7931b41f | 399 | void Lock(); |
earlz | 0:217a7931b41f | 400 | //!Unlocks the PhysMemory in use |
earlz | 0:217a7931b41f | 401 | void Unlock(); |
earlz | 0:217a7931b41f | 402 | //! Tells if PhysMemory in use is locked |
earlz | 0:217a7931b41f | 403 | /*! |
earlz | 0:217a7931b41f | 404 | \return 1 if PhysMemory in use is locked, otherwise returns 0 |
earlz | 0:217a7931b41f | 405 | */ |
earlz | 0:217a7931b41f | 406 | bool IsLocked(); |
earlz | 0:217a7931b41f | 407 | /*Added after inital multi-branch switch over*/ |
earlz | 0:217a7931b41f | 408 | //!Checks if an interrupt is on the stack waiting to be answered. |
earlz | 0:217a7931b41f | 409 | /*! |
earlz | 0:217a7931b41f | 410 | \return 1 if an interrupt is waiting to be answered by the CPU, else, 0. |
earlz | 0:217a7931b41f | 411 | */ |
earlz | 0:217a7931b41f | 412 | bool IntPending(); |
earlz | 0:217a7931b41f | 413 | |
earlz | 0:217a7931b41f | 414 | /*End public interface*/ |
earlz | 0:217a7931b41f | 415 | #ifdef X86LIB_BUILD |
earlz | 0:217a7931b41f | 416 | private: |
earlz | 0:217a7931b41f | 417 | #include <opcode_def.h> |
earlz | 0:217a7931b41f | 418 | #endif |
earlz | 0:217a7931b41f | 419 | |
earlz | 0:217a7931b41f | 420 | }; |
earlz | 0:217a7931b41f | 421 | |
earlz | 0:217a7931b41f | 422 | |
earlz | 0:217a7931b41f | 423 | |
earlz | 0:217a7931b41f | 424 | #ifdef X86LIB_BUILD |
earlz | 0:217a7931b41f | 425 | #define X86_POST_CPU |
earlz | 0:217a7931b41f | 426 | #include "x86Lib_internal.h" |
earlz | 0:217a7931b41f | 427 | #undef X86_POST_CPU |
earlz | 0:217a7931b41f | 428 | #endif |
earlz | 0:217a7931b41f | 429 | |
earlz | 0:217a7931b41f | 430 | |
earlz | 0:217a7931b41f | 431 | |
earlz | 0:217a7931b41f | 432 | |
earlz | 0:217a7931b41f | 433 | |
earlz | 0:217a7931b41f | 434 | |
earlz | 0:217a7931b41f | 435 | |
earlz | 0:217a7931b41f | 436 | |
earlz | 0:217a7931b41f | 437 | |
earlz | 0:217a7931b41f | 438 | |
earlz | 0:217a7931b41f | 439 | |
earlz | 0:217a7931b41f | 440 | |
earlz | 0:217a7931b41f | 441 | |
earlz | 0:217a7931b41f | 442 | |
earlz | 0:217a7931b41f | 443 | |
earlz | 0:217a7931b41f | 444 | |
earlz | 0:217a7931b41f | 445 | |
earlz | 0:217a7931b41f | 446 | |
earlz | 0:217a7931b41f | 447 | |
earlz | 0:217a7931b41f | 448 | } |
earlz | 0:217a7931b41f | 449 | |
earlz | 0:217a7931b41f | 450 | |
earlz | 0:217a7931b41f | 451 | #endif |
earlz | 0:217a7931b41f | 452 |