Files
miraclemage/cpu/i186.h
2018-05-21 08:48:53 +01:00

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;
}