4 #include "./i386_real.h"
6 #ifdef I386_PSEUDO_BIOS
7 #define BIOS_INT(num) if(cpustate->bios != NULL) { \
8 uint16_t regs[8], sregs[4]; \
9 regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
10 regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
11 sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
12 sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
13 int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \
14 if(cpustate->bios->bios_int_i86(num, regs, sregs, &ZeroFlag, &CarryFlag)) { \
15 REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
16 REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
17 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
21 #define BIOS_CALL(address) if(cpustate->bios != NULL) { \
22 uint16_t regs[8], sregs[4]; \
23 regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
24 regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
25 sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
26 sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
27 int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \
28 if(cpustate->bios->bios_call_i86(address, regs, sregs, &ZeroFlag, &CarryFlag)) { \
29 REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
30 REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
31 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
37 void I386_OPS::i386_call_abs16() // Opcode 0x9a
39 UINT16 offset = FETCH16();
40 UINT16 ptr = FETCH16();
41 #ifdef I386_PSEUDO_BIOS
42 BIOS_CALL(((ptr << 4) + offset) & cpustate->a20_mask)
46 if( PROTECTED_MODE && !V8086_MODE)
48 i386_protected_mode_call(ptr,offset,0,0);
52 PUSH16( cpustate->sreg[CS].selector );
53 PUSH16( cpustate->eip );
54 cpustate->sreg[CS].selector = ptr;
55 cpustate->performed_intersegment_jump = 1;
56 cpustate->eip = offset;
57 i386_load_segment_descriptor(CS);
59 CYCLES(CYCLES_CALL_INTERSEG); /* TODO: Timing = 17 + m */
60 CHANGE_PC(cpustate->eip);
63 void I386_OPS::i386_call_rel16() // Opcode 0xe8
65 INT16 disp = FETCH16();
67 #ifdef I386_PSEUDO_BIOS
68 BIOS_CALL((cpustate->pc + disp) & cpustate->a20_mask)
71 PUSH16( cpustate->eip );
72 if (cpustate->sreg[CS].d)
74 cpustate->eip += disp;
78 cpustate->eip = (cpustate->eip + disp) & 0xffff;
80 CHANGE_PC(cpustate->eip);
81 CYCLES(CYCLES_CALL); /* TODO: Timing = 7 + m */
84 void I386_OPS::i386_groupFF_16() // Opcode 0xff
86 UINT8 modrm = FETCH();
88 switch( (modrm >> 3) & 0x7 )
90 case 0: /* INC Rm16 */
92 UINT16 dst = LOAD_RM16(modrm);
94 STORE_RM16(modrm, dst);
95 CYCLES(CYCLES_INC_REG);
97 UINT32 ea = GetEA(modrm,1);
98 UINT16 dst = READ16(ea);
101 CYCLES(CYCLES_INC_MEM);
104 case 1: /* DEC Rm16 */
105 if( modrm >= 0xc0 ) {
106 UINT16 dst = LOAD_RM16(modrm);
108 STORE_RM16(modrm, dst);
109 CYCLES(CYCLES_DEC_REG);
111 UINT32 ea = GetEA(modrm,1);
112 UINT16 dst = READ16(ea);
115 CYCLES(CYCLES_DEC_MEM);
118 case 2: /* CALL Rm16 */
121 if( modrm >= 0xc0 ) {
122 address = LOAD_RM16(modrm);
123 CYCLES(CYCLES_CALL_REG); /* TODO: Timing = 7 + m */
125 UINT32 ea = GetEA(modrm,0);
126 address = READ16(ea);
127 CYCLES(CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */
129 #ifdef I386_PSEUDO_BIOS
130 BIOS_CALL(((cpustate->sreg[CS].selector << 4) + address) & cpustate->a20_mask)
132 PUSH16( cpustate->eip );
133 cpustate->eip = address;
134 CHANGE_PC(cpustate->eip);
137 case 3: /* CALL FAR Rm16 */
139 UINT16 address, selector;
142 report_invalid_modrm( "groupFF_16", modrm);
146 UINT32 ea = GetEA(modrm,0);
147 address = READ16(ea + 0);
148 selector = READ16(ea + 2);
149 CYCLES(CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */
150 #ifdef I386_PSEUDO_BIOS
151 BIOS_CALL(((selector << 4) + address) & cpustate->a20_mask)
153 if(PROTECTED_MODE && !V8086_MODE)
155 i386_protected_mode_call(selector,address,1,0);
159 PUSH16( cpustate->sreg[CS].selector );
160 PUSH16( cpustate->eip );
161 cpustate->sreg[CS].selector = selector;
162 cpustate->performed_intersegment_jump = 1;
163 i386_load_segment_descriptor( CS );
164 cpustate->eip = address;
165 CHANGE_PC(cpustate->eip);
170 case 4: /* JMP Rm16 */
173 if( modrm >= 0xc0 ) {
174 address = LOAD_RM16(modrm);
175 CYCLES(CYCLES_JMP_REG); /* TODO: Timing = 7 + m */
177 UINT32 ea = GetEA(modrm,0);
178 address = READ16(ea);
179 CYCLES(CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */
181 cpustate->eip = address;
182 CHANGE_PC(cpustate->eip);
185 case 5: /* JMP FAR Rm16 */
187 UINT16 address, selector;
191 report_invalid_modrm( "groupFF_16", modrm);
195 UINT32 ea = GetEA(modrm,0);
196 address = READ16(ea + 0);
197 selector = READ16(ea + 2);
198 CYCLES(CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */
199 if(PROTECTED_MODE && !V8086_MODE)
201 i386_protected_mode_jump(selector,address,1,0);
205 cpustate->sreg[CS].selector = selector;
206 cpustate->performed_intersegment_jump = 1;
207 i386_load_segment_descriptor( CS );
208 cpustate->eip = address;
209 CHANGE_PC(cpustate->eip);
214 case 6: /* PUSH Rm16 */
217 if( modrm >= 0xc0 ) {
218 value = LOAD_RM16(modrm);
220 UINT32 ea = GetEA(modrm,0);
224 CYCLES(CYCLES_PUSH_RM);
228 report_invalid_modrm( "groupFF_16", modrm);