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];
363 return regs8[REG_CL];
369 return regs8[REG_CH];
373 void i8086::setAX(uint16_t value)
375 regs16[REG_AX] = value;
379 void i8086::setBX(uint16_t value)
381 regs16[REG_BX] = value;
385 void i8086::setCX(uint16_t value)
387 regs16[REG_CX] = value;
391 void i8086::setDX(uint16_t value)
393 regs16[REG_DX] = value;
397 void i8086::setCS(uint16_t value)
399 regs16[REG_CS] = value;
403 void i8086::setDS(uint16_t value)
405 regs16[REG_DS] = value;
409 void i8086::setSS(uint16_t value)
411 regs16[REG_SS] = value;
415 void i8086::setIP(uint16_t value)
421 void i8086::setSP(uint16_t value)
423 regs16[REG_SP] = value;
429 return regs16[REG_AX];
435 return regs16[REG_BX];
441 return regs16[REG_CX];
447 return regs16[REG_DX];
453 return regs16[REG_BP];
459 return regs16[REG_SI];
465 return regs16[REG_DI];
471 return regs16[REG_SP];
477 return regs16[REG_CS];
483 return regs16[REG_ES];
489 return regs16[REG_DS];
495 return regs16[REG_SS];
522 void i8086::setFlagZF(
bool value)
528 void i8086::setFlagCF(
bool value)
537 bool i8086::IRQ(uint8_t interrupt_num)
541 s_pendingIRQIndex = interrupt_num;
554 #define MEM8(addr) s_memory[addr] 555 #define MEM16(addr) (*(uint16_t*)(s_memory + (addr))) 558 inline __attribute__((always_inline)) uint8_t i8086::RMEM8(
int addr)
560 if (addr >= VIDEOMEM_START && addr < VIDEOMEM_END) {
561 return s_readVideoMemory8(s_context, addr);
563 return s_memory[addr];
568 inline __attribute__((always_inline)) uint16_t i8086::RMEM16(
int addr)
570 if (addr >= VIDEOMEM_START && addr < VIDEOMEM_END) {
571 return s_readVideoMemory16(s_context, addr);
573 return *(uint16_t*)(s_memory + addr);
578 inline __attribute__((always_inline)) uint8_t i8086::WMEM8(
int addr, uint8_t value)
580 if (addr >= VIDEOMEM_START && addr < VIDEOMEM_END) {
581 s_writeVideoMemory8(s_context, addr, value);
583 s_memory[addr] = value;
589 inline __attribute__((always_inline)) uint16_t i8086::WMEM16(
int addr, uint16_t value)
591 if (addr >= VIDEOMEM_START && addr < VIDEOMEM_END) {
592 s_writeVideoMemory16(s_context, addr, value);
594 *(uint16_t*)(s_memory + addr) = value;
607 static int8_t set_CF(
int new_CF)
609 return FLAG_CF = !!new_CF;
614 static int8_t set_AF(
int new_AF)
616 return FLAG_AF = !!new_AF;
621 static int8_t set_OF(
int new_OF)
623 return FLAG_OF = !!new_OF;
628 int8_t set_AF_OF_arith(int32_t op_result, uint8_t i_w)
630 set_AF((op_source ^= op_dest ^ op_result) & 0x10);
631 if (op_result == op_dest)
634 return set_OF(1 & (FLAG_CF ^ op_source >> (8 * (i_w + 1) - 1)));
639 uint16_t i8086::make_flags()
647 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;
651 void i8086::set_flags(
int new_flags)
653 FLAG_CF = (new_flags >> 0) & 1;
654 FLAG_PF = (new_flags >> 2) & 1;
655 FLAG_AF = (new_flags >> 4) & 1;
656 FLAG_ZF = (new_flags >> 6) & 1;
657 FLAG_SF = (new_flags >> 7) & 1;
658 FLAG_TF = (new_flags >> 8) & 1;
659 FLAG_IF = (new_flags >> 9) & 1;
660 FLAG_DF = (new_flags >> 10) & 1;
661 FLAG_OF = (new_flags >> 11) & 1;
667 void i8086::set_opcode(uint8_t opcode)
669 raw_opcode_id = opcode;
670 xlat_opcode_id = xlat_ids[opcode];
671 extra = ex_data[opcode];
672 i_mod_size = i_mod_adder[opcode];
673 set_flags_type = std_flags[opcode];
678 uint8_t i8086::pc_interrupt(uint8_t interrupt_num)
686 if (!s_interrupt(s_context, interrupt_num)) {
688 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = make_flags();
691 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_CS];
694 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = reg_ip;
696 regs16[REG_CS] = MEM16(4 * interrupt_num + 2);
698 reg_ip = MEM16(4 * interrupt_num);
700 FLAG_TF = FLAG_IF = 0;
707 uint8_t i8086::raiseDivideByZeroInterrupt()
709 if (seg_override_en || rep_override_en) {
712 uint8_t opcode = MEM8(16 * regs16[REG_CS] + reg_ip - 1);
714 if ((opcode & 0xfe) != 0xf2 && (opcode & 0xe7) != 0x26)
719 return pc_interrupt(0);
724 int i8086::AAA_AAS(int8_t which_operation)
726 regs16[REG_AX] += 262 * which_operation * set_AF(set_CF(((regs8[REG_AL] & 0x0F) > 9) || FLAG_AF));
727 return regs8[REG_AL] &= 0x0F;
733 regs_offset = (int32_t)(regs - s_memory);
735 regs8 = (uint8_t *)(s_memory + regs_offset);
736 regs16 = (uint16_t *)(s_memory + regs_offset);
738 memset(regs8, 0,
sizeof(regs));
747 regs16[REG_CS] = 0xffff;
752 void IRAM_ATTR i8086::step()
754 uint8_t
const * opcode_stream = s_memory + 16 * regs16[REG_CS] + reg_ip;
758 #if I8086_SHOW_OPCODE_STATS 759 static uint32_t opcodeStats[256] = {0};
760 static int opcodeStatsCount = 0;
761 static uint64_t opcodeStatsT0 = esp_timer_get_time();
762 opcodeStats[*opcode_stream] += 1;
764 if ((opcodeStatsCount % 1000000) == 0) {
765 opcodeStatsCount = 0;
766 if (Serial.available()) {
768 printf(
"\ntime delta = %llu uS\n\n", esp_timer_get_time() - opcodeStatsT0);
769 opcodeStatsT0 = esp_timer_get_time();
770 for (
int i = 0; i < 256; ++i) {
771 if (opcodeStats[i] > 0)
772 printf(
"%d, %02X\n", opcodeStats[i], i);
787 switch (*opcode_stream) {
798 seg_override = ex_data[*opcode_stream];
799 rep_override_en && rep_override_en++;
821 int inv = *opcode_stream & 1;
822 int idx = (*opcode_stream >> 1) & 7;
823 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]]));
829 reg_ip += 2 + (int8_t)opcode_stream[1];
835 static const int FADDR[3] = { CF_ADDR, IF_ADDR, DF_ADDR };
836 flags[FADDR[(*opcode_stream >> 1) & 3]] = *opcode_stream & 1;
843 reg_ip += 2 + !regs16[REG_CX] * (int8_t)opcode_stream[1];
849 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = reg_ip + 3;
853 reg_ip += 3 + *(uint16_t*)(opcode_stream + 1);
858 reg_ip = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
865 regs16[*opcode_stream & 7] = MEM16(16 * regs16[REG_SS] + (uint16_t)(regs16[REG_SP] - 2));
872 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[*opcode_stream & 7];
878 regs8[((*opcode_stream >> 2) & 1) + (*opcode_stream & 3) * 2] = *(opcode_stream + 1);
884 regs16[*opcode_stream & 0x7] = *(uint16_t*)(opcode_stream + 1);
896 regs16[REG_ES + (*opcode_stream >> 3)] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
902 stepEx(opcode_stream);
915 if (!seg_override_en && !rep_override_en && FLAG_IF && !FLAG_TF && s_pendingIRQ) {
916 pc_interrupt(s_pendingIRQIndex);
917 s_pendingIRQ =
false;
923 void i8086::stepEx(uint8_t
const * opcode_stream)
925 set_opcode(*opcode_stream);
928 uint8_t i_reg4bit = raw_opcode_id & 7;
930 i_d = i_reg4bit / 2 & 1;
933 uint16_t i_data0 = * (int16_t *) & opcode_stream[1];
934 uint16_t i_data1 = * (int16_t *) & opcode_stream[2];
935 uint16_t i_data2 = * (int16_t *) & opcode_stream[3];
937 uint8_t i_mod = 0, i_rm = 0, i_reg = 0;
938 int32_t op_result = 0;
945 i_mod = (i_data0 & 0xFF) >> 6;
947 i_reg = i_data0 / 8 & 7;
949 if ((!i_mod && i_rm == 6) || (i_mod == 2))
950 i_data2 = * (int16_t *) & opcode_stream[4];
954 i_data1 = (int8_t) i_data1;
956 int idx = 4 * !i_mod;
957 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));
958 op_from_addr = regs_offset + (i_w ? 2 * i_reg : (2 * i_reg + i_reg / 4) & 7);
960 auto t = op_from_addr;
961 op_from_addr = rm_addr;
967 switch (xlat_opcode_id) {
973 int idx = 4 * !i_mod;
974 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);
975 op_from_addr = regs_offset + 2 * i_reg;
982 op_dest = RMEM16(op_from_addr);
983 op_result = WMEM16(op_from_addr, (uint16_t)op_dest + 1 - 2 * i_reg);
985 op_dest = RMEM8(op_from_addr);
986 op_result = WMEM8(op_from_addr, (uint16_t)op_dest + 1 - 2 * i_reg);
989 set_AF_OF_arith(op_result, i_w);
990 set_OF(op_dest + 1 - i_reg == 1 << (8 * (i_w + 1) - 1));
991 if (xlat_opcode_id == 5)
993 }
else if (i_reg != 6) {
995 uint16_t jumpTo = i_w ? MEM16(op_from_addr) : MEM8(op_from_addr);
996 if (i_reg - 3 == 0) {
1000 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_CS];
1005 regs16[REG_SP] -= 2;
1006 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = (reg_ip + 2 + i_mod * (i_mod != 3) + 2 * (!i_mod && i_rm == 6));
1010 regs16[REG_CS] = MEM16(op_from_addr + 2);
1017 regs16[REG_SP] -= 2;
1018 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = MEM16(rm_addr);
1022 op_to_addr = op_from_addr;
1029 op_dest = RMEM16(op_to_addr);
1030 op_source = (uint16_t)i_data2;
1031 op_result = (uint16_t)(op_dest & op_source);
1033 op_dest = RMEM8(op_to_addr);
1034 op_source = (uint8_t)i_data2;
1035 op_result = (uint8_t)(op_dest & op_source);
1040 WMEM16(op_to_addr, ~RMEM16(op_from_addr));
1042 WMEM8(op_to_addr, ~RMEM8(op_from_addr));
1046 op_result = WMEM16(op_to_addr, -(op_source = RMEM16(op_from_addr)));
1048 op_result = WMEM8(op_to_addr, -(op_source = RMEM8(op_from_addr)));
1051 FLAG_CF = op_result > op_dest;
1056 regs16[REG_DX] = (op_result = RMEM16(rm_addr) * regs16[REG_AX]) >> 16;
1057 regs16[REG_AX] = op_result;
1058 set_OF(set_CF(op_result - (uint16_t)op_result));
1061 regs16[REG_AX] = op_result = RMEM8(rm_addr) * regs8[REG_AL];
1062 set_OF(set_CF(op_result - (uint8_t) op_result));
1069 regs16[REG_DX] = (op_result = (int16_t)RMEM16(rm_addr) * (int16_t)regs16[REG_AX]) >> 16;
1070 regs16[REG_AX] = op_result;
1071 set_OF(set_CF(op_result - (int16_t)op_result));
1074 regs16[REG_AX] = op_result = (int8_t)RMEM8(rm_addr) * (int8_t)regs8[REG_AL];
1075 set_OF(set_CF(op_result - (int8_t) op_result));
1081 int32_t scratch_int;
1082 int32_t scratch_uint, scratch2_uint;
1084 (scratch_int = RMEM16(rm_addr))
1086 !(scratch2_uint = (uint32_t)(scratch_uint = (regs16[REG_DX] << 16) + regs16[REG_AX]) / scratch_int, scratch2_uint - (uint16_t) scratch2_uint)
1088 regs16[REG_DX] = scratch_uint - scratch_int * (regs16[REG_AX] = scratch2_uint)
1090 (raiseDivideByZeroInterrupt(), calcIP =
false);
1092 (scratch_int = RMEM8(rm_addr))
1094 !(scratch2_uint = (uint16_t)(scratch_uint = regs16[REG_AX]) / scratch_int, scratch2_uint - (uint8_t) scratch2_uint)
1096 regs8[REG_AH] = scratch_uint - scratch_int * (regs8[REG_AL] = scratch2_uint)
1098 (raiseDivideByZeroInterrupt(), calcIP =
false);
1104 int32_t scratch_int;
1105 int32_t scratch2_uint, scratch_uint;
1107 (scratch_int = (int16_t)RMEM16(rm_addr))
1109 !(scratch2_uint = (
int)(scratch_uint = (regs16[REG_DX] << 16) + regs16[REG_AX]) / scratch_int, scratch2_uint - (int16_t) scratch2_uint)
1111 regs16[REG_DX] = scratch_uint - scratch_int * (regs16[REG_AX] = scratch2_uint)
1113 (raiseDivideByZeroInterrupt(), calcIP =
false);
1115 (scratch_int = (int8_t)RMEM8(rm_addr))
1117 !(scratch2_uint = (int16_t)(scratch_uint = regs16[REG_AX]) / scratch_int, scratch2_uint - (int8_t) scratch2_uint)
1119 regs8[REG_AH] = scratch_uint - scratch_int * (regs8[REG_AL] = scratch2_uint)
1121 (raiseDivideByZeroInterrupt(), calcIP =
false);
1128 rm_addr = regs_offset;
1135 op_to_addr = rm_addr;
1136 regs16[REG_SCRATCH] = (i_d |= !i_w) ? (int8_t) i_data2 : i_data2;
1137 op_from_addr = regs_offset + 2 * REG_SCRATCH;
1139 set_opcode(0x08 * (extra = i_reg));
1146 op_dest = RMEM16(op_to_addr);
1147 op_source = RMEM16(op_from_addr);
1148 op_result = (uint16_t)(op_dest + op_source);
1149 WMEM16(op_to_addr, op_result);
1151 op_dest = RMEM8(op_to_addr);
1152 op_source = RMEM8(op_from_addr);
1153 op_result = (uint8_t)(op_dest + op_source);
1154 WMEM8(op_to_addr, op_result);
1156 FLAG_CF = op_result < op_dest;
1162 op_dest = RMEM16(op_to_addr);
1163 op_source = RMEM16(op_from_addr);
1164 op_result = op_dest | op_source;
1165 WMEM16(op_to_addr, op_result);
1167 op_dest = RMEM8(op_to_addr);
1168 op_source = RMEM8(op_from_addr);
1169 op_result = op_dest | op_source;
1170 WMEM8(op_to_addr, op_result);
1176 op_dest = RMEM16(op_to_addr);
1177 op_source = RMEM16(op_from_addr);
1178 op_result = WMEM16(op_to_addr, op_dest + FLAG_CF + op_source);
1180 op_dest = RMEM8(op_to_addr);
1181 op_source = RMEM8(op_from_addr);
1182 op_result = WMEM8(op_to_addr, op_dest + FLAG_CF + op_source);
1184 set_CF((FLAG_CF && (op_result == op_dest)) || (+op_result < +(
int) op_dest));
1185 set_AF_OF_arith(op_result, i_w);
1189 op_dest = RMEM16(op_to_addr);
1190 op_source = RMEM16(op_from_addr);
1191 op_result = WMEM16(op_to_addr, op_dest - (FLAG_CF + op_source));
1193 op_dest = RMEM8(op_to_addr);
1194 op_source = RMEM8(op_from_addr);
1195 op_result = WMEM8(op_to_addr, op_dest - (FLAG_CF + op_source));
1197 set_CF((FLAG_CF && (op_result == op_dest)) || (-op_result < -(
int) op_dest));
1198 set_AF_OF_arith(op_result, i_w);
1203 op_dest = RMEM16(op_to_addr);
1204 op_source = RMEM16(op_from_addr);
1205 op_result = op_dest & op_source;
1206 WMEM16(op_to_addr, op_result);
1208 op_dest = RMEM8(op_to_addr);
1209 op_source = RMEM8(op_from_addr);
1210 op_result = op_dest & op_source;
1211 WMEM8(op_to_addr, op_result);
1217 op_dest = RMEM16(op_to_addr);
1218 op_source = RMEM16(op_from_addr);
1219 op_result = WMEM16(op_to_addr, op_dest - op_source);
1221 op_dest = RMEM8(op_to_addr);
1222 op_source = RMEM8(op_from_addr);
1223 op_result = WMEM8(op_to_addr, op_dest - op_source);
1225 FLAG_CF = op_result > op_dest;
1230 op_dest = RMEM16(op_to_addr);
1231 op_source = RMEM16(op_from_addr);
1232 op_result = op_dest ^ op_source;
1233 WMEM16(op_to_addr, op_result);
1235 op_dest = RMEM8(op_to_addr);
1236 op_source = RMEM8(op_from_addr);
1237 op_result = op_dest ^ op_source;
1238 WMEM8(op_to_addr, op_result);
1244 op_dest = RMEM16(op_to_addr);
1245 op_source = RMEM16(op_from_addr);
1247 op_dest = RMEM8(op_to_addr);
1248 op_source = RMEM8(op_from_addr);
1250 op_result = op_dest - op_source;
1251 FLAG_CF = op_result > op_dest;
1255 WMEM16(op_to_addr, RMEM16(op_from_addr));
1257 WMEM8(op_to_addr, RMEM8(op_from_addr));
1267 int32_t scratch2_uint = 4 * !i_mod;
1268 rm_addr = i_mod < 3 ?
1269 16 * regs16[seg_override_en ?
1271 : 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]])
1272 : (regs_offset + (2 * i_rm));
1274 regs16[i_reg] = RMEM16(rm_addr);
1276 WMEM16(rm_addr, regs16[i_reg]);
1280 int idx = 4 * !i_mod;
1281 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]];
1284 regs16[REG_SP] += 2;
1285 WMEM16(rm_addr, RMEM16(16 * regs16[REG_SS] + (uint16_t)(-2 + regs16[REG_SP])));
1289 rm_addr = 16 * regs16[seg_override_en ? seg_override : REG_DS] + i_data0;
1292 WMEM16(rm_addr, regs16[REG_AX]);
1294 WMEM8(rm_addr, regs8[REG_AL]);
1298 regs16[REG_AX] = RMEM16(rm_addr);
1300 regs8[REG_AL] = RMEM8(rm_addr);
1307 uint16_t scratch2_uint = (1 & (i_w ? (int16_t)RMEM16(rm_addr) : RMEM8(rm_addr)) >> (8 * (i_w + 1) - 1));
1308 uint16_t scratch_uint = extra ?
1311 31 & regs8[REG_CL] :
1316 scratch_uint %= i_reg / 2 + 8 * (i_w + 1);
1317 scratch2_uint = i_w ? RMEM16(rm_addr) : RMEM8(rm_addr);
1322 op_dest = RMEM16(rm_addr);
1323 op_result = WMEM16(rm_addr, (uint16_t)op_dest >> scratch_uint);
1325 op_dest = RMEM8(rm_addr);
1326 op_result = WMEM8(rm_addr, (uint8_t)op_dest >> (uint8_t)scratch_uint);
1331 op_dest = RMEM16(rm_addr);
1332 op_result = WMEM16(rm_addr, (uint16_t)op_dest << scratch_uint);
1334 op_dest = RMEM8(rm_addr);
1335 op_result = WMEM8(rm_addr, (uint8_t)op_dest << (uint8_t)scratch_uint);
1341 set_CF(op_dest >> (scratch_uint - 1) & 1);
1347 op_dest = RMEM16(rm_addr);
1348 op_result = WMEM16(rm_addr, (uint16_t)op_dest + (op_source = scratch2_uint >> (16 - scratch_uint)));
1350 op_dest = RMEM8(rm_addr);
1351 op_result = WMEM8(rm_addr, (uint8_t)op_dest + (op_source = (uint8_t)scratch2_uint >> (8 - scratch_uint)));
1354 set_OF((1 & op_result >> (8 * (i_w + 1) - 1)) ^ set_CF(op_result & 1));
1357 scratch2_uint &= (1 << scratch_uint) - 1;
1359 op_dest = RMEM16(rm_addr);
1360 op_result = WMEM16(rm_addr, (uint16_t)op_dest + (op_source = scratch2_uint << (16 - scratch_uint)));
1362 op_dest = RMEM8(rm_addr);
1363 op_result = WMEM8(rm_addr, (uint8_t)op_dest + (op_source = (uint8_t)scratch2_uint << (8 - scratch_uint)));
1366 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))));
1370 op_dest = RMEM16(rm_addr);
1371 op_result = WMEM16(rm_addr, (uint16_t)op_dest + (FLAG_CF << (scratch_uint - 1)) + (op_source = scratch2_uint >> (17 - scratch_uint)));
1373 op_dest = RMEM8(rm_addr);
1374 op_result = WMEM8(rm_addr, (uint8_t)op_dest + (FLAG_CF << (scratch_uint - 1)) + (op_source = (uint8_t)scratch2_uint >> (9 - scratch_uint)));
1377 set_OF((1 & op_result >> (8 * (i_w + 1) - 1)) ^ set_CF(scratch2_uint & 1 << (8 * (i_w + 1) - scratch_uint)));
1381 op_dest = RMEM16(rm_addr);
1382 op_result = WMEM16(rm_addr, (uint16_t)op_dest + (FLAG_CF << (16 - scratch_uint)) + (op_source = scratch2_uint << (17 - scratch_uint)));
1384 op_dest = RMEM8(rm_addr);
1385 op_result = WMEM8(rm_addr, (uint8_t)op_dest + (FLAG_CF << (8 - scratch_uint)) + (op_source = (uint8_t)scratch2_uint << (9 - scratch_uint)));
1388 set_CF(scratch2_uint & 1 << (scratch_uint - 1));
1389 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)));
1394 set_OF((1 & op_result >> (8 * (i_w + 1) - 1)) ^ set_CF((1 & (op_dest << (scratch_uint - 1)) >> (8 * (i_w + 1) - 1))));
1398 set_OF((1 & op_dest >> (8 * (i_w + 1) - 1)));
1401 scratch_uint < 8 * (i_w + 1) || set_CF(scratch2_uint);
1404 op_dest = RMEM16(rm_addr);
1405 uint16_t u16 = (uint16_t)scratch2_uint * ~(((1 << 16) - 1) >> scratch_uint);
1406 op_result = WMEM16(rm_addr, op_dest + (op_source = u16));
1408 op_dest = RMEM8(rm_addr);
1409 uint8_t u8 = (uint8_t)scratch2_uint * ~(((1 << 8) - 1) >> scratch_uint);
1410 op_result = WMEM8(rm_addr, op_dest + (op_source = u8));
1418 int32_t scratch_uint = !!--regs16[REG_CX];
1419 switch (i_reg4bit) {
1421 scratch_uint &= !FLAG_ZF;
1424 scratch_uint &= FLAG_ZF;
1428 reg_ip += scratch_uint * (int8_t) i_data0;
1437 regs16[REG_CS] = i_data2;
1441 regs16[REG_SP] -= 2;
1442 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = reg_ip;
1445 reg_ip += i_d && i_w ? (int8_t) i_data0 : i_data0;
1449 op_result = RMEM16(op_from_addr) & RMEM16(op_to_addr);
1451 op_result = RMEM8(op_from_addr) & RMEM8(op_to_addr);
1455 if (i_reg4bit != REG_AX) {
1456 uint16_t t = regs16[REG_AX];
1457 regs16[REG_AX] = regs16[i_reg4bit];
1458 regs16[i_reg4bit] = t;
1463 if (op_to_addr != op_from_addr) {
1465 uint16_t t = RMEM16(op_to_addr);
1466 WMEM16(op_to_addr, RMEM16(op_from_addr));
1467 WMEM16(op_from_addr, t);
1469 uint16_t t = RMEM8(op_to_addr);
1470 WMEM8(op_to_addr, RMEM8(op_from_addr));
1471 WMEM8(op_from_addr, t);
1477 int32_t seg = seg_override_en ? seg_override : REG_DS;
1479 const int dec = (2 * FLAG_DF - 1) * 2;
1480 for (int32_t i = rep_override_en ? regs16[REG_CX] : 1; i; --i) {
1481 uint16_t src = extra & 1 ? regs16[REG_AX] : RMEM16(16 * regs16[seg] + regs16[REG_SI]);
1483 WMEM16(16 * regs16[REG_ES] + regs16[REG_DI], src);
1485 regs16[REG_AX] = src;
1486 extra & 1 || (regs16[REG_SI] -= dec);
1487 extra & 2 || (regs16[REG_DI] -= dec);
1490 const int dec = (2 * FLAG_DF - 1);
1491 for (int32_t i = rep_override_en ? regs16[REG_CX] : 1; i; --i) {
1492 uint8_t src = extra & 1 ? regs8[REG_AL] : RMEM8(16 * regs16[seg] + regs16[REG_SI]);
1494 WMEM8(16 * regs16[REG_ES] + regs16[REG_DI], src);
1496 regs8[REG_AL] = src;
1497 extra & 1 || (regs16[REG_SI] -= dec);
1498 extra & 2 || (regs16[REG_DI] -= dec);
1501 if (rep_override_en)
1508 int count = rep_override_en ? regs16[REG_CX] : 1;
1510 int incval = (2 * FLAG_DF - 1) * (i_w + 1);
1513 op_dest = i_w ? regs16[REG_AX] : regs8[REG_AL];
1514 for (; count; rep_override_en || count--) {
1516 op_result = op_dest - (op_source = RMEM16(16 * regs16[REG_ES] + regs16[REG_DI]));
1518 op_result = op_dest - (op_source = RMEM8(16 * regs16[REG_ES] + regs16[REG_DI]));
1520 regs16[REG_DI] -= incval;
1521 rep_override_en && !(--regs16[REG_CX] && ((!op_result) == rep_mode)) && (count = 0);
1525 int scratch2_uint = seg_override_en ? seg_override : REG_DS;
1526 for (; count; rep_override_en || count--) {
1528 op_dest = RMEM16(16 * regs16[scratch2_uint] + regs16[REG_SI]);
1529 op_result = op_dest - (op_source = RMEM16(16 * regs16[REG_ES] + regs16[REG_DI]));
1531 op_dest = RMEM8(16 * regs16[scratch2_uint] + regs16[REG_SI]);
1532 op_result = op_dest - (op_source = RMEM8(16 * regs16[REG_ES] + regs16[REG_DI]));
1534 regs16[REG_SI] -= incval;
1535 regs16[REG_DI] -= incval;
1536 rep_override_en && !(--regs16[REG_CX] && ((!op_result) == rep_mode)) && (count = 0);
1539 set_flags_type = 1 | 2;
1540 FLAG_CF = op_result > op_dest;
1548 reg_ip = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1549 regs16[REG_SP] += 2;
1552 regs16[REG_CS] = MEM16(16 * regs16[REG_SS] + regs16[REG_SP]);
1553 regs16[REG_SP] += 2;
1557 set_flags(MEM16(16 * regs16[REG_SS] + regs16[REG_SP]));
1558 regs16[REG_SP] += 2;
1560 regs16[REG_SP] += i_data0;
1564 WMEM16(op_from_addr, i_data2);
1566 WMEM8(op_from_addr, i_data2);
1571 int32_t port = extra ? regs16[REG_DX] : (uint8_t) i_data0;
1572 regs8[REG_AL] = s_readPort(s_context, port);
1574 regs8[REG_AH] = s_readPort(s_context, port + 1);
1579 int32_t port = extra ? regs16[REG_DX] : (uint8_t) i_data0;
1580 s_writePort(s_context, port, regs8[REG_AL]);
1582 s_writePort(s_context, port + 1, regs8[REG_AH]);
1586 rep_override_en = 2;
1588 seg_override_en && seg_override_en++;
1592 regs16[REG_SP] -= 2;
1593 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[extra];
1599 FLAG_AF = (regs8[REG_AL] & 0x0f) > 9 || FLAG_AF;
1600 FLAG_CF = regs8[REG_AL] > 0x99 || FLAG_CF;
1604 regs8[REG_AL] -= 0x60;
1606 FLAG_CF = (regs8[REG_AL] < 6);
1612 regs8[REG_AL] += 0x60;
1616 op_result = regs8[REG_AL];
1619 op_result = AAA_AAS(extra - 1);
1622 regs8[REG_AH] = -(1 & (i_w ? * (int16_t *) & regs8[REG_AL] : regs8[REG_AL]) >> (8 * (i_w + 1) - 1));
1625 regs16[REG_DX] = -(1 & (i_w ? * (int16_t *) & regs16[REG_AX] : regs16[REG_AX]) >> (8 * (i_w + 1) - 1));
1628 regs16[REG_SP] -= 2;
1629 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = regs16[REG_CS];
1630 regs16[REG_SP] -= 2;
1631 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = reg_ip + 5;
1632 regs16[REG_CS] = i_data2;
1636 regs16[REG_SP] -= 2;
1637 MEM16(16 * regs16[REG_SS] + regs16[REG_SP]) = make_flags();
1641 regs16[REG_SP] += 2;
1642 set_flags(MEM16(16 * regs16[REG_SS] + (uint16_t)(-2 + regs16[REG_SP])));
1646 set_flags((make_flags() & 0xFF00) + regs8[REG_AH]);
1649 regs8[REG_AH] = make_flags();
1653 regs16[i_reg] = RMEM16(rm_addr);
1654 regs16[extra / 2] = RMEM16(rm_addr + 2);
1662 pc_interrupt(i_data0);
1666 FLAG_OF && pc_interrupt(4);
1669 if (i_data0 &= 0xFF) {
1670 regs8[REG_AH] = regs8[REG_AL] / i_data0;
1671 op_result = regs8[REG_AL] %= i_data0;
1674 raiseDivideByZeroInterrupt();
1680 regs16[REG_AX] = op_result = 0xFF & (regs8[REG_AL] + i_data0 * regs8[REG_AH]);
1683 regs8[REG_AL] = -FLAG_CF;
1686 regs8[REG_AL] = RMEM8(16 * regs16[seg_override_en ? seg_override : REG_DS] + (uint16_t)(regs8[REG_AL] + regs16[REG_BX]));
1695 op_result = regs16[REG_AX] & i_data0;
1697 op_result = regs8[REG_AL] & (uint8_t)i_data0;
1752 printf(
"Unsupported 8086 opcode %02X %02X\n", opcode_stream[0], opcode_stream[1]);
1758 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);
1761 if (set_flags_type & 1) {
1762 FLAG_SF = (1 & op_result >> (8 * (i_w + 1) - 1));
1763 FLAG_ZF = !op_result;
1764 FLAG_PF = parity[(uint8_t) op_result];
1767 if (set_flags_type & 2)
1768 set_AF_OF_arith(op_result, i_w);
1769 if (set_flags_type & 4) {