diff --git a/src/cpu/8080.c b/src/cpu/8080.c index 28af66974..418d2a95c 100644 --- a/src/cpu/8080.c +++ b/src/cpu/8080.c @@ -15,6 +15,151 @@ #include +#include +#include "cpu.h" +#include <86box/timer.h> #include <86box/i8080.h> +#include <86box/mem.h> + +static int prefetching = 1, completed = 1; +static int in_rep = 0, repeating = 0, rep_c_flag = 0; +static int oldc, clear_lock = 0; +static int refresh = 0, cycdiff; + +static void +clock_start(void) +{ + cycdiff = cycles; +} + + +static void +clock_end(void) +{ + int diff = cycdiff - cycles; + + /* On 808x systems, clock speed is usually crystal frequency divided by an integer. */ + tsc += (uint64_t)diff * ((uint64_t)xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) + timer_process(); +} + +static void +wait(int c, int bus) +{ + cycles -= c; + if (bus < 2) { + clock_end(); + clock_start(); + } +} + +static uint8_t +readmemb(uint32_t a) +{ + uint8_t ret; + + wait(4, 1); + ret = read_mem_b(a); + + return ret; +} + +static uint8_t +ins_fetch(i8080* cpu) +{ + uint8_t ret = readmemb(cpu->pmembase + cpu->pc); + + cpu->pc++; + return ret; +} + +void +transfer_from_808x(i8080* cpu) +{ + cpu->hl = BX; + cpu->bc = CX; + cpu->de = DX; + cpu->a = AL; + cpu->flags = cpu_state.flags & 0xFF; + cpu->sp = BP; + cpu->pc = cpu_state.pc; + cpu->oldpc = cpu_state.oldpc; + cpu->pmembase = cs; + cpu->dmembase = ds; +} + +void +transfer_to_808x(i8080* cpu) +{ + BX = cpu->hl; + CX = cpu->bc; + DX = cpu->de; + AL = cpu->a; + cpu_state.flags &= 0xFF00; + cpu_state.flags |= cpu->flags & 0xFF; + BP = cpu->sp; + cpu_state.pc = cpu->pc; +} + +uint8_t +getreg_i8080(i8080 *cpu, uint8_t reg) +{ + uint8_t ret = 0xFF; + switch(reg) + { + case 0x0: ret = cpu->b; break; + case 0x1: ret = cpu->c; break; + case 0x2: ret = cpu->d; break; + case 0x3: ret = cpu->e; break; + case 0x4: ret = cpu->h; break; + case 0x5: ret = cpu->l; break; + case 0x6: ret = readmemb(cpu->dmembase + cpu->sp); break; + case 0x7: ret = cpu->a; break; + } + return ret; +} + +void +interpret_exec8080(i8080* cpu, uint8_t opcode, uint8_t (*fetch_instruction)(i8080*)) +{ + switch (opcode) { + case 0x00: + { + break; + } + } +} /* Actually implement i8080 emulation. */ +void +exec8080(i8080* cpu, int cycs) +{ + uint8_t temp = 0, temp2; + uint8_t old_af; + uint8_t handled = 0; + uint16_t addr, tempw; + uint16_t new_ip; + int bits; + + cycles += cycs; + + while (cycles > 0) { + clock_start(); + + if (!repeating) { + cpu->oldpc = cpu->pc; + opcode = ins_fetch(cpu); + oldc = cpu->flags & C_FLAG_I8080; + wait(1, 0); + } + completed = 1; + if (completed) { + repeating = 0; + in_rep = 0; + rep_c_flag = 0; + clock_end(); + //check_interrupts(); + } + } +} \ No newline at end of file diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 7863ccefa..43d026910 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -608,6 +608,7 @@ reset_808x(int hard) load_cs(0xFFFF); cpu_state.pc = 0; + cpu_state.flags |= 0x8000; rammask = 0xfffff; prefetching = 1; @@ -971,7 +972,7 @@ interrupt(uint16_t addr) pfq_clear(); ovr_seg = NULL; access(39, 16); - tempf = cpu_state.flags & 0x0fd7; + tempf = cpu_state.flags & (is_nec && cpu_state.inside_emulation_mode ? 0x8fd7 : 0x0fd7); push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); access(40, 16); @@ -984,6 +985,11 @@ interrupt(uint16_t addr) push(&old_ip); } +void +interrupt_808x(uint16_t addr) +{ + interrupt(addr); +} static void custom_nmi(void) @@ -1315,25 +1321,7 @@ set_sf(int bits) static void set_pf(void) { - static uint8_t table[0x100] = { - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4}; - - cpu_state.flags = (cpu_state.flags & ~4) | table[cpu_data & 0xff]; + cpu_state.flags = (cpu_state.flags & ~4) | (!__builtin_parity(cpu_data & 0xFF) << 2); } @@ -2450,7 +2438,7 @@ execx86(int cycs) } case 0x78: /*JS*/ case 0x69: /*JNS alias*/ - if (is186) { /* IMUL reg16,reg16/mem16,imm16 */ + if (is186 && opcode == 0x69) { /* IMUL reg16,reg16/mem16,imm16 */ uint16_t immediate = 0; bits = 16; do_mod_rm(); @@ -2466,17 +2454,13 @@ execx86(int cycs) break; case 0x6A: /*JP alias*/ if (is186) { /* PUSH imm8 */ - uint8_t bytetopush = pfq_fetchb(); - { - SP -= 1; - cpu_state.eaaddr = (SP & 0xffff); - writememb(ss, cpu_state.eaaddr, bytetopush); - } + uint16_t wordtopush = sign_extend(pfq_fetchb()); + push(&wordtopush); break; } case 0x7A: /*JP*/ case 0x6B: /*JNP alias*/ - if (is186) { /* IMUL reg16,reg16/mem16,imm8 */ + if (is186 && opcode == 0x6B) { /* IMUL reg16,reg16/mem16,imm8 */ uint16_t immediate = 0; bits = 16; do_mod_rm(); @@ -2687,7 +2671,7 @@ execx86(int cycs) break; case 0x9C: /*PUSHF*/ access(33, 16); - tempw = (cpu_state.flags & 0x0fd7) | 0xf000; + tempw = cpu_state.flags & (is_nec && cpu_state.inside_emulation_mode ? 0x8fd7 : 0x0fd7); push(&tempw); break; case 0x9D: /*POPF*/ @@ -2931,7 +2915,7 @@ execx86(int cycs) access(62, 8); set_ip(new_ip); access(45, 8); - cpu_state.flags = pop() | 2; + cpu_state.flags = pop() | 2 | (!is_nec ? 0 : (!cpu_state.inside_emulation_mode ? 0x8000 : 0)); wait(5, 0); noint = 1; nmi_enable = 1; diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 268221ff5..c6f60136a 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -188,6 +188,7 @@ typedef struct { #define D_FLAG 0x0400 #define V_FLAG 0x0800 #define NT_FLAG 0x4000 +#define MD_FLAG 0x8000 #define RF_FLAG 0x0001 /* in EFLAGS */ #define VM_FLAG 0x0002 /* in EFLAGS */ @@ -399,6 +400,8 @@ typedef struct { uint16_t flags, eflags; uint32_t _smbase; + + uint8_t inside_emulation_mode; } cpu_state_t; @@ -743,6 +746,7 @@ extern void (*cpu_exec)(int cycs); extern uint8_t do_translate, do_translate2; extern void reset_808x(int hard); +extern void interrupt_808x(uint16_t addr); extern void cpu_register_fast_off_handler(void *timer); extern void cpu_fast_off_advance(void); diff --git a/src/include/86box/i8080.h b/src/include/86box/i8080.h index 07cdadcc1..995c0c2a0 100644 --- a/src/include/86box/i8080.h +++ b/src/include/86box/i8080.h @@ -37,4 +37,13 @@ typedef struct i8080 struct { uint8_t h, l; }; }; uint16_t pc, sp; -} i8080; \ No newline at end of file + uint16_t oldpc, ei; + uint32_t pmembase, dmembase; /* Base from where i8080 starts. */ + uint8_t emulated; /* 0 = not emulated, use separate registers, 1 = emulated, use x86 registers. */ +} i8080; + +#define C_FLAG_I8080 (1 << 0) +#define P_FLAG_I8080 (1 << 2) +#define AC_FLAG_I8080 (1 << 4) +#define Z_FLAG_I8080 (1 << 6) +#define S_FLAG_I8080 (1 << 7)