summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/i386/i386priv.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/i386/i386priv.h')
-rw-r--r--src/devices/cpu/i386/i386priv.h206
1 files changed, 44 insertions, 162 deletions
diff --git a/src/devices/cpu/i386/i386priv.h b/src/devices/cpu/i386/i386priv.h
index 1e5439f205f..954e49ee6c7 100644
--- a/src/devices/cpu/i386/i386priv.h
+++ b/src/devices/cpu/i386/i386priv.h
@@ -5,7 +5,6 @@
#ifndef __I386_H__
#define __I386_H__
-#include "i386.h"
#include "i386dasm.h"
//#define DEBUG_MISSING_OPCODE
@@ -322,6 +321,12 @@ extern int i386_parity_table[256];
#define MMX(n) (*((MMX_REG *)(&m_x87_reg[(n)].low)))
#define XMM(n) m_sse_reg[(n)]
+#define VTLB_FLAG_DIRTY 0x100
+#define CYCLES_NUM(x) (m_cycles -= (x))
+
+#define FAULT(fault,error) {m_ext = 1; i386_trap_with_error(fault,0,0,error); return;}
+#define FAULT_EXP(fault,error) {m_ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;}
+
/***********************************************************************************/
struct MODRM_TABLE {
@@ -361,167 +366,6 @@ extern MODRM_TABLE i386_MODRM_table[256];
/***********************************************************************************/
-uint32_t i386_device::i386_translate(int segment, uint32_t ip, int rwn)
-{
- // TODO: segment limit access size, execution permission, handle exception thrown from exception handler
- if(PROTECTED_MODE && !V8086_MODE && (rwn != -1))
- {
- if(!(m_sreg[segment].valid))
- FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0);
- if(i386_limit_check(segment, ip))
- FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0);
- if((rwn == 0) && ((m_sreg[segment].flags & 8) && !(m_sreg[segment].flags & 2)))
- FAULT_THROW(FAULT_GP, 0);
- if((rwn == 1) && ((m_sreg[segment].flags & 8) || !(m_sreg[segment].flags & 2)))
- FAULT_THROW(FAULT_GP, 0);
- }
- return m_sreg[segment].base + ip;
-}
-
-#define VTLB_FLAG_DIRTY 0x100
-
-vtlb_entry i386_device::get_permissions(uint32_t pte, int wp)
-{
- vtlb_entry ret = VTLB_READ_ALLOWED | ((pte & 4) ? VTLB_USER_READ_ALLOWED : 0);
- if(!wp)
- ret |= VTLB_WRITE_ALLOWED;
- if(pte & 2)
- ret |= VTLB_WRITE_ALLOWED | ((pte & 4) ? VTLB_USER_WRITE_ALLOWED : 0);
- return ret;
-}
-
-bool i386_device::i386_translate_address(int intention, offs_t *address, vtlb_entry *entry)
-{
- uint32_t a = *address;
- uint32_t pdbr = m_cr[3] & 0xfffff000;
- uint32_t directory = (a >> 22) & 0x3ff;
- uint32_t table = (a >> 12) & 0x3ff;
- vtlb_entry perm = 0;
- bool ret;
- bool user = (intention & TRANSLATE_USER_MASK) ? true : false;
- bool write = (intention & TRANSLATE_WRITE) ? true : false;
- bool debug = (intention & TRANSLATE_DEBUG_MASK) ? true : false;
-
- if(!(m_cr[0] & 0x80000000))
- {
- if(entry)
- *entry = 0x77;
- return true;
- }
-
- uint32_t page_dir = m_program->read_dword(pdbr + directory * 4);
- if(page_dir & 1)
- {
- if ((page_dir & 0x80) && (m_cr[4] & 0x10))
- {
- a = (page_dir & 0xffc00000) | (a & 0x003fffff);
- if(debug)
- {
- *address = a;
- return true;
- }
- perm = get_permissions(page_dir, WP);
- if(write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED))))
- ret = false;
- else if(user && !(perm & VTLB_USER_READ_ALLOWED))
- ret = false;
- else
- {
- if(write)
- perm |= VTLB_FLAG_DIRTY;
- if(!(page_dir & 0x40) && write)
- m_program->write_dword(pdbr + directory * 4, page_dir | 0x60);
- else if(!(page_dir & 0x20))
- m_program->write_dword(pdbr + directory * 4, page_dir | 0x20);
- ret = true;
- }
- }
- else
- {
- uint32_t page_entry = m_program->read_dword((page_dir & 0xfffff000) + (table * 4));
- if(!(page_entry & 1))
- ret = false;
- else
- {
- a = (page_entry & 0xfffff000) | (a & 0xfff);
- if(debug)
- {
- *address = a;
- return true;
- }
- perm = get_permissions(page_entry, WP);
- if(write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED))))
- ret = false;
- else if(user && !(perm & VTLB_USER_READ_ALLOWED))
- ret = false;
- else
- {
- if(write)
- perm |= VTLB_FLAG_DIRTY;
- if(!(page_dir & 0x20))
- m_program->write_dword(pdbr + directory * 4, page_dir | 0x20);
- if(!(page_entry & 0x40) && write)
- m_program->write_dword((page_dir & 0xfffff000) + (table * 4), page_entry | 0x60);
- else if(!(page_entry & 0x20))
- m_program->write_dword((page_dir & 0xfffff000) + (table * 4), page_entry | 0x20);
- ret = true;
- }
- }
- }
- }
- else
- ret = false;
- if(entry)
- *entry = perm;
- if(ret)
- *address = a;
- return ret;
-}
-
-//#define TEST_TLB
-
-bool i386_device::translate_address(int pl, int type, uint32_t *address, uint32_t *error)
-{
- if(!(m_cr[0] & 0x80000000)) // Some (very few) old OS's won't work with this
- return true;
-
- const vtlb_entry *table = vtlb_table();
- uint32_t index = *address >> 12;
- vtlb_entry entry = table[index];
- if(type == TRANSLATE_FETCH)
- type = TRANSLATE_READ;
- if(pl == 3)
- type |= TRANSLATE_USER_MASK;
-#ifdef TEST_TLB
- uint32_t test_addr = *address;
-#endif
-
- if(!(entry & VTLB_FLAG_VALID) || ((type & TRANSLATE_WRITE) && !(entry & VTLB_FLAG_DIRTY)))
- {
- if(!i386_translate_address(type, address, &entry))
- {
- *error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((m_CPL == 3) ? 4 : 0);
- if(entry)
- *error |= 1;
- return false;
- }
- vtlb_dynload(index, *address, entry);
- return true;
- }
- if(!(entry & (1 << type)))
- {
- *error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((m_CPL == 3) ? 4 : 0) | 1;
- return false;
- }
- *address = (entry & 0xfffff000) | (*address & 0xfff);
-#ifdef TEST_TLB
- int test_ret = i386_translate_address(type | TRANSLATE_DEBUG_MASK, &test_addr, nullptr);
- if(!test_ret || (test_addr != *address))
- logerror("TLB-PTE mismatch! %06X %06X %06x\n", *address, test_addr, m_pc);
-#endif
- return true;
-}
-
void i386_device::CHANGE_PC(uint32_t pc)
{
m_pc = i386_translate(CS, pc, -1 );
@@ -1093,6 +937,44 @@ void i386_device::BUMP_DI(int adjustment)
REG16(DI) += ((m_DF) ? -adjustment : +adjustment);
}
+void i386_device::CYCLES(int x)
+{
+ if (PROTECTED_MODE)
+ {
+ m_cycles -= m_cycle_table_pm[x];
+ }
+ else
+ {
+ m_cycles -= m_cycle_table_rm[x];
+ }
+}
+
+void i386_device::CYCLES_RM(int modrm, int r, int m)
+{
+ if (modrm >= 0xc0)
+ {
+ if (PROTECTED_MODE)
+ {
+ m_cycles -= m_cycle_table_pm[r];
+ }
+ else
+ {
+ m_cycles -= m_cycle_table_rm[r];
+ }
+ }
+ else
+ {
+ if (PROTECTED_MODE)
+ {
+ m_cycles -= m_cycle_table_pm[m];
+ }
+ else
+ {
+ m_cycles -= m_cycle_table_rm[m];
+ }
+ }
+}
+
/***********************************************************************************