Mode | Name | Size | |
---|---|---|---|
-rw-r--r-- | shell.c | 181708 | logstatsplainblame |
-rw-r--r-- | sqlite3.c | 7007293 | logstatsplainblame |
-rw-r--r-- | sqlite3.h | 491251 | logstatsplainblame |
-rw-r--r-- | sqlite3ext.h | 30004 | logstatsplainblame |
arset=UTF-8 Last-Modified: Fri, 02 May 2025 15:44:03 GMT Expires: Mon, 30 Apr 2035 15:44:03 GMT
// license:BSD-3-Clause
// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett
uint8_t i386_device::i386_shift_rotate8(uint8_t modrm, uint32_t value, uint8_t shift)
{
uint32_t src = value & 0xff;
uint8_t dst = value;
if( shift == 0 ) {
CYCLES_RM(modrm, 3, 7);
} else if( shift == 1 ) {
switch( (modrm >> 3) & 0x7 )
{
case 0: /* ROL rm8, 1 */
m_CF = (src & 0x80) ? 1 : 0;
dst = (src << 1) + m_CF;
m_OF = ((src ^ dst) & 0x80) ? 1 : 0;
CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
break;
case 1: /* ROR rm8, 1 */
m_CF = (src & 0x1) ? 1 : 0;
dst = (m_CF << 7) | (src >> 1);
m_OF = ((src ^ dst) & 0x80) ? 1 : 0;
CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
break;
case 2: /* RCL rm8, 1 */
dst = (src << 1) + m_CF;
m_CF = (src & 0x80) ? 1 : 0;
m_OF = ((src ^ dst) & 0x80) ? 1 : 0;
CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
break;
case 3: /* RCR rm8, 1 */
dst = (m_CF << 7) | (src >> 1);
m_CF = src & 0x1;
m_OF = ((src ^ dst) & 0x80) ? 1 : 0;
CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
break;
case 4: /* SHL/SAL rm8, 1 */
case 6:
dst = src << 1;
m_CF = (src & 0x80) ? 1 : 0;
m_OF = (((m_CF << 7) ^ dst) & 0x80) ? 1 : 0;
SetSZPF8(dst);
CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
break;
case 5: /* SHR rm8, 1 */
dst = src >> 1;
m_CF = src & 0x1;
m_OF = (dst & 0x80) ? 1 : 0;
SetSZPF8(dst);
CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
break;
case 7: /* SAR rm8, 1 */
dst = (int8_t)(src) >> 1;
m_CF = src & 0x1;
m_OF = 0;
SetSZPF8(dst);
CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
break;
}
} else {
switch( (modrm >> 3) & 0x7 )
{
case 0: /* ROL rm8, i8 */
if(!(shift & 7))
{
if(shift & 0x18)
{
m_CF = src & 1;
m_OF = (src & 1) ^ ((src >> 7) & 1);
}
break;
}
shift &= 7;
dst = ((src & ((uint8_t)0xff >> shift)) << shift) |
((src & ((uint8_t)0xff << (8-shift))) >> (8-shift));
m_CF = dst & 0x1;
m_OF = (dst & 1) ^ (dst >> 7);
CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
break;
case 1: /* ROR rm8, i8 */
if(!(shift & 7))
{
if(shift & 0x18)
{
m_CF = (src >> 7) & 1;
m_OF = ((src >> 7) & 1) ^ ((src >> 6) & 1);
}
break;
}
shift &= 7;
dst = ((src & ((uint8_t)0xff << shift)) >> shift) |
((src & ((uint8_t)0xff >> (8-shift))) << (8-shift));
m_CF = (dst >> 7) & 1;
m_OF = ((dst >> 7) ^ (dst >> 6)) & 1;
CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
break;
case 2: /* RCL rm8, i8 */
shift %= 9;
dst = ((src & ((uint8_t)0xff >> shift)) << shift) |
((src & ((uint8_t)0xff << (9-shift))) >> (9-shift)) |
(m_CF << (shift-1));
if(shift) m_CF = (src >> (8-shift)) & 0x1;
m_OF = m_CF ^ ((dst >> 7) & 1);
CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
break;
case 3: /* RCR rm8, i8 */
shift %= 9;
dst = ((src & ((uint8_t)0xff << shift)) >> shift) |
((src & ((uint8_t)0xff >> (8-shift))) << (9-shift)) |
(m_CF << (8-shift));
if(shift) m_CF = (src >> (shift-1)) & 0x1;
m_OF = ((dst >> 7) ^ (dst >> 6)) & 1;
CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
break;
case 4: /* SHL/SAL rm8, i8 */
case 6:
shift &= 31;
dst = src << shift;
m_CF = (shift <= 8) && ((src >> (8 - shift)) & 1);
SetSZPF8(dst);
CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
break;
case 5: /* SHR rm8, i8 */
shift &= 31;
dst = src >> shift;
m_CF = (src & (1 << (shift-1))) ? 1 : 0;
SetSZPF8(dst);
CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
break;
case 7: /* SAR rm8, i8 */
shift &= 31;
dst = (int8_t)src >> shift;
m_CF = (src & (1 << (shift-1))) ? 1 : 0;
SetSZPF8(dst);
CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
break;
}
}
return dst;
}
void i386_device::i386_adc_rm8_r8() // Opcode 0x10
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_REG8(modrm);
dst = LOAD_RM8(modrm);
dst = ADC8(dst, src, m_CF);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,1);
src = LOAD_REG8(modrm);
dst = READ8(ea);
dst = ADC8(dst, src, m_CF);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
}
void i386_device::i386_adc_r8_rm8() // Opcode 0x12
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_RM8(modrm);
dst = LOAD_REG8(modrm);
dst = ADC8(dst, src, m_CF);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,0);
src = READ8(ea);
dst = LOAD_REG8(modrm);
dst = ADC8(dst, src, m_CF);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_MEM_REG);
}
}
void i386_device::i386_adc_al_i8() // Opcode 0x14
{
uint8_t src, dst;
src = FETCH();
dst = REG8(AL);
dst = ADC8(dst, src, m_CF);
REG8(AL) = dst;
CYCLES(CYCLES_ALU_IMM_ACC);
}
void i386_device::i386_add_rm8_r8() // Opcode 0x00
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_REG8(modrm);
dst = LOAD_RM8(modrm);
dst = ADD8(dst, src);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,1);
src = LOAD_REG8(modrm);
dst = READ8(ea);
dst = ADD8(dst, src);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
}
void i386_device::i386_add_r8_rm8() // Opcode 0x02
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_RM8(modrm);
dst = LOAD_REG8(modrm);
dst = ADD8(dst, src);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,0);
src = READ8(ea);
dst = LOAD_REG8(modrm);
dst = ADD8(dst, src);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_MEM_REG);
}
}
void i386_device::i386_add_al_i8() // Opcode 0x04
{
uint8_t src, dst;
src = FETCH();
dst = REG8(AL);
dst = ADD8(dst, src);
REG8(AL) = dst;
CYCLES(CYCLES_ALU_IMM_ACC);
}
void i386_device::i386_and_rm8_r8() // Opcode 0x20
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_REG8(modrm);
dst = LOAD_RM8(modrm);
dst = AND8(dst, src);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,1);
src = LOAD_REG8(modrm);
dst = READ8(ea);
dst = AND8(dst, src);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
}
void i386_device::i386_and_r8_rm8() // Opcode 0x22
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_RM8(modrm);
dst = LOAD_REG8(modrm);
dst = AND8(dst, src);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,0);
src = READ8(ea);
dst = LOAD_REG8(modrm);
dst = AND8(dst, src);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_MEM_REG);
}
}
void i386_device::i386_and_al_i8() // Opcode 0x24
{
uint8_t src, dst;
src = FETCH();
dst = REG8(AL);
dst = AND8(dst, src);
REG8(AL) = dst;
CYCLES(CYCLES_ALU_IMM_ACC);
}
void i386_device::i386_clc() // Opcode 0xf8
{
m_CF = 0;
CYCLES(CYCLES_CLC);
}
void i386_device::i386_cld() // Opcode 0xfc
{
m_DF = 0;
CYCLES(CYCLES_CLD);
}
void i386_device::i386_cli() // Opcode 0xfa
{
if(PROTECTED_MODE)
{
uint8_t IOPL = m_IOP1 | (m_IOP2 << 1);
if(m_CPL > IOPL)
FAULT(FAULT_GP,0);
}
m_IF = 0;
CYCLES(CYCLES_CLI);
}
void i386_device::i386_cmc() // Opcode 0xf5
{
m_CF ^= 1;
CYCLES(CYCLES_CMC);
}
void i386_device::i386_cmp_rm8_r8() // Opcode 0x38
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_REG8(modrm);
dst = LOAD_RM8(modrm);
SUB8(dst, src);
CYCLES(CYCLES_CMP_REG_REG);
} else {
uint32_t ea = GetEA(modrm,0);
src = LOAD_REG8(modrm);
dst = READ8(ea);
SUB8(dst, src);
CYCLES(CYCLES_CMP_REG_MEM);
}
}
void i386_device::i386_cmp_r8_rm8() // Opcode 0x3a
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_RM8(modrm);
dst = LOAD_REG8(modrm);
SUB8(dst, src);
CYCLES(CYCLES_CMP_REG_REG);
} else {
uint32_t ea = GetEA(modrm,0);
src = READ8(ea);
dst = LOAD_REG8(modrm);
SUB8(dst, src);
CYCLES(CYCLES_CMP_MEM_REG);
}
}
void i386_device::i386_cmp_al_i8() // Opcode 0x3c
{
uint8_t src, dst;
src = FETCH();
dst = REG8(AL);
SUB8(dst, src);
CYCLES(CYCLES_CMP_IMM_ACC);
}
void i386_device::i386_cmpsb() // Opcode 0xa6
{
uint32_t eas, ead;
uint8_t src, dst;
if( m_segment_prefix ) {
eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 );
} else {
eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 );
}
ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 );
src = READ8(eas);
dst = READ8(ead);
SUB8(src, dst);
BUMP_SI(1);
BUMP_DI(1);
CYCLES(CYCLES_CMPS);
}
void i386_device::i386_in_al_i8() // Opcode 0xe4
{
uint16_t port = FETCH();
uint8_t data = READPORT8(port);
REG8(AL) = data;
CYCLES(CYCLES_IN_VAR);
}
void i386_device::i386_in_al_dx() // Opcode 0xec
{
uint16_t port = REG16(DX);
uint8_t data = READPORT8(port);
REG8(AL) = data;
CYCLES(CYCLES_IN);
}
void i386_device::i386_ja_rel8() // Opcode 0x77
{
int8_t disp = FETCH();
if( m_CF == 0 && m_ZF == 0 ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jbe_rel8() // Opcode 0x76
{
int8_t disp = FETCH();
if( m_CF != 0 || m_ZF != 0 ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jc_rel8() // Opcode 0x72
{
int8_t disp = FETCH();
if( m_CF != 0 ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jg_rel8() // Opcode 0x7f
{
int8_t disp = FETCH();
if( m_ZF == 0 && (m_SF == m_OF) ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jge_rel8() // Opcode 0x7d
{
int8_t disp = FETCH();
if(m_SF == m_OF) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jl_rel8() // Opcode 0x7c
{
int8_t disp = FETCH();
if( (m_SF != m_OF) ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jle_rel8() // Opcode 0x7e
{
int8_t disp = FETCH();
if( m_ZF != 0 || (m_SF != m_OF) ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jnc_rel8() // Opcode 0x73
{
int8_t disp = FETCH();
if( m_CF == 0 ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jno_rel8() // Opcode 0x71
{
int8_t disp = FETCH();
if( m_OF == 0 ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jnp_rel8() // Opcode 0x7b
{
int8_t disp = FETCH();
if( m_PF == 0 ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jns_rel8() // Opcode 0x79
{
int8_t disp = FETCH();
if( m_SF == 0 ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jnz_rel8() // Opcode 0x75
{
int8_t disp = FETCH();
if( m_ZF == 0 ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jo_rel8() // Opcode 0x70
{
int8_t disp = FETCH();
if( m_OF != 0 ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jp_rel8() // Opcode 0x7a
{
int8_t disp = FETCH();
if( m_PF != 0 ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_js_rel8() // Opcode 0x78
{
int8_t disp = FETCH();
if( m_SF != 0 ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jz_rel8() // Opcode 0x74
{
int8_t disp = FETCH();
if( m_ZF != 0 ) {
NEAR_BRANCH(disp);
CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
} else {
CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
}
}
void i386_device::i386_jmp_rel8() // Opcode 0xeb
{
int8_t disp = FETCH();
NEAR_BRANCH(disp);
CYCLES(CYCLES_JMP_SHORT); /* TODO: Timing = 7 + m */
}
void i386_device::i386_lahf() // Opcode 0x9f
{
REG8(AH) = get_flags() & 0xd7;
CYCLES(CYCLES_LAHF);
}
void i386_device::i386_lodsb() // Opcode 0xac
{
uint32_t eas;
if( m_segment_prefix ) {
eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 );
} else {
eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 );
}
REG8(AL) = READ8(eas);
BUMP_SI(1);
CYCLES(CYCLES_LODS);
}
void i386_device::i386_mov_rm8_r8() // Opcode 0x88
{
uint8_t src;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_REG8(modrm);
STORE_RM8(modrm, src);
CYCLES(CYCLES_MOV_REG_REG);
} else {
uint32_t ea = GetEA(modrm,1);
src = LOAD_REG8(modrm);
WRITE8(ea, src);
CYCLES(CYCLES_MOV_REG_MEM);
}
}
void i386_device::i386_mov_r8_rm8() // Opcode 0x8a
{
uint8_t src;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_RM8(modrm);
STORE_REG8(modrm, src);
CYCLES(CYCLES_MOV_REG_REG);
} else {
uint32_t ea = GetEA(modrm,0);
src = READ8(ea);
STORE_REG8(modrm, src);
CYCLES(CYCLES_MOV_MEM_REG);
}
}
void i386_device::i386_mov_rm8_i8() // Opcode 0xc6
{
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
uint8_t value = FETCH();
STORE_RM8(modrm, value);
CYCLES(CYCLES_MOV_IMM_REG);
} else {
uint32_t ea = GetEA(modrm,1);
uint8_t value = FETCH();
WRITE8(ea, value);
CYCLES(CYCLES_MOV_IMM_MEM);
}
}
void i386_device::i386_mov_r32_cr() // Opcode 0x0f 20
{
if(PROTECTED_MODE && m_CPL)
FAULT(FAULT_GP, 0);
uint8_t modrm = FETCH();
uint8_t cr = (modrm >> 3) & 0x7;
STORE_RM32(modrm, m_cr[cr]);
CYCLES(CYCLES_MOV_CR_REG);
}
void i386_device::i386_mov_r32_dr() // Opcode 0x0f 21
{
if(PROTECTED_MODE && m_CPL)
FAULT(FAULT_GP, 0);
uint8_t modrm = FETCH();
uint8_t dr = (modrm >> 3) & 0x7;
STORE_RM32(modrm, m_dr[dr]);
switch(dr)
{
case 0:
case 1:
case 2:
case 3:
CYCLES(CYCLES_MOV_REG_DR0_3);
break;
case 6:
case 7:
CYCLES(CYCLES_MOV_REG_DR6_7);
break;
}
}
void i386_device::i386_mov_cr_r32() // Opcode 0x0f 22
{
if(PROTECTED_MODE && m_CPL)
FAULT(FAULT_GP, 0);
uint8_t modrm = FETCH();
uint8_t cr = (modrm >> 3) & 0x7;
uint32_t data = LOAD_RM32(modrm);
switch(cr)
{
case 0:
data &= 0xfffeffff; // wp not supported on 386
CYCLES(CYCLES_MOV_REG_CR0);
if (PROTECTED_MODE != BIT(data, 0))
debugger_privilege_hook();
break;
case 2: CYCLES(CYCLES_MOV_REG_CR2); break;
case 3:
CYCLES(CYCLES_MOV_REG_CR3);
vtlb_flush_dynamic();
break;
case 4: CYCLES(1); break; // TODO
default:
logerror("i386: mov_cr_r32 CR%d!\n", cr);
return;
}
m_cr[cr] = data;
}
void i386_device::i386_mov_dr_r32() // Opcode 0x0f 23
{
if(PROTECTED_MODE && m_CPL)
FAULT(FAULT_GP, 0);
uint8_t modrm = FETCH();
uint8_t dr = (modrm >> 3) & 0x7;
uint32_t rm32 = LOAD_RM32(modrm);
switch(dr)
{
case 0:
case 1:
case 2:
case 3:
{
m_dr[dr] = rm32;
dri_changed();
CYCLES(CYCLES_MOV_DR0_3_REG);
break;
}
case 6: CYCLES(CYCLES_MOV_DR6_7_REG); m_dr[dr] = LOAD_RM32(modrm); break;
case 7:
{
dr7_changed(m_dr[7], rm32);
CYCLES(CYCLES_MOV_DR6_7_REG);
m_dr[dr] = rm32;
break;
}
default:
logerror("i386: mov_dr_r32 DR%d!\n", dr);
return;
}
}
void i386_device::i386_mov_al_m8() // Opcode 0xa0
{
uint32_t offset, ea;
if( m_address_size ) {
offset = FETCH32();
} else {
offset = FETCH16();
}
/* TODO: Not sure if this is correct... */
if( m_segment_prefix ) {
ea = i386_translate(m_segment_override, offset, 0 );
} else {
ea = i386_translate(DS, offset, 0 );
}
REG8(AL) = READ8(ea);
CYCLES(CYCLES_MOV_IMM_MEM);
}
void i386_device::i386_mov_m8_al() // Opcode 0xa2
{
uint32_t offset, ea;
if( m_address_size ) {
offset = FETCH32();
} else {
offset = FETCH16();
}
/* TODO: Not sure if this is correct... */
if( m_segment_prefix ) {
ea = i386_translate(m_segment_override, offset, 1 );
} else {
ea = i386_translate(DS, offset, 1 );
}
WRITE8(ea, REG8(AL) );
CYCLES(CYCLES_MOV_MEM_ACC);
}
void i386_device::i386_mov_rm16_sreg() // Opcode 0x8c
{
uint8_t modrm = FETCH();
int s = (modrm >> 3) & 0x7;
if( modrm >= 0xc0 ) {
if(m_operand_size)
STORE_RM32(modrm, m_sreg[s].selector);
else
STORE_RM16(modrm, m_sreg[s].selector);
CYCLES(CYCLES_MOV_SREG_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE16(ea, m_sreg[s].selector);
CYCLES(CYCLES_MOV_SREG_MEM);
}
}
void i386_device::i386_mov_sreg_rm16() // Opcode 0x8e
{
uint16_t selector;
uint8_t modrm = FETCH();
bool fault;
int s = (modrm >> 3) & 0x7;
if( modrm >= 0xc0 ) {
selector = LOAD_RM16(modrm);
CYCLES(CYCLES_MOV_REG_SREG);
} else {
uint32_t ea = GetEA(modrm,0);
selector = READ16(ea);
CYCLES(CYCLES_MOV_MEM_SREG);
}
i386_sreg_load(selector,s,&fault);
if((s == SS) && !fault)
{
if(m_IF != 0) // if external interrupts are enabled
{
m_IF = 0; // reset IF for the next instruction
m_delayed_interrupt_enable = 1;
}
}
}
void i386_device::i386_mov_al_i8() // Opcode 0xb0
{
REG8(AL) = FETCH();
CYCLES(CYCLES_MOV_IMM_REG);
}
void i386_device::i386_mov_cl_i8() // Opcode 0xb1
{
REG8(CL) = FETCH();
CYCLES(CYCLES_MOV_IMM_REG);
}
void i386_device::i386_mov_dl_i8() // Opcode 0xb2
{
REG8(DL) = FETCH();
CYCLES(CYCLES_MOV_IMM_REG);
}
void i386_device::i386_mov_bl_i8() // Opcode 0xb3
{
REG8(BL) = FETCH();
CYCLES(CYCLES_MOV_IMM_REG);
}
void i386_device::i386_mov_ah_i8() // Opcode 0xb4
{
REG8(AH) = FETCH();
CYCLES(CYCLES_MOV_IMM_REG);
}
void i386_device::i386_mov_ch_i8() // Opcode 0xb5
{
REG8(CH) = FETCH();
CYCLES(CYCLES_MOV_IMM_REG);
}
void i386_device::i386_mov_dh_i8() // Opcode 0xb6
{
REG8(DH) = FETCH();
CYCLES(CYCLES_MOV_IMM_REG);
}
void i386_device::i386_mov_bh_i8() // Opcode 0xb7
{
REG8(BH) = FETCH();
CYCLES(CYCLES_MOV_IMM_REG);
}
void i386_device::i386_movsb() // Opcode 0xa4
{
uint32_t eas, ead;
uint8_t v;
if( m_segment_prefix ) {
eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 );
} else {
eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 );
}
ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 );
v = READ8(eas);
WRITE8(ead, v);
BUMP_SI(1);
BUMP_DI(1);
CYCLES(CYCLES_MOVS);
}
void i386_device::i386_or_rm8_r8() // Opcode 0x08
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_REG8(modrm);
dst = LOAD_RM8(modrm);
dst = OR8(dst, src);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,1);
src = LOAD_REG8(modrm);
dst = READ8(ea);
dst = OR8(dst, src);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
}
void i386_device::i386_or_r8_rm8() // Opcode 0x0a
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_RM8(modrm);
dst = LOAD_REG8(modrm);
dst = OR8(dst, src);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,0);
src = READ8(ea);
dst = LOAD_REG8(modrm);
dst = OR8(dst, src);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_MEM_REG);
}
}
void i386_device::i386_or_al_i8() // Opcode 0x0c
{
uint8_t src, dst;
src = FETCH();
dst = REG8(AL);
dst = OR8(dst, src);
REG8(EAX) = dst;
CYCLES(CYCLES_ALU_IMM_ACC);
}
void i386_device::i386_out_al_i8() // Opcode 0xe6
{
uint16_t port = FETCH();
uint8_t data = REG8(AL);
WRITEPORT8(port, data);
CYCLES(CYCLES_OUT_VAR);
}
void i386_device::i386_out_al_dx() // Opcode 0xee
{
uint16_t port = REG16(DX);
uint8_t data = REG8(AL);
WRITEPORT8(port, data);
CYCLES(CYCLES_OUT);
}
void i386_device::i386_arpl() // Opcode 0x63
{
uint16_t src, dst;
uint8_t modrm = FETCH();
uint8_t flag = 0;
if(PROTECTED_MODE && !V8086_MODE)
{
if( modrm >= 0xc0 ) {
src = LOAD_REG16(modrm);
dst = LOAD_RM16(modrm);
if( (dst&0x3) < (src&0x3) ) {
dst = (dst&0xfffc) | (src&0x3);
flag = 1;
STORE_RM16(modrm, dst);
}
} else {
uint32_t ea = GetEA(modrm,1);
src = LOAD_REG16(modrm);
dst = READ16(ea);
if( (dst&0x3) < (src&0x3) ) {
dst = (dst&0xfffc) | (src&0x3);
flag = 1;
WRITE16(ea, dst);
}
}
SetZF(flag);
}
else
i386_trap(6, 0, 0); // invalid opcode in real mode or v8086 mode
}
void i386_device::i386_push_i8() // Opcode 0x6a
{
uint8_t value = FETCH();
PUSH8(value);
CYCLES(CYCLES_PUSH_IMM);
}
void i386_device::i386_ins_generic(int size)
{
uint32_t ead;
uint8_t vb;
uint16_t vw;
uint32_t vd;
ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 );
switch(size) {
case 1:
vb = READPORT8(REG16(DX));
WRITE8(ead, vb);
break;
case 2:
vw = READPORT16(REG16(DX));
WRITE16(ead, vw);
break;
case 4:
vd = READPORT32(REG16(DX));
WRITE32(ead, vd);
break;
}
if(m_address_size)
REG32(EDI) += ((m_DF) ? -1 : 1) * size;
else
REG16(DI) += ((m_DF) ? -1 : 1) * size;
CYCLES(CYCLES_INS); // TODO: Confirm this value
}
void i386_device::i386_insb() // Opcode 0x6c
{
i386_ins_generic(1);
}
void i386_device::i386_insw() // Opcode 0x6d
{
i386_ins_generic(2);
}
void i386_device::i386_insd() // Opcode 0x6d
{
i386_ins_generic(4);
}
void i386_device::i386_outs_generic(int size)
{
uint32_t eas;
uint8_t vb;
uint16_t vw;
uint32_t vd;
if( m_segment_prefix ) {
eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 );
} else {
eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 );
}
switch(size) {
case 1:
vb = READ8(eas);
WRITEPORT8(REG16(DX), vb);
break;
case 2:
vw = READ16(eas);
WRITEPORT16(REG16(DX), vw);
break;
case 4:
vd = READ32(eas);
WRITEPORT32(REG16(DX), vd);
break;
}
if(m_address_size)
REG32(ESI) += ((m_DF) ? -1 : 1) * size;
else
REG16(SI) += ((m_DF) ? -1 : 1) * size;
CYCLES(CYCLES_OUTS); // TODO: Confirm this value
}
void i386_device::i386_outsb() // Opcode 0x6e
{
i386_outs_generic(1);
}
void i386_device::i386_outsw() // Opcode 0x6f
{
i386_outs_generic(2);
}
void i386_device::i386_outsd() // Opcode 0x6f
{
i386_outs_generic(4);
}
void i386_device::i386_repeat(int invert_flag)
{
uint32_t repeated_eip = m_eip;
uint32_t repeated_pc = m_pc;
uint8_t opcode; // = FETCH();
// uint32_t eas, ead;
uint32_t count;
int32_t cycle_base = 0, cycle_adjustment = 0;
uint8_t prefix_flag=1;
uint8_t *flag = nullptr;
do {
repeated_eip = m_eip;
repeated_pc = m_pc;
opcode = FETCH();
switch(opcode) {
case 0x0f:
if (invert_flag == 0)
i386_decode_three_bytef3(); // sse f3 0f
else
i386_decode_three_bytef2(); // sse f2 0f
return;
case 0x26:
m_segment_override=ES;
m_segment_prefix=1;
break;
case 0x2e:
m_segment_override=CS;
m_segment_prefix=1;
break;
case 0x36:
m_segment_override=SS;
m_segment_prefix=1;
break;
case 0x3e:
m_segment_override=DS;
m_segment_prefix=1;
break;
case 0x64:
m_segment_override=FS;
m_segment_prefix=1;
break;
case 0x65:
m_segment_override=GS;
m_segment_prefix=1;
break;
case 0x66:
m_operand_size ^= 1;
m_xmm_operand_size ^= 1;
break;
case 0x67:
m_address_size ^= 1;
break;
default:
prefix_flag=0;
}
} while (prefix_flag);
if( m_segment_prefix ) {
// FIXME: the following does not work if both address override and segment override are used
i386_translate(m_segment_override, m_sreg[m_segment_prefix].d ? REG32(ESI) : REG16(SI), -1 );
} else {
//eas =
i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), -1 );
}
i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), -1 );
switch(opcode)
{
case 0x6c:
case 0x6d:
/* INSB, INSW, INSD */
// TODO: cycle count
cycle_base = 8;
cycle_adjustment = -4;
flag = nullptr;
break;
case 0x6e:
case 0x6f:
/* OUTSB, OUTSW, OUTSD */
// TODO: cycle count
cycle_base = 8;
cycle_adjustment = -4;
flag = nullptr;
break;
case 0xa4:
case 0xa5:
/* MOVSB, MOVSW, MOVSD */
cycle_base = 8;
cycle_adjustment = -4;
flag = nullptr;
break;
case 0xa6:
case 0xa7:
/* CMPSB, CMPSW, CMPSD */
cycle_base = 5;
cycle_adjustment = -1;
flag = &m_ZF;
break;
case 0xac:
case 0xad:
/* LODSB, LODSW, LODSD */
cycle_base = 5;
cycle_adjustment = 1;
flag = nullptr;
break;
case 0xaa:
case 0xab:
/* STOSB, STOSW, STOSD */
cycle_base = 5;
cycle_adjustment = 0;
flag = nullptr;
break;
case 0xae:
case 0xaf:
/* SCASB, SCASW, SCASD */
cycle_base = 5;
cycle_adjustment = 0;
flag = &m_ZF;
break;
case 0x90:
CYCLES(CYCLES_NOP);
return;
case 0xc2: // sigh
case 0xc3:
m_pc--;
return;
default:
logerror("i386: Invalid REP/opcode %02X combination at %08x\n",opcode, m_pc - 2);
m_pc--;
return;
}
if( m_address_size ) {
if( REG32(ECX) == 0 )
return;
} else {
if( REG16(CX) == 0 )
return;
}
/* now actually perform the repeat */
CYCLES_NUM(cycle_base);
do
{
m_eip = repeated_eip;
m_pc = repeated_pc;
try
{
i386_decode_opcode();
}
catch (uint64_t e)
{
m_eip = m_prev_eip;
throw e;
}
CYCLES_NUM(cycle_adjustment);
if (m_address_size)
count = --REG32(ECX);
else
count = --REG16(CX);
if (m_cycles <= 0)
goto outofcycles;
}
while( count && (!flag || (invert_flag ? !*flag : *flag)) );
return;
outofcycles:
/* if we run out of cycles to execute, and we are still in the repeat, we need
* to exit this instruction in such a way to go right back into it when we have
* time to execute cycles */
if(flag && (invert_flag ? *flag : !*flag))
return;
m_eip = m_prev_eip;
CHANGE_PC(m_eip);
CYCLES_NUM(-cycle_base);
}
void i386_device::i386_rep() // Opcode 0xf3
{
i386_repeat(0);
}
void i386_device::i386_repne() // Opcode 0xf2
{
i386_repeat(1);
}
void i386_device::i386_sahf() // Opcode 0x9e
{
set_flags((get_flags() & 0xffffff00) | (REG8(AH) & 0xd7) );
CYCLES(CYCLES_SAHF);
}
void i386_device::i386_sbb_rm8_r8() // Opcode 0x18
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_REG8(modrm);
dst = LOAD_RM8(modrm);
dst = SBB8(dst, src, m_CF);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,1);
src = LOAD_REG8(modrm);
dst = READ8(ea);
dst = SBB8(dst, src, m_CF);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
}
void i386_device::i386_sbb_r8_rm8() // Opcode 0x1a
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_RM8(modrm);
dst = LOAD_REG8(modrm);
dst = SBB8(dst, src, m_CF);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,0);
src = READ8(ea);
dst = LOAD_REG8(modrm);
dst = SBB8(dst, src, m_CF);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_MEM_REG);
}
}
void i386_device::i386_sbb_al_i8() // Opcode 0x1c
{
uint8_t src, dst;
src = FETCH();
dst = REG8(AL);
dst = SBB8(dst, src, m_CF);
REG8(EAX) = dst;
CYCLES(CYCLES_ALU_IMM_ACC);
}
void i386_device::i386_scasb() // Opcode 0xae
{
uint32_t eas;
uint8_t src, dst;
eas = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 );
src = READ8(eas);
dst = REG8(AL);
SUB8(dst, src);
BUMP_DI(1);
CYCLES(CYCLES_SCAS);
}
void i386_device::i386_setalc() // Opcode 0xd6 (undocumented)
{
if( m_CF ) {
REG8(AL) = 0xff;
} else {
REG8(AL) = 0;
}
CYCLES(3);
}
void i386_device::i386_seta_rm8() // Opcode 0x0f 97
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_CF == 0 && m_ZF == 0 ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_setbe_rm8() // Opcode 0x0f 96
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_CF != 0 || m_ZF != 0 ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_setc_rm8() // Opcode 0x0f 92
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_CF != 0 ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_setg_rm8() // Opcode 0x0f 9f
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_ZF == 0 && (m_SF == m_OF) ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_setge_rm8() // Opcode 0x0f 9d
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if(m_SF == m_OF) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_setl_rm8() // Opcode 0x0f 9c
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_SF != m_OF ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_setle_rm8() // Opcode 0x0f 9e
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_ZF != 0 || (m_SF != m_OF) ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_setnc_rm8() // Opcode 0x0f 93
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_CF == 0 ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_setno_rm8() // Opcode 0x0f 91
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_OF == 0 ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_setnp_rm8() // Opcode 0x0f 9b
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_PF == 0 ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_setns_rm8() // Opcode 0x0f 99
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_SF == 0 ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_setnz_rm8() // Opcode 0x0f 95
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_ZF == 0 ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_seto_rm8() // Opcode 0x0f 90
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_OF != 0 ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_setp_rm8() // Opcode 0x0f 9a
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_PF != 0 ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_sets_rm8() // Opcode 0x0f 98
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_SF != 0 ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_setz_rm8() // Opcode 0x0f 94
{
uint8_t modrm = FETCH();
uint8_t value = 0;
if( m_ZF != 0 ) {
value = 1;
}
if( modrm >= 0xc0 ) {
STORE_RM8(modrm, value);
CYCLES(CYCLES_SETCC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
WRITE8(ea, value);
CYCLES(CYCLES_SETCC_MEM);
}
}
void i386_device::i386_stc() // Opcode 0xf9
{
m_CF = 1;
CYCLES(CYCLES_STC);
}
void i386_device::i386_std() // Opcode 0xfd
{
m_DF = 1;
CYCLES(CYCLES_STD);
}
void i386_device::i386_sti() // Opcode 0xfb
{
if(PROTECTED_MODE)
{
uint8_t IOPL = m_IOP1 | (m_IOP2 << 1);
if(m_CPL > IOPL)
FAULT(FAULT_GP,0);
}
m_delayed_interrupt_enable = 1; // IF is set after the next instruction.
CYCLES(CYCLES_STI);
}
void i386_device::i386_stosb() // Opcode 0xaa
{
uint32_t ead;
ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 );
WRITE8(ead, REG8(AL));
BUMP_DI(1);
CYCLES(CYCLES_STOS);
}
void i386_device::i386_sub_rm8_r8() // Opcode 0x28
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_REG8(modrm);
dst = LOAD_RM8(modrm);
dst = SUB8(dst, src);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,1);
src = LOAD_REG8(modrm);
dst = READ8(ea);
dst = SUB8(dst, src);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
}
void i386_device::i386_sub_r8_rm8() // Opcode 0x2a
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_RM8(modrm);
dst = LOAD_REG8(modrm);
dst = SUB8(dst, src);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,0);
src = READ8(ea);
dst = LOAD_REG8(modrm);
dst = SUB8(dst, src);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_MEM_REG);
}
}
void i386_device::i386_sub_al_i8() // Opcode 0x2c
{
uint8_t src, dst;
src = FETCH();
dst = REG8(EAX);
dst = SUB8(dst, src);
REG8(EAX) = dst;
CYCLES(CYCLES_ALU_IMM_ACC);
}
void i386_device::i386_test_al_i8() // Opcode 0xa8
{
uint8_t src = FETCH();
uint8_t dst = REG8(AL);
dst = src & dst;
SetSZPF8(dst);
m_CF = 0;
m_OF = 0;
CYCLES(CYCLES_ALU_IMM_ACC);
}
void i386_device::i386_test_rm8_r8() // Opcode 0x84
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_REG8(modrm);
dst = LOAD_RM8(modrm);
dst = src & dst;
SetSZPF8(dst);
m_CF = 0;
m_OF = 0;
CYCLES(CYCLES_TEST_REG_REG);
} else {
uint32_t ea = GetEA(modrm,0);
src = LOAD_REG8(modrm);
dst = READ8(ea);
dst = src & dst;
SetSZPF8(dst);
m_CF = 0;
m_OF = 0;
CYCLES(CYCLES_TEST_REG_MEM);
}
}
void i386_device::i386_xchg_r8_rm8() // Opcode 0x86
{
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
uint8_t src = LOAD_RM8(modrm);
uint8_t dst = LOAD_REG8(modrm);
STORE_REG8(modrm, src);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_XCHG_REG_REG);
} else {
uint32_t ea = GetEA(modrm,1);
uint8_t src = READ8(ea);
uint8_t dst = LOAD_REG8(modrm);
WRITE8(ea, dst);
STORE_REG8(modrm, src);
CYCLES(CYCLES_XCHG_REG_MEM);
}
}
void i386_device::i386_xor_rm8_r8() // Opcode 0x30
{
uint8_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_REG8(modrm);
dst = LOAD_RM8(modrm);
dst = XOR8(dst, src);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,1);
src = LOAD_REG8(modrm);
dst = READ8(ea);
dst = XOR8(dst, src);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
}
void i386_device::i386_xor_r8_rm8() // Opcode 0x32
{
uint32_t src, dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
src = LOAD_RM8(modrm);
dst = LOAD_REG8(modrm);
dst = XOR8(dst, src);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
uint32_t ea = GetEA(modrm,0);
src = READ8(ea);
dst = LOAD_REG8(modrm);
dst = XOR8(dst, src);
STORE_REG8(modrm, dst);
CYCLES(CYCLES_ALU_MEM_REG);
}
}
void i386_device::i386_xor_al_i8() // Opcode 0x34
{
uint8_t src, dst;
src = FETCH();
dst = REG8(AL);
dst = XOR8(dst, src);
REG8(AL) = dst;
CYCLES(CYCLES_ALU_IMM_ACC);
}
void i386_device::i386_group80_8() // Opcode 0x80
{
uint32_t ea;
uint8_t src, dst;
uint8_t modrm = FETCH();
switch( (modrm >> 3) & 0x7 )
{
case 0: // ADD Rm8, i8
if( modrm >= 0xc0 ) {
dst = LOAD_RM8(modrm);
src = FETCH();
dst = ADD8(dst, src);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
ea = GetEA(modrm,0);
dst = READ8(ea);
src = FETCH();
dst = ADD8(dst, src);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
break;
case 1: // OR Rm8, i8
if( modrm >= 0xc0 ) {
dst = LOAD_RM8(modrm);
src = FETCH();
dst = OR8(dst, src);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
ea = GetEA(modrm,1);
dst = READ8(ea);
src = FETCH();
dst = OR8(dst, src);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
break;
case 2: // ADC Rm8, i8
if( modrm >= 0xc0 ) {
dst = LOAD_RM8(modrm);
src = FETCH();
dst = ADC8(dst, src, m_CF);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
ea = GetEA(modrm,1);
dst = READ8(ea);
src = FETCH();
dst = ADC8(dst, src, m_CF);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
break;
case 3: // SBB Rm8, i8
if( modrm >= 0xc0 ) {
dst = LOAD_RM8(modrm);
src = FETCH();
dst = SBB8(dst, src, m_CF);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
ea = GetEA(modrm,1);
dst = READ8(ea);
src = FETCH();
dst = SBB8(dst, src, m_CF);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
break;
case 4: // AND Rm8, i8
if( modrm >= 0xc0 ) {
dst = LOAD_RM8(modrm);
src = FETCH();
dst = AND8(dst, src);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
ea = GetEA(modrm,1);
dst = READ8(ea);
src = FETCH();
dst = AND8(dst, src);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
break;
case 5: // SUB Rm8, i8
if( modrm >= 0xc0 ) {
dst = LOAD_RM8(modrm);
src = FETCH();
dst = SUB8(dst, src);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
ea = GetEA(modrm,1);
dst = READ8(ea);
src = FETCH();
dst = SUB8(dst, src);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
break;
case 6: // XOR Rm8, i8
if( modrm >= 0xc0 ) {
dst = LOAD_RM8(modrm);
src = FETCH();
dst = XOR8(dst, src);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_ALU_REG_REG);
} else {
ea = GetEA(modrm,1);
dst = READ8(ea);
src = FETCH();
dst = XOR8(dst, src);
WRITE8(ea, dst);
CYCLES(CYCLES_ALU_REG_MEM);
}
break;
case 7: // CMP Rm8, i8
if( modrm >= 0xc0 ) {
dst = LOAD_RM8(modrm);
src = FETCH();
SUB8(dst, src);
CYCLES(CYCLES_CMP_REG_REG);
} else {
ea = GetEA(modrm,0);
dst = READ8(ea);
src = FETCH();
SUB8(dst, src);
CYCLES(CYCLES_CMP_REG_MEM);
}
break;
}
}
void i386_device::i386_groupC0_8() // Opcode 0xc0
{
uint8_t dst;
uint8_t modrm = FETCH();
uint8_t shift;
if( modrm >= 0xc0 ) {
dst = LOAD_RM8(modrm);
shift = FETCH() & 0x1f;
dst = i386_shift_rotate8(modrm, dst, shift);
STORE_RM8(modrm, dst);
} else {
uint32_t ea = GetEA(modrm,1);
dst = READ8(ea);
shift = FETCH() & 0x1f;
dst = i386_shift_rotate8(modrm, dst, shift);
WRITE8(ea, dst);
}
}
void i386_device::i386_groupD0_8() // Opcode 0xd0
{
uint8_t dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
dst = LOAD_RM8(modrm);
dst = i386_shift_rotate8(modrm, dst, 1);
STORE_RM8(modrm, dst);
} else {
uint32_t ea = GetEA(modrm,1);
dst = READ8(ea);
dst = i386_shift_rotate8(modrm, dst, 1);
WRITE8(ea, dst);
}
}
void i386_device::i386_groupD2_8() // Opcode 0xd2
{
uint8_t dst;
uint8_t modrm = FETCH();
if( modrm >= 0xc0 ) {
dst = LOAD_RM8(modrm);
dst = i386_shift_rotate8(modrm, dst, REG8(CL));
STORE_RM8(modrm, dst);
} else {
uint32_t ea = GetEA(modrm,1);
dst = READ8(ea);
dst = i386_shift_rotate8(modrm, dst, REG8(CL));
WRITE8(ea, dst);
}
}
void i386_device::i386_groupF6_8() // Opcode 0xf6
{
uint8_t modrm = FETCH();
switch( (modrm >> 3) & 0x7 )
{
case 0: /* TEST Rm8, i8 */
if( modrm >= 0xc0 ) {
uint8_t dst = LOAD_RM8(modrm);
uint8_t src = FETCH();
dst &= src;
m_CF = m_OF = m_AF = 0;
SetSZPF8(dst);
CYCLES(CYCLES_TEST_IMM_REG);
} else {
uint32_t ea = GetEA(modrm,0);
uint8_t dst = READ8(ea);
uint8_t src = FETCH();
dst &= src;
m_CF = m_OF = m_AF = 0;
SetSZPF8(dst);
CYCLES(CYCLES_TEST_IMM_MEM);
}
break;
case 2: /* NOT Rm8 */
if( modrm >= 0xc0 ) {
uint8_t dst = LOAD_RM8(modrm);
dst = ~dst;
STORE_RM8(modrm, dst);
CYCLES(CYCLES_NOT_REG);
} else {
uint32_t ea = GetEA(modrm,1);
uint8_t dst = READ8(ea);
dst = ~dst;
WRITE8(ea, dst);
CYCLES(CYCLES_NOT_MEM);
}
break;
case 3: /* NEG Rm8 */
if( modrm >= 0xc0 ) {
uint8_t dst = LOAD_RM8(modrm);
dst = SUB8(0, dst );
STORE_RM8(modrm, dst);
CYCLES(CYCLES_NEG_REG);
} else {
uint32_t ea = GetEA(modrm,1);
uint8_t dst = READ8(ea);
dst = SUB8(0, dst );
WRITE8(ea, dst);
CYCLES(CYCLES_NEG_MEM);
}
break;
case 4: /* MUL AL, Rm8 */
{
uint16_t result;
uint8_t src, dst;
if( modrm >= 0xc0 ) {
src = LOAD_RM8(modrm);
CYCLES(CYCLES_MUL8_ACC_REG); /* TODO: Correct multiply timing */
} else {
uint32_t ea = GetEA(modrm,0);
src = READ8(ea);
CYCLES(CYCLES_MUL8_ACC_MEM); /* TODO: Correct multiply timing */
}
dst = REG8(AL);
result = (uint16_t)src * (uint16_t)dst;
REG16(AX) = (uint16_t)result;
m_CF = m_OF = (REG16(AX) > 0xff);
}
break;
case 5: /* IMUL AL, Rm8 */
{
int16_t result;
int16_t src, dst;
if( modrm >= 0xc0 ) {
src = (int16_t)(int8_t)LOAD_RM8(modrm);
CYCLES(CYCLES_IMUL8_ACC_REG); /* TODO: Correct multiply timing */
} else {
uint32_t ea = GetEA(modrm,0);
src = (int16_t)(int8_t)READ8(ea);
CYCLES(CYCLES_IMUL8_ACC_MEM); /* TODO: Correct multiply timing */
}
dst = (int16_t)(int8_t)REG8(AL);
result = src * dst;
REG16(AX) = (uint16_t)result;
m_CF = m_OF = !(result == (int16_t)(int8_t)result);
}
break;
case 6: /* DIV AL, Rm8 */
{
uint16_t quotient, remainder, result;
uint8_t src;
if( modrm >= 0xc0 ) {
src = LOAD_RM8(modrm);
CYCLES(CYCLES_DIV8_ACC_REG);
} else {
uint32_t ea = GetEA(modrm,0);
src = READ8(ea);
CYCLES(CYCLES_DIV8_ACC_MEM);
}
quotient = (uint16_t)REG16(AX);
if( src ) {
remainder = quotient % (uint16_t)src;
result = quotient / (uint16_t)src;
if( result > 0xff ) {
/* TODO: Divide error */
} else {
REG8(AH) = (uint8_t)remainder & 0xff;
REG8(AL) = (uint8_t)result & 0xff;
// this flag is actually undefined, enable on non-cyrix
if (m_cpuid_id0 != 0x69727943)
m_CF = 1;
}
} else {
i386_trap(0, 0, 0);
}
}
break;
case 7: /* IDIV AL, Rm8 */
{
int16_t quotient, remainder, result;
uint8_t src;
if( modrm >= 0xc0 ) {
src = LOAD_RM8(modrm);
CYCLES(CYCLES_IDIV8_ACC_REG);
} else {
uint32_t ea = GetEA(modrm,0);
src = READ8(ea);
CYCLES(CYCLES_IDIV8_ACC_MEM);
}
quotient = (int16_t)REG16(AX);
if( src ) {
remainder = quotient % (int16_t)(int8_t)src;
result = quotient / (int16_t)(int8_t)src;
if( result > 0xff ) {
/* TODO: Divide error */
} else {
REG8(AH) = (uint8_t)remainder & 0xff;
REG8(AL) = (uint8_t)result & 0xff;
// this flag is actually undefined, enable on non-cyrix
if (m_cpuid_id0 != 0x69727943)
m_CF = 1;
}
} else {
i386_trap(0, 0, 0);
}
}
break;
}
}
void i386_device::i386_groupFE_8() // Opcode 0xfe
{
uint8_t modrm = FETCH();
switch( (modrm >> 3) & 0x7 )
{
case 0: /* INC Rm8 */
if( modrm >= 0xc0 ) {
uint8_t dst = LOAD_RM8(modrm);
dst = INC8(dst);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_INC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
uint8_t dst = READ8(ea);
dst = INC8(dst);
WRITE8(ea, dst);
CYCLES(CYCLES_INC_MEM);
}
break;
case 1: /* DEC Rm8 */
if( modrm >= 0xc0 ) {
uint8_t dst = LOAD_RM8(modrm);
dst = DEC8(dst);
STORE_RM8(modrm, dst);
CYCLES(CYCLES_DEC_REG);
} else {
uint32_t ea = GetEA(modrm,1);
uint8_t dst = READ8(ea);
dst = DEC8(dst);
WRITE8(ea, dst);
CYCLES(CYCLES_DEC_MEM);
}
break;
case 6: /* PUSH Rm8*/
{
uint8_t value;
if( modrm >= 0xc0 ) {
value = LOAD_RM8(modrm);
} else {
uint32_t ea = GetEA(modrm,0);
value = READ8(ea);
}
if( m_operand_size ) {
PUSH32(value);
} else {
PUSH16(value);
}
CYCLES(CYCLES_PUSH_RM);
}
break;
default:
report_invalid_modrm("groupFE_8", modrm);
break;
}
}
void i386_device::i386_segment_CS() // Opcode 0x2e
{
m_segment_prefix = 1;
m_segment_override = CS;
i386_decode_opcode();
}
void i386_device::i386_segment_DS() // Opcode 0x3e
{
m_segment_prefix = 1;
m_segment_override = DS;
CYCLES(0); // TODO: Specify cycle count
i386_decode_opcode();
}
void i386_device::i386_segment_ES() // Opcode 0x26
{
m_segment_prefix = 1;
m_segment_override = ES;
CYCLES(0); // TODO: Specify cycle count
i386_decode_opcode();
}
void i386_device::i386_segment_FS() // Opcode 0x64
{
m_segment_prefix = 1;
m_segment_override = FS;
CYCLES(1); // TODO: Specify cycle count
i386_decode_opcode();
}
void i386_device::i386_segment_GS() // Opcode 0x65
{
m_segment_prefix = 1;
m_segment_override = GS;
CYCLES(1); // TODO: Specify cycle count
i386_decode_opcode();
}
void i386_device::i386_segment_SS() // Opcode 0x36
{
m_segment_prefix = 1;
m_segment_override = SS;
CYCLES(0); // TODO: Specify cycle count
i386_decode_opcode();
}
void i386_device::i386_operand_size() // Opcode prefix 0x66
{
if(m_operand_prefix == 0)
{
m_operand_size ^= 1;
m_xmm_operand_size ^= 1;
m_operand_prefix = 1;
}
m_opcode = FETCH();
if (m_opcode == 0x0f)
i386_decode_three_byte66();
else
{
if( m_operand_size )
(this->*m_opcode_table1_32[m_opcode])();
else
(this->*m_opcode_table1_16[m_opcode])();
}
}
void i386_device::i386_address_size() // Opcode 0x67
{
if(m_address_prefix == 0)
{
m_address_size ^= 1;
m_address_prefix = 1;
}
i386_decode_opcode();
}
void i386_device::i386_nop() // Opcode 0x90
{
CYCLES(CYCLES_NOP);
}
void i386_device::i386_int3() // Opcode 0xcc
{
CYCLES(CYCLES_INT3);
m_ext = 0; // not an external interrupt
i386_trap(3, 1, 0);
m_ext = 1;
}
void i386_device::i386_int() // Opcode 0xcd
{
int interrupt = FETCH();
CYCLES(CYCLES_INT);
m_ext = 0; // not an external interrupt
i386_trap(interrupt, 1, 0);
m_ext = 1;
}
void i386_device::i386_into() // Opcode 0xce
{
if( m_OF ) {
m_ext = 0;
i386_trap(4, 1, 0);
m_ext = 1;
CYCLES(CYCLES_INTO_OF1);
}
else
{
CYCLES(CYCLES_INTO_OF0);
}
}
static uint32_t i386_escape_ea; // hack around GCC 4.6 error because we need the side effects of GetEA()
void i386_device::i386_escape() // Opcodes 0xd8 - 0xdf
{
uint8_t modrm = FETCH();
if(modrm < 0xc0)
{
i386_escape_ea = GetEA(modrm,0);
}
CYCLES(3); // TODO: confirm this
(void) LOAD_RM8(modrm);
}
void i386_device::i386_hlt() // Opcode 0xf4
{
if(PROTECTED_MODE && m_CPL != 0)
FAULT(FAULT_GP,0);
m_halted = 1;
CYCLES(CYCLES_HLT);
if (m_cycles > 0)
m_cycles = 0;
}
void i386_device::i386_decimal_adjust(int direction)
{
uint8_t tmpAL = REG8(AL);
uint8_t tmpCF = m_CF;
if (m_AF || ((REG8(AL) & 0xf) > 9))
{
uint16_t t= (uint16_t)REG8(AL) + (direction * 0x06);
REG8(AL) = (uint8_t)t&0xff;
m_AF = 1;
if (t & 0x100)
m_CF = 1;
if (direction > 0)
tmpAL = REG8(AL);
}
if (tmpCF || (tmpAL > 0x99))
{
REG8(AL) += (direction * 0x60);
m_CF = 1;
}
SetSZPF8(REG8(AL));
}
void i386_device::i386_daa() // Opcode 0x27
{
i386_decimal_adjust(+1);
CYCLES(CYCLES_DAA);
}
void i386_device::i386_das() // Opcode 0x2f
{
i386_decimal_adjust(-1);
CYCLES(CYCLES_DAS);
}
void i386_device::i386_aaa() // Opcode 0x37
{
if( ( (REG8(AL) & 0x0f) > 9) || (m_AF != 0) ) {
REG16(AX) = REG16(AX) + 6;
REG8(AH) = REG8(AH) + 1;
m_AF = 1;
m_CF = 1;
} else {
m_AF = 0;
m_CF = 0;
}
REG8(AL) = REG8(AL) & 0x0f;
CYCLES(CYCLES_AAA);
}
void i386_device::i386_aas() // Opcode 0x3f
{
if (m_AF || ((REG8(AL) & 0xf) > 9))
{
REG16(AX) -= 6;
REG8(AH) -= 1;
m_AF = 1;
m_CF = 1;
}
else
{
m_AF = 0;
m_CF = 0;
}
REG8(AL) &= 0x0f;
CYCLES(CYCLES_AAS);
}
void i386_device::i386_aad() // Opcode 0xd5
{
uint8_t tempAL = REG8(AL);
uint8_t tempAH = REG8(AH);
uint8_t i = FETCH();
REG8(AL) = (tempAL + (tempAH * i)) & 0xff;
REG8(AH) = 0;
SetSZPF8( REG8(AL) );
CYCLES(CYCLES_AAD);
}
void i386_device::i386_aam() // Opcode 0xd4
{
uint8_t tempAL = REG8(AL);
uint8_t i = FETCH();
if(!i)
{
i386_trap(0, 0, 0);
return;
}
REG8(AH) = tempAL / i;
REG8(AL) = tempAL % i;
SetSZPF8( REG8(AL) );
CYCLES(CYCLES_AAM);
}
void i386_device::i386_clts() // Opcode 0x0f 0x06
{
// Privileged instruction, CPL must be zero. Can be used in real or v86 mode.
if(PROTECTED_MODE && m_CPL != 0)
FAULT(FAULT_GP,0)
m_cr[0] &= ~0x08; /* clear TS bit */
CYCLES(CYCLES_CLTS);
}
void i386_device::i386_wait() // Opcode 0x9B
{
// TODO
}
void i386_device::i386_lock() // Opcode 0xf0
{
// lock doesn't depend on iopl on 386
m_lock = true;
CYCLES(CYCLES_LOCK); // TODO: Determine correct cycle count
i386_decode_opcode();
}
void i386_device::i386_mov_r32_tr() // Opcode 0x0f 24
{
FETCH();
CYCLES(1); // TODO: correct cycle count
}
void i386_device::i386_mov_tr_r32() // Opcode 0x0f 26
{
FETCH();
CYCLES(1); // TODO: correct cycle count
}
void i386_device::i386_loadall() // Opcode 0x0f 0x07 (0x0f 0x05 on 80286), undocumented
{
if(PROTECTED_MODE && (m_CPL != 0))
FAULT(FAULT_GP,0)
uint32_t ea = i386_translate(ES, REG32(EDI), 0);
uint32_t old_dr7 = m_dr[7];
m_cr[0] = READ32(ea) & 0xfffeffff; // wp not supported on 386
set_flags(READ32(ea + 0x04));
m_eip = READ32(ea + 0x08);
REG32(EDI) = READ32(ea + 0x0c);
REG32(ESI) = READ32(ea + 0x10);
REG32(EBP) = READ32(ea + 0x14);
REG32(ESP) = READ32(ea + 0x18);
REG32(EBX) = READ32(ea + 0x1c);
REG32(EDX) = READ32(ea + 0x20);
REG32(ECX) = READ32(ea + 0x24);
REG32(EAX) = READ32(ea + 0x28);
m_dr[6] = READ32(ea + 0x2c);
m_dr[7] = READ32(ea + 0x30);
m_task.segment = READ16(ea + 0x34);
m_ldtr.segment = READ16(ea + 0x38);
m_sreg[GS].selector = READ16(ea + 0x3c);
m_sreg[FS].selector = READ16(ea + 0x40);
m_sreg[DS].selector = READ16(ea + 0x44);
m_sreg[SS].selector = READ16(ea + 0x48);
m_sreg[CS].selector = READ16(ea + 0x4c);
m_sreg[ES].selector = READ16(ea + 0x50);
m_task.flags = READ32(ea + 0x54) >> 8;
m_task.base = READ32(ea + 0x58);
m_task.limit = READ32(ea + 0x5c);
m_idtr.base = READ32(ea + 0x64);
m_idtr.limit = READ32(ea + 0x68);
m_gdtr.base = READ32(ea + 0x70);
m_gdtr.limit = READ32(ea + 0x74);
m_ldtr.flags = READ32(ea + 0x78) >> 8;
m_ldtr.base = READ32(ea + 0x7c);
m_ldtr.limit = READ32(ea + 0x80);
m_sreg[GS].flags = READ32(ea + 0x84) >> 8;
m_sreg[GS].base = READ32(ea + 0x88);
m_sreg[GS].limit = READ32(ea + 0x8c);
m_sreg[FS].flags = READ32(ea + 0x90) >> 8;
m_sreg[FS].base = READ32(ea + 0x94);
m_sreg[FS].limit = READ32(ea + 0x98);
m_sreg[DS].flags = READ32(ea + 0x9c) >> 8;
m_sreg[DS].base = READ32(ea + 0xa0);
m_sreg[DS].limit = READ32(ea + 0xa4);
m_sreg[SS].flags = READ32(ea + 0xa8) >> 8;
m_sreg[SS].base = READ32(ea + 0xac);
m_sreg[SS].limit = READ32(ea + 0xb0);
m_sreg[CS].flags = READ32(ea + 0xb4) >> 8;
m_sreg[CS].base = READ32(ea + 0xb8);
m_sreg[CS].limit = READ32(ea + 0xbc);
m_sreg[ES].flags = READ32(ea + 0xc0) >> 8;
m_sreg[ES].base = READ32(ea + 0xc4);
m_sreg[ES].limit = READ32(ea + 0xc8);
m_CPL = (m_sreg[SS].flags >> 5) & 3; // cpl == dpl of ss
for(int i = 0; i <= GS; i++)
{
m_sreg[i].valid = (m_sreg[i].flags & 0x80) ? true : false;
m_sreg[i].d = (m_sreg[i].flags & 0x4000) ? 1 : 0;
}
dr7_changed(old_dr7, m_dr[7]);
CHANGE_PC(m_eip);
}
void i386_device::i386_invalid()
{
report_invalid_opcode();
i386_trap(6, 0, 0);
}
void i386_device::i386_xlat() // Opcode 0xd7
{
uint32_t ea;
if( m_segment_prefix ) {
if(!m_address_size)
{
ea = i386_translate(m_segment_override, REG16(BX) + REG8(AL), 0 );
}
else
{
ea = i386_translate(m_segment_override, REG32(EBX) + REG8(AL), 0 );
}
} else {
if(!m_address_size)
{
ea = i386_translate(DS, REG16(BX) + REG8(AL), 0 );
}
else
{
ea = i386_translate(DS, REG32(EBX) + REG8(AL), 0 );
}
}
REG8(AL) = READ8(ea);
CYCLES(CYCLES_XLAT);
}