36 #pragma GCC optimize ("O3") 38 #if FABGL_ESP_IDF_VERSION > FABGL_ESP_IDF_VERSION_VAL(3, 3, 5) 39 #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" 43 #define VIDEOMEM_START 0xA0000 44 #define VIDEOMEM_END 0xC0000 64 #define REG_SCRATCH 13 93 #define FLAG_CF (flags[CF_ADDR]) 94 #define FLAG_PF (flags[PF_ADDR]) 95 #define FLAG_AF (flags[AF_ADDR]) 96 #define FLAG_ZF (flags[ZF_ADDR]) 97 #define FLAG_SF (flags[SF_ADDR]) 98 #define FLAG_TF (flags[TF_ADDR]) 99 #define FLAG_IF (flags[IF_ADDR]) 100 #define FLAG_DF (flags[DF_ADDR]) 101 #define FLAG_OF (flags[OF_ADDR]) 106 static uint8_t regs[48];
107 static uint8_t flags[10];
108 static int32_t regs_offset;
109 static uint8_t * regs8, i_mod_size, i_d, i_w, raw_opcode_id, xlat_opcode_id, extra, rep_mode, seg_override_en, rep_override_en, trap_flag;
110 static uint16_t * regs16, reg_ip, seg_override;
111 static uint32_t op_source, op_dest, set_flags_type;
112 static int32_t op_to_addr, op_from_addr;
115 void * i8086::s_context;
116 i8086::ReadPort i8086::s_readPort;
117 i8086::WritePort i8086::s_writePort;
118 i8086::WriteVideoMemory8 i8086::s_writeVideoMemory8;
119 i8086::WriteVideoMemory16 i8086::s_writeVideoMemory16;
120 i8086::ReadVideoMemory8 i8086::s_readVideoMemory8;
121 i8086::ReadVideoMemory16 i8086::s_readVideoMemory16;
122 i8086::Interrupt i8086::s_interrupt;
124 uint8_t * i8086::s_memory;
125 bool i8086::s_pendingIRQ;
126 uint8_t i8086::s_pendingIRQIndex;
127 bool i8086::s_halted;
133 static uint8_t rm_mode12_reg1[] = { 3, 3, 5, 5, 6, 7, 5, 3 };
137 static uint8_t rm_mode012_reg2[] = { 6, 7, 6, 7, 12, 12, 12, 12 };
140 static uint8_t rm_mode12_disp[] = { 1, 1, 1, 1, 1, 1, 1, 1 };
143 static uint8_t rm_mode12_dfseg[] = { 11, 11, 10, 10, 11, 11, 10, 11 };
146 static uint8_t rm_mode0_reg1[] = { 3, 3, 5, 5, 6, 7, 12, 3 };
149 static uint8_t rm_mode0_disp[] = { 0, 0, 0, 0, 0, 0, 1, 0 };
152 static uint8_t rm_mode0_dfseg[] = { 11, 11, 10, 10, 11, 11, 11, 11 };
155 static uint8_t xlat_ids[] = { 9, 9, 9, 9, 7, 7, 25, 26, 9, 9, 9, 9, 7, 7, 25, 50,
156 9, 9, 9, 9, 7, 7, 25, 26, 9, 9, 9, 9, 7, 7, 25, 26,
157 9, 9, 9, 9, 7, 7, 27, 28, 9, 9, 9, 9, 7, 7, 27, 28,
158 9, 9, 9, 9, 7, 7, 27, 29, 9, 9, 9, 9, 7, 7, 27, 29,
159 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
160 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
161 53, 54, 55, 70, 71, 71, 72, 72, 56, 58, 57, 58, 59, 59, 60, 60,
162 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
163 8, 8, 8, 8, 15, 15, 24, 24, 9, 9, 9, 9, 10, 10, 10, 10,
164 16, 16, 16, 16, 16, 16, 16, 16, 30, 31, 32, 69, 33, 34, 35, 36,
165 11, 11, 11, 11, 17, 17, 18, 18, 47, 47, 17, 17, 17, 17, 18, 18,
166 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
167 12, 12, 19, 19, 37, 37, 20, 20, 51, 52, 19, 19, 38, 39, 40, 19,
168 12, 12, 12, 12, 41, 42, 43, 44, 69, 69, 69, 69, 69, 69, 69, 69,
169 13, 13, 13, 13, 21, 21, 22, 22, 14, 14, 14, 14, 21, 21, 22, 22,
170 48, 0, 23, 23, 49, 45, 6, 6, 46, 46, 46, 46, 46, 46, 5, 5 };
173 static uint8_t ex_data[] = { 0, 0, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 9, 36,
174 2, 2, 2, 2, 2, 2, 10, 10, 3, 3, 3, 3, 3, 3, 11, 11,
175 4, 4, 4, 4, 4, 4, 8, 0, 5, 5, 5, 5, 5, 5, 9, 1,
176 6, 6, 6, 6, 6, 6, 10, 2, 7, 7, 7, 7, 7, 7, 11, 0,
177 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
178 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
179 0, 0, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 21, 21, 21, 21,
180 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
181 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 12, 12, 12, 12,
182 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0,
183 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1,
184 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
185 1, 1, 0, 0, 16, 22, 0, 0, 0, 0, 1, 1, 0, 255, 48, 2,
186 0, 0, 0, 0, 255, 255, 40, 11, 3, 3, 3, 3, 3, 3, 3, 3,
187 43, 43, 43, 43, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
188 1, 21, 0, 0, 2, 40, 21, 21, 80, 81, 92, 93, 94, 95, 0, 0 };
191 static uint8_t std_flags[] = { 3, 3, 3, 3, 3, 3, 0, 0, 5, 5, 5, 5, 5, 5, 0, 0,
192 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0,
193 5, 5, 5, 5, 5, 5, 0, 1, 3, 3, 3, 3, 3, 3, 0, 1,
194 5, 5, 5, 5, 5, 5, 0, 1, 3, 3, 3, 3, 3, 3, 0, 1,
195 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
196 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
197 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
198 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
199 1, 1, 1, 1, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0,
202 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
203 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
204 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
205 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
206 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
209 static uint8_t parity[] = { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
210 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
211 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
212 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
213 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
214 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
215 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
216 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
217 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
218 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
219 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
220 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
221 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
222 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
223 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
224 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 };
227 static uint8_t base_size[] = { 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2,
228 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1,
229 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1,
230 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1,
231 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
232 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
233 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 1, 1, 1,
234 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
235 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
236 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
237 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
238 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
239 3, 3, 0, 0, 2, 2, 2, 2, 4, 1, 0, 0, 0, 0, 0, 0,
240 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
241 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1,
242 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2 };
245 static uint8_t i_w_adder[] = { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
246 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
247 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
248 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
249 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
250 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
251 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0,
252 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
253 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
254 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
255 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
256 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
257 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
258 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
259 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
260 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
263 static uint8_t i_mod_adder[] = { 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
264 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
265 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
266 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
267 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
268 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
269 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
270 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
271 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
272 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
273 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
274 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
275 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
276 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
277 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
278 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 };
281 static uint8_t jxx_dec_a[] = { OF_ADDR, CF_ADDR, ZF_ADDR, CF_ADDR, SF_ADDR, PF_ADDR, XX_ADDR, XX_ADDR };
284 static uint8_t jxx_dec_b[] = { XX_ADDR, XX_ADDR, XX_ADDR, ZF_ADDR, XX_ADDR, XX_ADDR, XX_ADDR, ZF_ADDR };
287 static uint8_t jxx_dec_c[] = { XX_ADDR, XX_ADDR, XX_ADDR,XX_ADDR, XX_ADDR, XX_ADDR, SF_ADDR, SF_ADDR };
290 static uint8_t jxx_dec_d[] = { XX_ADDR, XX_ADDR, XX_ADDR, XX_ADDR,XX_ADDR, XX_ADDR, OF_ADDR, OF_ADDR };
293 static uint8_t * instr_table_lookup[] = { rm_mode12_reg1,
313 void i8086::setAL(uint8_t value)
315 regs8[REG_AL] = value;
319 void i8086::setAH(uint8_t value)
321 regs8[REG_AH] = value;
327 return regs8[REG_AL];
333 return regs8[REG_AH];
337 void i8086::setBL(uint8_t value)
339 regs8[REG_BL] = value;
343 void i8086::setBH(uint8_t value)
345 regs8[REG_BH] = value;
351 return regs8[REG_BL];
357 return regs8[REG_BH];
361 void i8086::setCL(uint8_t value)
363 regs8[REG_CL] = value;
367 void i8086::setCH(uint8_t value)
369 regs8[REG_CH] = value;
375 return regs8[REG_CL];
381 return regs8[REG_CH];
385 void i8086::setDL(uint8_t value)
387 regs8[REG_DL] = value;
391 void i8086::setDH(uint8_t value)
393 regs8[REG_DH] = value;
399 return regs8[REG_DL];
405 return regs8[REG_DH];
409 void i8086::setAX(uint16_t value)
411 regs16[REG_AX] = value;
415 void i8086::setBX(uint16_t value)
417 regs16[REG_BX] = value;
421 void i8086::setCX(uint16_t value)
423 regs16[REG_CX] = value;
427 void i8086::setDX(uint16_t value)
429 regs16[REG_DX] = value;
433 void i8086::setDI(uint16_t value)
435 regs16[REG_DI] = value;
439 void i8086::setCS(uint16_t value)
441 regs16[REG_CS] = value;
445 void i8086::setDS(uint16_t value)
447 regs16[REG_DS] = value;
451 void i8086::setSS(uint16_t value)
453 regs16[REG_SS] = value;
457 void i8086::setES(uint16_t value)
459 regs16[REG_ES] = value;
463 void i8086::setIP(uint16_t value)
475 void i8086::setSP(uint16_t value)
477 regs16[REG_SP] = value;
483 return regs16[REG_AX];
489 return regs16[REG_BX];
495 return regs16[REG_CX];
501 return regs16[REG_DX];
507 return regs16[REG_BP];
513 return regs16[REG_SI];
519 return regs16[REG_DI];
525 return regs16[REG_SP];
531 return regs16[REG_CS];
537 return regs16[REG_ES];
543 return regs16[REG_DS];
549 return regs16[REG_SS];
601 void i8086::setFlagZF(
bool value)
607 void i8086::setFlagCF(
bool value)
616 bool i8086::IRQ(uint8_t interrupt_num)
620 s_pendingIRQIndex = interrupt_num;
633 #define MEM8(addr) s_memory[addr] 634 #define MEM16(addr) (*(uint16_t*)(s_memory + (addr))) 637 inline __attribute__((always_inline)) uint8_t i8086::RMEM8(
int addr)
639 if (addr >= VIDEOMEM_START && addr < VIDEOMEM_END) {
640 return s_readVideoMemory8(s_context, addr);
642 return s_memory[addr];
647 inline __attribute__((always_inline)) uint16_t i8086::RMEM16(
int addr)
649 if (addr >= VIDEOMEM_START && addr < VIDEOMEM_END) {
650 return s_readVideoMemory16(s_context, addr);
652 return *(uint16_t*)(s_memory + addr);
657 inline __attribute__((always_inline)) uint8_t i8086::WMEM8(
int addr, uint8_t value)
659 if (addr >= VIDEOMEM_START && addr < VIDEOMEM_END) {
660 s_writeVideoMemory8(s_context, addr, value);
662 s_memory[addr] = value;
668 inline __attribute__((always_inline)) uint16_t i8086::WMEM16(
int addr, uint16_t value)
670 if (addr >= VIDEOMEM_START && addr < VIDEOMEM_END) {
671 s_writeVideoMemory16(s_context, addr, value);
673 *(uint16_t*)(s_memory + addr) = value;
686 static int8_t set_CF(
int new_CF)
688 return FLAG_CF = !!new_CF;
693 static int8_t set_AF(
int new_AF)
695 return FLAG_AF = !!new_AF;
700 static int8_t set_OF(
int new_OF)
702 return FLAG_OF = !!new_OF;
707 int8_t set_AF_OF_arith(int32_t op_result, uint8_t i_w)
709 set_AF((op_source ^= op_dest ^ op_result) & 0x10);
710 if (op_result == op_dest)
713 return set_OF(1 & (FLAG_CF ^ op_source >> (8 * (i_w + 1) - 1)));
718 uint16_t i8086::make_flags()
726 return r | FLAG_CF << 0 | FLAG_PF << 2 | FLAG_AF << 4 | FLAG_ZF << 6 | FLAG_SF << 7 | FLAG_TF << 8 | FLAG_IF << 9 | FLAG_DF << 10 | FLAG_OF << 11;
730 void i8086::set_flags(
int new_flags)
732 FLAG_CF = (new_flags >> 0) & 1;
733 FLAG_PF = (new_flags >> 2) & 1;
734 FLAG_AF = (new_flags >> 4) & 1;
735 FLAG_ZF = (new_flags >> 6) & 1;
736 FLAG_SF = (new_flags >> 7) & 1;
737 FLAG_TF = (new_flags >> 8) & 1;
738 FLAG_IF = (new_flags >> 9) & 1;
739 FLAG_DF = (new_flags >> 10) & 1;
740 FLAG_OF = (new_flags >> 11) & 1;
746 void i8086::set_opcode(uint8_t opcode)
748 raw_opcode_id = opcode;
749 xlat_opcode_id = xlat_ids[opcode];
750 extra = ex_data[opcode];
751 i_mod_size = i_mod_adder[opcode];
752 set_flags_type = std_flags[opcode];
757 uint8_t i8086::pc_interrupt(uint8_t interrupt_num)
765 if (!s_interrupt(s_context, interrupt_num)) {
767 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = make_flags();
770 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_CS];
773 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = reg_ip;
775 regs16[REG_CS] = MEM16(4 * interrupt_num + 2);
777 reg_ip = MEM16(4 * interrupt_num);
779 FLAG_TF = FLAG_IF = 0;
786 uint8_t i8086::raiseDivideByZeroInterrupt()
788 if (seg_override_en || rep_override_en) {
791 uint8_t opcode = MEM8(16 * regs16[REG_CS] + reg_ip - 1);
793 if ((opcode & 0xfe) != 0xf2 && (opcode & 0xe7) != 0x26)
798 return pc_interrupt(0);
803 int i8086::AAA_AAS(int8_t which_operation)
805 regs16[REG_AX] += 262 * which_operation * set_AF(set_CF(((regs8[REG_AL] & 0x0F) > 9) || FLAG_AF));
806 return regs8[REG_AL] &= 0x0F;
812 regs_offset = (int32_t)(regs - s_memory);
814 regs8 = (uint8_t *)(s_memory + regs_offset);
815 regs16 = (uint16_t *)(s_memory + regs_offset);
817 memset(regs8, 0,
sizeof(regs));
826 regs16[REG_CS] = 0xffff;
831 void IRAM_ATTR i8086::step()
834 uint8_t
const * opcode_stream = s_memory + 16 * regs16[REG_CS] + reg_ip;
836 #if I8086_SHOW_OPCODE_STATS 837 static uint32_t opcodeStats[256] = {0};
838 static int opcodeStatsCount = 0;
839 static uint64_t opcodeStatsT0 = esp_timer_get_time();
840 opcodeStats[*opcode_stream] += 1;
842 if ((opcodeStatsCount % 1000000) == 0) {
843 opcodeStatsCount = 0;
844 if (Serial.available()) {
846 printf(
"\ntime delta = %llu uS\n\n", esp_timer_get_time() - opcodeStatsT0);
847 opcodeStatsT0 = esp_timer_get_time();
848 for (
int i = 0; i < 256; ++i) {
849 if (opcodeStats[i] > 0)
850 printf(
"%d, %02X\n", opcodeStats[i], i);
865 switch (*opcode_stream) {
876 seg_override = ex_data[*opcode_stream];
877 rep_override_en && rep_override_en++;
899 int inv = *opcode_stream & 1;
900 int idx = (*opcode_stream >> 1) & 7;
901 reg_ip += 2 + (int8_t)opcode_stream[1] * (inv ^ (flags[jxx_dec_a[idx]] || flags[jxx_dec_b[idx]] || flags[jxx_dec_c[idx]] ^ flags[jxx_dec_d[idx]]));
907 reg_ip += 2 + (int8_t)opcode_stream[1];
913 static const int FADDR[3] = { CF_ADDR, IF_ADDR, DF_ADDR };
914 flags[FADDR[(*opcode_stream >> 1) & 3]] = *opcode_stream & 1;
921 reg_ip += 2 + !regs16[REG_CX] * (int8_t)opcode_stream[1];
927 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = reg_ip + 3;
931 reg_ip += 3 + *(uint16_t*)(opcode_stream + 1);
936 reg_ip = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
943 regs16[*opcode_stream & 7] = MEM16(16 * regs16[REG_SS] + (uint16_t)(regs16[REG_SP] - 2));
950 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[*opcode_stream & 7];
956 regs8[((*opcode_stream >> 2) & 1) + (*opcode_stream & 3) * 2] = *(opcode_stream + 1);
962 regs16[*opcode_stream & 0x7] = *(uint16_t*)(opcode_stream + 1);
974 regs16[REG_ES + (*opcode_stream >> 3)] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
980 stepEx(opcode_stream);
985 }
while (seg_override_en > 1 || rep_override_en > 1);
995 if (FLAG_IF && !FLAG_TF && s_pendingIRQ) {
996 pc_interrupt(s_pendingIRQIndex);
997 s_pendingIRQ =
false;
1003 void i8086::stepEx(uint8_t
const * opcode_stream)
1005 set_opcode(*opcode_stream);
1008 uint8_t i_reg4bit = raw_opcode_id & 7;
1009 i_w = i_reg4bit & 1;
1010 i_d = i_reg4bit / 2 & 1;
1013 uint16_t i_data0 = * (int16_t *) & opcode_stream[1];
1014 uint16_t i_data1 = * (int16_t *) & opcode_stream[2];
1015 uint16_t i_data2 = * (int16_t *) & opcode_stream[3];
1017 uint8_t i_mod = 0, i_rm = 0, i_reg = 0;
1018 int32_t op_result = 0;
1019 int32_t rm_addr = 0;
1025 i_mod = (i_data0 & 0xFF) >> 6;
1027 i_reg = i_data0 / 8 & 7;
1029 if ((!i_mod && i_rm == 6) || (i_mod == 2))
1030 i_data2 = * (int16_t *) & opcode_stream[4];
1031 else if (i_mod != 1)
1034 i_data1 = (int8_t) i_data1;
1036 int idx = 4 * !i_mod;
1037 op_to_addr = rm_addr = i_mod < 3 ? 16 * regs16[seg_override_en ? seg_override : instr_table_lookup[idx + 3][i_rm]] + (uint16_t)(regs16[instr_table_lookup[idx + 1][i_rm]] + instr_table_lookup[idx + 2][i_rm] * i_data1 + regs16[instr_table_lookup[idx][i_rm]]) : (regs_offset + (i_w ? 2 * i_rm : (2 * i_rm + i_rm / 4) & 7));
1038 op_from_addr = regs_offset + (i_w ? 2 * i_reg : (2 * i_reg + i_reg / 4) & 7);
1040 auto t = op_from_addr;
1041 op_from_addr = rm_addr;
1047 switch (xlat_opcode_id) {
1053 int idx = 4 * !i_mod;
1054 op_to_addr = rm_addr = i_mod < 3 ? 16 * regs16[seg_override_en ? seg_override : instr_table_lookup[idx + 3][i_rm]] + (uint16_t)(regs16[instr_table_lookup[idx + 1][i_rm]] + instr_table_lookup[idx + 2][i_rm] * i_data1 + regs16[instr_table_lookup[idx][i_rm]]) : (regs_offset + 2 * i_rm);
1055 op_from_addr = regs_offset + 2 * i_reg;
1062 op_dest = RMEM16(op_from_addr);
1063 op_result = WMEM16(op_from_addr, (uint16_t)op_dest + 1 - 2 * i_reg);
1065 op_dest = RMEM8(op_from_addr);
1066 op_result = WMEM8(op_from_addr, (uint16_t)op_dest + 1 - 2 * i_reg);
1069 set_AF_OF_arith(op_result, i_w);
1070 set_OF(op_dest + 1 - i_reg == 1 << (8 * (i_w + 1) - 1));
1071 if (xlat_opcode_id == 5)
1073 }
else if (i_reg != 6) {
1075 uint16_t jumpTo = i_w ? MEM16(op_from_addr) : MEM8(op_from_addr);
1076 if (i_reg - 3 == 0) {
1079 regs16[REG_SP] -= 2;
1080 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_CS];
1085 regs16[REG_SP] -= 2;
1086 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = (reg_ip + 2 + i_mod * (i_mod != 3) + 2 * (!i_mod && i_rm == 6));
1090 regs16[REG_CS] = MEM16(op_from_addr + 2);
1097 regs16[REG_SP] -= 2;
1098 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = MEM16(rm_addr);
1102 op_to_addr = op_from_addr;
1109 op_dest = RMEM16(op_to_addr);
1110 op_source = (uint16_t)i_data2;
1111 op_result = (uint16_t)(op_dest & op_source);
1113 op_dest = RMEM8(op_to_addr);
1114 op_source = (uint8_t)i_data2;
1115 op_result = (uint8_t)(op_dest & op_source);
1120 WMEM16(op_to_addr, ~RMEM16(op_from_addr));
1122 WMEM8(op_to_addr, ~RMEM8(op_from_addr));
1126 op_result = WMEM16(op_to_addr, -(op_source = RMEM16(op_from_addr)));
1128 op_result = WMEM8(op_to_addr, -(op_source = RMEM8(op_from_addr)));
1131 FLAG_CF = op_result > op_dest;
1136 regs16[REG_DX] = (op_result = RMEM16(rm_addr) * regs16[REG_AX]) >> 16;
1137 regs16[REG_AX] = op_result;
1138 set_OF(set_CF(op_result - (uint16_t)op_result));
1141 regs16[REG_AX] = op_result = RMEM8(rm_addr) * regs8[REG_AL];
1142 set_OF(set_CF(op_result - (uint8_t) op_result));
1149 regs16[REG_DX] = (op_result = (int16_t)RMEM16(rm_addr) * (int16_t)regs16[REG_AX]) >> 16;
1150 regs16[REG_AX] = op_result;
1151 set_OF(set_CF(op_result - (int16_t)op_result));
1154 regs16[REG_AX] = op_result = (int8_t)RMEM8(rm_addr) * (int8_t)regs8[REG_AL];
1155 set_OF(set_CF(op_result - (int8_t) op_result));
1161 int32_t scratch_int;
1162 int32_t scratch_uint, scratch2_uint;
1164 (scratch_int = RMEM16(rm_addr))
1166 !(scratch2_uint = (uint32_t)(scratch_uint = (regs16[REG_DX] << 16) + regs16[REG_AX]) / scratch_int, scratch2_uint - (uint16_t) scratch2_uint)
1168 regs16[REG_DX] = scratch_uint - scratch_int * (regs16[REG_AX] = scratch2_uint)
1170 (raiseDivideByZeroInterrupt(), calcIP =
false);
1172 (scratch_int = RMEM8(rm_addr))
1174 !(scratch2_uint = (uint16_t)(scratch_uint = regs16[REG_AX]) / scratch_int, scratch2_uint - (uint8_t) scratch2_uint)
1176 regs8[REG_AH] = scratch_uint - scratch_int * (regs8[REG_AL] = scratch2_uint)
1178 (raiseDivideByZeroInterrupt(), calcIP =
false);
1184 int32_t scratch_int;
1185 int32_t scratch2_uint, scratch_uint;
1187 (scratch_int = (int16_t)RMEM16(rm_addr))
1189 !(scratch2_uint = (
int)(scratch_uint = (regs16[REG_DX] << 16) + regs16[REG_AX]) / scratch_int, scratch2_uint - (int16_t) scratch2_uint)
1191 regs16[REG_DX] = scratch_uint - scratch_int * (regs16[REG_AX] = scratch2_uint)
1193 (raiseDivideByZeroInterrupt(), calcIP =
false);
1195 (scratch_int = (int8_t)RMEM8(rm_addr))
1197 !(scratch2_uint = (int16_t)(scratch_uint = regs16[REG_AX]) / scratch_int, scratch2_uint - (int8_t) scratch2_uint)
1199 regs8[REG_AH] = scratch_uint - scratch_int * (regs8[REG_AL] = scratch2_uint)
1201 (raiseDivideByZeroInterrupt(), calcIP =
false);
1208 rm_addr = regs_offset;
1215 op_to_addr = rm_addr;
1216 regs16[REG_SCRATCH] = (i_d |= !i_w) ? (int8_t) i_data2 : i_data2;
1217 op_from_addr = regs_offset + 2 * REG_SCRATCH;
1219 set_opcode(0x08 * (extra = i_reg));
1226 op_dest = RMEM16(op_to_addr);
1227 op_source = RMEM16(op_from_addr);
1228 op_result = (uint16_t)(op_dest + op_source);
1229 WMEM16(op_to_addr, op_result);
1231 op_dest = RMEM8(op_to_addr);
1232 op_source = RMEM8(op_from_addr);
1233 op_result = (uint8_t)(op_dest + op_source);
1234 WMEM8(op_to_addr, op_result);
1236 FLAG_CF = op_result < op_dest;
1242 op_dest = RMEM16(op_to_addr);
1243 op_source = RMEM16(op_from_addr);
1244 op_result = op_dest | op_source;
1245 WMEM16(op_to_addr, op_result);
1247 op_dest = RMEM8(op_to_addr);
1248 op_source = RMEM8(op_from_addr);
1249 op_result = op_dest | op_source;
1250 WMEM8(op_to_addr, op_result);
1256 op_dest = RMEM16(op_to_addr);
1257 op_source = RMEM16(op_from_addr);
1258 op_result = WMEM16(op_to_addr, op_dest + FLAG_CF + op_source);
1260 op_dest = RMEM8(op_to_addr);
1261 op_source = RMEM8(op_from_addr);
1262 op_result = WMEM8(op_to_addr, op_dest + FLAG_CF + op_source);
1264 set_CF((FLAG_CF && (op_result == op_dest)) || (+op_result < +(
int) op_dest));
1265 set_AF_OF_arith(op_result, i_w);
1269 op_dest = RMEM16(op_to_addr);
1270 op_source = RMEM16(op_from_addr);
1271 op_result = WMEM16(op_to_addr, op_dest - (FLAG_CF + op_source));
1273 op_dest = RMEM8(op_to_addr);
1274 op_source = RMEM8(op_from_addr);
1275 op_result = WMEM8(op_to_addr, op_dest - (FLAG_CF + op_source));
1277 set_CF((FLAG_CF && (op_result == op_dest)) || (-op_result < -(
int) op_dest));
1278 set_AF_OF_arith(op_result, i_w);
1283 op_dest = RMEM16(op_to_addr);
1284 op_source = RMEM16(op_from_addr);
1285 op_result = op_dest & op_source;
1286 WMEM16(op_to_addr, op_result);
1288 op_dest = RMEM8(op_to_addr);
1289 op_source = RMEM8(op_from_addr);
1290 op_result = op_dest & op_source;
1291 WMEM8(op_to_addr, op_result);
1297 op_dest = RMEM16(op_to_addr);
1298 op_source = RMEM16(op_from_addr);
1299 op_result = WMEM16(op_to_addr, op_dest - op_source);
1301 op_dest = RMEM8(op_to_addr);
1302 op_source = RMEM8(op_from_addr);
1303 op_result = WMEM8(op_to_addr, op_dest - op_source);
1305 FLAG_CF = op_result > op_dest;
1310 op_dest = RMEM16(op_to_addr);
1311 op_source = RMEM16(op_from_addr);
1312 op_result = op_dest ^ op_source;
1313 WMEM16(op_to_addr, op_result);
1315 op_dest = RMEM8(op_to_addr);
1316 op_source = RMEM8(op_from_addr);
1317 op_result = op_dest ^ op_source;
1318 WMEM8(op_to_addr, op_result);
1324 op_dest = RMEM16(op_to_addr);
1325 op_source = RMEM16(op_from_addr);
1327 op_dest = RMEM8(op_to_addr);
1328 op_source = RMEM8(op_from_addr);
1330 op_result = op_dest - op_source;
1331 FLAG_CF = op_result > op_dest;
1335 WMEM16(op_to_addr, RMEM16(op_from_addr));
1337 WMEM8(op_to_addr, RMEM8(op_from_addr));
1347 int32_t scratch2_uint = 4 * !i_mod;
1348 rm_addr = i_mod < 3 ?
1349 16 * regs16[seg_override_en ?
1351 : instr_table_lookup[scratch2_uint + 3][i_rm]] + (uint16_t)(regs16[instr_table_lookup[scratch2_uint + 1][i_rm]] + instr_table_lookup[scratch2_uint + 2][i_rm] * i_data1 + regs16[instr_table_lookup[scratch2_uint][i_rm]])
1352 : (regs_offset + (2 * i_rm));
1354 regs16[i_reg] = RMEM16(rm_addr);
1356 WMEM16(rm_addr, regs16[i_reg]);
1360 int idx = 4 * !i_mod;
1361 regs16[i_reg] = regs16[instr_table_lookup[idx + 1][i_rm]] + instr_table_lookup[idx + 2][i_rm] * i_data1 + regs16[instr_table_lookup[idx][i_rm]];
1364 regs16[REG_SP] += 2;
1365 WMEM16(rm_addr, RMEM16(16 * regs16[REG_SS] + (uint16_t)(-2 + regs16[REG_SP])));
1369 rm_addr = 16 * regs16[seg_override_en ? seg_override : REG_DS] + i_data0;
1372 WMEM16(rm_addr, regs16[REG_AX]);
1374 WMEM8(rm_addr, regs8[REG_AL]);
1378 regs16[REG_AX] = RMEM16(rm_addr);
1380 regs8[REG_AL] = RMEM8(rm_addr);
1387 uint16_t scratch2_uint = (1 & (i_w ? (int16_t)RMEM16(rm_addr) : RMEM8(rm_addr)) >> (8 * (i_w + 1) - 1));
1388 uint16_t scratch_uint = extra ?
1391 31 & regs8[REG_CL] :
1396 scratch_uint %= i_reg / 2 + 8 * (i_w + 1);
1397 scratch2_uint = i_w ? RMEM16(rm_addr) : RMEM8(rm_addr);
1402 op_dest = RMEM16(rm_addr);
1403 op_result = WMEM16(rm_addr, (uint16_t)op_dest >> scratch_uint);
1405 op_dest = RMEM8(rm_addr);
1406 op_result = WMEM8(rm_addr, (uint8_t)op_dest >> (uint8_t)scratch_uint);
1411 op_dest = RMEM16(rm_addr);
1412 op_result = WMEM16(rm_addr, (uint16_t)op_dest << scratch_uint);
1414 op_dest = RMEM8(rm_addr);
1415 op_result = WMEM8(rm_addr, (uint8_t)op_dest << (uint8_t)scratch_uint);
1421 set_CF(op_dest >> (scratch_uint - 1) & 1);
1427 op_dest = RMEM16(rm_addr);
1428 op_result = WMEM16(rm_addr, (uint16_t)op_dest + (op_source = scratch2_uint >> (16 - scratch_uint)));
1430 op_dest = RMEM8(rm_addr);
1431 op_result = WMEM8(rm_addr, (uint8_t)op_dest + (op_source = (uint8_t)scratch2_uint >> (8 - scratch_uint)));
1434 set_OF((1 & op_result >> (8 * (i_w + 1) - 1)) ^ set_CF(op_result & 1));
1437 scratch2_uint &= (1 << scratch_uint) - 1;
1439 op_dest = RMEM16(rm_addr);
1440 op_result = WMEM16(rm_addr, (uint16_t)op_dest + (op_source = scratch2_uint << (16 - scratch_uint)));
1442 op_dest = RMEM8(rm_addr);
1443 op_result = WMEM8(rm_addr, (uint8_t)op_dest + (op_source = (uint8_t)scratch2_uint << (8 - scratch_uint)));
1446 set_OF((1 & (i_w ? (int16_t)op_result * 2 : op_result * 2) >> (8 * (i_w + 1) - 1)) ^ set_CF((1 & (i_w ? (int16_t)op_result : op_result) >> (8 * (i_w + 1) - 1))));
1450 op_dest = RMEM16(rm_addr);
1451 op_result = WMEM16(rm_addr, (uint16_t)op_dest + (FLAG_CF << (scratch_uint - 1)) + (op_source = scratch2_uint >> (17 - scratch_uint)));
1453 op_dest = RMEM8(rm_addr);
1454 op_result = WMEM8(rm_addr, (uint8_t)op_dest + (FLAG_CF << (scratch_uint - 1)) + (op_source = (uint8_t)scratch2_uint >> (9 - scratch_uint)));
1457 set_OF((1 & op_result >> (8 * (i_w + 1) - 1)) ^ set_CF(scratch2_uint & 1 << (8 * (i_w + 1) - scratch_uint)));
1461 op_dest = RMEM16(rm_addr);
1462 op_result = WMEM16(rm_addr, (uint16_t)op_dest + (FLAG_CF << (16 - scratch_uint)) + (op_source = scratch2_uint << (17 - scratch_uint)));
1464 op_dest = RMEM8(rm_addr);
1465 op_result = WMEM8(rm_addr, (uint8_t)op_dest + (FLAG_CF << (8 - scratch_uint)) + (op_source = (uint8_t)scratch2_uint << (9 - scratch_uint)));
1468 set_CF(scratch2_uint & 1 << (scratch_uint - 1));
1469 set_OF((1 & op_result >> (8 * (i_w + 1) - 1)) ^ (1 & (i_w ? (int16_t)op_result * 2 : op_result * 2) >> (8 * (i_w + 1) - 1)));
1474 set_OF((1 & op_result >> (8 * (i_w + 1) - 1)) ^ set_CF((1 & (op_dest << (scratch_uint - 1)) >> (8 * (i_w + 1) - 1))));
1478 set_OF((1 & op_dest >> (8 * (i_w + 1) - 1)));
1481 scratch_uint < 8 * (i_w + 1) || set_CF(scratch2_uint);
1484 op_dest = RMEM16(rm_addr);
1485 uint16_t u16 = (uint16_t)scratch2_uint * ~(((1 << 16) - 1) >> scratch_uint);
1486 op_result = WMEM16(rm_addr, op_dest + (op_source = u16));
1488 op_dest = RMEM8(rm_addr);
1489 uint8_t u8 = (uint8_t)scratch2_uint * ~(((1 << 8) - 1) >> scratch_uint);
1490 op_result = WMEM8(rm_addr, op_dest + (op_source = u8));
1498 int32_t scratch_uint = !!--regs16[REG_CX];
1499 switch (i_reg4bit) {
1501 scratch_uint &= !FLAG_ZF;
1504 scratch_uint &= FLAG_ZF;
1508 reg_ip += scratch_uint * (int8_t) i_data0;
1517 regs16[REG_CS] = i_data2;
1521 regs16[REG_SP] -= 2;
1522 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = reg_ip;
1525 reg_ip += i_d && i_w ? (int8_t) i_data0 : i_data0;
1529 op_result = RMEM16(op_from_addr) & RMEM16(op_to_addr);
1531 op_result = RMEM8(op_from_addr) & RMEM8(op_to_addr);
1535 if (i_reg4bit != REG_AX) {
1536 uint16_t t = regs16[REG_AX];
1537 regs16[REG_AX] = regs16[i_reg4bit];
1538 regs16[i_reg4bit] = t;
1543 if (op_to_addr != op_from_addr) {
1545 uint16_t t = RMEM16(op_to_addr);
1546 WMEM16(op_to_addr, RMEM16(op_from_addr));
1547 WMEM16(op_from_addr, t);
1549 uint16_t t = RMEM8(op_to_addr);
1550 WMEM8(op_to_addr, RMEM8(op_from_addr));
1551 WMEM8(op_from_addr, t);
1557 int32_t seg = seg_override_en ? seg_override : REG_DS;
1559 const int dec = (2 * FLAG_DF - 1) * 2;
1560 for (int32_t i = rep_override_en ? regs16[REG_CX] : 1; i; --i) {
1561 uint16_t src = extra & 1 ? regs16[REG_AX] : RMEM16(16 * regs16[seg] + regs16[REG_SI]);
1563 WMEM16(16 * regs16[REG_ES] + regs16[REG_DI], src);
1565 regs16[REG_AX] = src;
1566 extra & 1 || (regs16[REG_SI] -= dec);
1567 extra & 2 || (regs16[REG_DI] -= dec);
1570 const int dec = (2 * FLAG_DF - 1);
1571 for (int32_t i = rep_override_en ? regs16[REG_CX] : 1; i; --i) {
1572 uint8_t src = extra & 1 ? regs8[REG_AL] : RMEM8(16 * regs16[seg] + regs16[REG_SI]);
1574 WMEM8(16 * regs16[REG_ES] + regs16[REG_DI], src);
1576 regs8[REG_AL] = src;
1577 extra & 1 || (regs16[REG_SI] -= dec);
1578 extra & 2 || (regs16[REG_DI] -= dec);
1581 if (rep_override_en)
1588 int count = rep_override_en ? regs16[REG_CX] : 1;
1590 int incval = (2 * FLAG_DF - 1) * (i_w + 1);
1593 op_dest = i_w ? regs16[REG_AX] : regs8[REG_AL];
1594 for (; count; rep_override_en || count--) {
1596 op_result = op_dest - (op_source = RMEM16(16 * regs16[REG_ES] + regs16[REG_DI]));
1598 op_result = op_dest - (op_source = RMEM8(16 * regs16[REG_ES] + regs16[REG_DI]));
1600 regs16[REG_DI] -= incval;
1601 rep_override_en && !(--regs16[REG_CX] && ((!op_result) == rep_mode)) && (count = 0);
1605 int scratch2_uint = seg_override_en ? seg_override : REG_DS;
1606 for (; count; rep_override_en || count--) {
1608 op_dest = RMEM16(16 * regs16[scratch2_uint] + regs16[REG_SI]);
1609 op_result = op_dest - (op_source = RMEM16(16 * regs16[REG_ES] + regs16[REG_DI]));
1611 op_dest = RMEM8(16 * regs16[scratch2_uint] + regs16[REG_SI]);
1612 op_result = op_dest - (op_source = RMEM8(16 * regs16[REG_ES] + regs16[REG_DI]));
1614 regs16[REG_SI] -= incval;
1615 regs16[REG_DI] -= incval;
1616 rep_override_en && !(--regs16[REG_CX] && ((!op_result) == rep_mode)) && (count = 0);
1619 set_flags_type = 1 | 2;
1620 FLAG_CF = op_result > op_dest;
1628 reg_ip = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1629 regs16[REG_SP] += 2;
1632 regs16[REG_CS] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1633 regs16[REG_SP] += 2;
1637 set_flags(MEM16(16 * regs16[REG_SS] + regs16[REG_SP]));
1638 regs16[REG_SP] += 2;
1640 regs16[REG_SP] += i_data0;
1644 WMEM16(op_from_addr, i_data2);
1646 WMEM8(op_from_addr, i_data2);
1651 int32_t port = extra ? regs16[REG_DX] : (uint8_t) i_data0;
1652 regs8[REG_AL] = s_readPort(s_context, port);
1654 regs8[REG_AH] = s_readPort(s_context, port + 1);
1659 int32_t port = extra ? regs16[REG_DX] : (uint8_t) i_data0;
1660 s_writePort(s_context, port, regs8[REG_AL]);
1662 s_writePort(s_context, port + 1, regs8[REG_AH]);
1666 rep_override_en = 2;
1668 seg_override_en && seg_override_en++;
1672 regs16[REG_SP] -= 2;
1673 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[extra];
1679 FLAG_AF = (regs8[REG_AL] & 0x0f) > 9 || FLAG_AF;
1680 FLAG_CF = regs8[REG_AL] > 0x99 || FLAG_CF;
1684 regs8[REG_AL] -= 0x60;
1686 FLAG_CF = (regs8[REG_AL] < 6);
1692 regs8[REG_AL] += 0x60;
1696 op_result = regs8[REG_AL];
1699 op_result = AAA_AAS(extra - 1);
1702 regs8[REG_AH] = -(1 & (i_w ? * (int16_t *) & regs8[REG_AL] : regs8[REG_AL]) >> (8 * (i_w + 1) - 1));
1705 regs16[REG_DX] = -(1 & (i_w ? * (int16_t *) & regs16[REG_AX] : regs16[REG_AX]) >> (8 * (i_w + 1) - 1));
1708 regs16[REG_SP] -= 2;
1709 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_CS];
1710 regs16[REG_SP] -= 2;
1711 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = reg_ip + 5;
1712 regs16[REG_CS] = i_data2;
1716 regs16[REG_SP] -= 2;
1717 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = make_flags();
1721 regs16[REG_SP] += 2;
1722 set_flags(MEM16(16 * regs16[REG_SS] + (uint16_t)(-2 + regs16[REG_SP])));
1726 set_flags((make_flags() & 0xFF00) + regs8[REG_AH]);
1729 regs8[REG_AH] = make_flags();
1733 regs16[i_reg] = RMEM16(rm_addr);
1734 regs16[extra / 2] = RMEM16(rm_addr + 2);
1742 pc_interrupt(i_data0);
1746 FLAG_OF && pc_interrupt(4);
1749 if (i_data0 &= 0xFF) {
1750 regs8[REG_AH] = regs8[REG_AL] / i_data0;
1751 op_result = regs8[REG_AL] %= i_data0;
1754 raiseDivideByZeroInterrupt();
1760 regs16[REG_AX] = op_result = 0xFF & (regs8[REG_AL] + i_data0 * regs8[REG_AH]);
1763 regs8[REG_AL] = -FLAG_CF;
1766 regs8[REG_AL] = RMEM8(16 * regs16[seg_override_en ? seg_override : REG_DS] + (uint16_t)(regs8[REG_AL] + regs16[REG_BX]));
1775 op_result = regs16[REG_AX] & i_data0;
1777 op_result = regs8[REG_AL] & (uint8_t)i_data0;
1790 regs16[REG_SP] -= 2;
1791 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_BP];
1792 uint16_t framePtr = regs16[REG_SP];
1793 int16_t level = i_data2 & 31;
1796 regs16[REG_BP] -= 2;
1797 regs16[REG_SP] -= 2;
1798 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = MEM16(16 * regs16[REG_SS] + regs16[REG_BP]);
1800 regs16[REG_SP] -= 2;
1801 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = framePtr;
1803 regs16[REG_BP] = framePtr;
1804 regs16[REG_SP] -= i_data0;
1809 regs16[REG_SP] = regs16[REG_BP];
1810 regs16[REG_BP] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1811 regs16[REG_SP] += 2;
1816 uint16_t temp = regs16[REG_SP];
1817 regs16[REG_SP] -= 2;
1818 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_AX];
1819 regs16[REG_SP] -= 2;
1820 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_CX];
1821 regs16[REG_SP] -= 2;
1822 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_DX];
1823 regs16[REG_SP] -= 2;
1824 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_BX];
1825 regs16[REG_SP] -= 2;
1826 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = temp;
1827 regs16[REG_SP] -= 2;
1828 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_BP];
1829 regs16[REG_SP] -= 2;
1830 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_SI];
1831 regs16[REG_SP] -= 2;
1832 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_DI];
1838 regs16[REG_DI] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1839 regs16[REG_SP] += 2;
1840 regs16[REG_SI] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1841 regs16[REG_SP] += 2;
1842 regs16[REG_BP] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1843 regs16[REG_SP] += 2;
1844 regs16[REG_SP] += 2;
1845 regs16[REG_BX] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1846 regs16[REG_SP] += 2;
1847 regs16[REG_DX] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1848 regs16[REG_SP] += 2;
1849 regs16[REG_CX] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1850 regs16[REG_SP] += 2;
1851 regs16[REG_AX] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1852 regs16[REG_SP] += 2;
1856 printf(
"80186: BOUND - not implemented!\n");
1860 regs16[REG_SP] -= 2;
1861 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = i_data0;
1865 regs16[REG_SP] -= 2;
1866 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = (i_data0 & 0xff) | (i_data0 & 0x80 ? 0xff00 : 0);
1869 printf(
"80186 IMUL - not implemented!\n");
1872 printf(
"80186: INSB INSW - not implemented!\n");
1875 printf(
"80186: OUTSB OUTSW - not implemented!\n");
1878 printf(
"8087 MATH Coprocessor %02X %02X %02X %02X - not implemented!\n", opcode_stream[0], opcode_stream[1], opcode_stream[2], opcode_stream[3]);
1892 printf(
"Unsupported 8086 opcode %02X %02X\n", opcode_stream[0], opcode_stream[1]);
1898 reg_ip += (i_mod * (i_mod != 3) + 2 * (!i_mod && i_rm == 6)) * i_mod_size + base_size[raw_opcode_id] + i_w_adder[raw_opcode_id] * (i_w + 1);
1901 if (set_flags_type & 1) {
1902 FLAG_SF = (1 & op_result >> (8 * (i_w + 1) - 1));
1903 FLAG_ZF = !op_result;
1904 FLAG_PF = parity[(uint8_t) op_result];
1907 if (set_flags_type & 2)
1908 set_AF_OF_arith(op_result, i_w);
1909 if (set_flags_type & 4) {