412 lines
7.2 KiB
C
412 lines
7.2 KiB
C
/* i186 instruction implement */
|
|
|
|
static INLINE2 void i_pusha(void)
|
|
{
|
|
/* Opcode 0x60 */
|
|
|
|
unsigned tmp;
|
|
unsigned tmp2;
|
|
|
|
tmp = (WORD)ReadWord(&wregs[SP]);
|
|
PushWordReg(AX);
|
|
PushWordReg(CX);
|
|
PushWordReg(DX);
|
|
PushWordReg(BX);
|
|
tmp2 = (WORD)ReadWord(&wregs[SP]);
|
|
tmp2 -= 2;
|
|
WriteWord(&wregs[SP], (WORD)tmp2);
|
|
PutMemW(c_stack, (WORD)tmp2, (WORD)tmp);
|
|
PushWordReg(BP);
|
|
PushWordReg(SI);
|
|
PushWordReg(DI);
|
|
}
|
|
|
|
static INLINE2 void i_popa(void)
|
|
{
|
|
/* Opcode 0x61 */
|
|
|
|
unsigned tmp;
|
|
|
|
PopWordReg(DI);
|
|
PopWordReg(SI);
|
|
PopWordReg(BP);
|
|
tmp = (WORD)ReadWord(&wregs[SP]);
|
|
tmp += 2;
|
|
WriteWord(&wregs[SP], (WORD)tmp);
|
|
PopWordReg(BX);
|
|
PopWordReg(DX);
|
|
PopWordReg(CX);
|
|
PopWordReg(AX);
|
|
}
|
|
|
|
static INLINE2 void i_bound(void)
|
|
{
|
|
/* Opcode 0x62 */
|
|
|
|
unsigned ModRM = (unsigned)GetMemInc(c_cs, ip);
|
|
}
|
|
|
|
static INLINE2 void i_push_d16(void)
|
|
{
|
|
/* Opcode 0x68 */
|
|
unsigned tmp1;
|
|
unsigned tmp2;
|
|
|
|
tmp1 = GetMemInc(c_cs, ip);
|
|
tmp1 |= GetMemInc(c_cs, ip) << 8;
|
|
tmp2 = (WORD)ReadWord(&wregs[SP]);
|
|
tmp2 -= 2;
|
|
WriteWord(&wregs[SP], (WORD)tmp2);
|
|
PutMemW(c_stack, (WORD)tmp2, (WORD)tmp1);
|
|
}
|
|
|
|
static INLINE2 void i_imul_d16(void)
|
|
{
|
|
/* Opcode 0x69 */
|
|
INT32 result;
|
|
unsigned tmp1;
|
|
unsigned tmp2;
|
|
|
|
unsigned ModRM = GetMemInc(c_cs, ip);
|
|
WORD *dest = GetModRMRegW(ModRM);
|
|
tmp1 = *(GetModRMRMW(ModRM));
|
|
tmp2 = (unsigned)GetMemInc(c_cs, ip);
|
|
tmp2 |= (unsigned)GetMemInc(c_cs, ip) << 8;
|
|
|
|
result = (INT16)(tmp1) * (INT16)(tmp2);
|
|
|
|
WriteWord(dest, result);
|
|
*dest = (INT16)result;
|
|
|
|
CF = OF = (result >> 16) > 0;
|
|
}
|
|
|
|
static INLINE2 void i_push_d8(void)
|
|
{
|
|
/* Opcode 0x6a */
|
|
unsigned tmp1;
|
|
unsigned tmp2;
|
|
|
|
tmp1 = GetMemInc(c_cs, ip);
|
|
tmp2 = (WORD)ReadWord(&wregs[SP]);
|
|
tmp2 -= 2;
|
|
WriteWord(&wregs[SP], (WORD)tmp2);
|
|
PutMemW(c_stack, (WORD)tmp2, (WORD)tmp1);
|
|
}
|
|
|
|
static INLINE2 void i_imul_d8(void)
|
|
{
|
|
/* Opcode 0x6b */
|
|
INT32 result;
|
|
unsigned tmp1;
|
|
unsigned tmp2;
|
|
|
|
unsigned ModRM = GetMemInc(c_cs, ip);
|
|
WORD *dest = GetModRMRegW(ModRM);
|
|
tmp1 = *(GetModRMRMW(ModRM));
|
|
tmp2 = (unsigned)GetMemInc(c_cs, ip);
|
|
|
|
result = (INT16)(tmp1) * (INT16)(tmp2);
|
|
|
|
WriteWord(dest, result);
|
|
*dest = (INT16)result;
|
|
|
|
CF = OF = (result >> 16) > 0;
|
|
}
|
|
|
|
static INLINE2 void i_insb(void)
|
|
{
|
|
/* Opcode 0x6c */
|
|
;
|
|
}
|
|
|
|
static INLINE2 void i_insw(void)
|
|
{
|
|
/* Opcode 0x6d */
|
|
;
|
|
}
|
|
|
|
static INLINE2 void i_outsb(void)
|
|
{
|
|
/* Opcode 0x6e */
|
|
;
|
|
}
|
|
|
|
static INLINE2 void i_outsw(void)
|
|
{
|
|
/* Opcode 0x6f */
|
|
;
|
|
}
|
|
|
|
static INLINE2 void i_rotshft_bd8(void)
|
|
{
|
|
/* Opcode 0xc0 */
|
|
|
|
unsigned ModRM = GetMemInc(c_cs, ip);
|
|
BYTE *dest = GetModRMRMB(ModRM);
|
|
unsigned tmp = *dest;
|
|
unsigned tmp2;
|
|
unsigned count = GetMemInc(c_cs, ip);
|
|
|
|
switch(ModRM & 0x38) {
|
|
case 0x00: /* ROL r/m8, imm8 */
|
|
for(; count > 0; count--) {
|
|
CF = (tmp & 0x80) != 0;
|
|
tmp = (tmp << 1) + CF;
|
|
}
|
|
*dest = (BYTE)tmp;
|
|
break;
|
|
case 0x08: /* ROR r/m8, imm8 */
|
|
for(; count > 0; count--) {
|
|
CF = (tmp & 0x01) != 0;
|
|
tmp = (tmp >> 1) + (CF << 7);
|
|
}
|
|
*dest = (BYTE)tmp;
|
|
break;
|
|
case 0x10: /* RCL r/m8, imm8 */
|
|
for(; count > 0; count--) {
|
|
tmp2 = CF;
|
|
CF = (tmp & 0x80) != 0;
|
|
tmp = (tmp << 1) + tmp2;
|
|
}
|
|
*dest = (BYTE)tmp;
|
|
break;
|
|
case 0x18: /* RCR r/m8, imm8 */
|
|
for(; count > 0; count--) {
|
|
tmp2 = (tmp >> 1) + (CF << 7);
|
|
CF = (tmp & 0x01) != 0;
|
|
tmp = tmp2;
|
|
}
|
|
*dest = (BYTE)tmp;
|
|
break;
|
|
case 0x20: /* SHL r/m8, imm8 */
|
|
if(count >= 9) {
|
|
CF = 0;
|
|
tmp = 0;
|
|
} else {
|
|
CF = ((tmp << (count - 1)) & 0x80) != 0;
|
|
tmp <<= count;
|
|
}
|
|
|
|
AF = 1;
|
|
SetZFB(tmp);
|
|
SetSFB(tmp);
|
|
SetPF(tmp);
|
|
|
|
*dest = (BYTE)tmp;
|
|
break;
|
|
case 0x28: /* SHR r/m8, imm8 */
|
|
if(count >= 9) {
|
|
CF = 0;
|
|
tmp = 0;
|
|
} else {
|
|
CF = ((tmp >> (count - 1)) & 0x1) != 0;
|
|
tmp >>= count;
|
|
}
|
|
|
|
SetSFB(tmp);
|
|
SetPF(tmp);
|
|
SetZFB(tmp);
|
|
AF = 1;
|
|
*dest = (BYTE)tmp;
|
|
break;
|
|
case 0x38: /* SAR r/m8, imm8 */
|
|
tmp2 = tmp & 0x80;
|
|
CF = (((INT8)tmp >> (count - 1)) & 0x01) != 0;
|
|
for(; count > 0; count--)
|
|
tmp = (tmp >> 1) | tmp2;
|
|
|
|
SetSFB(tmp);
|
|
SetPF(tmp);
|
|
SetZFB(tmp);
|
|
AF = 1;
|
|
*dest = (BYTE)tmp;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static INLINE2 void i_rotshft_wd8(void)
|
|
{
|
|
/* Opcode 0xc1 */
|
|
unsigned ModRM = GetMemInc(c_cs, ip);
|
|
WORD *dest = GetModRMRMW(ModRM);
|
|
unsigned tmp = *dest;
|
|
unsigned tmp2;
|
|
unsigned count = GetMemInc(c_cs, ip);
|
|
|
|
switch(ModRM & 0x38) {
|
|
case 0x00: /* ROL r/m16, imm8 */
|
|
for(; count > 0; count--) {
|
|
CF = (tmp & 0x80) != 0;
|
|
tmp = (tmp << 1) + CF;
|
|
}
|
|
*dest = (WORD)tmp;
|
|
break;
|
|
case 0x08: /* ROR r/m16, imm8 */
|
|
for(; count > 0; count--) {
|
|
CF = (tmp & 0x01) != 0;
|
|
tmp = (tmp >> 1) + (CF << 7);
|
|
}
|
|
*dest = (WORD)tmp;
|
|
break;
|
|
case 0x10: /* RCL r/m16, imm8 */
|
|
for(; count > 0; count--) {
|
|
tmp2 = CF;
|
|
CF = (tmp & 0x80) != 0;
|
|
tmp = (tmp << 1) + tmp2;
|
|
}
|
|
*dest = (WORD)tmp;
|
|
break;
|
|
case 0x18: /* RCR r/m16, imm8 */
|
|
for(; count > 0; count--) {
|
|
tmp2 = (tmp >> 1) + (CF << 7);
|
|
CF = (tmp & 0x01) != 0;
|
|
tmp = tmp2;
|
|
}
|
|
*dest = (WORD)tmp;
|
|
break;
|
|
case 0x20: /* SHL r/m16, imm8 */
|
|
if(count >= 9) {
|
|
CF = 0;
|
|
tmp = 0;
|
|
} else {
|
|
CF = ((tmp << (count - 1)) & 0x80) != 0;
|
|
tmp <<= count;
|
|
}
|
|
|
|
AF = 1;
|
|
SetZFB(tmp);
|
|
SetSFB(tmp);
|
|
SetPF(tmp);
|
|
|
|
*dest = (WORD)tmp;
|
|
break;
|
|
case 0x28: /* SHR r/m16, imm8 */
|
|
if(count >= 9) {
|
|
CF = 0;
|
|
tmp = 0;
|
|
} else {
|
|
CF = ((tmp >> (count - 1)) & 0x1) != 0;
|
|
tmp >>= count;
|
|
}
|
|
|
|
SetSFB(tmp);
|
|
SetPF(tmp);
|
|
SetZFB(tmp);
|
|
AF = 1;
|
|
*dest = (WORD)tmp;
|
|
break;
|
|
case 0x38: /* SAR r/m16, imm8 */
|
|
tmp2 = tmp & 0x80;
|
|
CF = (((INT16)tmp >> (count - 1)) & 0x01) != 0;
|
|
for(; count > 0; count--)
|
|
tmp = (tmp >> 1) | tmp2;
|
|
|
|
SetSFB(tmp);
|
|
SetPF(tmp);
|
|
SetZFB(tmp);
|
|
AF = 1;
|
|
*dest = (WORD)tmp;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static INLINE2 void i_enter(void)
|
|
{
|
|
/* Opcode 0xc8 */
|
|
unsigned size;
|
|
unsigned level;
|
|
unsigned tmp;
|
|
unsigned tmp2;
|
|
unsigned i;
|
|
|
|
|
|
size = GetMemInc(c_cs, ip);
|
|
size |= GetMemInc(c_cs, ip) << 8;
|
|
level = GetMemInc(c_cs, ip);
|
|
/*
|
|
PushWordReg(BP);
|
|
tmp = ReadWord(&wregs[SP]);
|
|
WriteWord(&wregs[BP], (WORD)tmp);
|
|
WriteWord(&wregs[SP], (WORD)(tmp - size));
|
|
for(i = 1; i < level; i++) {
|
|
tmp = GetMemW(c_stack, ReadWord(&wregs[BP]) - i * 2);
|
|
tmp2 = (WORD)(ReadWord(&wregs[SP]) - 2);
|
|
WriteWord(&wregs[SP], tmp2);
|
|
PutMemW(c_stack, tmp2, tmp);
|
|
}
|
|
if(level) {
|
|
PushWordReg(BP);
|
|
}
|
|
*/
|
|
level %= 32;
|
|
PushWordReg(BP);
|
|
tmp = (WORD)ReadWord(&wregs[SP]);
|
|
|
|
if(level > 0) {
|
|
for(i = 1; i < level; i++) {
|
|
tmp2 = (WORD)ReadWord(&wregs[BP]);
|
|
tmp2 -= 2;
|
|
WriteWord(&wregs[BP], (WORD)tmp2);
|
|
PushWordReg(BP);
|
|
}
|
|
tmp2 = (WORD)ReadWord(&wregs[SP]);
|
|
tmp2 -= 2;
|
|
WriteWord(&wregs[SP], (WORD)tmp2);
|
|
PutMemW(c_stack, tmp2, (WORD)tmp);
|
|
}
|
|
|
|
WriteWord(&wregs[BP], (WORD)tmp);
|
|
WriteWord(&wregs[SP], (WORD)(tmp - size));
|
|
}
|
|
|
|
static INLINE2 void i_leave(void)
|
|
{
|
|
/* Opcode 0xc9 */
|
|
unsigned tmp;
|
|
|
|
tmp = ReadWord(&wregs[BP]);
|
|
WriteWord(&wregs[SP], (WORD)tmp);
|
|
PopWordReg(BP);
|
|
}
|
|
|
|
static INLINE void i_das(void)
|
|
{
|
|
/* Opcode 0x2f */
|
|
unsigned tmp;
|
|
|
|
if(((*bregs[AL] & 0x0f) > 9) || AF) {
|
|
tmp = *bregs[AL] - 6;
|
|
*bregs[AL] = tmp;
|
|
CF = CF | ((tmp & 0x100) ? 1 : 0);
|
|
AF = 0x10;
|
|
} else {
|
|
AF = 0;
|
|
}
|
|
if((*bregs[AL] > 0x9f) || CF) {
|
|
*bregs[AL] = *bregs[AL] - 0x60;
|
|
CF = 1;
|
|
}
|
|
}
|
|
|
|
static INLINE void i_aas(void)
|
|
{
|
|
/* Opcode 0x3f */
|
|
|
|
if(((*bregs[AL] & 0x0f) > 9) || AF) {
|
|
*bregs[AL] = (BYTE)(*bregs[AL] - 6);
|
|
*bregs[AH] = (BYTE)(*bregs[AH] - 1);
|
|
AF = 0x10;
|
|
CF = 1;
|
|
} else {
|
|
AF = 0;
|
|
CF = 0;
|
|
}
|
|
*bregs[AL] = *bregs[AL] & 0x0f;
|
|
}
|