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
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])
106static uint8_t regs[48];
107static uint8_t flags[10];
108static int32_t regs_offset;
109static 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;
110static uint16_t * regs16, reg_ip, seg_override;
111static uint32_t op_source, op_dest, set_flags_type;
112static int32_t op_to_addr, op_from_addr;
115void * i8086::s_context;
116i8086::ReadPort i8086::s_readPort;
117i8086::WritePort i8086::s_writePort;
118i8086::WriteVideoMemory8 i8086::s_writeVideoMemory8;
119i8086::WriteVideoMemory16 i8086::s_writeVideoMemory16;
120i8086::ReadVideoMemory8 i8086::s_readVideoMemory8;
121i8086::ReadVideoMemory16 i8086::s_readVideoMemory16;
122i8086::Interrupt i8086::s_interrupt;
124uint8_t * i8086::s_memory;
125bool i8086::s_pendingIRQ;
126uint8_t i8086::s_pendingIRQIndex;
133static uint8_t rm_mode12_reg1[] = { 3, 3, 5, 5, 6, 7, 5, 3 };
137static uint8_t rm_mode012_reg2[] = { 6, 7, 6, 7, 12, 12, 12, 12 };
140static uint8_t rm_mode12_disp[] = { 1, 1, 1, 1, 1, 1, 1, 1 };
143static uint8_t rm_mode12_dfseg[] = { 11, 11, 10, 10, 11, 11, 10, 11 };
146static uint8_t rm_mode0_reg1[] = { 3, 3, 5, 5, 6, 7, 12, 3 };
149static uint8_t rm_mode0_disp[] = { 0, 0, 0, 0, 0, 0, 1, 0 };
152static uint8_t rm_mode0_dfseg[] = { 11, 11, 10, 10, 11, 11, 11, 11 };
155static 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 };
173static 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 };
191static 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 };
209static 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 };
227static 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 };
245static 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 };
263static 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 };
281static uint8_t jxx_dec_a[] = { OF_ADDR, CF_ADDR, ZF_ADDR, CF_ADDR, SF_ADDR, PF_ADDR, XX_ADDR, XX_ADDR };
284static uint8_t jxx_dec_b[] = { XX_ADDR, XX_ADDR, XX_ADDR, ZF_ADDR, XX_ADDR, XX_ADDR, XX_ADDR, ZF_ADDR };
287static uint8_t jxx_dec_c[] = { XX_ADDR, XX_ADDR, XX_ADDR,XX_ADDR, XX_ADDR, XX_ADDR, SF_ADDR, SF_ADDR };
290static uint8_t jxx_dec_d[] = { XX_ADDR, XX_ADDR, XX_ADDR, XX_ADDR,XX_ADDR, XX_ADDR, OF_ADDR, OF_ADDR };
293static uint8_t * instr_table_lookup[] = { rm_mode12_reg1,
313void i8086::setAL(uint8_t value)
315 regs8[REG_AL] = value;
319void i8086::setAH(uint8_t value)
321 regs8[REG_AH] = value;
327 return regs8[REG_AL];
333 return regs8[REG_AH];
337void i8086::setBL(uint8_t value)
339 regs8[REG_BL] = value;
343void i8086::setBH(uint8_t value)
345 regs8[REG_BH] = value;
351 return regs8[REG_BL];
357 return regs8[REG_BH];
361void i8086::setCL(uint8_t value)
363 regs8[REG_CL] = value;
367void i8086::setCH(uint8_t value)
369 regs8[REG_CH] = value;
375 return regs8[REG_CL];
381 return regs8[REG_CH];
385void i8086::setDL(uint8_t value)
387 regs8[REG_DL] = value;
391void i8086::setDH(uint8_t value)
393 regs8[REG_DH] = value;
399 return regs8[REG_DL];
405 return regs8[REG_DH];
409void i8086::setAX(uint16_t value)
411 regs16[REG_AX] = value;
415void i8086::setBX(uint16_t value)
417 regs16[REG_BX] = value;
421void i8086::setCX(uint16_t value)
423 regs16[REG_CX] = value;
427void i8086::setDX(uint16_t value)
429 regs16[REG_DX] = value;
433void i8086::setDI(uint16_t value)
435 regs16[REG_DI] = value;
439void i8086::setCS(uint16_t value)
441 regs16[REG_CS] = value;
445void i8086::setDS(uint16_t value)
447 regs16[REG_DS] = value;
451void i8086::setSS(uint16_t value)
453 regs16[REG_SS] = value;
457void i8086::setES(uint16_t value)
459 regs16[REG_ES] = value;
463void i8086::setIP(uint16_t value)
475void 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];
601void i8086::setFlagZF(
bool value)
607void i8086::setFlagCF(
bool value)
616bool 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)))
637uint8_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];
647uint16_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);
657inline __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;
668inline __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;
683void IRAM_ATTR set_AF_OF_arith(int32_t op_result)
685 FLAG_AF = (bool)((op_source ^= op_dest ^ op_result) & 0x10);
686 if (op_result == op_dest)
689 FLAG_OF = 1 & (FLAG_CF ^ op_source >> (8 * (i_w + 1) - 1));
694uint16_t IRAM_ATTR i8086::make_flags()
702 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;
706void IRAM_ATTR i8086::set_flags(
int new_flags)
708 FLAG_CF = (bool)(new_flags & 0x001);
709 FLAG_PF = (bool)(new_flags & 0x004);
710 FLAG_AF = (bool)(new_flags & 0x010);
711 FLAG_ZF = (bool)(new_flags & 0x040);
712 FLAG_SF = (bool)(new_flags & 0x080);
713 FLAG_TF = (bool)(new_flags & 0x100);
714 FLAG_IF = (bool)(new_flags & 0x200);
715 FLAG_DF = (bool)(new_flags & 0x400);
716 FLAG_OF = (bool)(new_flags & 0x800);
722void IRAM_ATTR set_opcode(uint8_t opcode)
724 raw_opcode_id = opcode;
725 xlat_opcode_id = xlat_ids[opcode];
726 extra = ex_data[opcode];
727 i_mod_size = i_mod_adder[opcode];
728 set_flags_type = std_flags[opcode];
733void IRAM_ATTR i8086::pc_interrupt(uint8_t interrupt_num)
741 if (!s_interrupt(s_context, interrupt_num)) {
742 uint16_t newIP = MEM16(4 * interrupt_num);
743 uint16_t newCS = MEM16(4 * interrupt_num + 2);
746 uint16_t * stack = &MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
747 stack[2] = make_flags();
748 stack[1] = regs16[REG_CS];
752 regs16[REG_CS] = newCS;
754 FLAG_TF = FLAG_IF = 0;
760uint8_t i8086::raiseDivideByZeroInterrupt()
762 if (seg_override_en || rep_override_en) {
765 uint8_t opcode = MEM8(16 * regs16[REG_CS] + reg_ip - 1);
767 if ((opcode & 0xfe) != 0xf2 && (opcode & 0xe7) != 0x26)
778static int32_t AAA_AAS()
780 FLAG_AF = FLAG_CF = ((regs8[REG_AL] & 0x0F) > 9) || FLAG_AF;
781 regs16[REG_AX] += 262 * (extra - 1) * FLAG_AF;
782 return regs8[REG_AL] &= 0x0F;
786static int32_t DAA_DAS()
790 FLAG_AF = (regs8[REG_AL] & 0x0f) > 9 || FLAG_AF;
791 FLAG_CF = regs8[REG_AL] > 0x99 || FLAG_CF;
795 regs8[REG_AL] -= 0x60;
797 FLAG_CF = (regs8[REG_AL] < 6);
803 regs8[REG_AL] += 0x60;
807 return regs8[REG_AL];
813 regs_offset = (int32_t)(regs - s_memory);
815 regs8 = (uint8_t *)(s_memory + regs_offset);
816 regs16 = (uint16_t *)(s_memory + regs_offset);
818 memset(regs8, 0,
sizeof(regs));
827 regs16[REG_CS] = 0xffff;
833static uint8_t optcodes[] = {
835 0, 0, 0, 0, 0, 0, 13, 12, 0, 0, 0, 0, 0, 0, 13, 0,
836 0, 0, 0, 0, 0, 0, 13, 12, 0, 0, 0, 0, 0, 0, 13, 12,
837 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
838 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
839 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
840 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8,
841 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
842 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
843 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0,
844 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
845 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
846 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11,
847 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 17, 0, 15, 0, 16,
848 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
849 0, 0, 0, 5, 0, 0, 0, 0, 6, 0, 0, 3, 0, 0, 0, 0,
850 0, 0, 14, 14, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 0, 0,
854void IRAM_ATTR i8086::step()
865 if (FLAG_TF && !seg_override_en && !rep_override_en) {
869 else if (FLAG_IF && s_pendingIRQ && !seg_override_en && !rep_override_en) {
870 pc_interrupt(s_pendingIRQIndex);
871 s_pendingIRQ =
false;
887 uint8_t
const * opcode_stream = s_memory + 16 * regs16[REG_CS] + reg_ip;
889 #if I8086_SHOW_OPCODE_STATS
890 static uint32_t opcodeStats[256] = {0};
891 static int opcodeStatsCount = 0;
892 static uint64_t opcodeStatsT0 = esp_timer_get_time();
893 opcodeStats[*opcode_stream] += 1;
895 if ((opcodeStatsCount % 500000000) == 0) {
896 opcodeStatsCount = 0;
897 if (Serial.available()) {
899 printf(
"\ntime delta = %llu uS\n\n", esp_timer_get_time() - opcodeStatsT0);
900 opcodeStatsT0 = esp_timer_get_time();
901 for (
int i = 0; i < 256; ++i) {
902 if (opcodeStats[i] > 0)
903 printf(
"%d, %02X\n", opcodeStats[i], i);
912 switch (optcodes[*opcode_stream]) {
921 seg_override = ex_data[*opcode_stream];
946 int32_t inv = *opcode_stream & 1;
947 int32_t idx = (*opcode_stream >> 1) & 7;
948 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]]));
955 reg_ip += 2 + (int8_t)opcode_stream[1];
962 static int16_t FADDR[3] = { CF_ADDR, IF_ADDR, DF_ADDR };
963 flags[FADDR[(*opcode_stream >> 1) & 3]] = *opcode_stream & 1;
971 reg_ip += 2 + !regs16[REG_CX] * (int8_t)opcode_stream[1];
978 uint16_t pIP = reg_ip + 3;
979 reg_ip = pIP + *(uint16_t*)(opcode_stream + 1);
981 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = pIP;
988 reg_ip = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
996 regs16[*opcode_stream & 7] = MEM16(16 * regs16[REG_SS] + (uint16_t)(regs16[REG_SP] - 2));
1003 regs16[REG_SP] -= 2;
1004 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[*opcode_stream & 7];
1011 regs8[((*opcode_stream >> 2) & 1) + (*opcode_stream & 3) * 2] = *(opcode_stream + 1);
1018 regs16[*opcode_stream & 0x7] = *(uint16_t*)(opcode_stream + 1);
1027 regs16[REG_ES + (*opcode_stream >> 3)] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1028 regs16[REG_SP] += 2;
1038 regs16[REG_SP] -= 2;
1039 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_ES + (*opcode_stream >> 3)];
1046 rep_override_en = 2;
1047 rep_mode = *opcode_stream & 1;
1048 if (seg_override_en)
1057 pc_interrupt(opcode_stream[1]);
1064 uint16_t * stack = &MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1066 regs16[REG_CS] = stack[1];
1067 set_flags(stack[2]);
1068 regs16[REG_SP] += 6;
1076 uint16_t * stack = &MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1078 regs16[REG_CS] = stack[1];
1079 regs16[REG_SP] += 4;
1085 stepEx(opcode_stream);
1089 stepEx(opcode_stream);
1099void IRAM_ATTR i8086::stepEx(uint8_t
const * opcode_stream)
1101 set_opcode(*opcode_stream);
1104 uint8_t i_reg4bit = raw_opcode_id & 7;
1105 i_w = i_reg4bit & 1;
1106 i_d = i_reg4bit / 2 & 1;
1109 uint16_t i_data0 = opcode_stream[1] | (opcode_stream[2] << 8);
1110 uint16_t i_data1 = (i_data0 >> 8) | (opcode_stream[3] << 8);
1111 uint16_t i_data2 = (i_data1 >> 8) | (opcode_stream[4] << 8);
1113 uint8_t i_mod = 0, i_rm = 0, i_reg = 0;
1114 int32_t op_result = 0;
1115 int32_t rm_addr = 0;
1121 i_mod = (i_data0 & 0xFF) >> 6;
1123 i_reg = i_data0 / 8 & 7;
1125 if ((!i_mod && i_rm == 6) || (i_mod == 2))
1126 i_data2 = (i_data2 >> 8) | (opcode_stream[5] << 8);
1127 else if (i_mod != 1)
1130 i_data1 = (int8_t) i_data1;
1132 int idx = 4 * !i_mod;
1133 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));
1134 op_from_addr = regs_offset + (i_w ? 2 * i_reg : (2 * i_reg + i_reg / 4) & 7);
1136 auto t = op_from_addr;
1137 op_from_addr = rm_addr;
1143 switch (xlat_opcode_id) {
1149 int idx = 4 * !i_mod;
1150 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);
1151 op_from_addr = regs_offset + 2 * i_reg;
1158 op_dest = RMEM16(op_from_addr);
1159 op_result = WMEM16(op_from_addr, (uint16_t)op_dest + 1 - 2 * i_reg);
1161 op_dest = RMEM8(op_from_addr);
1162 op_result = WMEM8(op_from_addr, (uint16_t)op_dest + 1 - 2 * i_reg);
1165 set_AF_OF_arith(op_result);
1166 FLAG_OF = (bool)(op_dest + 1 - i_reg == 1 << (8 * (i_w + 1) - 1));
1167 if (xlat_opcode_id == 5) {
1169 xlat_opcode_id = 0x10;
1172 }
else if (i_reg != 6) {
1174 uint16_t jumpTo = i_w ? MEM16(op_from_addr) : MEM8(op_from_addr);
1175 if (i_reg - 3 == 0) {
1178 regs16[REG_SP] -= 2;
1179 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_CS];
1184 regs16[REG_SP] -= 2;
1185 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = (reg_ip + 2 + i_mod * (i_mod != 3) + 2 * (!i_mod && i_rm == 6));
1190 regs16[REG_CS] = MEM16(op_from_addr + 2);
1197 regs16[REG_SP] -= 2;
1198 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = RMEM16(rm_addr);
1202 op_to_addr = op_from_addr;
1207 raw_opcode_id = 0x20;
1212 op_dest = RMEM16(op_to_addr);
1213 op_source = (uint16_t)i_data2;
1214 op_result = (uint16_t)(op_dest & op_source);
1216 op_dest = RMEM8(op_to_addr);
1217 op_source = (uint8_t)i_data2;
1218 op_result = (uint8_t)(op_dest & op_source);
1223 WMEM16(op_to_addr, ~RMEM16(op_from_addr));
1225 WMEM8(op_to_addr, ~RMEM8(op_from_addr));
1229 op_result = WMEM16(op_to_addr, -(op_source = RMEM16(op_from_addr)));
1231 op_result = WMEM8(op_to_addr, -(op_source = RMEM8(op_from_addr)));
1235 raw_opcode_id = 0x28;
1238 FLAG_CF = op_result > op_dest;
1241 raw_opcode_id = 0x10;
1244 regs16[REG_DX] = (op_result = RMEM16(rm_addr) * regs16[REG_AX]) >> 16;
1245 regs16[REG_AX] = op_result;
1246 FLAG_OF = FLAG_CF = (bool)(op_result - (uint16_t)op_result);
1248 regs16[REG_AX] = op_result = RMEM8(rm_addr) * regs8[REG_AL];
1249 FLAG_OF = FLAG_CF = (bool)(op_result - (uint8_t) op_result);
1253 raw_opcode_id = 0x10;
1256 regs16[REG_DX] = (op_result = (int16_t)RMEM16(rm_addr) * (int16_t)regs16[REG_AX]) >> 16;
1257 regs16[REG_AX] = op_result;
1258 FLAG_OF = FLAG_CF = (bool)(op_result - (int16_t)op_result);
1260 regs16[REG_AX] = op_result = (int8_t)RMEM8(rm_addr) * (int8_t)regs8[REG_AL];
1261 FLAG_OF = FLAG_CF = (bool)(op_result - (int8_t) op_result);
1266 int32_t scratch_int;
1267 int32_t scratch_uint, scratch2_uint;
1269 (scratch_int = RMEM16(rm_addr))
1271 !(scratch2_uint = (uint32_t)(scratch_uint = (regs16[REG_DX] << 16) + regs16[REG_AX]) / scratch_int, scratch2_uint - (uint16_t) scratch2_uint)
1273 regs16[REG_DX] = scratch_uint - scratch_int * (regs16[REG_AX] = scratch2_uint)
1275 (raiseDivideByZeroInterrupt(), calcIP =
false);
1277 (scratch_int = RMEM8(rm_addr))
1279 !(scratch2_uint = (uint16_t)(scratch_uint = regs16[REG_AX]) / scratch_int, scratch2_uint - (uint8_t) scratch2_uint)
1281 regs8[REG_AH] = scratch_uint - scratch_int * (regs8[REG_AL] = scratch2_uint)
1283 (raiseDivideByZeroInterrupt(), calcIP =
false);
1289 int32_t scratch_int;
1290 int32_t scratch2_uint, scratch_uint;
1292 (scratch_int = (int16_t)RMEM16(rm_addr))
1294 !(scratch2_uint = (
int)(scratch_uint = (regs16[REG_DX] << 16) + regs16[REG_AX]) / scratch_int, scratch2_uint - (int16_t) scratch2_uint)
1296 regs16[REG_DX] = scratch_uint - scratch_int * (regs16[REG_AX] = scratch2_uint)
1298 (raiseDivideByZeroInterrupt(), calcIP =
false);
1300 (scratch_int = (int8_t)RMEM8(rm_addr))
1302 !(scratch2_uint = (int16_t)(scratch_uint = regs16[REG_AX]) / scratch_int, scratch2_uint - (int8_t) scratch2_uint)
1304 regs8[REG_AH] = scratch_uint - scratch_int * (regs8[REG_AL] = scratch2_uint)
1306 (raiseDivideByZeroInterrupt(), calcIP =
false);
1313 rm_addr = regs_offset;
1320 op_to_addr = rm_addr;
1321 regs16[REG_SCRATCH] = (i_d |= !i_w) ? (int8_t) i_data2 : i_data2;
1322 op_from_addr = regs_offset + 2 * REG_SCRATCH;
1324 set_opcode(0x08 * (extra = i_reg));
1330 op_dest = RMEM16(op_to_addr);
1331 op_source = RMEM16(op_from_addr);
1332 op_result = (uint16_t)(op_dest + op_source);
1333 WMEM16(op_to_addr, op_result);
1335 op_dest = RMEM8(op_to_addr);
1336 op_source = RMEM8(op_from_addr);
1337 op_result = (uint8_t)(op_dest + op_source);
1338 WMEM8(op_to_addr, op_result);
1340 FLAG_CF = op_result < op_dest;
1344 op_dest = RMEM16(op_to_addr);
1345 op_source = RMEM16(op_from_addr);
1346 op_result = op_dest | op_source;
1347 WMEM16(op_to_addr, op_result);
1349 op_dest = RMEM8(op_to_addr);
1350 op_source = RMEM8(op_from_addr);
1351 op_result = op_dest | op_source;
1352 WMEM8(op_to_addr, op_result);
1357 op_dest = RMEM16(op_to_addr);
1358 op_source = RMEM16(op_from_addr);
1359 op_result = WMEM16(op_to_addr, op_dest + FLAG_CF + op_source);
1361 op_dest = RMEM8(op_to_addr);
1362 op_source = RMEM8(op_from_addr);
1363 op_result = WMEM8(op_to_addr, op_dest + FLAG_CF + op_source);
1365 FLAG_CF = (FLAG_CF && (op_result == op_dest)) || (op_result < (int) op_dest);
1366 set_AF_OF_arith(op_result);
1370 op_dest = RMEM16(op_to_addr);
1371 op_source = RMEM16(op_from_addr);
1372 op_result = WMEM16(op_to_addr, op_dest - (FLAG_CF + op_source));
1374 op_dest = RMEM8(op_to_addr);
1375 op_source = RMEM8(op_from_addr);
1376 op_result = WMEM8(op_to_addr, op_dest - (FLAG_CF + op_source));
1378 FLAG_CF = (FLAG_CF && (op_result == op_dest)) || (-op_result < -(int) op_dest);
1379 set_AF_OF_arith(op_result);
1383 op_dest = RMEM16(op_to_addr);
1384 op_source = RMEM16(op_from_addr);
1385 op_result = op_dest & op_source;
1386 WMEM16(op_to_addr, op_result);
1388 op_dest = RMEM8(op_to_addr);
1389 op_source = RMEM8(op_from_addr);
1390 op_result = op_dest & op_source;
1391 WMEM8(op_to_addr, op_result);
1396 op_dest = RMEM16(op_to_addr);
1397 op_source = RMEM16(op_from_addr);
1398 op_result = WMEM16(op_to_addr, op_dest - op_source);
1400 op_dest = RMEM8(op_to_addr);
1401 op_source = RMEM8(op_from_addr);
1402 op_result = WMEM8(op_to_addr, op_dest - op_source);
1404 FLAG_CF = op_result > op_dest;
1408 op_dest = RMEM16(op_to_addr);
1409 op_source = RMEM16(op_from_addr);
1410 op_result = op_dest ^ op_source;
1411 WMEM16(op_to_addr, op_result);
1413 op_dest = RMEM8(op_to_addr);
1414 op_source = RMEM8(op_from_addr);
1415 op_result = op_dest ^ op_source;
1416 WMEM8(op_to_addr, op_result);
1421 op_dest = RMEM16(op_to_addr);
1422 op_source = RMEM16(op_from_addr);
1424 op_dest = RMEM8(op_to_addr);
1425 op_source = RMEM8(op_from_addr);
1427 op_result = op_dest - op_source;
1428 FLAG_CF = op_result > op_dest;
1432 WMEM16(op_to_addr, RMEM16(op_from_addr));
1434 WMEM8(op_to_addr, RMEM8(op_from_addr));
1444 int32_t scratch2_uint = 4 * !i_mod;
1445 rm_addr = i_mod < 3 ?
1446 16 * regs16[seg_override_en ?
1448 : 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]])
1449 : (regs_offset + (2 * i_rm));
1451 regs16[i_reg] = RMEM16(rm_addr);
1453 WMEM16(rm_addr, regs16[i_reg]);
1457 int idx = 4 * !i_mod;
1458 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]];
1461 regs16[REG_SP] += 2;
1462 WMEM16(rm_addr, MEM16(16 * regs16[REG_SS] + (uint16_t)(-2 + regs16[REG_SP])));
1466 rm_addr = 16 * regs16[seg_override_en ? seg_override : REG_DS] + i_data0;
1469 WMEM16(rm_addr, regs16[REG_AX]);
1471 WMEM8(rm_addr, regs8[REG_AL]);
1475 regs16[REG_AX] = RMEM16(rm_addr);
1477 regs8[REG_AL] = RMEM8(rm_addr);
1484 uint16_t scratch2_uint = (1 & (i_w ? (int16_t)RMEM16(rm_addr) : RMEM8(rm_addr)) >> (8 * (i_w + 1) - 1));
1485 uint16_t scratch_uint = extra ?
1488 31 & regs8[REG_CL] :
1493 scratch_uint %= i_reg / 2 + 8 * (i_w + 1);
1494 scratch2_uint = i_w ? RMEM16(rm_addr) : RMEM8(rm_addr);
1499 op_dest = RMEM16(rm_addr);
1500 op_result = WMEM16(rm_addr, (uint16_t)op_dest >> scratch_uint);
1502 op_dest = RMEM8(rm_addr);
1503 op_result = WMEM8(rm_addr, (uint8_t)op_dest >> (uint8_t)scratch_uint);
1508 op_dest = RMEM16(rm_addr);
1509 op_result = WMEM16(rm_addr, (uint16_t)op_dest << scratch_uint);
1511 op_dest = RMEM8(rm_addr);
1512 op_result = WMEM8(rm_addr, (uint8_t)op_dest << (uint8_t)scratch_uint);
1518 FLAG_CF = op_dest >> (scratch_uint - 1) & 1;
1524 op_dest = RMEM16(rm_addr);
1525 op_result = WMEM16(rm_addr, (uint16_t)op_dest + (op_source = scratch2_uint >> (16 - scratch_uint)));
1527 op_dest = RMEM8(rm_addr);
1528 op_result = WMEM8(rm_addr, (uint8_t)op_dest + (op_source = (uint8_t)scratch2_uint >> (8 - scratch_uint)));
1531 FLAG_OF = (1 & op_result >> (8 * (i_w + 1) - 1)) ^ (FLAG_CF = op_result & 1);
1534 scratch2_uint &= (1 << scratch_uint) - 1;
1536 op_dest = RMEM16(rm_addr);
1537 op_result = WMEM16(rm_addr, (uint16_t)op_dest + (op_source = scratch2_uint << (16 - scratch_uint)));
1539 op_dest = RMEM8(rm_addr);
1540 op_result = WMEM8(rm_addr, (uint8_t)op_dest + (op_source = (uint8_t)scratch2_uint << (8 - scratch_uint)));
1543 FLAG_OF = (1 & (i_w ? (int16_t)op_result * 2 : op_result * 2) >> (8 * (i_w + 1) - 1)) ^ (FLAG_CF = 1 & (i_w ? (int16_t)op_result : op_result) >> (8 * (i_w + 1) - 1));
1548 op_dest = RMEM16(rm_addr);
1549 op_result = WMEM16(rm_addr, (uint16_t)op_dest + (FLAG_CF << (scratch_uint - 1)) + (op_source = scratch2_uint >> (17 - scratch_uint)));
1551 op_dest = RMEM8(rm_addr);
1552 op_result = WMEM8(rm_addr, (uint8_t)op_dest + (FLAG_CF << (scratch_uint - 1)) + (op_source = (uint8_t)scratch2_uint >> (9 - scratch_uint)));
1555 FLAG_OF = (1 & op_result >> (8 * (i_w + 1) - 1)) ^ (FLAG_CF = (
bool)(scratch2_uint & 1 << (8 * (i_w + 1) - scratch_uint)));
1559 op_dest = RMEM16(rm_addr);
1560 op_result = WMEM16(rm_addr, (uint16_t)op_dest + (FLAG_CF << (16 - scratch_uint)) + (op_source = scratch2_uint << (17 - scratch_uint)));
1562 op_dest = RMEM8(rm_addr);
1563 op_result = WMEM8(rm_addr, (uint8_t)op_dest + (FLAG_CF << (8 - scratch_uint)) + (op_source = (uint8_t)scratch2_uint << (9 - scratch_uint)));
1566 FLAG_CF = (bool)(scratch2_uint & 1 << (scratch_uint - 1));
1567 FLAG_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));
1572 FLAG_OF = (1 & op_result >> (8 * (i_w + 1) - 1)) ^ (FLAG_CF = (1 & (op_dest << (scratch_uint - 1)) >> (8 * (i_w + 1) - 1)));
1576 FLAG_OF = 1 & op_dest >> (8 * (i_w + 1) - 1);
1579 scratch_uint < 8 * (i_w + 1) || (FLAG_CF = (
bool)scratch2_uint);
1582 op_dest = RMEM16(rm_addr);
1583 uint16_t u16 = (uint16_t)scratch2_uint * ~(((1 << 16) - 1) >> scratch_uint);
1584 op_result = WMEM16(rm_addr, op_dest + (op_source = u16));
1586 op_dest = RMEM8(rm_addr);
1587 uint8_t u8 = (uint8_t)scratch2_uint * ~(((1 << 8) - 1) >> scratch_uint);
1588 op_result = WMEM8(rm_addr, op_dest + (op_source = u8));
1596 if (--regs16[REG_CX])
1597 reg_ip += ((FLAG_ZF ^ !i_reg4bit) | (
bool)(i_reg4bit & 2)) * (int8_t) i_data0;
1605 regs16[REG_CS] = i_data2;
1609 regs16[REG_SP] -= 2;
1610 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = reg_ip;
1613 reg_ip += i_d && i_w ? (int8_t) i_data0 : i_data0;
1617 op_result = RMEM16(op_from_addr) & RMEM16(op_to_addr);
1619 op_result = RMEM8(op_from_addr) & RMEM8(op_to_addr);
1623 if (i_reg4bit != REG_AX) {
1624 uint16_t t = regs16[REG_AX];
1625 regs16[REG_AX] = regs16[i_reg4bit];
1626 regs16[i_reg4bit] = t;
1631 if (op_to_addr != op_from_addr) {
1633 uint16_t t = RMEM16(op_to_addr);
1634 WMEM16(op_to_addr, RMEM16(op_from_addr));
1635 WMEM16(op_from_addr, t);
1637 uint16_t t = RMEM8(op_to_addr);
1638 WMEM8(op_to_addr, RMEM8(op_from_addr));
1639 WMEM8(op_from_addr, t);
1645 int32_t seg = seg_override_en ? seg_override : REG_DS;
1647 const int dec = (2 * FLAG_DF - 1) * 2;
1648 for (int32_t i = rep_override_en ? regs16[REG_CX] : 1; i; --i) {
1649 uint16_t src = extra & 1 ? regs16[REG_AX] : RMEM16(16 * regs16[seg] + regs16[REG_SI]);
1651 WMEM16(16 * regs16[REG_ES] + regs16[REG_DI], src);
1654 regs16[REG_AX] = src;
1655 extra & 1 || (regs16[REG_SI] -= dec);
1656 extra & 2 || (regs16[REG_DI] -= dec);
1660 const int dec = (2 * FLAG_DF - 1);
1661 for (int32_t i = rep_override_en ? regs16[REG_CX] : 1; i; --i) {
1662 uint8_t src = extra & 1 ? regs8[REG_AL] : RMEM8(16 * regs16[seg] + regs16[REG_SI]);
1664 WMEM8(16 * regs16[REG_ES] + regs16[REG_DI], src);
1667 regs8[REG_AL] = src;
1668 extra & 1 || (regs16[REG_SI] -= dec);
1669 extra & 2 || (regs16[REG_DI] -= dec);
1672 if (rep_override_en)
1679 int count = rep_override_en ? regs16[REG_CX] : 1;
1681 int incval = (2 * FLAG_DF - 1) * (i_w + 1);
1684 op_dest = i_w ? regs16[REG_AX] : regs8[REG_AL];
1685 for (; count; rep_override_en || count--) {
1687 op_result = op_dest - (op_source = RMEM16(16 * regs16[REG_ES] + regs16[REG_DI]));
1689 op_result = op_dest - (op_source = RMEM8(16 * regs16[REG_ES] + regs16[REG_DI]));
1691 regs16[REG_DI] -= incval;
1692 rep_override_en && !(--regs16[REG_CX] && ((!op_result) == rep_mode)) && (count = 0);
1696 int scratch2_uint = seg_override_en ? seg_override : REG_DS;
1697 for (; count; rep_override_en || count--) {
1699 op_dest = RMEM16(16 * regs16[scratch2_uint] + regs16[REG_SI]);
1700 op_result = op_dest - (op_source = RMEM16(16 * regs16[REG_ES] + regs16[REG_DI]));
1702 op_dest = RMEM8(16 * regs16[scratch2_uint] + regs16[REG_SI]);
1703 op_result = op_dest - (op_source = RMEM8(16 * regs16[REG_ES] + regs16[REG_DI]));
1705 regs16[REG_SI] -= incval;
1706 regs16[REG_DI] -= incval;
1707 rep_override_en && !(--regs16[REG_CX] && ((!op_result) == rep_mode)) && (count = 0);
1711 FLAG_CF = op_result > op_dest;
1718 reg_ip = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1719 regs16[REG_SP] += 2;
1722 regs16[REG_CS] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1723 regs16[REG_SP] += 2;
1725 regs16[REG_SP] += i_data0;
1729 WMEM16(op_from_addr, i_data2);
1731 WMEM8(op_from_addr, i_data2);
1736 int32_t port = extra ? regs16[REG_DX] : (uint8_t) i_data0;
1737 regs8[REG_AL] = s_readPort(s_context, port);
1739 regs8[REG_AH] = s_readPort(s_context, port + 1);
1744 int32_t port = extra ? regs16[REG_DX] : (uint8_t) i_data0;
1745 s_writePort(s_context, port, regs8[REG_AL]);
1747 s_writePort(s_context, port + 1, regs8[REG_AH]);
1751 op_result = DAA_DAS();
1754 op_result = AAA_AAS();
1757 regs8[REG_AH] = -(1 & (i_w ? * (int16_t *) & regs8[REG_AL] : regs8[REG_AL]) >> (8 * (i_w + 1) - 1));
1760 regs16[REG_DX] = -(1 & (i_w ? * (int16_t *) & regs16[REG_AX] : regs16[REG_AX]) >> (8 * (i_w + 1) - 1));
1764 regs16[REG_SP] -= 4;
1765 uint16_t * stack = &MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1766 stack[1] = regs16[REG_CS];
1767 stack[0] = reg_ip + 5;
1768 regs16[REG_CS] = i_data2;
1773 regs16[REG_SP] -= 2;
1774 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = make_flags();
1778 regs16[REG_SP] += 2;
1779 set_flags(MEM16(16 * regs16[REG_SS] + (uint16_t)(-2 + regs16[REG_SP])));
1783 set_flags((make_flags() & 0xFF00) + regs8[REG_AH]);
1786 regs8[REG_AH] = make_flags();
1790 regs16[i_reg] = RMEM16(rm_addr);
1791 regs16[extra / 2] = RMEM16(rm_addr + 2);
1803 if (i_data0 &= 0xFF) {
1804 regs8[REG_AH] = regs8[REG_AL] / i_data0;
1805 op_result = regs8[REG_AL] %= i_data0;
1808 raiseDivideByZeroInterrupt();
1814 regs16[REG_AX] = op_result = 0xFF & (regs8[REG_AL] + i_data0 * regs8[REG_AH]);
1817 regs8[REG_AL] = -FLAG_CF;
1820 regs8[REG_AL] = RMEM8(16 * regs16[seg_override_en ? seg_override : REG_DS] + (uint16_t)(regs8[REG_AL] + regs16[REG_BX]));
1829 op_result = regs16[REG_AX] & i_data0;
1831 op_result = regs8[REG_AL] & (uint8_t)i_data0;
1843 regs16[REG_SP] -= 2;
1844 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_BP];
1845 uint16_t framePtr = regs16[REG_SP];
1846 int16_t level = i_data2 & 31;
1849 regs16[REG_BP] -= 2;
1850 regs16[REG_SP] -= 2;
1851 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = MEM16(16 * regs16[REG_SS] + regs16[REG_BP]);
1853 regs16[REG_SP] -= 2;
1854 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = framePtr;
1856 regs16[REG_BP] = framePtr;
1857 regs16[REG_SP] -= i_data0;
1862 regs16[REG_SP] = regs16[REG_BP];
1863 regs16[REG_BP] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1864 regs16[REG_SP] += 2;
1869 uint16_t temp = regs16[REG_SP];
1870 regs16[REG_SP] -= 2;
1871 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_AX];
1872 regs16[REG_SP] -= 2;
1873 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_CX];
1874 regs16[REG_SP] -= 2;
1875 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_DX];
1876 regs16[REG_SP] -= 2;
1877 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_BX];
1878 regs16[REG_SP] -= 2;
1879 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = temp;
1880 regs16[REG_SP] -= 2;
1881 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_BP];
1882 regs16[REG_SP] -= 2;
1883 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_SI];
1884 regs16[REG_SP] -= 2;
1885 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_DI];
1891 regs16[REG_DI] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1892 regs16[REG_SP] += 2;
1893 regs16[REG_SI] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1894 regs16[REG_SP] += 2;
1895 regs16[REG_BP] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1896 regs16[REG_SP] += 2;
1897 regs16[REG_SP] += 2;
1898 regs16[REG_BX] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1899 regs16[REG_SP] += 2;
1900 regs16[REG_DX] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1901 regs16[REG_SP] += 2;
1902 regs16[REG_CX] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1903 regs16[REG_SP] += 2;
1904 regs16[REG_AX] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1905 regs16[REG_SP] += 2;
1909 printf(
"80186: BOUND - not implemented!\n");
1913 regs16[REG_SP] -= 2;
1914 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = i_data0;
1918 regs16[REG_SP] -= 2;
1919 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = (i_data0 & 0xff) | (i_data0 & 0x80 ? 0xff00 : 0);
1922 printf(
"80186 IMUL - not implemented!\n");
1925 printf(
"80186: INSB INSW - not implemented!\n");
1928 printf(
"80186: OUTSB OUTSW - not implemented!\n");
1931 printf(
"8087 MATH Coprocessor %02X %02X %02X %02X - not implemented!\n", opcode_stream[0], opcode_stream[1], opcode_stream[2], opcode_stream[3]);
1945 printf(
"Unsupported 8086 opcode %02X %02X\n", opcode_stream[0], opcode_stream[1]);
1951 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);
1954 if (set_flags_type & 1) {
1955 FLAG_SF = (1 & op_result >> (8 * (i_w + 1) - 1));
1956 FLAG_ZF = !op_result;
1957 FLAG_PF = parity[(uint8_t) op_result];
1960 if (set_flags_type & 2)
1961 set_AF_OF_arith(op_result);
1962 else if (set_flags_type & 4)
1963 FLAG_CF = FLAG_OF = 0;