diff --git a/cpuinstr/add.c b/cpuinstr/add.c index 71041f4..6a64f5f 100644 --- a/cpuinstr/add.c +++ b/cpuinstr/add.c @@ -99,7 +99,7 @@ static void add(struct cpu *cpu, WORD op) } if(op & 0x100) { - ea_begin_modify(cpu, op, r, 0, long_ops(op), 0, 0); + ea_begin_modify_ugly(cpu, op, r, 0, long_ops(op), 0, 0); cpu_set_flags_add(cpu, cpu->d[reg]&m, operand&m, r&m, r); } else { cpu_set_flags_add(cpu, operand&m, cpu->d[reg]&m, r&m, r); diff --git a/cpuinstr/clr.c b/cpuinstr/clr.c index afe393d..91b9bb6 100644 --- a/cpuinstr/clr.c +++ b/cpuinstr/clr.c @@ -2,10 +2,7 @@ #include "cpu.h" #include "cprint.h" #include "ea.h" - -#define CLR_READ 1 -#define CLR_PREFETCH 2 -#define CLR_WRITE 3 +#include "ucode.h" /* * -------------------------------------------------------------------- @@ -32,41 +29,33 @@ * (xxx).W | 12(1/2) 12(3/0) | np nR nr | np nw nW * (xxx).L | 12(1/2) 16(4/0) | np np nR nr | np nw nW */ -static void clr(struct cpu *cpu, WORD op) + +static void clr_compute(struct cpu *cpu, WORD op) { - LONG operand; - ENTER; + ea_set_data(0); + cpu_set_flags_clr(cpu); - switch(cpu->instr_state) { - case INSTR_STATE_NONE: - ea_begin_read(cpu, op); - cpu->instr_state = CLR_READ; - // Fall through. - case CLR_READ: - if(!ea_done(&operand)) { - ADD_CYCLE(2); - break; - } else { - cpu->instr_state = CLR_PREFETCH; - } - // Fall through. - case CLR_PREFETCH: - ADD_CYCLE(4); - cpu_prefetch(); - cpu->instr_state = CLR_WRITE; - ea_begin_modify(cpu, op, 0, 0, 2, 0, 0); - break; - case CLR_WRITE: - if(ea_done(&operand)) { - cpu->instr_state = INSTR_STATE_FINISHED; - } else { - ADD_CYCLE(2); - } - cpu_set_flags_clr(cpu); - break; + if((op & 0xc38) == 0x800) { + ujump(nop_uops, 1); + } else { + ujump(0, 0); } } +static u_sequence clr_seq[] = +{ + ea_begin_read, + u_prefetch, + clr_compute, + ea_begin_modify, + u_end_sequence +}; + +static void clr(struct cpu *cpu, WORD op) +{ + u_start_sequence(clr_seq, cpu, op); +} + static struct cprint *clr_print(LONG addr, WORD op) { struct cprint *ret; diff --git a/cpuinstr/ea.c b/cpuinstr/ea.c index 870dff1..177df14 100644 --- a/cpuinstr/ea.c +++ b/cpuinstr/ea.c @@ -247,13 +247,18 @@ void ea_begin_read(struct cpu *cpu, WORD op) } } +void ea_begin_modify(struct cpu *cpu, WORD op) +{ + ea_begin_modify_ugly(cpu, op, ea_data, 0, 0, 0, 0); +} + static uop_t write_reg_uops[] = { n, n, n }; static uop_t write_mem_uops[] = { w, n, w, n }; // dw, dl, aw, al are the number of additional microcycles needed to // write a data or address register with a word or a long. -void ea_begin_modify(struct cpu *cpu, WORD op, LONG data, - int dw, int dl, int aw, int al) +void ea_begin_modify_ugly(struct cpu *cpu, WORD op, LONG data, + int dw, int dl, int aw, int al) { // Byte/Word Long // Dn, An, Mem Dn, An, Mem @@ -339,6 +344,11 @@ int ea_done(LONG *operand) return 0; } +void ea_set_data(LONG data) +{ + ea_data = data; +} + LONG ea_get_address(void) { return ea_address; diff --git a/cpuinstr/ea.h b/cpuinstr/ea.h index 5dd57ac..cd8eabc 100644 --- a/cpuinstr/ea.h +++ b/cpuinstr/ea.h @@ -121,8 +121,11 @@ void ea_clear_prefetch_before_write(); void ea_begin_address(struct cpu *cpu, WORD op); void ea_begin_read(struct cpu *cpu, WORD op); void ea_begin_write(struct cpu *cpu, WORD op); -void ea_begin_modify(struct cpu *cpu, WORD op, LONG data, int, int, int, int); +void ea_begin_modify(struct cpu *cpu, WORD op); int ea_done(LONG *); +void ea_begin_modify_ugly(struct cpu *cpu, WORD op, LONG data, int, int, int, int); +int ea_done(LONG *); +void ea_set_data(LONG data); LONG ea_get_address(void); #endif diff --git a/cpuinstr/exg.c b/cpuinstr/exg.c index 110f0c2..2b90c54 100644 --- a/cpuinstr/exg.c +++ b/cpuinstr/exg.c @@ -1,8 +1,7 @@ #include "common.h" #include "cpu.h" #include "cprint.h" - -#define EXG_IN_PROGRESS 1 +#include "ucode.h" /* * -------------------------------------------------------------------- @@ -14,43 +13,44 @@ * Ax,Ay | 6(1/0) | np n * Dx,Ay | 6(1/0) | np n */ -static void exg(struct cpu *cpu, WORD op) +static void exg_compute(struct cpu *cpu, WORD op) { + int rx, ry; LONG t; - int rx,ry; - - ENTER; - switch(cpu->instr_state) { - case INSTR_STATE_NONE: - ADD_CYCLE(4); - cpu->instr_state = EXG_IN_PROGRESS; - cpu_prefetch(); + rx = (op&0xe00)>>9; + ry = (op&7); + switch(op&0xf8) { + case 0x40: /* Dx,Dy */ + t = cpu->d[rx]; + cpu->d[rx] = cpu->d[ry]; + cpu->d[ry] = t; break; - case EXG_IN_PROGRESS: - rx = (op&0xe00)>>9; - ry = (op&7); - switch(op&0xf8) { - case 0x40: /* Dx,Dy */ - t = cpu->d[rx]; - cpu->d[rx] = cpu->d[ry]; - cpu->d[ry] = t; - break; - case 0x48:/* Ax,Ay */ - t = cpu->a[rx]; - cpu->a[rx] = cpu->a[ry]; - cpu->a[ry] = t; - break; - case 0x88:/* Dx,Ay */ - t = cpu->d[rx]; - cpu->d[rx] = cpu->a[ry]; - cpu->a[ry] = t; - break; - } - ADD_CYCLE(2); - cpu->instr_state = INSTR_STATE_FINISHED; + case 0x48:/* Ax,Ay */ + t = cpu->a[rx]; + cpu->a[rx] = cpu->a[ry]; + cpu->a[ry] = t; + break; + case 0x88:/* Dx,Ay */ + t = cpu->d[rx]; + cpu->d[rx] = cpu->a[ry]; + cpu->a[ry] = t; break; } + + ujump(nop_uops, 1); +} + +static u_sequence exg_seq[] = +{ + u_prefetch, + exg_compute, + u_end_sequence +}; + +static void exg(struct cpu *cpu, WORD op) +{ + u_start_sequence(exg_seq, cpu, op); } static struct cprint *exg_print(LONG addr, WORD op) diff --git a/cpuinstr/neg.c b/cpuinstr/neg.c index 424a930..ee134ad 100644 --- a/cpuinstr/neg.c +++ b/cpuinstr/neg.c @@ -55,7 +55,7 @@ static void neg(struct cpu *cpu, WORD op) cpu_prefetch(); cpu->instr_state = NEG_WRITE; r = -operand; - ea_begin_modify(cpu, op, r, 0, 2, 0, 0); + ea_begin_modify_ugly(cpu, op, r, 0, 2, 0, 0); switch((op&0xc0)>>6) { case 0: m = 0x80; r &= 0xff; break; diff --git a/cpuinstr/negx.c b/cpuinstr/negx.c index 19bb2db..664e04e 100644 --- a/cpuinstr/negx.c +++ b/cpuinstr/negx.c @@ -58,7 +58,7 @@ static void negx(struct cpu *cpu, WORD op) if(CHKX) { r--; } - ea_begin_modify(cpu, op, r, 0, 2, 0, 0); + ea_begin_modify_ugly(cpu, op, r, 0, 2, 0, 0); switch((op&0xc0)>>6) { case 0: m = 0x80; r &= 0xff; break; diff --git a/cpuinstr/not.c b/cpuinstr/not.c index 2478151..2d98190 100644 --- a/cpuinstr/not.c +++ b/cpuinstr/not.c @@ -34,7 +34,7 @@ */ static void not(struct cpu *cpu, WORD op) { - LONG operand, r, m = 0; + LONG operand, m = 0; ENTER; switch(cpu->instr_state) { @@ -54,11 +54,11 @@ static void not(struct cpu *cpu, WORD op) ADD_CYCLE(4); cpu_prefetch(); cpu->instr_state = NOT_WRITE; - ea_begin_modify(cpu, op, ~operand, 0, 2, 0, 0); + ea_begin_modify_ugly(cpu, op, ~operand, 0, 2, 0, 0); switch((op&0xc0)>>6) { - case 0: m = 0x80; r &= 0xff; break; - case 1: m = 0x8000; r &= 0xffff; break; + case 0: m = 0x80; break; + case 1: m = 0x8000; break; case 2: m = 0x80000000; break; } cpu_set_flags_move(cpu, operand & m, operand); diff --git a/cpuinstr/sub.c b/cpuinstr/sub.c index 21e8f8f..97f0949 100644 --- a/cpuinstr/sub.c +++ b/cpuinstr/sub.c @@ -99,7 +99,7 @@ static void sub(struct cpu *cpu, WORD op) if(op & 0x100) { r = operand - cpu->d[reg]; - ea_begin_modify(cpu, op, r, 0, long_ops(op), 0, 0); + ea_begin_modify_ugly(cpu, op, r, 0, long_ops(op), 0, 0); cpu_set_flags_sub(cpu, cpu->d[reg]&m1, operand&m1, r&m1, r&m2); } else { r = cpu->d[reg] - operand; diff --git a/cpuinstr/ucode.c b/cpuinstr/ucode.c index 6a6e94f..e333b40 100644 --- a/cpuinstr/ucode.c +++ b/cpuinstr/ucode.c @@ -1,5 +1,10 @@ +#include "common.h" #include "ucode.h" +#define INSTR_STATE_RUNNING 1 + +static u_sequence *seq_pointer; + static int ucycles; static uop_t *upc; @@ -20,3 +25,46 @@ int ustep(void) return 0; } + +void u_start_sequence(u_sequence *seq, struct cpu *cpu, WORD op) +{ + if(cpu->instr_state == INSTR_STATE_NONE) { + cpu->instr_state = INSTR_STATE_RUNNING; + seq_pointer = seq; + ujump(0, 0); + } + + while(ustep()) { + (*seq_pointer)(cpu, op); + seq_pointer++; + if(cpu->instr_state == INSTR_STATE_FINISHED) + break; + else + ADD_CYCLE(2); + } +} + +void u_end_sequence(struct cpu *cpu, WORD op) +{ + cpu->instr_state = INSTR_STATE_FINISHED; + ujump(0, 0); +} + +// Do nothing. +static void u_nop(void) +{ +} + +// Fetch from program. +static void u_pf(void) +{ + cpu_prefetch(); +} + +uop_t nop_uops[] = { u_nop, u_nop }; +static uop_t prefetch_uops[] = { u_pf, u_nop }; + +void u_prefetch(struct cpu *cpu, WORD op) +{ + ujump(prefetch_uops, 2); +} diff --git a/cpuinstr/ucode.h b/cpuinstr/ucode.h index 65eed9d..acac00d 100644 --- a/cpuinstr/ucode.h +++ b/cpuinstr/ucode.h @@ -1,8 +1,15 @@ #ifndef UCODE_H #define UCODE_H +typedef void (*u_sequence)(struct cpu *cpu, WORD op); +extern void u_start_sequence(u_sequence *, struct cpu *, WORD); +extern void u_end_sequence(struct cpu *, WORD); +extern void u_prefetch(struct cpu *, WORD); + typedef void (*uop_t)(void); extern void ujump(uop_t *, int); extern int ustep(void); +extern uop_t nop_uops[]; + #endif /* UCODE_H */