--- hatari/src/falcon/dsp_cpu.c 2019/04/01 07:14:55 1.1.1.2 +++ hatari/src/falcon/dsp_cpu.c 2019/04/09 08:47:23 1.1.1.4 @@ -1,6 +1,6 @@ /* DSP M56001 emulation - Instructions interpreter, execution thread + Instructions interpreter (C) 2003-2008 ARAnyM developer team @@ -25,13 +25,11 @@ #include "dsp_core.h" #include "dsp_cpu.h" -#ifdef DSP_DISASM #include "dsp_disasm.h" -#endif -#define DEBUG 0 /* More disasm infos, if wanted */ +#define DSP_DISASM 0 /* Main DSP disassembler switch */ #define DSP_DISASM_INST 0 /* Instructions */ #define DSP_DISASM_REG 0 /* Registers changes */ #define DSP_DISASM_MEM 0 /* Memory changes */ @@ -52,15 +50,25 @@ #define BITMASK(x) ((1<<(x))-1) +/* cycle counter wait state time when access to external memory */ +#define XY_WAITSTATE 1 +#define P_WAITSTATE 1 +#define XP_WAITSTATE 1 /* X Peripheral WaitState */ +#define YP_WAITSTATE 1 /* Y Peripheral WaitState */ + /********************************** * Variables **********************************/ +/* Instructions per second */ +static Uint32 start_time; +static Uint32 num_inst; + /* Length of current instruction */ static Uint32 cur_inst_len; /* =0:jump, >0:increment */ /* Current instruction */ -static Uint32 cur_inst; +static Uint32 cur_inst; /* Parallel move temp data */ typedef union { @@ -75,8 +83,6 @@ static Uint32 tmp_parmove_len[2]; /* Ho static Uint32 tmp_parmove_type[2]; /* 0=register, 1=memory */ static Uint32 tmp_parmove_space[2]; /* Memory space to write to */ -/* PC on Rep instruction ? */ -static Uint32 pc_on_rep; /********************************** * Functions @@ -84,32 +90,25 @@ static Uint32 pc_on_rep; typedef void (*dsp_emul_t)(void); -static void dsp_execute_instruction(void); static void dsp_postexecute_update_pc(void); static void dsp_postexecute_interrupts(void); -static void dsp_ccr_extension(Uint32 *reg0, Uint32 *reg1); -static void dsp_ccr_unnormalized(Uint32 *reg0, Uint32 *reg1); -static void dsp_ccr_negative(Uint32 *reg0); -static void dsp_ccr_zero(Uint32 *reg0, Uint32 *reg1, Uint32 *reg2); +static void dsp_ccr_update_e_u_n_z(Uint32 *reg0, Uint32 *reg1, Uint32 *reg2); +static inline Uint32 read_memory_p(Uint16 address); static Uint32 read_memory(int space, Uint16 address); -static void write_memory_raw(int space, Uint32 address, Uint32 value); +static void write_memory_raw(int space, Uint16 address, Uint32 value); #if defined(DSP_DISASM) && (DSP_DISASM_MEM==1) static Uint32 read_memory_disasm(int space, Uint16 address); -static void write_memory_disasm(int space, Uint32 address, Uint32 value); +static void write_memory_disasm(int space, Uint16 address, Uint32 value); #endif +static void dsp_write_reg(Uint32 numreg, Uint32 value); -static void dsp_stack_push(Uint32 curpc, Uint32 cursr); +static void dsp_stack_push(Uint32 curpc, Uint32 cursr, Uint16 sshOnly); static void dsp_stack_pop(Uint32 *curpc, Uint32 *cursr); +static void dsp_compute_ssh_ssl(void); static void opcode8h_0(void); -static void opcode8h_1(void); -static void opcode8h_4(void); -static void opcode8h_6(void); -static void opcode8h_8(void); -static void opcode8h_a(void); -static void opcode8h_b(void); static void dsp_update_rn(Uint32 numreg, Sint16 modifier); static void dsp_update_rn_bitreverse(Uint32 numreg); @@ -121,30 +120,55 @@ static void dsp_undefined(void); /* Instructions without parallel moves */ static void dsp_andi(void); -static void dsp_bchg(void); -static void dsp_bclr(void); -static void dsp_bset(void); -static void dsp_btst(void); +static void dsp_bchg_aa(void); +static void dsp_bchg_ea(void); +static void dsp_bchg_pp(void); +static void dsp_bchg_reg(void); +static void dsp_bclr_aa(void); +static void dsp_bclr_ea(void); +static void dsp_bclr_pp(void); +static void dsp_bclr_reg(void); +static void dsp_bset_aa(void); +static void dsp_bset_ea(void); +static void dsp_bset_pp(void); +static void dsp_bset_reg(void); +static void dsp_btst_aa(void); +static void dsp_btst_ea(void); +static void dsp_btst_pp(void); +static void dsp_btst_reg(void); static void dsp_div(void); -static void dsp_do(void); static void dsp_enddo(void); static void dsp_illegal(void); -static void dsp_jcc(void); -static void dsp_jclr(void); -static void dsp_jmp(void); -static void dsp_jscc(void); -static void dsp_jsclr(void); -static void dsp_jset(void); -static void dsp_jsr(void); -static void dsp_jsset(void); +static void dsp_jcc_imm(void); +static void dsp_jcc_ea(void); +static void dsp_jclr_aa(void); +static void dsp_jclr_ea(void); +static void dsp_jclr_pp(void); +static void dsp_jclr_reg(void); +static void dsp_jmp_ea(void); +static void dsp_jmp_imm(void); +static void dsp_jscc_ea(void); +static void dsp_jscc_imm(void); +static void dsp_jsclr_aa(void); +static void dsp_jsclr_ea(void); +static void dsp_jsclr_pp(void); +static void dsp_jsclr_reg(void); +static void dsp_jset_aa(void); +static void dsp_jset_ea(void); +static void dsp_jset_pp(void); +static void dsp_jset_reg(void); +static void dsp_jsr_ea(void); +static void dsp_jsr_imm(void); +static void dsp_jsset_aa(void); +static void dsp_jsset_ea(void); +static void dsp_jsset_pp(void); +static void dsp_jsset_reg(void); static void dsp_lua(void); -static void dsp_movec(void); -static void dsp_movem(void); -static void dsp_movep(void); +static void dsp_movem_ea(void); +static void dsp_movem_aa(void); static void dsp_nop(void); static void dsp_norm(void); static void dsp_ori(void); -static void dsp_rep(void); static void dsp_reset(void); static void dsp_rti(void); static void dsp_rts(void); @@ -153,25 +177,26 @@ static void dsp_swi(void); static void dsp_tcc(void); static void dsp_wait(void); -static void dsp_do_0(void); -static void dsp_do_2(void); -static void dsp_do_4(void); -static void dsp_do_c(void); -static void dsp_rep_1(void); -static void dsp_rep_3(void); -static void dsp_rep_5(void); -static void dsp_rep_d(void); -static void dsp_movec_7(void); -static void dsp_movec_9(void); -static void dsp_movec_b(void); -static void dsp_movec_d(void); +static void dsp_do_ea(void); +static void dsp_do_aa(void); +static void dsp_do_imm(void); +static void dsp_do_reg(void); +static void dsp_rep_aa(void); +static void dsp_rep_ea(void); +static void dsp_rep_imm(void); +static void dsp_rep_reg(void); +static void dsp_movec_aa(void); +static void dsp_movec_ea(void); +static void dsp_movec_imm(void); +static void dsp_movec_reg(void); static void dsp_movep_0(void); static void dsp_movep_1(void); -static void dsp_movep_2(void); +static void dsp_movep_23(void); /* Parallel move analyzer */ static void dsp_parmove_read(void); static void dsp_parmove_write(void); +static void dsp_pm_class2(void); static int dsp_pm_read_accu24(int numreg, Uint32 *dest); static void dsp_pm_writereg(int numreg, int position); @@ -182,7 +207,7 @@ static void dsp_pm_2(void); static void dsp_pm_2_2(void); static void dsp_pm_3(void); static void dsp_pm_4(void); -static void dsp_pm_4x(int immediat, Uint32 l_addr); +static void dsp_pm_4x(void); static void dsp_pm_5(void); static void dsp_pm_8(void); @@ -228,123 +253,86 @@ static void dsp_subr(void); static void dsp_tfr(void); static void dsp_tst(void); -static void dsp_move_pm(void); - -static dsp_emul_t opcodes8h[16]={ - opcode8h_0, - opcode8h_1, - dsp_tcc, - dsp_tcc, - opcode8h_4, - dsp_movec, - opcode8h_6, - dsp_movem, - opcode8h_8, - opcode8h_8, - opcode8h_a, - opcode8h_b, - dsp_jmp, - dsp_jsr, - dsp_jcc, - dsp_jscc -}; - -static dsp_emul_t opcodes_0809[16]={ - dsp_move_pm, - dsp_move_pm, - dsp_move_pm, - dsp_move_pm, - - dsp_movep, - dsp_movep, - dsp_movep, - dsp_movep, - - dsp_move_pm, - dsp_move_pm, - dsp_move_pm, - dsp_move_pm, - - dsp_movep, - dsp_movep, - dsp_movep, - dsp_movep -}; - -static dsp_emul_t opcodes_0a[32]={ - /* 00 000 */ dsp_bclr, - /* 00 001 */ dsp_bset, - /* 00 010 */ dsp_bclr, - /* 00 011 */ dsp_bset, - /* 00 100 */ dsp_jclr, - /* 00 101 */ dsp_jset, - /* 00 110 */ dsp_jclr, - /* 00 111 */ dsp_jset, - - /* 01 000 */ dsp_bclr, - /* 01 001 */ dsp_bset, - /* 01 010 */ dsp_bclr, - /* 01 011 */ dsp_bset, - /* 01 100 */ dsp_jclr, - /* 01 101 */ dsp_jset, - /* 01 110 */ dsp_jclr, - /* 01 111 */ dsp_jset, - - /* 10 000 */ dsp_bclr, - /* 10 001 */ dsp_bset, - /* 10 010 */ dsp_bclr, - /* 10 011 */ dsp_bset, - /* 10 100 */ dsp_jclr, - /* 10 101 */ dsp_jset, - /* 10 110 */ dsp_jclr, - /* 10 111 */ dsp_jset, - - /* 11 000 */ dsp_jclr, - /* 11 001 */ dsp_jset, - /* 11 010 */ dsp_bclr, - /* 11 011 */ dsp_bset, - /* 11 100 */ dsp_jmp, - /* 11 101 */ dsp_jcc, - /* 11 110 */ dsp_undefined, - /* 11 111 */ dsp_undefined -}; - -static dsp_emul_t opcodes_0b[32]={ - /* 00 000 */ dsp_bchg, - /* 00 001 */ dsp_btst, - /* 00 010 */ dsp_bchg, - /* 00 011 */ dsp_btst, - /* 00 100 */ dsp_jsclr, - /* 00 101 */ dsp_jsset, - /* 00 110 */ dsp_jsclr, - /* 00 111 */ dsp_jsset, - - /* 01 000 */ dsp_bchg, - /* 01 001 */ dsp_btst, - /* 01 010 */ dsp_bchg, - /* 01 011 */ dsp_btst, - /* 01 100 */ dsp_jsclr, - /* 01 101 */ dsp_jsset, - /* 01 110 */ dsp_jsclr, - /* 01 111 */ dsp_jsset, - - /* 10 000 */ dsp_bchg, - /* 10 001 */ dsp_btst, - /* 10 010 */ dsp_bchg, - /* 10 011 */ dsp_btst, - /* 10 100 */ dsp_jsclr, - /* 10 101 */ dsp_jsset, - /* 10 110 */ dsp_jsclr, - /* 10 111 */ dsp_jsset, - - /* 11 000 */ dsp_jsclr, - /* 11 001 */ dsp_jsclr, - /* 11 010 */ dsp_bchg, - /* 11 011 */ dsp_btst, - /* 11 100 */ dsp_jsr, - /* 11 101 */ dsp_jscc, - /* 11 110 */ dsp_undefined, - /* 11 111 */ dsp_undefined +static dsp_emul_t opcodes8h[512]={ + /* 0x00 - 0x3f */ + opcode8h_0, dsp_undefined, dsp_undefined, dsp_undefined, opcode8h_0, dsp_andi, dsp_undefined, dsp_ori, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_andi, dsp_undefined, dsp_ori, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_andi, dsp_undefined, dsp_ori, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_andi, dsp_undefined, dsp_ori, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_div, dsp_div, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_norm, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + + /* 0x40 - 0x7f */ + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + + /* 0x80 - 0xbf */ + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_lua, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_movec_reg, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_movec_reg, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_movec_aa, dsp_undefined, dsp_movec_aa, dsp_undefined, dsp_movec_imm, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_movec_ea, dsp_undefined, dsp_movec_ea, dsp_undefined, dsp_movec_imm, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_movec_aa, dsp_undefined, dsp_movec_aa, dsp_undefined, dsp_movec_imm, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_movec_ea, dsp_undefined, dsp_movec_ea, dsp_undefined, dsp_movec_imm, dsp_undefined, dsp_undefined, + + /* 0xc0 - 0xff */ + dsp_do_aa, dsp_rep_aa, dsp_do_aa, dsp_rep_aa, dsp_do_imm, dsp_rep_imm, dsp_undefined, dsp_undefined, + dsp_do_ea, dsp_rep_ea, dsp_do_ea, dsp_rep_ea, dsp_do_imm, dsp_rep_imm, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_do_imm, dsp_rep_imm, dsp_undefined, dsp_undefined, + dsp_do_reg, dsp_rep_reg, dsp_undefined, dsp_undefined, dsp_do_imm, dsp_rep_imm, dsp_undefined, dsp_undefined, + dsp_movem_aa, dsp_movem_aa, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_movem_ea, dsp_movem_ea, dsp_undefined, dsp_undefined, + dsp_movem_aa, dsp_movem_aa, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_movem_ea, dsp_movem_ea, dsp_undefined, dsp_undefined, + + /* 0x100 - 0x13f */ + dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, + dsp_movep_0, dsp_movep_0, dsp_movep_1, dsp_movep_1, dsp_movep_23, dsp_movep_23, dsp_movep_23, dsp_movep_23, + dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, + dsp_movep_0, dsp_movep_0, dsp_movep_1, dsp_movep_1, dsp_movep_23, dsp_movep_23, dsp_movep_23, dsp_movep_23, + dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, + dsp_movep_0, dsp_movep_0, dsp_movep_1, dsp_movep_1, dsp_movep_23, dsp_movep_23, dsp_movep_23, dsp_movep_23, + dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, + dsp_movep_0, dsp_movep_0, dsp_movep_1, dsp_movep_1, dsp_movep_23, dsp_movep_23, dsp_movep_23, dsp_movep_23, + + /* 0x140 - 0x17f */ + dsp_bclr_aa, dsp_bset_aa, dsp_bclr_aa, dsp_bset_aa, dsp_jclr_aa, dsp_jset_aa, dsp_jclr_aa, dsp_jset_aa, + dsp_bclr_ea, dsp_bset_ea, dsp_bclr_ea, dsp_bset_ea, dsp_jclr_ea, dsp_jset_ea, dsp_jclr_ea, dsp_jset_ea, + dsp_bclr_pp, dsp_bset_pp, dsp_bclr_pp, dsp_bset_pp, dsp_jclr_pp, dsp_jset_pp, dsp_jclr_pp, dsp_jset_pp, + dsp_jclr_reg, dsp_jset_reg, dsp_bclr_reg, dsp_bset_reg, dsp_jmp_ea, dsp_jcc_ea, dsp_undefined, dsp_undefined, + dsp_bchg_aa, dsp_btst_aa, dsp_bchg_aa, dsp_btst_aa, dsp_jsclr_aa, dsp_jsset_aa, dsp_jsclr_aa, dsp_jsset_aa, + dsp_bchg_ea, dsp_btst_ea, dsp_bchg_ea, dsp_btst_ea, dsp_jsclr_ea, dsp_jsset_ea, dsp_jsclr_ea, dsp_jsset_ea, + dsp_bchg_pp, dsp_btst_pp, dsp_bchg_pp, dsp_btst_pp, dsp_jsclr_pp, dsp_jsset_pp, dsp_jsclr_pp, dsp_jsset_pp, + dsp_jsclr_reg, dsp_jsset_reg, dsp_bchg_reg, dsp_btst_reg, dsp_jsr_ea, dsp_jscc_ea, dsp_undefined, dsp_undefined, + + /* 0x180 - 0x1bf */ + dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + + /* 0x1c0 - 0x1ff */ + dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, + dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, + dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, + dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, + dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, + dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, + dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, + dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, }; static dsp_emul_t opcodes_parmove[16]={ @@ -367,188 +355,46 @@ static dsp_emul_t opcodes_parmove[16]={ dsp_pm_8 }; -static dsp_emul_t opcodes_alu003f[64]={ - /* 0x00 - 0x0f */ - dsp_move, - dsp_tfr, - dsp_addr, - dsp_tst, - dsp_undefined, - dsp_cmp, - dsp_subr, - dsp_cmpm, - dsp_undefined, - dsp_tfr, - dsp_addr, - dsp_tst, - dsp_undefined, - dsp_cmp, - dsp_subr, - dsp_cmpm, - - /* 0x10 - 0x1f */ - dsp_add, - dsp_rnd, - dsp_addl, - dsp_clr, - dsp_sub, - dsp_undefined, - dsp_subl, - dsp_not, - dsp_add, - dsp_rnd, - dsp_addl, - dsp_clr, - dsp_sub, - dsp_undefined, - dsp_subl, - dsp_not, - - /* 0x20 - 0x2f */ - dsp_add, - dsp_adc, - dsp_asr, - dsp_lsr, - dsp_sub, - dsp_sbc, - dsp_abs, - dsp_ror, - dsp_add, - dsp_adc, - dsp_asr, - dsp_lsr, - dsp_sub, - dsp_sbc, - dsp_abs, - dsp_ror, - - /* 0x30 - 0x3f */ - dsp_add, - dsp_adc, - dsp_asl, - dsp_lsl, - dsp_sub, - dsp_sbc, - dsp_neg, - dsp_rol, - dsp_add, - dsp_adc, - dsp_asl, - dsp_lsl, - dsp_sub, - dsp_sbc, - dsp_neg, - dsp_rol -}; - -static dsp_emul_t opcodes_alu407f[16]={ - dsp_add, - dsp_tfr, - dsp_or, - dsp_eor, - dsp_sub, - dsp_cmp, - dsp_and, - dsp_cmpm, - dsp_add, - dsp_tfr, - dsp_or, - dsp_eor, - dsp_sub, - dsp_cmp, - dsp_and, - dsp_cmpm -}; - -static dsp_emul_t opcodes_alu80ff[4]={ - dsp_mpy, - dsp_mpyr, - dsp_mac, - dsp_macr -}; - -static dsp_emul_t opcodes_do[16]={ - dsp_do_0, - dsp_undefined, - dsp_do_2, - dsp_undefined, - - dsp_do_4, - dsp_undefined, - dsp_do_2, - dsp_undefined, - - dsp_undefined, - dsp_undefined, - dsp_do_2, - dsp_undefined, - - dsp_do_c, - dsp_undefined, - dsp_do_2, - dsp_undefined -}; - -static dsp_emul_t opcodes_rep[16]={ - dsp_undefined, - dsp_rep_1, - dsp_undefined, - dsp_rep_3, - - dsp_undefined, - dsp_rep_5, - dsp_undefined, - dsp_rep_3, - - dsp_undefined, - dsp_undefined, - dsp_undefined, - dsp_rep_3, - - dsp_undefined, - dsp_rep_d, - dsp_undefined, - dsp_rep_3 -}; - -static dsp_emul_t opcodes_movec[16]={ - dsp_undefined, - dsp_undefined, - dsp_undefined, - dsp_undefined, - - dsp_undefined, - dsp_undefined, - dsp_undefined, - dsp_movec_7, - - dsp_undefined, - dsp_movec_9, - dsp_undefined, - dsp_movec_b, - - dsp_undefined, - dsp_movec_d, - dsp_undefined, - dsp_movec_b -}; - -static dsp_emul_t opcodes_movep[4]={ - dsp_movep_0, - dsp_movep_1, - dsp_movep_2, - dsp_movep_2 -}; - -static int registers_lmove[8][2]={ - {DSP_REG_A1,DSP_REG_A0}, /* A10 */ - {DSP_REG_B1,DSP_REG_B0}, /* B10 */ - {DSP_REG_X1,DSP_REG_X0}, /* X */ - {DSP_REG_Y1,DSP_REG_Y0}, /* Y */ - {DSP_REG_A,DSP_REG_A}, /* A */ - {DSP_REG_B,DSP_REG_B}, /* B */ - {DSP_REG_A,DSP_REG_B}, /* AB */ - {DSP_REG_B,DSP_REG_A} /* BA */ +static dsp_emul_t opcodes_alu[256]={ + /* 0x00 - 0x3f */ + dsp_move, dsp_tfr, dsp_addr, dsp_tst, dsp_undefined, dsp_cmp, dsp_subr, dsp_cmpm, + dsp_undefined, dsp_tfr, dsp_addr, dsp_tst, dsp_undefined, dsp_cmp, dsp_subr, dsp_cmpm, + dsp_add, dsp_rnd, dsp_addl, dsp_clr, dsp_sub, dsp_undefined, dsp_subl, dsp_not, + dsp_add, dsp_rnd, dsp_addl, dsp_clr, dsp_sub, dsp_undefined, dsp_subl, dsp_not, + dsp_add, dsp_adc, dsp_asr, dsp_lsr, dsp_sub, dsp_sbc, dsp_abs, dsp_ror, + dsp_add, dsp_adc, dsp_asr, dsp_lsr, dsp_sub, dsp_sbc, dsp_abs, dsp_ror, + dsp_add, dsp_adc, dsp_asl, dsp_lsl, dsp_sub, dsp_sbc, dsp_neg, dsp_rol, + dsp_add, dsp_adc, dsp_asl, dsp_lsl, dsp_sub, dsp_sbc, dsp_neg, dsp_rol, + + /* 0x40 - 0x7f */ + dsp_add, dsp_tfr, dsp_or, dsp_eor, dsp_sub, dsp_cmp, dsp_and, dsp_cmpm, + dsp_add, dsp_tfr, dsp_or, dsp_eor, dsp_sub, dsp_cmp, dsp_and, dsp_cmpm, + dsp_add, dsp_tfr, dsp_or, dsp_eor, dsp_sub, dsp_cmp, dsp_and, dsp_cmpm, + dsp_add, dsp_tfr, dsp_or, dsp_eor, dsp_sub, dsp_cmp, dsp_and, dsp_cmpm, + dsp_add, dsp_tfr, dsp_or, dsp_eor, dsp_sub, dsp_cmp, dsp_and, dsp_cmpm, + dsp_add, dsp_tfr, dsp_or, dsp_eor, dsp_sub, dsp_cmp, dsp_and, dsp_cmpm, + dsp_add, dsp_tfr, dsp_or, dsp_eor, dsp_sub, dsp_cmp, dsp_and, dsp_cmpm, + dsp_add, dsp_tfr, dsp_or, dsp_eor, dsp_sub, dsp_cmp, dsp_and, dsp_cmpm, + + /* 0x80 - 0xbf */ + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + + /* 0xc0 - 0xff */ + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, + dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr, dsp_mpy, dsp_mpyr, dsp_mac, dsp_macr }; static int registers_tcc[16][2]={ @@ -604,9 +450,23 @@ static int registers_mask[64]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 8, 6, - 6, 6, 16, 16 + 16, 16, 16, 16 +}; + +static int interrupt_adress[13]={ + 0x0, 0x3e, 0x2, 0x4, + 0x6, 0xff, 0x20, 0x22, 0x0, + 0xe, 0xc, 0x12, 0x10 }; +#if DSP_DISASM_INTER +static const char *interrupt_label[13]={ + "Reset", "Illegal", "Stack Error", "Trace", + "Swi", "Host Command", "Host receive", "Host transmit", "", + "SSI receive with exception", "SSI receive", "SSI transmit with exception", "SSI tramsmit" +}; +#endif + /********************************** * Emulator kernel **********************************/ @@ -614,45 +474,17 @@ static int registers_mask[64]={ /* Yep, feel lazy, so put it there */ static dsp_core_t *dsp_core; -int dsp56k_do_execute(void *th_dsp_core) +void dsp56k_init_cpu(void *th_dsp_core) { - Uint32 start_time, num_inst; - dsp_core = th_dsp_core; #ifdef DSP_DISASM dsp56k_disasm_init(dsp_core); #endif - -#if DSP_DISASM_STATE - fprintf(stderr, "Dsp: WAIT_BOOTSTRAP\n"); -#endif - SDL_SemWait(dsp_core->semaphore); - start_time = SDL_GetTicks(); num_inst = 0; - while(dsp_core->running) { - dsp_execute_instruction(); -#if DSP_COUNT_IPS - ++num_inst; - if ((num_inst & 63) == 0) { - /* Evaluate time after instructions have been executed to avoid asking too frequently */ - Uint32 cur_time = SDL_GetTicks(); - if (cur_time-start_time>1000) { - fprintf(stderr, "Dsp: %d i/s\n", (num_inst*1000)/(cur_time-start_time)); - start_time=cur_time; - num_inst=0; - } - } -#endif - } - -#if DSP_DISASM_STATE - fprintf(stderr, "Dsp: SHUTDOWN\n"); -#endif - return 0; } -static void dsp_execute_instruction(void) +void dsp56k_execute_instruction(void) { Uint32 value; @@ -664,37 +496,47 @@ static void dsp_execute_instruction(void dsp56k_disasm(); #endif #endif - /* Decode and execute current instruction */ - cur_inst = read_memory(DSP_SPACE_P, dsp_core->pc); + cur_inst = read_memory_p(dsp_core->pc); cur_inst_len = 1; + + /* Initialize instruction cycle counter */ + dsp_core->instr_cycle = 2; - value = (cur_inst >> 16) & BITMASK(8); - if (value< 0x10) { + if (cur_inst < 0x100000) { + value = (cur_inst >> 11) & (BITMASK(6) << 3); + value += (cur_inst >> 5) & BITMASK(3); opcodes8h[value](); } else { dsp_parmove_read(); value = cur_inst & BITMASK(8); - if (value < 0x40) { - opcodes_alu003f[value](); - } else if (value < 0x80) { - value &= BITMASK(4); - opcodes_alu407f[value](); - } else { - value &= BITMASK(2); - opcodes_alu80ff[value](); - } + opcodes_alu[value](); dsp_parmove_write(); } - /* Don't update the PC if we are halted */ - /*if (dsp_core->state == DSP_RUNNING)*/ { - dsp_postexecute_update_pc(); - } + /* Process the PC */ + dsp_postexecute_update_pc(); - /* Interrupts ? */ + /* Process Interrupts */ dsp_postexecute_interrupts(); + /* process peripherals On Chip components */ + dsp_core_process_host_interface(dsp_core); + dsp_core_process_ssi_interface(dsp_core); + +#if DSP_COUNT_IPS + ++num_inst; + if ((num_inst & 63) == 0) { + /* Evaluate time after instructions have been executed to avoid asking too frequently */ + Uint32 cur_time = SDL_GetTicks(); + if (cur_time-start_time>1000) { + fprintf(stderr, "Dsp: %d i/s\n", (num_inst*1000)/(cur_time-start_time)); + start_time=cur_time; + num_inst=0; + } + } +#endif + #ifdef DSP_DISASM #if DSP_DISASM_REG dsp56k_disasm_reg_compare(); @@ -711,7 +553,7 @@ static void dsp_postexecute_update_pc(vo /* When running a REP, PC must stay on the current instruction */ if (dsp_core->loop_rep) { /* Is PC on the instruction to repeat ? */ - if (pc_on_rep==0) { + if (dsp_core->pc_on_rep==0) { --dsp_core->registers[DSP_REG_LC]; dsp_core->registers[DSP_REG_LC] &= BITMASK(16); @@ -732,7 +574,7 @@ static void dsp_postexecute_update_pc(vo dsp56k_disasm_force_reg_changed(DSP_REG_LC); #endif } - pc_on_rep = 0; + dsp_core->pc_on_rep = 0; } } @@ -752,13 +594,15 @@ static void dsp_postexecute_update_pc(vo if (dsp_core->registers[DSP_REG_LC]==0) { /* end of loop */ - Uint32 newpc; - - dsp_stack_pop(&newpc, &dsp_core->registers[DSP_REG_SR]); + Uint32 saved_pc, saved_sr; + + dsp_stack_pop(&saved_pc, &saved_sr); + dsp_core->registers[DSP_REG_SR] &= 0x7f; + dsp_core->registers[DSP_REG_SR] |= saved_sr & (1<registers[DSP_REG_LA], &dsp_core->registers[DSP_REG_LC]); } else { /* Loop one more time */ - dsp_core->pc = dsp_core->stack[0][dsp_core->registers[DSP_REG_SSH]]; + dsp_core->pc = dsp_core->registers[DSP_REG_SSH]; } #ifdef DSP_DISASM dsp56k_disasm_force_reg_changed(DSP_REG_LC); @@ -773,55 +617,164 @@ static void dsp_postexecute_update_pc(vo static void dsp_postexecute_interrupts(void) { - Uint32 ipl, ipl_hi; - - ipl = (dsp_core->registers[DSP_REG_SR]>>DSP_SR_I0) & BITMASK(2); - ipl_hi = (dsp_core->periph[DSP_SPACE_X][DSP_IPR]>>10) & BITMASK(2); + Uint32 ipl, ipl_to_raise, ipl_hi, ipl_ssi, instr1, instr2, i, count1, count2, ipl1, ipl2; - /* Trace, level 3 */ + /* REP is not interruptible */ + if (dsp_core->loop_rep) { + return; + } + + /* A fast interrupt can not be interrupted. */ + if (dsp_core->interrupt_state == DSP_INTERRUPT_FAST) { + /* Did we execute the 2-inst interrupt of the vector ? */ + if (dsp_core->pc >= dsp_core->interrupt_instr_fetch+2) { + if (dsp_core->pc == dsp_core->interrupt_instr_fetch+2) { + dsp_core->pc = dsp_core->interrupt_save_pc; + } + dsp_core->interrupt_save_pc = -1; + dsp_core->interrupt_instr_fetch = -1; + dsp_core->interrupt_state = DSP_INTERRUPT_NONE; + } + return; + } + + /* Trace Interrupt ? */ if (dsp_core->registers[DSP_REG_SR] & (1<0) && ((ipl_hi-1)>=ipl)) { + /* No interrupt to execute */ + if (dsp_core->interrupt_counter == 0) { + return; + } - /* Host transmit */ - if ( - (dsp_core->periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<interrupt_table[i] != 0) { + ipl_to_raise = 3; + dsp_core->interrupt_instr_fetch = interrupt_adress[i]; + dsp_core->interrupt_table[i] = 0; + dsp_core->interrupt_counter --; #if DSP_DISASM_INTER - fprintf(stderr, "Dsp: Interrupt: Host transmit\n"); + fprintf(stderr, "Dsp: Interrupt: %s\n", interrupt_label[i]); #endif + break; + } + } + + /* Level 2 and above interrupt ? */ + ipl = (dsp_core->registers[DSP_REG_SR]>>DSP_SR_I0) & BITMASK(2); + if ((ipl_to_raise==99) && (ipl<3)) { + ipl_hi = (dsp_core->periph[DSP_SPACE_X][DSP_IPR]>>10) & BITMASK(2); + ipl_ssi = (dsp_core->periph[DSP_SPACE_X][DSP_IPR]>>12) & BITMASK(2); + + /* Determine the order of the peripheral interrupt to test . + If 2 or more peripharal have the same interrupt level, + the order is (high priority) : HI, SSI, SCI (low priority) */ + if (ipl_hi >= ipl_ssi) { + ipl1 = ipl_hi; + ipl2 = ipl_ssi; + count1 = 5; + count2 = 9; + } else { + ipl1 = ipl_ssi; + ipl2 = ipl_hi; + count1 = 9; + count2 = 5; } - /* Host receive */ - if ( - (dsp_core->periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<= ipl) { + for (i=count1; iinterrupt_table[i] != 0) { + ipl_to_raise = ipl1; + dsp_core->interrupt_instr_fetch = interrupt_adress[i]; + dsp_core->interrupt_table[i] = 0; + dsp_core->interrupt_counter --; #if DSP_DISASM_INTER - fprintf(stderr, "Dsp: Interrupt: Host receive\n"); + fprintf(stderr, "Dsp: Interrupt: %s\n", interrupt_label[i]); #endif + break; + } + } } - - /* Host command */ - if ( - (dsp_core->periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<=ipl) { + for (i=count2; iinterrupt_table[i] != 0) { + ipl_to_raise = ipl2; + dsp_core->interrupt_instr_fetch = interrupt_adress[i]; + dsp_core->interrupt_table[i] = 0; + dsp_core->interrupt_counter --; #if DSP_DISASM_INTER - fprintf(stderr, "Dsp: Interrupt: Host command\n"); + fprintf(stderr, "Dsp: Interrupt: %s\n", interrupt_label[i]); #endif + break; + } + } + } } } + + if (ipl_to_raise == 99) { + return; + } + + /* SSI receive data with exception */ + if (dsp_core->interrupt_instr_fetch == 0xe) { + dsp_core->periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<interrupt_instr_fetch == 0x12) { + dsp_core->periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<interrupt_instr_fetch == 0xff) { + /* Clear HC and HCP interrupt */ + dsp_core->periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff - (1<hostport[CPU_HOST_CVR] &= 0xff - (1<interrupt_instr_fetch = dsp_core->hostport[CPU_HOST_CVR] & BITMASK(5); + dsp_core->interrupt_instr_fetch *= 2; + } + + /* Read the 2 vectored instructions to search a "JSR" (long interrupt) or not (fast interrupt) */ + instr1 = read_memory_p(dsp_core->interrupt_instr_fetch); + instr2 = read_memory_p(dsp_core->interrupt_instr_fetch+1); + dsp_core->interrupt_state = DSP_INTERRUPT_FAST; + + if ( ((instr1 & 0xfff000) == 0x0d0000) || ((instr1 & 0xffc0ff) == 0x0bc080) ){ + dsp_core->interrupt_state = DSP_INTERRUPT_LONG; + } + + else if ( ((instr2 & 0xfff000) == 0x0d0000) || ((instr2 & 0xffc0ff) == 0x0bc080) ){ + dsp_core->interrupt_state = DSP_INTERRUPT_LONG; + } + + if (dsp_core->interrupt_state == DSP_INTERRUPT_FAST){ + /* Execute a fast interrupt */ + dsp_core->interrupt_save_pc = dsp_core->pc; + dsp_core->pc = dsp_core->interrupt_instr_fetch; +#if DSP_DISASM_INTER + fprintf(stderr, "Dsp: Fast Interrupt: %06x\n", dsp_core->pc); +#endif + } else { + /* Execute a long interrupt */ + dsp_stack_push(dsp_core->pc, dsp_core->registers[DSP_REG_SR], 0); + dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= ipl_to_raise<pc = dsp_core->interrupt_instr_fetch; + dsp_core->interrupt_instr_fetch = -1; + dsp_core->interrupt_save_pc = -1; +#if DSP_DISASM_INTER + fprintf(stderr, "Dsp: Long Interrupt: %06x\n", dsp_core->pc); +#endif + } } /********************************** @@ -832,86 +785,59 @@ static void dsp_postexecute_interrupts(v /* reg1 has bits 47..24 */ /* reg2 has bits 23..0 */ -static void dsp_ccr_extension(Uint32 *reg0, Uint32 *reg1) -{ - Uint32 scaling, value, numbits; - int sr_extension = 1<>7) & 1) << DSP_SR_N; + int sr_zero = 1 << DSP_SR_Z; scaling = (dsp_core->registers[DSP_REG_SR]>>DSP_SR_S0) & BITMASK(2); - value = (*reg0) & 0xff; + value_e = (*reg0) & 0xff; numbits = 8; + switch(scaling) { case 0: - value <<=1; - value |= ((*reg1)>>23) & 1; + value_e <<=1; + value_e |= ((*reg1)>>23) & 1; numbits=9; + value_u = ((*reg1)>>22) & 3; break; case 1: + value_u = ((*reg0)<<1) & 2; + value_u |= ((*reg1)>>23) & 1; break; case 2: - value <<=2; - value |= ((*reg1)>>22) & 3; + value_e <<=2; + value_e |= ((*reg1)>>22) & 3; numbits=10; + value_u = ((*reg1)>>21) & 3; break; default: return; break; } - if ((value==0) || (value==(Uint32)BITMASK(numbits))) { - sr_extension = 0; - } - - dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= sr_extension; -} - -static void dsp_ccr_unnormalized(Uint32 *reg0, Uint32 *reg1) -{ - Uint32 scaling, value; - - scaling = (dsp_core->registers[DSP_REG_SR]>>DSP_SR_S0) & BITMASK(2); - switch(scaling) { - case 0: - value = ((*reg1)>>22) & 3; - break; - case 1: - value = ((*reg0)<<1) & 2; - value |= ((*reg1)>>23) & 1; - break; - case 2: - value = ((*reg1)>>21) & 3; - break; - default: - return; - break; + if ((value_e==0) || (value_e==(Uint32)BITMASK(numbits))) { + sr_extension = 0; } - dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= ((value==0) || (value==BITMASK(2)))<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= (((*reg0)>>7) & 1)<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= zeroed<registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= sr_extension; + dsp_core->registers[DSP_REG_SR] |= sr_unnormalized; + dsp_core->registers[DSP_REG_SR] |= sr_negative; + dsp_core->registers[DSP_REG_SR] |= sr_zero; } /********************************** @@ -921,242 +847,343 @@ static void dsp_ccr_zero(Uint32 *reg0, U #if defined(DSP_DISASM) && (DSP_DISASM_MEM==1) static Uint32 read_memory_disasm(int space, Uint16 address) { - address &= BITMASK(16); + /* Internal RAM ? */ + if (address<0x100) { + return dsp_core->ramint[space][address] & BITMASK(24); + } - switch(space) { - case DSP_SPACE_X: - case DSP_SPACE_Y: - /* Internal RAM? */ - if (address<0x100) { - return dsp_core->ramint[space][address] & BITMASK(24); - } - /* Internal ROM? */ - if ((dsp_core->registers[DSP_REG_OMR] & (1<rom[space][address] & BITMASK(24); - } - /* Peripheral address ? */ - if (address >= 0xffc0) { - return dsp_core->periph[space][address-0xffc0] & BITMASK(24); - } - /* Falcon: External RAM, map X to upper 16K of matching space in Y,P */ - if (space == DSP_SPACE_X) { - address += DSP_RAMSIZE>>1; - } - /* Falcon: External RAM, map X,Y to P */ - space = DSP_SPACE_P; - break; - case DSP_SPACE_P: - /* Internal RAM? */ - if (address<0x200) { - return dsp_core->ramint[space][address] & BITMASK(24); - } - break; + if (space==DSP_SPACE_P) { + return read_memory_p(address); } - /* External RAM, mask address to available ram size */ - return dsp_core->ram[space][address & (DSP_RAMSIZE-1)] & BITMASK(24); + /* Internal ROM? */ + if ((dsp_core->registers[DSP_REG_OMR] & (1<rom[space][address] & BITMASK(24); + } + + /* Peripheral address ? */ + if (address >= 0xffc0) { + if ((space==DSP_SPACE_X) && (address==0xffc0+DSP_HOST_HRX)) { + return dsp_core->dsp_host_rtx; + } + if ((space==DSP_SPACE_X) && (address==0xffc0+DSP_SSI_TX)) { + return dsp_core->ssi.transmit_value; + } + return dsp_core->periph[space][address-0xffc0] & BITMASK(24); + } + + /* Falcon: External RAM, map X to upper 16K of matching space in Y,P */ + address &= (DSP_RAMSIZE>>1) - 1; + if (space == DSP_SPACE_X) { + address += DSP_RAMSIZE>>1; + } + + /* Falcon: External RAM, finally map X,Y to P */ + return dsp_core->ramext[address & (DSP_RAMSIZE-1)] & BITMASK(24); } #endif +static inline Uint32 read_memory_p(Uint16 address) +{ + /* Internal RAM ? */ + if (address<0x200) { + return dsp_core->ramint[DSP_SPACE_P][address] & BITMASK(24); + } + + /* External RAM, mask address to available ram size */ +// dsp_core->instr_cycle += P_WAITSTATE; + return dsp_core->ramext[address & (DSP_RAMSIZE-1)] & BITMASK(24); +} + static Uint32 read_memory(int space, Uint16 address) { - address &= BITMASK(16); + Uint32 value; - switch(space) { - case DSP_SPACE_X: - case DSP_SPACE_Y: - /* Internal RAM ?*/ - if (address<0x100) { - return dsp_core->ramint[space][address] & BITMASK(24); - } - /* Internal ROM ?*/ - if ((dsp_core->registers[DSP_REG_OMR] & (1<rom[space][address] & BITMASK(24); - } - /* Peripheral address ? */ - if (address >= 0xffc0) { - Uint32 value; - - SDL_LockMutex(dsp_core->mutex); - if ((space==DSP_SPACE_X) && (address==0xffc0+DSP_HOST_HRX)) { - dsp_core_hostport_dspread(dsp_core); - } - value = dsp_core->periph[space][address-0xffc0] & BITMASK(24); - SDL_UnlockMutex(dsp_core->mutex); + /* Internal RAM ? */ + if (address < 0x100) { + return dsp_core->ramint[space][address] & BITMASK(24); + } - return value; - } - /* Falcon: External RAM, map X to upper 16K of matching space in Y,P */ - if (space == DSP_SPACE_X) { - address += DSP_RAMSIZE>>1; - } - /* Falcon: External RAM, map X,Y to P */ - space = DSP_SPACE_P; - break; - case DSP_SPACE_P: - /* Internal RAM ?*/ - if (address<0x200) { - return dsp_core->ramint[space][address] & BITMASK(24); + if (space == DSP_SPACE_P) { + return read_memory_p(address); + } + + /* Internal ROM ? */ + if (address < 0x200) { + if (dsp_core->registers[DSP_REG_OMR] & (1<rom[space][address] & BITMASK(24); + } + } + + /* Peripheral address ? */ + if (address >= 0xffc0) { + value = dsp_core->periph[space][address-0xffc0] & BITMASK(24); + if (space == DSP_SPACE_X) { + if (address == 0xffc0+DSP_HOST_HRX) { + value = dsp_core->dsp_host_rtx; + dsp_core_hostport_dspread(dsp_core); + } + else if (address == 0xffc0+DSP_SSI_RX) { + value = dsp_core_ssi_readRX(dsp_core); } - break; + dsp_core->instr_cycle += XP_WAITSTATE; + } + else { + dsp_core->instr_cycle += YP_WAITSTATE; + } + return value; } - /* External RAM, mask address to available ram size */ - return dsp_core->ram[space][address & (DSP_RAMSIZE-1)] & BITMASK(24); + /* 1 more cycle for external RAM access */ + dsp_core->instr_cycle += XY_WAITSTATE; + + /* Falcon: External RAM, map X to upper 16K of matching space in Y,P */ + address &= (DSP_RAMSIZE>>1) - 1; + + if (space == DSP_SPACE_X) { + address += DSP_RAMSIZE>>1; + } + + /* Falcon: External RAM, finally map X,Y to P */ + return dsp_core->ramext[address & (DSP_RAMSIZE-1)] & BITMASK(24); } /* Note: MACRO write_memory defined to either write_memory_raw or write_memory_disasm */ -static void write_memory_raw(int space, Uint32 address, Uint32 value) +static void write_memory_raw(int space, Uint16 address, Uint32 value) { - address &= BITMASK(16); value &= BITMASK(24); - switch(space) { - case DSP_SPACE_X: - /* Internal RAM ? */ - if (address<0x100) { - dsp_core->ramint[space][address] = value; - return; - } - /* Internal ROM ?*/ - if ((dsp_core->registers[DSP_REG_OMR] & (1<= 0xffc0) { + if (space == DSP_SPACE_X) { + switch(address-0xffc0) { + case DSP_HOST_HTX: + dsp_core->dsp_host_htx = value; + dsp_core_hostport_dspwrite(dsp_core); + break; + case DSP_HOST_HCR: + dsp_core->periph[DSP_SPACE_X][DSP_HOST_HCR] = value; + /* Set HF3 and HF2 accordingly on the host side */ + dsp_core->hostport[CPU_HOST_ISR] &= + BITMASK(8)-((1<hostport[CPU_HOST_ISR] |= + dsp_core->periph[DSP_SPACE_X][DSP_HOST_HCR] & ((1<periph[DSP_SPACE_X][address-0xffc0] = value; + break; } - /* Peripheral space ? */ - if ((address >= 0xffc0) && (address <= 0xffff)) { - SDL_LockMutex(dsp_core->mutex); - switch(address-0xffc0) { - case DSP_HOST_HTX: - dsp_core->periph[space][DSP_HOST_HTX] = value; + dsp_core->instr_cycle += XP_WAITSTATE; + return; + } + else if (space == DSP_SPACE_Y) { + dsp_core->periph[DSP_SPACE_Y][address-0xffc0] = value; + dsp_core->instr_cycle += YP_WAITSTATE; + return; + } + } + + /* Internal RAM ? */ + if (address < 0x100) { + dsp_core->ramint[space][address] = value; + return; + } - dsp_core_hostport_dspwrite(dsp_core); - break; - case DSP_HOST_HCR: - dsp_core->periph[space][DSP_HOST_HCR] = value; - /* Set HF3 and HF2 accordingly on the host side */ - dsp_core->hostport[CPU_HOST_ISR] &= - BITMASK(8)-((1<hostport[CPU_HOST_ISR] |= - dsp_core->periph[DSP_SPACE_X][DSP_HOST_HCR] & ((1<periph[space][address-0xffc0] = value; - break; - } - SDL_UnlockMutex(dsp_core->mutex); - return; - } - /* Falcon: External RAM, map X to upper 16K of matching space in Y,P */ - if (space == DSP_SPACE_X) { - address += DSP_RAMSIZE>>1; - } - /* Falcon: External RAM, map X to P */ - space = DSP_SPACE_P; - break; - case DSP_SPACE_Y: - /* Internal RAM ? */ - if (address<0x100) { - dsp_core->ramint[space][address] = value; - return; - } - /* Internal ROM ?*/ - if ((dsp_core->registers[DSP_REG_OMR] & (1<registers[DSP_REG_OMR] & (1<= 0xffc0) && (address <= 0xffff)) { - dsp_core->periph[space][address-0xffc0] = value; - return; - } - /* Falcon: External RAM, map Y to P */ - space = DSP_SPACE_P; - break; - case DSP_SPACE_P: - /* Internal RAM ?*/ - if (address<0x200) { - dsp_core->ramint[space][address] = value; - return; - } - break; + } + else { + /* Space P RAM */ + dsp_core->ramint[DSP_SPACE_P][address] = value; + return; + } } - /* External RAM, mask address to available ram size */ - dsp_core->ram[space][address & (DSP_RAMSIZE-1)] = value; + /* 1 more cycle for external RAM access */ + dsp_core->instr_cycle += XY_WAITSTATE; + + /* Falcon: External RAM, map X to upper 16K of matching space in Y,P */ + if (space != DSP_SPACE_P) { + address &= (DSP_RAMSIZE>>1) - 1; + } + + if (space == DSP_SPACE_X) { + address += DSP_RAMSIZE>>1; + } + + /* Falcon: External RAM, map X,Y to P */ + dsp_core->ramext[address & (DSP_RAMSIZE-1)] = value; } #if defined(DSP_DISASM) && (DSP_DISASM_MEM==1) -static void write_memory_disasm(int space, Uint32 address, Uint32 value) +static void write_memory_disasm(int space, Uint16 address, Uint32 value) { - address &= BITMASK(16); + Uint32 oldvalue, curvalue; + Uint8 space_c = 'p'; + value &= BITMASK(24); - Uint32 curvalue = read_memory_disasm(space, address); + if ((address == 0xffeb) && (space == DSP_SPACE_X) ) { + oldvalue = dsp_core->dsp_host_htx; + } else { + oldvalue = read_memory_disasm(space, address); + } write_memory_raw(space,address,value); switch(space) { - case DSP_SPACE_P: - fprintf(stderr,"Dsp: Mem: p:0x%04x:0x%06x -> 0x%06x\n", address, curvalue, read_memory_disasm(space, address)); - break; case DSP_SPACE_X: - fprintf(stderr,"Dsp: Mem: x:0x%04x:0x%06x -> 0x%06x\n", address, curvalue, read_memory_disasm(space, address)); + space_c = 'x'; break; case DSP_SPACE_Y: - fprintf(stderr,"Dsp: Mem: y:0x%04x:0x%06x -> 0x%06x\n", address, curvalue, read_memory_disasm(space, address)); + space_c = 'y'; + break; + default: break; } + + if ((address == 0xffeb) && (space == DSP_SPACE_X) ) { + curvalue = dsp_core->dsp_host_htx; + } else { + curvalue = read_memory_disasm(space, address); + } + + fprintf(stderr,"Dsp: Mem: %c:0x%04x:0x%06x -> 0x%06x\n", space_c, address, oldvalue, curvalue); } #endif +static void dsp_write_reg(Uint32 numreg, Uint32 value) +{ + Uint32 reg = numreg; + + if ((reg==DSP_REG_A) || (reg==DSP_REG_B)) { + reg &= 1; + dsp_core->registers[DSP_REG_A0+reg]= 0; + dsp_core->registers[DSP_REG_A1+reg]= value; + dsp_core->registers[DSP_REG_A2+reg]= 0; + if (value & (1<<23)) { + dsp_core->registers[DSP_REG_A2+reg]= 0xff; + } + } else { + switch (reg) { + case DSP_REG_OMR: + dsp_core->registers[DSP_REG_OMR] = value & 0xc7; + break; + case DSP_REG_SR: + dsp_core->registers[DSP_REG_SR] = value & 0xaf7f; + break; + case DSP_REG_SP: + dsp_core->registers[DSP_REG_SP] = value & BITMASK(6); + dsp_compute_ssh_ssl(); + break; + case DSP_REG_SSH: + dsp_stack_push(value, 0, 1); + break; + case DSP_REG_SSL: + reg = dsp_core->registers[DSP_REG_SP] & BITMASK(4); + if (reg == 0) { + value = 0; + } + dsp_core->stack[1][reg] = value & BITMASK(16); + dsp_core->registers[DSP_REG_SSL] = value & BITMASK(16); + break; + default: + dsp_core->registers[reg] = value; + dsp_core->registers[reg] &= BITMASK(registers_mask[reg]); + break; + } + } +} + /********************************** * Stack push/pop **********************************/ -static void dsp_stack_push(Uint32 curpc, Uint32 cursr) +static void dsp_stack_push(Uint32 curpc, Uint32 cursr, Uint16 sshOnly) { - if (dsp_core->registers[DSP_REG_SP]==0x0f) { + Uint32 stack_error, underflow, stack; + + stack_error = dsp_core->registers[DSP_REG_SP] & (1<registers[DSP_REG_SP] & (1<registers[DSP_REG_SP] & BITMASK(4)) + 1; + + + if ((stack_error==0) && (stack & (1<semaphore); - return; + dsp_core_add_interrupt(dsp_core, DSP_INTER_STACK_ERROR); + fprintf(stderr,"Dsp: Stack Overflow\n"); } + + dsp_core->registers[DSP_REG_SP] = (underflow | stack_error | stack) & BITMASK(6); + stack &= BITMASK(4); - dsp_core->registers[DSP_REG_SP]++; - dsp_core->registers[DSP_REG_SSH]++; - dsp_core->registers[DSP_REG_SSL]++; + if (stack) { + /* SSH part */ + dsp_core->stack[0][stack] = curpc & BITMASK(16); + /* SSL part, if instruction is not like "MOVEC xx, SSH" */ + if (sshOnly == 0) { + dsp_core->stack[1][stack] = cursr & BITMASK(16); + } + } else { + dsp_core->stack[0][0] = 0; + dsp_core->stack[1][0] = 0; + } - dsp_core->stack[0][dsp_core->registers[DSP_REG_SSH]]=curpc; - dsp_core->stack[1][dsp_core->registers[DSP_REG_SSL]]=cursr; + /* Update SSH and SSL registers */ + dsp_core->registers[DSP_REG_SSH] = dsp_core->stack[0][stack]; + dsp_core->registers[DSP_REG_SSL] = dsp_core->stack[1][stack]; } static void dsp_stack_pop(Uint32 *newpc, Uint32 *newsr) { - if (dsp_core->registers[DSP_REG_SP]==0x00) { - /* Stack empty, raise interrupt */ -#if DSP_DISASM_STATE - fprintf(stderr, "Dsp: Stack error (underflow)\n"); -#endif - SDL_SemWait(dsp_core->semaphore); - return; + Uint32 stack_error, underflow, stack; + + stack_error = dsp_core->registers[DSP_REG_SP] & (1<registers[DSP_REG_SP] & (1<registers[DSP_REG_SP] & BITMASK(4)) - 1; + + if ((stack_error==0) && (stack & (1<stack[0][dsp_core->registers[DSP_REG_SSH]]; - *newsr = dsp_core->stack[1][dsp_core->registers[DSP_REG_SSL]]; + dsp_core->registers[DSP_REG_SP] = (underflow | stack_error | stack) & BITMASK(6); + stack &= BITMASK(4); + *newpc = dsp_core->registers[DSP_REG_SSH]; + *newsr = dsp_core->registers[DSP_REG_SSL]; - --dsp_core->registers[DSP_REG_SP]; - --dsp_core->registers[DSP_REG_SSH]; - --dsp_core->registers[DSP_REG_SSL]; + dsp_core->registers[DSP_REG_SSH] = dsp_core->stack[0][stack]; + dsp_core->registers[DSP_REG_SSL] = dsp_core->stack[1][stack]; +} + +static void dsp_compute_ssh_ssl(void) +{ + Uint32 stack; + + stack = dsp_core->registers[DSP_REG_SP]; + stack &= BITMASK(4); + dsp_core->registers[DSP_REG_SSH] = dsp_core->stack[0][stack]; + dsp_core->registers[DSP_REG_SSL] = dsp_core->stack[1][stack]; } /********************************** @@ -1172,7 +1199,7 @@ static void dsp_update_rn(Uint32 numreg, if (m_reg == 0) { /* Bit reversed carry update */ dsp_update_rn_bitreverse(numreg); - } else if ((m_reg>=1) && (m_reg<=32767)) { + } else if (m_reg<=32767) { /* Modulo update */ dsp_update_rn_modulo(numreg, modifier); } else if (m_reg == 65535) { @@ -1229,34 +1256,40 @@ static void dsp_update_rn_bitreverse(Uin static void dsp_update_rn_modulo(Uint32 numreg, Sint16 modifier) { Uint16 bufsize, modulo, lobound, hibound, bufmask; - Sint16 r_reg; + Sint16 r_reg, orig_modifier=modifier; - modulo = (dsp_core->registers[DSP_REG_M0+numreg]+1) & BITMASK(16); + modulo = dsp_core->registers[DSP_REG_M0+numreg]+1; bufsize = 1; bufmask = BITMASK(16); while (bufsize < modulo) { bufsize <<= 1; bufmask <<= 1; } - bufmask &= BITMASK(16); lobound = dsp_core->registers[DSP_REG_R0+numreg] & bufmask; hibound = lobound + modulo - 1; - r_reg = (Sint16) (dsp_core->registers[DSP_REG_R0+numreg] & BITMASK(16)); - while (modifier>=bufsize) { - r_reg += bufsize; - modifier -= bufsize; - } - while (modifier<=-bufsize) { - r_reg -= bufsize; - modifier += bufsize; + r_reg = (Sint16) dsp_core->registers[DSP_REG_R0+numreg]; + + if (orig_modifier>modulo) { + while (modifier>bufsize) { + r_reg += bufsize; + modifier -= bufsize; + } + while (modifier<-bufsize) { + r_reg -= bufsize; + modifier += bufsize; + } } + r_reg += modifier; - if (r_reg>hibound) { - r_reg -= modulo; - } else if (r_reghibound) { + r_reg -= modulo; + } else if (r_regregisters[DSP_REG_R0+numreg] = ((Uint32) r_reg) & BITMASK(16); @@ -1295,6 +1328,7 @@ static int dsp_calc_ea(Uint32 ea_mode, U break; case 5: /* (Rx+Nx) */ + dsp_core->instr_cycle += 2; curreg = dsp_core->registers[DSP_REG_R0+numreg]; dsp_update_rn(numreg, dsp_core->registers[DSP_REG_N0+numreg]); *dst_addr = dsp_core->registers[DSP_REG_R0+numreg]; @@ -1302,7 +1336,8 @@ static int dsp_calc_ea(Uint32 ea_mode, U break; case 6: /* aa */ - *dst_addr = read_memory(DSP_SPACE_P,dsp_core->pc+1); + dsp_core->instr_cycle += 2; + *dst_addr = read_memory_p(dsp_core->pc+1); cur_inst_len++; if (numreg != 0) { return 1; /* immediate value */ @@ -1310,6 +1345,7 @@ static int dsp_calc_ea(Uint32 ea_mode, U break; case 7: /* -(Rx) */ + dsp_core->instr_cycle += 2; dsp_update_rn(numreg, -1); *dst_addr = dsp_core->registers[DSP_REG_R0+numreg]; break; @@ -1322,34 +1358,71 @@ static int dsp_calc_ea(Uint32 ea_mode, U * Condition code test **********************************/ -#define DSP_SR_NV 8 /* N xor V */ -#define DSP_SR_ZUE 9 /* Z or ((not U) and (not E)) */ -#define DSP_SR_ZNV 10 /* Z or (N xor V) */ - -#define CCR_BIT(x,y) \ - (((x) >> (y)) & 1) - -static int cc_code_map[8]={ - DSP_SR_C, - DSP_SR_NV, - DSP_SR_Z, - DSP_SR_N, - DSP_SR_ZUE, - DSP_SR_E, - DSP_SR_L, - DSP_SR_ZNV -}; - static int dsp_calc_cc(Uint32 cc_code) { - Uint16 value; + Uint16 value1, value2, value3; - value = dsp_core->registers[DSP_REG_SR] & BITMASK(8); - value |= (CCR_BIT(value,DSP_SR_N) ^ CCR_BIT(value, DSP_SR_V))<>3) & 1); + switch (cc_code) { + case 0: /* CC (HS) */ + value1 = dsp_core->registers[DSP_REG_SR] & (1<registers[DSP_REG_SR] >> DSP_SR_N) & 1; + value2 = (dsp_core->registers[DSP_REG_SR] >> DSP_SR_V) & 1; + return ((value1 ^ value2) == 0); + case 2: /* NE */ + value1 = dsp_core->registers[DSP_REG_SR] & (1<registers[DSP_REG_SR] & (1<registers[DSP_REG_SR] >> DSP_SR_Z) & 1; + value2 = (~(dsp_core->registers[DSP_REG_SR] >> DSP_SR_U)) & 1; + value3 = (~(dsp_core->registers[DSP_REG_SR] >> DSP_SR_E)) & 1; + return ((value1 | (value2 & value3)) == 0); + case 5: /* EC */ + value1 = dsp_core->registers[DSP_REG_SR] & (1<registers[DSP_REG_SR] & (1<registers[DSP_REG_SR] >> DSP_SR_N) & 1; + value2 = (dsp_core->registers[DSP_REG_SR] >> DSP_SR_V) & 1; + value3 = (dsp_core->registers[DSP_REG_SR] >> DSP_SR_Z) & 1; + return ((value3 | (value1 ^ value2)) == 0); + case 8: /* CS (LO) */ + value1 = dsp_core->registers[DSP_REG_SR] & (1<registers[DSP_REG_SR] >> DSP_SR_N) & 1; + value2 = (dsp_core->registers[DSP_REG_SR] >> DSP_SR_V) & 1; + return ((value1 ^ value2) == 1); + case 10: /* EQ */ + value1 = (dsp_core->registers[DSP_REG_SR] >> DSP_SR_Z) & 1; + return (value1==1); + case 11: /* MI */ + value1 = (dsp_core->registers[DSP_REG_SR] >> DSP_SR_N) & 1; + return (value1==1); + case 12: /* NR */ + value1 = (dsp_core->registers[DSP_REG_SR] >> DSP_SR_Z) & 1; + value2 = (~(dsp_core->registers[DSP_REG_SR] >> DSP_SR_U)) & 1; + value3 = (~(dsp_core->registers[DSP_REG_SR] >> DSP_SR_E)) & 1; + return ((value1 | (value2 & value3)) == 1); + case 13: /* ES */ + value1 = (dsp_core->registers[DSP_REG_SR] >> DSP_SR_E) & 1; + return (value1==1); + case 14: /* LS */ + value1 = (dsp_core->registers[DSP_REG_SR] >> DSP_SR_L) & 1; + return (value1==1); + case 15: /* LE */ + value1 = (dsp_core->registers[DSP_REG_SR] >> DSP_SR_N) & 1; + value2 = (dsp_core->registers[DSP_REG_SR] >> DSP_SR_V) & 1; + value3 = (dsp_core->registers[DSP_REG_SR] >> DSP_SR_Z) & 1; + return ((value3 | (value1 ^ value2)) == 1); + } + return 0; } /********************************** @@ -1358,376 +1431,457 @@ static int dsp_calc_cc(Uint32 cc_code) static void opcode8h_0(void) { - if (cur_inst <= 0x00008c) { - switch(cur_inst) { - case 0x000000: - dsp_nop(); - break; - case 0x000004: - dsp_rti(); - break; - case 0x000005: - dsp_illegal(); - break; - case 0x000006: - dsp_swi(); - break; - case 0x00000c: - dsp_rts(); - break; - case 0x000084: - dsp_reset(); - break; - case 0x000086: - dsp_wait(); - break; - case 0x000087: - dsp_stop(); - break; - case 0x00008c: - dsp_enddo(); - break; - } - } else { - switch (cur_inst & 0xf8) { - case 0x0000b8: - dsp_andi(); - break; - case 0x0000f8: - dsp_ori(); - break; - } + switch(cur_inst) { + case 0x000000: + dsp_nop(); + break; + case 0x000004: + dsp_rti(); + break; + case 0x000005: + dsp_illegal(); + break; + case 0x000006: + dsp_swi(); + break; + case 0x00000c: + dsp_rts(); + break; + case 0x000084: + dsp_reset(); + break; + case 0x000086: + dsp_wait(); + break; + case 0x000087: + dsp_stop(); + break; + case 0x00008c: + dsp_enddo(); + break; } } -static void opcode8h_1(void) +/********************************** + * Non-parallel moves instructions + **********************************/ + +static void dsp_undefined(void) { - switch(cur_inst & 0xfff8c7) { - case 0x018040: - dsp_div(); - break; - case 0x01c805: - dsp_norm(); - break; - } + cur_inst_len = 0; + fprintf(stderr, "Dsp: 0x%04x: 0x%06x unknown instruction\n",dsp_core->pc, cur_inst); } -static void opcode8h_4(void) +static void dsp_andi(void) { - switch((cur_inst>>5) & BITMASK(3)) { + Uint32 regnum, value; + + value = (cur_inst >> 8) & BITMASK(8); + regnum = cur_inst & BITMASK(2); + switch(regnum) { case 0: - dsp_lua(); + /* mr */ + dsp_core->registers[DSP_REG_SR] &= (value<<8)|BITMASK(8); break; - case 5: - dsp_movec(); + case 1: + /* ccr */ + dsp_core->registers[DSP_REG_SR] &= (BITMASK(8)<<8)|value; + break; + case 2: + /* omr */ + dsp_core->registers[DSP_REG_OMR] &= value; break; } } -static void opcode8h_6(void) +static void dsp_bchg_aa(void) { - if (cur_inst & (1<<5)) { - dsp_rep(); + Uint32 memspace, addr, value, newcarry, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + addr = value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + if (newcarry) { + value -= (1<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; + if (addr>=0x200) { + dsp_core->instr_cycle += XY_WAITSTATE; } } -static void opcode8h_8(void) +static void dsp_bchg_ea(void) { - Uint32 value; + Uint32 memspace, addr, value, newcarry, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); - value = (cur_inst >> 12) & BITMASK(4); - opcodes_0809[value](); + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + if (newcarry) { + value -= (1<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; + if (addr>=0x200) { + dsp_core->instr_cycle += XY_WAITSTATE; + } } -static void opcode8h_a(void) +static void dsp_bchg_pp(void) { - Uint32 value; + Uint32 memspace, addr, value, newcarry, numbit; - value = (cur_inst >> 11) & (BITMASK(2)<<3); - value |= (cur_inst >> 5) & BITMASK(3); + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + if (newcarry) { + value -= (1<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; + if (memspace == DSP_SPACE_X) { + dsp_core->instr_cycle += XP_WAITSTATE; + } else { + dsp_core->instr_cycle += YP_WAITSTATE; + } } -static void opcode8h_b(void) +static void dsp_bchg_reg(void) { - Uint32 value; + Uint32 value, numreg, newcarry, numbit; - value = (cur_inst >> 11) & (BITMASK(2)<<3); - value |= (cur_inst >> 5) & BITMASK(3); + numreg = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); - opcodes_0b[value](); -} + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core->registers[numreg]; + } -/********************************** - * Non-parallel moves instructions - **********************************/ + newcarry = (value>>numbit) & 1; + if (newcarry) { + value -= (1<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; +} + +static void dsp_bclr_aa(void) { - cur_inst_len = 0; - fprintf(stderr, "Dsp: 0x%04x: 0x%06x unknown instruction\n",dsp_core->pc, cur_inst); + Uint32 memspace, addr, value, newcarry, numbit; + + memspace = (cur_inst>>6) & 1; + addr = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + value &= 0xffffffff-(1<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; + if (addr>=0x200) { + dsp_core->instr_cycle += XY_WAITSTATE; + } } -static void dsp_andi(void) +static void dsp_bclr_ea(void) { - Uint32 regnum, value; + Uint32 memspace, addr, value, newcarry, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); - value = (cur_inst >> 8) & BITMASK(8); - regnum = cur_inst & BITMASK(2); - switch(regnum) { - case 0: - /* mr */ - dsp_core->registers[DSP_REG_SR] &= (value<<8)|BITMASK(8); - break; - case 1: - /* ccr */ - dsp_core->registers[DSP_REG_SR] &= (BITMASK(8)<<8)|value; - break; - case 2: - /* omr */ - dsp_core->registers[DSP_REG_OMR] &= value; - break; + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + value &= 0xffffffff-(1<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; + if (addr>=0x200) { + dsp_core->instr_cycle += XY_WAITSTATE; } } -static void dsp_bchg(void) +static void dsp_bclr_pp(void) { - Uint32 memspace, addr, value, numreg, newcarry, numbit, srcreg; + Uint32 memspace, addr, value, newcarry, numbit; memspace = (cur_inst>>6) & 1; value = (cur_inst>>8) & BITMASK(6); numbit = cur_inst & BITMASK(5); - newcarry = 0; - switch((cur_inst>>14) & BITMASK(2)) { - case 0: - /* bchg #n,x:aa */ - /* bchg #n,y:aa */ - addr = value; - value = read_memory(memspace, addr); - newcarry = (value>>numbit) & 1; - if (newcarry) { - value -= (1<>numbit) & 1; - if (newcarry) { - value -= (1<>numbit) & 1; - if (newcarry) { - value -= (1<registers[numreg]; - newcarry = (value>>numbit) & 1; - if (newcarry) { - value -= (1<registers[numreg] = value; - if (((srcreg==DSP_REG_A) || (srcreg==DSP_REG_B)) && (numbit==23)) { - dsp_core->registers[DSP_REG_A2+(srcreg & 1)]= (newcarry ? 0x00 : 0xff); - } - break; + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + value &= 0xffffffff-(1<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; + if (memspace == DSP_SPACE_X) { + dsp_core->instr_cycle += XP_WAITSTATE; + } else { + dsp_core->instr_cycle += YP_WAITSTATE; + } +} + +static void dsp_bclr_reg(void) +{ + Uint32 value, numreg, newcarry, numbit; + + numreg = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core->registers[numreg]; } + newcarry = (value>>numbit) & 1; + value &= 0xffffffff-(1<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; } -static void dsp_bclr(void) +static void dsp_bset_aa(void) { - Uint32 memspace, addr, value, numreg, newcarry, numbit, srcreg; + Uint32 memspace, addr, value, newcarry, numbit; memspace = (cur_inst>>6) & 1; value = (cur_inst>>8) & BITMASK(6); numbit = cur_inst & BITMASK(5); - newcarry = 0; - switch((cur_inst>>14) & BITMASK(2)) { - case 0: - /* bclr #n,x:aa */ - /* bclr #n,y:aa */ - addr = value; - value = read_memory(memspace, addr); - newcarry = (value>>numbit) & 1; - value &= 0xffffffff-(1<>numbit) & 1; - value &= 0xffffffff-(1<>numbit) & 1; - value &= 0xffffffff-(1<registers[numreg]; - newcarry = (value>>numbit) & 1; - value &= 0xffffffff-(1<registers[numreg] = value; - if (((srcreg==DSP_REG_A) || (srcreg==DSP_REG_B)) && (numbit==23)) { - dsp_core->registers[DSP_REG_A2+(srcreg & 1)]=0x00; - } - break; + addr = value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + value |= (1<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; + if (addr>=0x200) { + dsp_core->instr_cycle += XY_WAITSTATE; } +} + +static void dsp_bset_ea(void) +{ + Uint32 memspace, addr, value, newcarry, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + value |= (1<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; + if (addr>=0x200) { + dsp_core->instr_cycle += XY_WAITSTATE; + } } -static void dsp_bset(void) +static void dsp_bset_pp(void) { - Uint32 memspace, addr, value, numreg, newcarry, numbit, srcreg; + Uint32 memspace, addr, value, newcarry, numbit; memspace = (cur_inst>>6) & 1; value = (cur_inst>>8) & BITMASK(6); numbit = cur_inst & BITMASK(5); - newcarry = 0; + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + value |= (1<>14) & BITMASK(2)) { - case 0: - /* bset #n,x:aa */ - /* bset #n,y:aa */ - addr = value; - value = read_memory(memspace, addr); - newcarry = (value>>numbit) & 1; - value |= (1<>numbit) & 1; - value |= (1<>numbit) & 1; - value |= (1<registers[numreg]; - newcarry = (value>>numbit) & 1; - value |= (1<registers[numreg] = value; - if (((srcreg==DSP_REG_A) || (srcreg==DSP_REG_B)) && (numbit==23)) { - dsp_core->registers[DSP_REG_A2+(srcreg & 1)]=0xff; - } - break; + /* Set carry */ + dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; + if (memspace == DSP_SPACE_X) { + dsp_core->instr_cycle += XP_WAITSTATE; + } else { + dsp_core->instr_cycle += YP_WAITSTATE; + } +} + +static void dsp_bset_reg(void) +{ + Uint32 value, numreg, newcarry, numbit; + + numreg = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core->registers[numreg]; } + newcarry = (value>>numbit) & 1; + value |= (1<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; } -static void dsp_btst(void) +static void dsp_btst_aa(void) { - Uint32 memspace, addr, value, numreg, newcarry, numbit; + Uint32 memspace, addr, value, newcarry, numbit; memspace = (cur_inst>>6) & 1; value = (cur_inst>>8) & BITMASK(6); numbit = cur_inst & BITMASK(5); - newcarry = 0; - switch((cur_inst>>14) & BITMASK(2)) { - case 0: - /* btst #n,x:aa */ - /* btst #n,y:aa */ - addr = value; - value = read_memory(memspace, addr); - newcarry = (value>>numbit) & 1; - break; - case 1: - /* btst #n,x:ea */ - /* btst #n,y:ea */ - dsp_calc_ea(value, &addr); - value = read_memory(memspace, addr); - newcarry = (value>>numbit) & 1; - break; - case 2: - /* btst #n,x:pp */ - /* btst #n,y:pp */ - addr = 0xffc0 + value; - value = read_memory(memspace, addr); - newcarry = (value>>numbit) & 1; - break; - case 3: - /* btst #n,R */ - numreg = value; - if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { - numreg = DSP_REG_A1+(numreg & 1); - } - value = dsp_core->registers[numreg]; - newcarry = (value>>numbit) & 1; - break; + addr = value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + + /* Set carry */ + dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; +} + +static void dsp_btst_ea(void) +{ + Uint32 memspace, addr, value, newcarry, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + + /* Set carry */ + dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; +} + +static void dsp_btst_pp(void) +{ + Uint32 memspace, addr, value, newcarry, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + + /* Set carry */ + dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; +} + +static void dsp_btst_reg(void) +{ + Uint32 value, numreg, newcarry, numbit; + + numreg = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core->registers[numreg]; } + newcarry = (value>>numbit) & 1; + /* Set carry */ dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newcarry<instr_cycle += 2; } static void dsp_div(void) @@ -1745,11 +1899,11 @@ static void dsp_div(void) destreg = DSP_REG_A+((cur_inst>>3) & 1); source[0] = 0; - source[1] = dsp_core->registers[srcreg]; - if (source[1] & (1<<23)) { - source[0] = 0xff; - } - source[2] = 0; + source[1] = dsp_core->registers[srcreg]; + if (source[1] & (1<<23)) { + source[0] = 0xff; + } + source[2] = 0; dest[0] = dsp_core->registers[DSP_REG_A2+(destreg & 1)]; dest[1] = dsp_core->registers[DSP_REG_A1+(destreg & 1)]; @@ -1777,64 +1931,82 @@ static void dsp_div(void) dsp_core->registers[DSP_REG_SR] |= newsr & (1<registers[DSP_REG_LA], dsp_core->registers[DSP_REG_LC]); - - dsp_core->registers[DSP_REG_LA] = read_memory(DSP_SPACE_P, dsp_core->pc+1) & BITMASK(16); - cur_inst_len++; - - dsp_stack_push(dsp_core->pc+cur_inst_len, dsp_core->registers[DSP_REG_SR]); - - dsp_core->registers[DSP_REG_SR] |= (1<>12) & (BITMASK(2)<<2); - value |= (cur_inst>>6) & 1<<1; - value |= (cur_inst>>5) & 1; +/* + DO instruction parameter encoding - opcodes_do[value](); -} + xxxxxxxx 00xxxxxx 0xxxxxxx aa + xxxxxxxx 01xxxxxx 0xxxxxxx ea + xxxxxxxx YYxxxxxx 1xxxxxxx imm + xxxxxxxx 11xxxxxx 0xxxxxxx reg +*/ -static void dsp_do_0(void) +static void dsp_do_aa(void) { Uint32 memspace, addr; /* x:aa */ /* y:aa */ + dsp_stack_push(dsp_core->registers[DSP_REG_LA], dsp_core->registers[DSP_REG_LC], 0); + dsp_core->registers[DSP_REG_LA] = read_memory_p(dsp_core->pc+1) & BITMASK(16); + cur_inst_len++; + dsp_stack_push(dsp_core->pc+cur_inst_len, dsp_core->registers[DSP_REG_SR], 0); + dsp_core->registers[DSP_REG_SR] |= (1<>6) & 1; addr = (cur_inst>>8) & BITMASK(6); dsp_core->registers[DSP_REG_LC] = read_memory(memspace, addr) & BITMASK(16); + + dsp_core->instr_cycle += 4; } -static void dsp_do_2(void) +static void dsp_do_imm(void) { /* #xx */ - dsp_core->registers[DSP_REG_LC] = (cur_inst>>8) & BITMASK(8); - dsp_core->registers[DSP_REG_LC] |= (cur_inst & BITMASK(4))<<8; + + dsp_stack_push(dsp_core->registers[DSP_REG_LA], dsp_core->registers[DSP_REG_LC], 0); + dsp_core->registers[DSP_REG_LA] = read_memory_p(dsp_core->pc+1) & BITMASK(16); + cur_inst_len++; + dsp_stack_push(dsp_core->pc+cur_inst_len, dsp_core->registers[DSP_REG_SR], 0); + dsp_core->registers[DSP_REG_SR] |= (1<registers[DSP_REG_LC] = ((cur_inst>>8) & BITMASK(8)) + + ((cur_inst & BITMASK(4))<<8); + + dsp_core->instr_cycle += 4; } -static void dsp_do_4(void) +static void dsp_do_ea(void) { Uint32 memspace, ea_mode, addr; /* x:ea */ /* y:ea */ + dsp_stack_push(dsp_core->registers[DSP_REG_LA], dsp_core->registers[DSP_REG_LC], 0); + dsp_core->registers[DSP_REG_LA] = read_memory_p(dsp_core->pc+1) & BITMASK(16); + cur_inst_len++; + dsp_stack_push(dsp_core->pc+cur_inst_len, dsp_core->registers[DSP_REG_SR], 0); + dsp_core->registers[DSP_REG_SR] |= (1<>6) & 1; ea_mode = (cur_inst>>8) & BITMASK(6); dsp_calc_ea(ea_mode, &addr); dsp_core->registers[DSP_REG_LC] = read_memory(memspace, addr) & BITMASK(16); + + dsp_core->instr_cycle += 4; } -static void dsp_do_c(void) +static void dsp_do_reg(void) { Uint32 numreg; /* S */ + dsp_stack_push(dsp_core->registers[DSP_REG_LA], dsp_core->registers[DSP_REG_LC], 0); + dsp_core->registers[DSP_REG_LA] = read_memory_p(dsp_core->pc+1) & BITMASK(16); + cur_inst_len++; + numreg = (cur_inst>>8) & BITMASK(6); if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { dsp_pm_read_accu24(numreg, &dsp_core->registers[DSP_REG_LC]); @@ -1842,331 +2014,584 @@ static void dsp_do_c(void) dsp_core->registers[DSP_REG_LC] = dsp_core->registers[numreg]; } dsp_core->registers[DSP_REG_LC] &= BITMASK(16); + + dsp_stack_push(dsp_core->pc+cur_inst_len, dsp_core->registers[DSP_REG_SR], 0); + dsp_core->registers[DSP_REG_SR] |= (1<instr_cycle += 4; } static void dsp_enddo(void) { - Uint32 newpc; + Uint32 saved_pc, saved_sr; - dsp_stack_pop(&newpc, &dsp_core->registers[DSP_REG_SR]); + dsp_stack_pop(&saved_pc, &saved_sr); + dsp_core->registers[DSP_REG_SR] &= 0x7f; + dsp_core->registers[DSP_REG_SR] |= saved_sr & (1<registers[DSP_REG_LA], &dsp_core->registers[DSP_REG_LC]); } static void dsp_illegal(void) { /* Raise interrupt p:0x003e */ -#if DSP_DISASM_INTER - fprintf(stderr, "Dsp: Interrupt: Illegal\n"); -#endif + dsp_core_add_interrupt(dsp_core, DSP_INTER_ILLEGAL); } -static void dsp_jcc(void) +static void dsp_jcc_imm(void) { - Uint32 newpc, cc_code; + Uint32 cc_code, newpc; - cc_code = 0; - switch((cur_inst >> 16) & BITMASK(8)) { - case 0x0a: - dsp_calc_ea((cur_inst >>8) & BITMASK(6), &newpc); - cc_code=cur_inst & BITMASK(4); - break; - case 0x0e: - newpc = cur_inst & BITMASK(12); - cc_code=(cur_inst>>12) & BITMASK(4); - break; + newpc = cur_inst & BITMASK(12); + cc_code=(cur_inst>>12) & BITMASK(4); + if (dsp_calc_cc(cc_code)) { + dsp_core->pc = newpc; + cur_inst_len = 0; + } + + dsp_core->instr_cycle += 2; + if (newpc >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; } +} + +static void dsp_jcc_ea(void) +{ + Uint32 newpc, cc_code; + + dsp_calc_ea((cur_inst >>8) & BITMASK(6), &newpc); + cc_code=cur_inst & BITMASK(4); if (dsp_calc_cc(cc_code)) { dsp_core->pc = newpc; cur_inst_len = 0; } + + dsp_core->instr_cycle += 2; + if (newpc >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } } -static void dsp_jclr(void) +static void dsp_jclr_aa(void) { - Uint32 memspace, addr, value, numreg, newpc, numbit; + Uint32 memspace, addr, value, numbit, newaddr; memspace = (cur_inst>>6) & 1; - value = (cur_inst>>8) & BITMASK(6); + addr = (cur_inst>>8) & BITMASK(6); numbit = cur_inst & BITMASK(5); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core->pc+1); - switch((cur_inst>>14) & BITMASK(2)) { - case 0: - /* jclr #n,x:aa,p:xx */ - /* jclr #n,y:aa,p:xx */ - addr = value; - value = read_memory(memspace, addr); - break; - case 1: - /* jclr #n,x:ea,p:xx */ - /* jclr #n,y:ea,p:xx */ - dsp_calc_ea(value, &addr); - value = read_memory(memspace, addr); - break; - case 2: - /* jclr #n,x:pp,p:xx */ - /* jclr #n,y:pp,p:xx */ - addr = 0xffc0 + value; - value = read_memory(memspace, addr); - break; - case 3: - /* jclr #n,R,p:xx */ - numreg = value; - value = dsp_core->registers[numreg]; - addr = 0xffff0000; /* invalid address */ - memspace = 0xffff0000; /* invalid memspace */ - break; + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; } + if ((value & (1<pc = newaddr; + cur_inst_len = 0; + return; + } ++cur_inst_len; +} + +static void dsp_jclr_ea(void) +{ + Uint32 memspace, addr, value, numbit, newaddr; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + newaddr = read_memory_p(dsp_core->pc+1); + + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } if ((value & (1<pc = newaddr; + cur_inst_len = 0; + return; + } + ++cur_inst_len; +} - newpc = read_memory(DSP_SPACE_P, dsp_core->pc+1); +static void dsp_jclr_pp(void) +{ + Uint32 memspace, addr, value, numbit, newaddr; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core->pc+1); + + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } - /* Polling loop if jump to same PC as current JCLR instruction */ - pollingLoop = (newpc == dsp_core->pc); - if (!pollingLoop && (newpcpc)) { - /* or if only NOPs from jump address to current JCLR instruction */ - pollingLoop = 1; - for (i=newpc; ipc; i++) { - if (read_memory(DSP_SPACE_P, i) != 0) { - pollingLoop=0; - break; - } - } - } - if (!pollingLoop && (newpc+2 == dsp_core->pc)) { - /* or programs that re-set host port operation (Papa was a bladerunner/Eko) */ - pollingLoop = (read_memory(DSP_SPACE_P, newpc) == 0x08f4a0) /* movep #0x000001,x:0xffe0 */ - && (read_memory(DSP_SPACE_P, newpc+1) == 0x000001); - } + if ((value & (1<pc = newaddr; + cur_inst_len = 0; + return; + } + ++cur_inst_len; +} - if (pollingLoop) { - /* Are we waiting for host port ? */ - if ((memspace==DSP_SPACE_X) && (addr==0xffc0+DSP_HOST_HSR)) { - /* Wait for host to write */ - if (numbit==DSP_HOST_HSR_HRDF) { -#if DSP_DISASM_STATE - fprintf(stderr, "Dsp: WAIT_HOSTWRITE\n"); -#endif - SDL_SemWait(dsp_core->semaphore); - } +static void dsp_jclr_reg(void) +{ + Uint32 value, numreg, numbit, newaddr; + + numreg = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + newaddr = read_memory_p(dsp_core->pc+1); - /* Wait for host to read */ - if (numbit==DSP_HOST_HSR_HTDE) { -#if DSP_DISASM_STATE - fprintf(stderr, "Dsp: WAIT_HOSTREAD\n"); -#endif - SDL_SemWait(dsp_core->semaphore); - } - } - } + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core->registers[numreg]; + } - dsp_core->pc = newpc; + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } + + if ((value & (1<pc = newaddr; cur_inst_len = 0; return; } + ++cur_inst_len; } -static void dsp_jmp(void) +static void dsp_jmp_ea(void) { Uint32 newpc; - switch((cur_inst >> 16) & BITMASK(8)) { - case 0x0a: - dsp_calc_ea((cur_inst >>8) & BITMASK(6), &newpc); - break; - case 0x0c: - newpc = cur_inst & BITMASK(12); - break; - } - + dsp_calc_ea((cur_inst>>8) & BITMASK(6), &newpc); cur_inst_len = 0; + dsp_core->pc = newpc; - /* Infinite loop ? */ - if (newpc == dsp_core->pc) { -#if DSP_DISASM_STATE - fprintf(stderr, "Dsp: JMP instruction, infinite loop\n"); -#endif - SDL_SemWait(dsp_core->semaphore); - return; + dsp_core->instr_cycle += 2; + if (newpc >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; } +} + +static void dsp_jmp_imm(void) +{ + Uint32 newpc; + newpc = cur_inst & BITMASK(12); + cur_inst_len = 0; dsp_core->pc = newpc; + + dsp_core->instr_cycle += 2; + if (newpc >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } } -static void dsp_jscc(void) +static void dsp_jscc_ea(void) { Uint32 newpc, cc_code; - cc_code = 0; - switch((cur_inst >> 16) & BITMASK(8)) { - case 0x0b: - dsp_calc_ea((cur_inst >>8) & BITMASK(6), &newpc); - cc_code=cur_inst & BITMASK(4); - break; - case 0x0f: - newpc = cur_inst & BITMASK(12); - cc_code=(cur_inst>>12) & BITMASK(4); - break; + dsp_calc_ea((cur_inst >>8) & BITMASK(6), &newpc); + cc_code=cur_inst & BITMASK(4); + + if (dsp_calc_cc(cc_code)) { + dsp_stack_push(dsp_core->pc+cur_inst_len, dsp_core->registers[DSP_REG_SR], 0); + dsp_core->pc = newpc; + cur_inst_len = 0; + } + + dsp_core->instr_cycle += 2; + if (newpc >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; } +} + +static void dsp_jscc_imm(void) +{ + Uint32 cc_code, newpc; + newpc = cur_inst & BITMASK(12); + cc_code=(cur_inst>>12) & BITMASK(4); if (dsp_calc_cc(cc_code)) { - dsp_stack_push(dsp_core->pc+cur_inst_len, dsp_core->registers[DSP_REG_SR]); + dsp_stack_push(dsp_core->pc+cur_inst_len, dsp_core->registers[DSP_REG_SR], 0); + dsp_core->pc = newpc; + cur_inst_len = 0; + } + dsp_core->instr_cycle += 2; + if (newpc >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } +} + +static void dsp_jsclr_aa(void) +{ + Uint32 memspace, addr, value, newpc, numbit, newaddr; + + memspace = (cur_inst>>6) & 1; + addr = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core->pc+1); + + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } + + if ((value & (1<pc+2, dsp_core->registers[DSP_REG_SR], 0); + newpc = newaddr; dsp_core->pc = newpc; cur_inst_len = 0; + return; } + ++cur_inst_len; } -static void dsp_jsclr(void) +static void dsp_jsclr_ea(void) { - Uint32 memspace, addr, value, numreg, newpc, numbit; + Uint32 memspace, addr, value, newpc, numbit, newaddr; memspace = (cur_inst>>6) & 1; value = (cur_inst>>8) & BITMASK(6); numbit = cur_inst & BITMASK(5); - - switch((cur_inst>>14) & BITMASK(2)) { - case 0: - /* jsclr #n,x:aa,p:xx */ - /* jsclr #n,y:aa,p:xx */ - addr = value; - value = read_memory(memspace, addr); - break; - case 1: - /* jsclr #n,x:ea,p:xx */ - /* jsclr #n,y:ea,p:xx */ - dsp_calc_ea(value, &addr); - value = read_memory(memspace, addr); - break; - case 2: - /* jsclr #n,x:pp,p:xx */ - /* jsclr #n,y:pp,p:xx */ - addr = 0xffc0 + value; - value = read_memory(memspace, addr); - break; - case 3: - /* jsclr #n,R,p:xx */ - numreg = value; - value = dsp_core->registers[numreg]; - break; + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core->pc+1); + + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; } - + + if ((value & (1<pc+2, dsp_core->registers[DSP_REG_SR], 0); + newpc = newaddr; + dsp_core->pc = newpc; + cur_inst_len = 0; + return; + } ++cur_inst_len; +} + +static void dsp_jsclr_pp(void) +{ + Uint32 memspace, addr, value, newpc, numbit, newaddr; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core->pc+1); + + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } + if ((value & (1<pc+cur_inst_len, dsp_core->registers[DSP_REG_SR]); + dsp_stack_push(dsp_core->pc+2, dsp_core->registers[DSP_REG_SR], 0); + newpc = newaddr; + dsp_core->pc = newpc; + cur_inst_len = 0; + return; + } + ++cur_inst_len; +} - newpc = read_memory(DSP_SPACE_P, dsp_core->pc+1); +static void dsp_jsclr_reg(void) +{ + Uint32 value, numreg, newpc, numbit, newaddr; + + numreg = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + newaddr = read_memory_p(dsp_core->pc+1); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core->registers[numreg]; + } + + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } + + if ((value & (1<pc+2, dsp_core->registers[DSP_REG_SR], 0); + newpc = newaddr; dsp_core->pc = newpc; cur_inst_len = 0; + return; } + ++cur_inst_len; } -static void dsp_jset(void) +static void dsp_jset_aa(void) { - Uint32 memspace, addr, value, numreg, numbit; - Uint32 newpc; + Uint32 memspace, addr, value, numbit, newpc, newaddr; memspace = (cur_inst>>6) & 1; - value = (cur_inst>>8) & BITMASK(6); + addr = (cur_inst>>8) & BITMASK(6); numbit = cur_inst & BITMASK(5); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core->pc+1); - switch((cur_inst>>14) & BITMASK(2)) { - case 0: - /* jset #n,x:aa,p:xx */ - /* jset #n,y:aa,p:xx */ - addr = value; - value = read_memory(memspace, addr); - break; - case 1: - /* jset #n,x:ea,p:xx */ - /* jset #n,y:ea,p:xx */ - dsp_calc_ea(value, &addr); - value = read_memory(memspace, addr); - break; - case 2: - /* jset #n,x:pp,p:xx */ - /* jset #n,y:pp,p:xx */ - addr = 0xffc0 + value; - value = read_memory(memspace, addr); - break; - case 3: - /* jset #n,R,p:xx */ - numreg = value; - value = dsp_core->registers[numreg]; - break; + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; } + + if (value & (1<pc = newpc; + cur_inst_len=0; + return; + } + ++cur_inst_len; +} +static void dsp_jset_ea(void) +{ + Uint32 memspace, addr, value, numbit, newpc, newaddr; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core->pc+1); + + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } + + if (value & (1<pc = newpc; + cur_inst_len=0; + return; + } ++cur_inst_len; +} + +static void dsp_jset_pp(void) +{ + Uint32 memspace, addr, value, numbit, newpc, newaddr; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core->pc+1); + + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } + if (value & (1<pc+1); + newpc = newaddr; + dsp_core->pc = newpc; + cur_inst_len=0; + return; + } + ++cur_inst_len; +} +static void dsp_jset_reg(void) +{ + Uint32 value, numreg, numbit, newpc, newaddr; + + numreg = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + newaddr = read_memory_p(dsp_core->pc+1); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core->registers[numreg]; + } + + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } + + if (value & (1<pc = newpc; cur_inst_len=0; + return; } + ++cur_inst_len; } -static void dsp_jsr(void) +static void dsp_jsr_imm(void) { Uint32 newpc; - if (((cur_inst>>12) & BITMASK(4))==0) { - newpc = cur_inst & BITMASK(12); - } else { - dsp_calc_ea((cur_inst>>8) & BITMASK(6),&newpc); + newpc = cur_inst & BITMASK(12); + + if (dsp_core->interrupt_state != DSP_INTERRUPT_LONG){ + dsp_stack_push(dsp_core->pc+cur_inst_len, dsp_core->registers[DSP_REG_SR], 0); + } + else { + dsp_core->interrupt_state = DSP_INTERRUPT_NONE; + } + + dsp_core->pc = newpc; + cur_inst_len = 0; + + dsp_core->instr_cycle += 2; + if (newpc >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; } +} + +static void dsp_jsr_ea(void) +{ + Uint32 newpc; + + dsp_calc_ea((cur_inst>>8) & BITMASK(6),&newpc); - dsp_stack_push(dsp_core->pc+cur_inst_len, dsp_core->registers[DSP_REG_SR]); + if (dsp_core->interrupt_state != DSP_INTERRUPT_LONG){ + dsp_stack_push(dsp_core->pc+cur_inst_len, dsp_core->registers[DSP_REG_SR], 0); + } + else { + dsp_core->interrupt_state = DSP_INTERRUPT_NONE; + } dsp_core->pc = newpc; cur_inst_len = 0; + + dsp_core->instr_cycle += 2; + if (newpc >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } } -static void dsp_jsset(void) +static void dsp_jsset_aa(void) { - Uint32 memspace, addr, value, numreg, newpc, numbit; + Uint32 memspace, addr, value, newpc, numbit, newaddr; memspace = (cur_inst>>6) & 1; - value = (cur_inst>>8) & BITMASK(6); + addr = (cur_inst>>8) & BITMASK(6); numbit = cur_inst & BITMASK(5); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core->pc+1); + + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } - switch((cur_inst>>14) & BITMASK(2)) { - case 0: - /* jsset #n,x:aa,p:xx */ - /* jsset #n,y:aa,p:xx */ - addr = value; - value = read_memory(memspace, addr); - break; - case 1: - /* jsset #n,x:ea,p:xx */ - /* jsset #n,y:ea,p:xx */ - dsp_calc_ea(value, &addr); - value = read_memory(memspace, addr); - break; - case 2: - /* jsset #n,x:pp,p:xx */ - /* jsset #n,y:pp,p:xx */ - addr = 0xffc0 + value; - value = read_memory(memspace, addr); - break; - case 3: - /* jsset #n,R,p:xx */ - numreg = value; - value = dsp_core->registers[numreg]; - break; + if (value & (1<pc+2, dsp_core->registers[DSP_REG_SR], 0); + newpc = newaddr; + dsp_core->pc = newpc; + cur_inst_len = 0; + return; + } + ++cur_inst_len; +} + +static void dsp_jsset_ea(void) +{ + Uint32 memspace, addr, value, newpc, numbit, newaddr; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core->pc+1); + + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; } + if (value & (1<pc+2, dsp_core->registers[DSP_REG_SR], 0); + newpc = newaddr; + dsp_core->pc = newpc; + cur_inst_len = 0; + return; + } ++cur_inst_len; +} + +static void dsp_jsset_pp(void) +{ + Uint32 memspace, addr, value, newpc, numbit, newaddr; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core->pc+1); + + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } + if (value & (1<pc+cur_inst_len, dsp_core->registers[DSP_REG_SR]); + dsp_stack_push(dsp_core->pc+2, dsp_core->registers[DSP_REG_SR], 0); + newpc = newaddr; + dsp_core->pc = newpc; + cur_inst_len = 0; + return; + } + ++cur_inst_len; +} - newpc = read_memory(DSP_SPACE_P, dsp_core->pc+1); +static void dsp_jsset_reg(void) +{ + Uint32 value, numreg, newpc, numbit, newaddr; + + numreg = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + newaddr = read_memory_p(dsp_core->pc+1); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core->registers[numreg]; + } + + dsp_core->instr_cycle += 4; + if (newaddr >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } + + if (value & (1<pc+2, dsp_core->registers[DSP_REG_SR], 0); + newpc = newaddr; dsp_core->pc = newpc; cur_inst_len = 0; + return; } + ++cur_inst_len; } static void dsp_lua(void) @@ -2187,44 +2612,40 @@ static void dsp_lua(void) } else { dsp_core->registers[DSP_REG_R0+dstreg] = srcnew; } -} - -static void dsp_movec(void) -{ - Uint32 value; - - value = (cur_inst>>13) & (1<<3); - value |= (cur_inst>>12) & (1<<2); - value |= (cur_inst>>6) & (1<<1); - value |= (cur_inst>>5) & 1; - opcodes_movec[value](); + dsp_core->instr_cycle += 2; } -static void dsp_movec_7(void) +static void dsp_movec_reg(void) { - Uint32 numreg1, numreg2, value; + Uint32 numreg1, numreg2, value, dummy; /* S1,D2 */ /* S2,D1 */ numreg2 = (cur_inst>>8) & BITMASK(6); - numreg1 = (cur_inst & BITMASK(5))|0x20; + numreg1 = cur_inst & BITMASK(6); if (cur_inst & (1<<15)) { /* Write D1 */ if ((numreg2 == DSP_REG_A) || (numreg2 == DSP_REG_B)) { - dsp_pm_read_accu24(numreg2, &dsp_core->registers[numreg1]); + dsp_pm_read_accu24(numreg2, &value); } else { - dsp_core->registers[numreg1] = dsp_core->registers[numreg2]; + value = dsp_core->registers[numreg2]; } - dsp_core->registers[numreg1] &= BITMASK(registers_mask[numreg1]); + value &= BITMASK(registers_mask[numreg1]); + dsp_write_reg(numreg1, value); } else { /* Read S1 */ + if (numreg1 == DSP_REG_SSH) { + dsp_stack_pop(&value, &dummy); + } + else { + value = dsp_core->registers[numreg1]; + } if ((numreg2 == DSP_REG_A) || (numreg2 == DSP_REG_B)) { - value = dsp_core->registers[numreg1]; dsp_core->registers[DSP_REG_A2+(numreg2 & 1)] = 0; if (value & (1<<23)) { dsp_core->registers[DSP_REG_A2+(numreg2 & 1)] = 0xff; @@ -2232,50 +2653,55 @@ static void dsp_movec_7(void) dsp_core->registers[DSP_REG_A1+(numreg2 & 1)] = value & BITMASK(24); dsp_core->registers[DSP_REG_A0+(numreg2 & 1)] = 0; } else { - dsp_core->registers[numreg2] = dsp_core->registers[numreg1]; - dsp_core->registers[numreg2] &= BITMASK(registers_mask[numreg2]); + dsp_core->registers[numreg2] = value & BITMASK(registers_mask[numreg2]); } } } -static void dsp_movec_9(void) +static void dsp_movec_aa(void) { - Uint32 numreg, addr, memspace; + Uint32 numreg, addr, memspace, value, dummy; /* x:aa,D1 */ /* S1,x:aa */ /* y:aa,D1 */ /* S1,y:aa */ - numreg = (cur_inst & BITMASK(5))|0x20; + numreg = cur_inst & BITMASK(6); addr = (cur_inst>>8) & BITMASK(6); memspace = (cur_inst>>6) & 1; if (cur_inst & (1<<15)) { /* Write D1 */ - - dsp_core->registers[numreg] = read_memory(memspace, addr); - dsp_core->registers[numreg] &= BITMASK(registers_mask[numreg]); + value = read_memory(memspace, addr); + value &= BITMASK(registers_mask[numreg]); + dsp_write_reg(numreg, value); } else { /* Read S1 */ - - write_memory(memspace, addr, dsp_core->registers[numreg]); + if (numreg == DSP_REG_SSH) { + dsp_stack_pop(&value, &dummy); + } + else { + value = dsp_core->registers[numreg]; + } + write_memory(memspace, addr, value); } } -static void dsp_movec_b(void) +static void dsp_movec_imm(void) { - Uint32 numreg; + Uint32 numreg, value; /* #xx,D1 */ - - numreg = (cur_inst & BITMASK(5))|0x20; - dsp_core->registers[numreg] = (cur_inst>>8) & BITMASK(8); + numreg = cur_inst & BITMASK(6); + value = (cur_inst>>8) & BITMASK(8); + value &= BITMASK(registers_mask[numreg]); + dsp_write_reg(numreg, value); } -static void dsp_movec_d(void) +static void dsp_movec_ea(void) { - Uint32 numreg, addr, memspace, ea_mode; + Uint32 numreg, addr, memspace, ea_mode, value, dummy; int retour; /* x:ea,D1 */ @@ -2284,82 +2710,96 @@ static void dsp_movec_d(void) /* S1,y:ea */ /* #xxxx,D1 */ - numreg = (cur_inst & BITMASK(5))|0x20; + numreg = cur_inst & BITMASK(6); ea_mode = (cur_inst>>8) & BITMASK(6); memspace = (cur_inst>>6) & 1; if (cur_inst & (1<<15)) { /* Write D1 */ - retour = dsp_calc_ea(ea_mode, &addr); if (retour) { - dsp_core->registers[numreg] = addr; + value = addr; } else { - dsp_core->registers[numreg] = read_memory(memspace, addr); + value = read_memory(memspace, addr); } - dsp_core->registers[numreg] &= BITMASK(registers_mask[numreg]); + value &= BITMASK(registers_mask[numreg]); + dsp_write_reg(numreg, value); } else { /* Read S1 */ - - retour = dsp_calc_ea(ea_mode, &addr); - - write_memory(memspace, addr, dsp_core->registers[numreg]); + dsp_calc_ea(ea_mode, &addr); + if (numreg == DSP_REG_SSH) { + dsp_stack_pop(&value, &dummy); + } + else { + value = dsp_core->registers[numreg]; + } + write_memory(memspace, addr, value); } } -static void dsp_movem(void) +static void dsp_movem_aa(void) { - Uint32 numreg, addr, ea_mode, value; + Uint32 numreg, addr, value, dummy; numreg = cur_inst & BITMASK(6); + addr = (cur_inst>>8) & BITMASK(6); - if (cur_inst & (1<<14)) { - /* S,p:ea */ - /* p:ea,D */ - - ea_mode = (cur_inst>>8) & BITMASK(6); - dsp_calc_ea(ea_mode, &addr); + if (cur_inst & (1<<15)) { + /* Write D */ + value = read_memory_p(addr); + value &= BITMASK(registers_mask[numreg]); + dsp_write_reg(numreg, value); } else { - /* S,p:aa */ - /* p:aa,D */ + /* Read S */ + if (numreg == DSP_REG_SSH) { + dsp_stack_pop(&value, &dummy); + } + else if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } + else { + value = dsp_core->registers[numreg]; + } + write_memory(DSP_SPACE_P, addr, value); + } - addr = (cur_inst>>8) & BITMASK(6); + dsp_core->instr_cycle += 4; + if (addr>=0x200) { + dsp_core->instr_cycle += P_WAITSTATE; } +} + +static void dsp_movem_ea(void) +{ + Uint32 numreg, addr, ea_mode, value, dummy; + + numreg = cur_inst & BITMASK(6); + ea_mode = (cur_inst>>8) & BITMASK(6); + dsp_calc_ea(ea_mode, &addr); if (cur_inst & (1<<15)) { /* Write D */ - - if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { - value = read_memory(DSP_SPACE_P, addr); - dsp_core->registers[DSP_REG_A2+(numreg & 1)] = 0; - if (value & (1<<23)) { - dsp_core->registers[DSP_REG_A2+(numreg & 1)] = 0xff; - } - dsp_core->registers[DSP_REG_A1+(numreg & 1)] = value & BITMASK(24); - dsp_core->registers[DSP_REG_A0+(numreg & 1)] = 0; - } else { - dsp_core->registers[numreg] = read_memory(DSP_SPACE_P, addr); - dsp_core->registers[numreg] &= BITMASK(registers_mask[numreg]); - } + value = read_memory_p(addr); + value &= BITMASK(registers_mask[numreg]); + dsp_write_reg(numreg, value); } else { /* Read S */ - - if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { + if (numreg == DSP_REG_SSH) { + dsp_stack_pop(&value, &dummy); + } + else if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { dsp_pm_read_accu24(numreg, &value); - } else { + } + else { value = dsp_core->registers[numreg]; } write_memory(DSP_SPACE_P, addr, value); } -} -static void dsp_movep(void) -{ - Uint32 value; - - value = (cur_inst>>6) & BITMASK(2); - - opcodes_movep[value](); + dsp_core->instr_cycle += 4; + if (addr>=0x200) { + dsp_core->instr_cycle += P_WAITSTATE; + } } static void dsp_movep_0(void) @@ -2369,7 +2809,7 @@ static void dsp_movep_0(void) /* S,y:pp */ /* y:pp,D */ - Uint32 addr, memspace, numreg, value; + Uint32 addr, memspace, numreg, value, dummy; addr = 0xffc0 + (cur_inst & BITMASK(6)); memspace = (cur_inst>>16) & 1; @@ -2377,30 +2817,24 @@ static void dsp_movep_0(void) if (cur_inst & (1<<15)) { /* Write pp */ - if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { dsp_pm_read_accu24(numreg, &value); - } else { + } + else if (numreg == DSP_REG_SSH) { + dsp_stack_pop(&value, &dummy); + } + else { value = dsp_core->registers[numreg]; } write_memory(memspace, addr, value); } else { /* Read pp */ - value = read_memory(memspace, addr); - - if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { - dsp_core->registers[DSP_REG_A2+(numreg & 1)] = 0; - if (value & (1<<23)) { - dsp_core->registers[DSP_REG_A2+(numreg & 1)] = 0xff; - } - dsp_core->registers[DSP_REG_A1+(numreg & 1)] = value & BITMASK(24); - dsp_core->registers[DSP_REG_A0+(numreg & 1)] = 0; - } else { - dsp_core->registers[numreg] = value; - dsp_core->registers[numreg] &= BITMASK(registers_mask[numreg]); - } + value &= BITMASK(registers_mask[numreg]); + dsp_write_reg(numreg, value); } + + dsp_core->instr_cycle += 2; } static void dsp_movep_1(void) @@ -2418,14 +2852,16 @@ static void dsp_movep_1(void) if (cur_inst & (1<<15)) { /* Write pp */ - write_memory(memspace, xyaddr, read_memory(DSP_SPACE_P, paddr)); + write_memory(memspace, xyaddr, read_memory_p(paddr)); } else { /* Read pp */ write_memory(DSP_SPACE_P, paddr, read_memory(memspace, xyaddr)); } + + dsp_core->instr_cycle += 2; } -static void dsp_movep_2(void) +static void dsp_movep_23(void) { /* x:ea,x:pp */ /* y:ea,x:pp */ @@ -2454,13 +2890,20 @@ static void dsp_movep_2(void) if (retour) { write_memory(perspace, peraddr, addr); } else { + if (peraddr>=0x200) { + dsp_core->instr_cycle += P_WAITSTATE; + } write_memory(perspace, peraddr, read_memory(easpace, addr)); } } else { /* Read pp */ - + if (peraddr>=0x200) { + dsp_core->instr_cycle += P_WAITSTATE; + } write_memory(easpace, addr, read_memory(perspace, peraddr)); } + + dsp_core->instr_cycle += 4; } static void dsp_norm(void) @@ -2497,10 +2940,7 @@ static void dsp_norm(void) dsp_core->registers[DSP_REG_A1+numreg] = dest[1]; dsp_core->registers[DSP_REG_A0+numreg] = dest[2]; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; @@ -2528,53 +2968,69 @@ static void dsp_ori(void) } } -static void dsp_rep(void) -{ - Uint32 value; - - dsp_core->registers[DSP_REG_LCSAVE] = dsp_core->registers[DSP_REG_LC]; - - value = (cur_inst>>12) & (BITMASK(2)<<2); - value |= (cur_inst>>6) & (1<<1); - value |= (cur_inst>>5) & 1; +/* + REP instruction parameter encoding - opcodes_rep[value](); - pc_on_rep = 1; /* Not decrement LC at first time */ - dsp_core->loop_rep = 1; /* We are now running rep */ -} + xxxxxxxx 00xxxxxx 0xxxxxxx aa + xxxxxxxx 01xxxxxx 0xxxxxxx ea + xxxxxxxx YYxxxxxx 1xxxxxxx imm + xxxxxxxx 11xxxxxx 0xxxxxxx reg +*/ -static void dsp_rep_1(void) +static void dsp_rep_aa(void) { /* x:aa */ /* y:aa */ + dsp_core->registers[DSP_REG_LCSAVE] = dsp_core->registers[DSP_REG_LC]; + dsp_core->pc_on_rep = 1; /* Not decrement LC at first time */ + dsp_core->loop_rep = 1; /* We are now running rep */ dsp_core->registers[DSP_REG_LC]=read_memory((cur_inst>>6) & 1,(cur_inst>>8) & BITMASK(6)); + + dsp_core->instr_cycle += 2; } -static void dsp_rep_3(void) +static void dsp_rep_imm(void) { /* #xxx */ - dsp_core->registers[DSP_REG_LC]= (cur_inst>>8) & BITMASK(8); + dsp_core->registers[DSP_REG_LCSAVE] = dsp_core->registers[DSP_REG_LC]; + dsp_core->pc_on_rep = 1; /* Not decrement LC at first time */ + dsp_core->loop_rep = 1; /* We are now running rep */ + + dsp_core->registers[DSP_REG_LC] = ((cur_inst>>8) & BITMASK(8)) + + ((cur_inst & BITMASK(4))<<8); + + dsp_core->instr_cycle += 2; } -static void dsp_rep_5(void) +static void dsp_rep_ea(void) { Uint32 value; /* x:ea */ /* y:ea */ + dsp_core->registers[DSP_REG_LCSAVE] = dsp_core->registers[DSP_REG_LC]; + dsp_core->pc_on_rep = 1; /* Not decrement LC at first time */ + dsp_core->loop_rep = 1; /* We are now running rep */ + dsp_calc_ea((cur_inst>>8) & BITMASK(6),&value); dsp_core->registers[DSP_REG_LC]= read_memory((cur_inst>>6) & 1, value); + + dsp_core->instr_cycle += 2; } -static void dsp_rep_d(void) +static void dsp_rep_reg(void) { Uint32 numreg; /* R */ + dsp_core->registers[DSP_REG_LCSAVE] = dsp_core->registers[DSP_REG_LC]; + dsp_core->pc_on_rep = 1; /* Not decrement LC at first time */ + dsp_core->loop_rep = 1; /* We are now running rep */ + numreg = (cur_inst>>8) & BITMASK(6); if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { dsp_pm_read_accu24(numreg, &dsp_core->registers[DSP_REG_LC]); @@ -2582,11 +3038,14 @@ static void dsp_rep_d(void) dsp_core->registers[DSP_REG_LC] = dsp_core->registers[numreg]; } dsp_core->registers[DSP_REG_LC] &= BITMASK(16); + + dsp_core->instr_cycle += 2; } static void dsp_reset(void) { /* Reset external peripherals */ + dsp_core->instr_cycle += 2; } static void dsp_rti(void) @@ -2594,11 +3053,14 @@ static void dsp_rti(void) Uint32 newpc = 0, newsr = 0; dsp_stack_pop(&newpc, &newsr); - dsp_core->pc = newpc; dsp_core->registers[DSP_REG_SR] = newsr; - cur_inst_len = 0; + + dsp_core->instr_cycle += 2; + if (newpc >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } } static void dsp_rts(void) @@ -2606,9 +3068,13 @@ static void dsp_rts(void) Uint32 newpc = 0, newsr; dsp_stack_pop(&newpc, &newsr); - dsp_core->pc = newpc; cur_inst_len = 0; + + dsp_core->instr_cycle += 2; + if (newpc >= 0x200) { + dsp_core->instr_cycle += 2*P_WAITSTATE; + } } static void dsp_stop(void) @@ -2616,15 +3082,14 @@ static void dsp_stop(void) #if DSP_DISASM_STATE fprintf(stderr, "Dsp: STOP instruction\n"); #endif - SDL_SemWait(dsp_core->semaphore); } static void dsp_swi(void) { /* Raise interrupt p:0x0006 */ -#if DSP_DISASM_INTER - fprintf(stderr, "Dsp: Interrupt: Swi\n"); -#endif + dsp_core_add_interrupt(dsp_core, DSP_INTER_SWI); + + dsp_core->instr_cycle += 6; } static void dsp_tcc(void) @@ -2673,7 +3138,6 @@ static void dsp_wait(void) #if DSP_DISASM_STATE fprintf(stderr, "Dsp: WAIT instruction\n"); #endif - SDL_SemWait(dsp_core->semaphore); } /********************************** @@ -2693,6 +3157,15 @@ static void dsp_parmove_read(void) opcodes_parmove[value](); } +static void dsp_pm_class2(void) { + Uint32 value; + + dsp_pm_0(); + value = cur_inst & BITMASK(8); + opcodes_alu[value](); + dsp_parmove_write(); +} + static void dsp_parmove_write(void) { Uint32 i,j; @@ -2724,35 +3197,55 @@ static void dsp_parmove_write(void) static int dsp_pm_read_accu24(int numreg, Uint32 *dest) { - Uint32 scaling, value, numbits; + Uint32 scaling, value, reg; int got_limited=0; /* Read an accumulator, stores it limited */ scaling = (dsp_core->registers[DSP_REG_SR]>>DSP_SR_S0) & BITMASK(2); - numreg &= 1; + reg = numreg & 1; - /* scaling==1 */ - value = dsp_core->registers[DSP_REG_A2+numreg] & 0xff; - numbits = 8; + value = (dsp_core->registers[DSP_REG_A2+reg]) << 24; + value += dsp_core->registers[DSP_REG_A1+reg]; switch(scaling) { case 0: - value <<=1; - value |= (dsp_core->registers[DSP_REG_A1+numreg]>>23) & 1; - numbits=9; + /* No scaling */ + break; + case 1: + /* scaling down */ + value >>= 1; break; case 2: - value <<=2; - value |= (dsp_core->registers[DSP_REG_A1+numreg]>>22) & 3; - numbits=10; + /* scaling up */ + value <<= 1; + value |= (dsp_core->registers[DSP_REG_A0+reg]>>23) & 1; + break; + /* indeterminate */ + case 3: break; } - if ((value==0) || (value==(Uint32)(BITMASK(numbits)))) { - /* No limiting */ - *dest=dsp_core->registers[DSP_REG_A1+numreg]; - } else if (dsp_core->registers[DSP_REG_A2+numreg] & (1<<7)) { + /* limiting ? */ + value &= BITMASK(24); + + if (dsp_core->registers[DSP_REG_A2+reg] == 0) { + if (value <= 0x007fffff) { + /* No limiting */ + *dest=value; + return 0; + } + } + + if (dsp_core->registers[DSP_REG_A2+reg] == 0xff) { + if (value >= 0x00800000) { + /* No limiting */ + *dest=value; + return 0; + } + } + + if (dsp_core->registers[DSP_REG_A2+reg] & (1<<7)) { /* Limited to maximum negative value */ *dest=0x00800000; dsp_core->registers[DSP_REG_SR] |= (1<registers[DSP_REG_A1+numreg]; tmp_parmove_dest[1][2].host_pointer=&dsp_core->registers[DSP_REG_A0+numreg]; - tmp_parmove_start[1] = 0; - tmp_parmove_len[1] = 3; + tmp_parmove_start[1]=0; + tmp_parmove_len[1]=3; + tmp_parmove_type[1]=0; } static void dsp_pm_1(void) @@ -2929,16 +3423,16 @@ static void dsp_pm_2(void) 0010 00ee eeed dddd S,D 001d dddd iiii iiii #xx,D */ - if (((cur_inst >> 8) & 0xffff) == 0x2000) { + if ((cur_inst & 0xffff00) == 0x200000) { return; } - if (((cur_inst >> 8) & 0xffe0) == 0x2040) { + if ((cur_inst & 0xffe000) == 0x204000) { dsp_calc_ea((cur_inst>>8) & BITMASK(5), &dummy); return; } - if (((cur_inst >> 8) & 0xfc00) == 0x2000) { + if ((cur_inst & 0xfc0000) == 0x200000) { dsp_pm_2_2(); return; } @@ -2963,19 +3457,20 @@ static void dsp_pm_2_2(void) if ((srcreg == DSP_REG_A) || (srcreg == DSP_REG_B)) { /* Accu to register or accu: limited 24 bits */ dsp_pm_read_accu24(srcreg, &tmp_parmove_src[0][1]); + tmp_parmove_src[0][1] &= BITMASK(registers_mask[dstreg]); if (tmp_parmove_src[0][1] & (1<<23)) { tmp_parmove_src[0][0]=0x0000ff; } } else { if ((dstreg == DSP_REG_A) || (dstreg == DSP_REG_B)) { /* Register to accu: sign extended to 56 bits */ - tmp_parmove_src[0][1]=dsp_core->registers[srcreg] & BITMASK(registers_mask[srcreg]); + tmp_parmove_src[0][1]=dsp_core->registers[srcreg] & BITMASK(registers_mask[dstreg]); if (tmp_parmove_src[0][1] & (1<<23)) { tmp_parmove_src[0][0]=0x0000ff; } } else { /* Register to register: n bits */ - tmp_parmove_src[0][1]=dsp_core->registers[srcreg] & BITMASK(registers_mask[srcreg]); + tmp_parmove_src[0][1]=dsp_core->registers[srcreg] & BITMASK(registers_mask[dstreg]); } } @@ -3018,114 +3513,179 @@ static void dsp_pm_3(void) static void dsp_pm_4(void) { - Uint32 l_addr, value; - int retour; /* - 0100 l0ll w0aa aaaa l:aa,D + 0100 l0ll w0aa aaaa l:aa,D S,l:aa - 0100 l0ll w1mm mrrr l:ea,D + 0100 l0ll w1mm mrrr l:ea,D S,l:ea - 01dd 0ddd w0aa aaaa x:aa,D + 01dd 0ddd w0aa aaaa x:aa,D S,x:aa - 01dd 0ddd w1mm mrrr x:ea,D + 01dd 0ddd w1mm mrrr x:ea,D S,x:ea #xxxxxx,D - 01dd 1ddd w0aa aaaa y:aa,D + 01dd 1ddd w0aa aaaa y:aa,D S,y:aa - 01dd 1ddd w1mm mrrr y:ea,D + 01dd 1ddd w1mm mrrr y:ea,D S,y:ea #xxxxxx,D */ - value = (cur_inst>>16) & BITMASK(3); - value |= (cur_inst>>17) & (BITMASK(2)<<3); - - if ((value>>2)==0) { - value = (cur_inst>>8) & BITMASK(6); - if (cur_inst & (1<<14)) { - retour = dsp_calc_ea(value, &l_addr); - } else { - l_addr = value; - retour = 0; - } - dsp_pm_4x(retour, l_addr); + if ((cur_inst & 0xf40000)==0x400000) { + dsp_pm_4x(); return; } dsp_pm_5(); } -static void dsp_pm_4x(int immediat, Uint32 l_addr) +static void dsp_pm_4x(void) { - Uint32 value, numreg, numreg2; - immediat = 0; /* UNUSED */ + Uint32 value, numreg, l_addr; /* - 0100 l0ll w0aa aaaa l:aa,D - S,l:aa - 0100 l0ll w1mm mrrr l:ea,D - S,l:ea + 0100 l0ll w0aa aaaa l:aa,D + S,l:aa + 0100 l0ll w1mm mrrr l:ea,D + S,l:ea */ - l_addr &= BITMASK(16); + value = (cur_inst>>8) & BITMASK(6); + if (cur_inst & (1<<14)) { + dsp_calc_ea(value, &l_addr); + } else { + l_addr = value; + } + numreg = (cur_inst>>16) & BITMASK(2); numreg |= (cur_inst>>17) & (1<<2); + /* 2 more cycles are needed if address is in external memory */ + if (l_addr>=0x200) { + dsp_core->instr_cycle += 2; + } + if (cur_inst & (1<<15)) { /* Write D */ + tmp_parmove_src[0][1] = read_memory(DSP_SPACE_X,l_addr); - /* Sources */ - value = read_memory(DSP_SPACE_X,l_addr); - tmp_parmove_src[0][0] = (value & (1<<23) ? 0xff : 0); - tmp_parmove_src[0][1] = value & BITMASK(registers_mask[registers_lmove[numreg][0]]); - tmp_parmove_src[0][2] = 0x000000; - value = read_memory(DSP_SPACE_Y,l_addr); - - if (registers_lmove[numreg][0]==registers_lmove[numreg][1]) { - /* Write to 56bit accumulator, setup a single transfer as 56 bit */ - tmp_parmove_src[0][2] = value & BITMASK(registers_mask[registers_lmove[numreg][1]]); - } else { - /* Writes to 24bit registers, setup second 24 bit transfer */ - tmp_parmove_src[1][0] = (value & (1<<23) ? 0xff : 0); - tmp_parmove_src[1][1] = value & BITMASK(registers_mask[registers_lmove[numreg][1]]); - tmp_parmove_src[1][2] = 0x000000; + switch(numreg) { + case 0: + /* A10 */ + tmp_parmove_src[1][1] = read_memory(DSP_SPACE_Y,l_addr); + dsp_pm_writereg(DSP_REG_A1, 0); + dsp_pm_writereg(DSP_REG_A0, 1); + break; + case 1: + /* B10 */ + tmp_parmove_src[1][1] = read_memory(DSP_SPACE_Y,l_addr); + dsp_pm_writereg(DSP_REG_B1, 0); + dsp_pm_writereg(DSP_REG_B0, 1); + break; + case 2: + /* X */ + tmp_parmove_src[1][1] = read_memory(DSP_SPACE_Y,l_addr); + dsp_pm_writereg(DSP_REG_X1, 0); + dsp_pm_writereg(DSP_REG_X0, 1); + break; + case 3: + /* Y */ + tmp_parmove_src[1][1] = read_memory(DSP_SPACE_Y,l_addr); + dsp_pm_writereg(DSP_REG_Y1, 0); + dsp_pm_writereg(DSP_REG_Y0, 1); + break; + case 4: + /* A */ + tmp_parmove_src[0][0] = (tmp_parmove_src[0][1] & (1<<23) ? 0xff : 0); + tmp_parmove_src[0][2] = read_memory(DSP_SPACE_Y,l_addr); + dsp_pm_writereg(DSP_REG_A, 0); + break; + case 5: + /* B */ + tmp_parmove_src[0][0] = (tmp_parmove_src[0][1] & (1<<23) ? 0xff : 0); + tmp_parmove_src[0][2] = read_memory(DSP_SPACE_Y,l_addr); + dsp_pm_writereg(DSP_REG_B, 0); + break; + case 6: + /* AB */ + tmp_parmove_src[0][0] = (tmp_parmove_src[0][1] & (1<<23) ? 0xff : 0); + tmp_parmove_src[0][2] = 0; + tmp_parmove_src[1][1] = read_memory(DSP_SPACE_Y,l_addr); + tmp_parmove_src[1][0] = (tmp_parmove_src[1][1] & (1<<23) ? 0xff : 0); + tmp_parmove_src[1][2] = 0; + dsp_pm_writereg(DSP_REG_A, 0); + dsp_pm_writereg(DSP_REG_B, 1); + break; + case 7: + /* BA */ + tmp_parmove_src[0][0] = (tmp_parmove_src[0][1] & (1<<23) ? 0xff : 0); + tmp_parmove_src[0][2] = 0; + tmp_parmove_src[1][1] = read_memory(DSP_SPACE_Y,l_addr); + tmp_parmove_src[1][0] = (tmp_parmove_src[1][1] & (1<<23) ? 0xff : 0); + tmp_parmove_src[1][2] = 0; + dsp_pm_writereg(DSP_REG_B, 0); + dsp_pm_writereg(DSP_REG_A, 1); + break; } - /* Destinations */ - dsp_pm_writereg(registers_lmove[numreg][0], 0); tmp_parmove_type[0]=0; - - if (registers_lmove[numreg][0]!=registers_lmove[numreg][1]) { - /* Two 24 or 56 bits registers */ - dsp_pm_writereg(registers_lmove[numreg][1], 1); - tmp_parmove_type[1]=0; - } + tmp_parmove_type[1]=0; } else { /* Read S */ - /* Sources */ - if (numreg<4) { - /* Two 24 bits tranfers */ - tmp_parmove_src[0][1] = dsp_core->registers[registers_lmove[numreg][0]]; - tmp_parmove_src[1][1] = dsp_core->registers[registers_lmove[numreg][1]]; - } else if (numreg<6) { - /* Single accumulator transfer */ - numreg2 = registers_lmove[numreg][0]; - if (dsp_pm_read_accu24(numreg2, &tmp_parmove_src[0][1])) { - /* Was limited, set lower part */ - tmp_parmove_src[1][1] = (tmp_parmove_src[0][1] & (1<<23) ? 0 : 0xffffff); - } else { - /* Not limited */ - tmp_parmove_src[1][1] = dsp_core->registers[DSP_REG_A0+(numreg2 & 1)]; - } - } else { - /* Two accumulators tranfers */ - dsp_pm_read_accu24(registers_lmove[numreg][0], &tmp_parmove_src[0][1]); - dsp_pm_read_accu24(registers_lmove[numreg][1], &tmp_parmove_src[1][1]); + switch(numreg) { + case 0: + /* A10 */ + tmp_parmove_src[0][1] = dsp_core->registers[DSP_REG_A1]; + tmp_parmove_src[1][1] = dsp_core->registers[DSP_REG_A0]; + break; + case 1: + /* B10 */ + tmp_parmove_src[0][1] = dsp_core->registers[DSP_REG_B1]; + tmp_parmove_src[1][1] = dsp_core->registers[DSP_REG_B0]; + break; + case 2: + /* X */ + tmp_parmove_src[0][1] = dsp_core->registers[DSP_REG_X1]; + tmp_parmove_src[1][1] = dsp_core->registers[DSP_REG_X0]; + break; + case 3: + /* Y */ + tmp_parmove_src[0][1] = dsp_core->registers[DSP_REG_Y1]; + tmp_parmove_src[1][1] = dsp_core->registers[DSP_REG_Y0]; + break; + case 4: + /* A */ + if (dsp_pm_read_accu24(DSP_REG_A, &tmp_parmove_src[0][1])) { + /* Was limited, set lower part */ + tmp_parmove_src[1][1] = (tmp_parmove_src[0][1] & (1<<23) ? 0 : 0xffffff); + } else { + /* Not limited */ + tmp_parmove_src[1][1] = dsp_core->registers[DSP_REG_A0]; + } + break; + case 5: + /* B */ + if (dsp_pm_read_accu24(DSP_REG_B, &tmp_parmove_src[0][1])) { + /* Was limited, set lower part */ + tmp_parmove_src[1][1] = (tmp_parmove_src[0][1] & (1<<23) ? 0 : 0xffffff); + } else { + /* Not limited */ + tmp_parmove_src[1][1] = dsp_core->registers[DSP_REG_B0]; + } + break; + case 6: + /* AB */ + dsp_pm_read_accu24(DSP_REG_A, &tmp_parmove_src[0][1]); + dsp_pm_read_accu24(DSP_REG_B, &tmp_parmove_src[1][1]); + break; + case 7: + /* BA */ + dsp_pm_read_accu24(DSP_REG_B, &tmp_parmove_src[0][1]); + dsp_pm_read_accu24(DSP_REG_A, &tmp_parmove_src[1][1]); + break; } /* D1 */ tmp_parmove_dest[0][1].dsp_address=l_addr; tmp_parmove_start[0]=1; tmp_parmove_len[0]=1; - tmp_parmove_type[0]=1; tmp_parmove_space[0]=DSP_SPACE_X; @@ -3133,7 +3693,6 @@ static void dsp_pm_4x(int immediat, Uint tmp_parmove_dest[1][1].dsp_address=l_addr; tmp_parmove_start[1]=1; tmp_parmove_len[1]=1; - tmp_parmove_type[1]=1; tmp_parmove_space[1]=DSP_SPACE_Y; } @@ -3143,14 +3702,14 @@ static void dsp_pm_5(void) { Uint32 memspace, numreg, value, xy_addr, retour; /* - 01dd 0ddd w0aa aaaa x:aa,D + 01dd 0ddd w0aa aaaa x:aa,D S,x:aa - 01dd 0ddd w1mm mrrr x:ea,D + 01dd 0ddd w1mm mrrr x:ea,D S,x:ea #xxxxxx,D - 01dd 1ddd w0aa aaaa y:aa,D + 01dd 1ddd w0aa aaaa y:aa,D S,y:aa - 01dd 1ddd w1mm mrrr y:ea,D + 01dd 1ddd w1mm mrrr y:ea,D S,y:ea #xxxxxx,D */ @@ -3176,12 +3735,12 @@ static void dsp_pm_5(void) } else { value = read_memory(memspace, xy_addr); } + tmp_parmove_src[0][1]= value & BITMASK(registers_mask[numreg]); + tmp_parmove_src[0][2]= 0x000000; tmp_parmove_src[0][0]= 0x000000; if (value & (1<<23)) { tmp_parmove_src[0][0]= 0x0000ff; } - tmp_parmove_src[0][1]= value & BITMASK(registers_mask[numreg]); - tmp_parmove_src[0][2]= 0x000000; dsp_pm_writereg(numreg, 0); tmp_parmove_type[0]=0; @@ -3208,9 +3767,9 @@ static void dsp_pm_8(void) { Uint32 ea1, ea2; Uint32 numreg1, numreg2; - Uint32 value, dummy1, dummy2; + Uint32 value, x_addr, y_addr; /* - 1wmm eeff WrrM MRRR x:ea,D1 y:ea,D2 + 1wmm eeff WrrM MRRR x:ea,D1 y:ea,D2 x:ea,D1 S2,y:ea S1,x:ea y:ea,D2 S1,x:ea S2,y:ea @@ -3230,8 +3789,13 @@ static void dsp_pm_8(void) ea2 |= (1<<5); } - dsp_calc_ea(ea1, &dummy1); - dsp_calc_ea(ea2, &dummy2); + dsp_calc_ea(ea1, &x_addr); + dsp_calc_ea(ea2, &y_addr); + + /* 2 more cycles are needed if X:address1 and Y:address2 are both in external memory */ + if ((x_addr>=0x200) && (y_addr>=0x200)) { + dsp_core->instr_cycle += 2; + } switch((cur_inst>>18) & BITMASK(2)) { case 0: numreg1=DSP_REG_X0; break; @@ -3249,14 +3813,13 @@ static void dsp_pm_8(void) if (cur_inst & (1<<15)) { /* Write D1 */ - value = read_memory(DSP_SPACE_X, dummy1); + value = read_memory(DSP_SPACE_X, x_addr); tmp_parmove_src[0][0]= 0x000000; if (value & (1<<23)) { tmp_parmove_src[0][0]= 0x0000ff; } tmp_parmove_src[0][1]= value & BITMASK(registers_mask[numreg1]); tmp_parmove_src[0][2]= 0x000000; - dsp_pm_writereg(numreg1, 0); tmp_parmove_type[0]=0; } else { @@ -3267,12 +3830,9 @@ static void dsp_pm_8(void) } else { tmp_parmove_src[0][1]=dsp_core->registers[numreg1]; } - - tmp_parmove_dest[0][1].dsp_address=dummy1; - + tmp_parmove_dest[0][1].dsp_address=x_addr; tmp_parmove_start[0]=1; tmp_parmove_len[0]=1; - tmp_parmove_type[0]=1; tmp_parmove_space[0]=DSP_SPACE_X; } @@ -3280,29 +3840,26 @@ static void dsp_pm_8(void) if (cur_inst & (1<<22)) { /* Write D2 */ - value = read_memory(DSP_SPACE_Y, dummy2); + value = read_memory(DSP_SPACE_Y, y_addr); tmp_parmove_src[1][0]= 0x000000; if (value & (1<<23)) { tmp_parmove_src[1][0]= 0x0000ff; } tmp_parmove_src[1][1]= value & BITMASK(registers_mask[numreg2]); tmp_parmove_src[1][2]= 0x000000; - dsp_pm_writereg(numreg2, 1); tmp_parmove_type[1]=0; } else { /* Read S2 */ - if ((numreg1==DSP_REG_A) || (numreg1==DSP_REG_B)) { - dsp_pm_read_accu24(numreg1, &tmp_parmove_src[1][1]); + if ((numreg2==DSP_REG_A) || (numreg2==DSP_REG_B)) { + dsp_pm_read_accu24(numreg2, &tmp_parmove_src[1][1]); } else { - tmp_parmove_src[1][1]=dsp_core->registers[numreg1]; + tmp_parmove_src[1][1]=dsp_core->registers[numreg2]; } - tmp_parmove_dest[1][1].dsp_address=dummy2; - + tmp_parmove_dest[1][1].dsp_address=y_addr; tmp_parmove_start[1]=1; tmp_parmove_len[1]=1; - tmp_parmove_type[1]=1; tmp_parmove_space[1]=DSP_SPACE_Y; } @@ -3387,45 +3944,88 @@ static Uint16 dsp_asr56(Uint32 *dest) static Uint16 dsp_add56(Uint32 *source, Uint32 *dest) { - Uint16 overflow, carry; + Uint16 overflow, carry, flg_s, flg_d, flg_r; + Uint32 not_dest[3]; + + flg_s = (source[0]>>7) & 1; + flg_d = (dest[0]>>7) & 1; + + not_dest[2] = ((Uint32)(~dest[2])) & BITMASK(24); + not_dest[1] = ((Uint32)(~dest[1])) & BITMASK(24); + not_dest[0] = ((Uint32)(~dest[0])) & BITMASK(8); /* Add source to dest: D = D+S */ dest[2] += source[2]; dest[1] += source[1]+((dest[2]>>24) & 1); dest[0] += source[0]+((dest[1]>>24) & 1); - /* overflow if we go below -256.0 or above +256.0 */ - overflow = (((dest[0] & 0xff)!=0) && ((dest[0] & 0xff)!=0xff)); - - /* set carry from the virtual 56th bit */ - carry = (dest[0]>>8) & 1; - dest[2] &= BITMASK(24); dest[1] &= BITMASK(24); dest[0] &= BITMASK(8); + flg_r = (dest[0]>>7) & 1; + + /*set overflow*/ + overflow = (flg_s ^ flg_r) & (flg_d ^ flg_r); + + /* set carry : carry (for a add) = ~dest < source */ + carry = 0; + + if (not_dest[0] < source[0]) { + carry = 1; + } else if (not_dest[0] == source[0]) { + if (not_dest[1] < source[1]) { + carry = 1; + } else if (not_dest[1] == source[1]) { + if (not_dest[2] < source[2]) { + carry = 1; + } + } + } + return (overflow<>24) & 1); dest[0] -= source[0]+((dest[1]>>24) & 1); - /* overflow if we go below -256.0 or above +256.0 */ - overflow = (((dest[0] & 0xff)!=0) && ((dest[0] & 0xff)!=0xff)); - - /* set carry from the virtual 56th bit */ - carry = (dest[0]>>8) & 1; - dest[2] &= BITMASK(24); dest[1] &= BITMASK(24); dest[0] &= BITMASK(8); + flg_s = (source[0]>>7) & 1; + flg_d = (dest_save[0]>>7) & 1; + flg_r = (dest[0]>>7) & 1; + + /* set overflow */ + overflow = (flg_s ^ flg_d) & (flg_r ^ flg_d); + + /* set carry : carry (for a sub) = dest < source */ + carry = 0; + + if (dest_save[0] < source[0]) { + carry = 1; + } else if (dest_save[0] == source[0]) { + if (dest_save[1] < source[1]) { + carry = 1; + } else if (dest_save[1] == source[1]) { + if (dest_save[2] < source[2]) { + carry = 1; + } + } + } + return (overflow<>24) & BITMASK(8)) { - ++dest[0]; - dest[0] &= BITMASK(8); - dest[1] &= BITMASK(24); - } - } - } else if (value>0x800000) { - ++dest[1]; - if ((dest[1]>>24) & BITMASK(8)) { - ++dest[0]; - dest[0] &= BITMASK(8); - dest[1] &= BITMASK(24); + /* Scaling mode S0 */ + if (dsp_core->registers[DSP_REG_SR] & (1<registers[DSP_REG_SR] & (1<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= (overflowed<registers[DSP_REG_A1+destreg] = dest[1]; dsp_core->registers[DSP_REG_A0+destreg] = dest[2]; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; @@ -3681,10 +4289,7 @@ static void dsp_add(void) dsp_core->registers[DSP_REG_A1+destreg] = dest[1]; dsp_core->registers[DSP_REG_A0+destreg] = dest[2]; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; @@ -3711,10 +4316,7 @@ static void dsp_addl(void) dsp_core->registers[DSP_REG_A1+numreg] = dest[1]; dsp_core->registers[DSP_REG_A0+numreg] = dest[2]; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; @@ -3741,10 +4343,7 @@ static void dsp_addr(void) dsp_core->registers[DSP_REG_A1+numreg] = dest[1]; dsp_core->registers[DSP_REG_A0+numreg] = dest[2]; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; @@ -3771,7 +4370,6 @@ static void dsp_and(void) dstreg = DSP_REG_A1+((cur_inst>>3) & 1); dsp_core->registers[dstreg] &= dsp_core->registers[srcreg]; - dsp_core->registers[dstreg] &= BITMASK(24); /* FIXME: useless ? */ dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= ((dsp_core->registers[dstreg]>>23) & 1)<registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); } static void dsp_asr(void) @@ -3823,10 +4418,7 @@ static void dsp_asr(void) dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); } static void dsp_clr(void) @@ -3900,10 +4492,7 @@ static void dsp_cmp(void) newsr = dsp_sub56(source, dest); - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; @@ -3968,10 +4557,7 @@ static void dsp_cmpm(void) dsp_abs56(source); newsr = dsp_sub56(source, dest); - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; @@ -4069,10 +4655,7 @@ static void dsp_mac(void) dsp_core->registers[DSP_REG_A1+destreg] = dest[1]; dsp_core->registers[DSP_REG_A0+destreg] = dest[2]; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newsr & 0xfe; @@ -4111,10 +4694,7 @@ static void dsp_macr(void) dsp_core->registers[DSP_REG_A1+destreg] = dest[1]; dsp_core->registers[DSP_REG_A0+destreg] = dest[2]; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= newsr & 0xfe; @@ -4126,13 +4706,6 @@ static void dsp_move(void) taken care of by parallel move dispatcher */ } -static void dsp_move_pm(void) -{ - /* move instruction outside alu opcodes */ - dsp_parmove_read(); - dsp_parmove_write(); -} - static void dsp_mpy(void) { Uint32 srcreg1, srcreg2, destreg, value, dest[3], source[3]; @@ -4158,10 +4731,9 @@ static void dsp_mpy(void) dsp_core->registers[DSP_REG_A0+destreg] = source[2]; } - dsp_ccr_extension(&dsp_core->registers[DSP_REG_A2+destreg], &dsp_core->registers[DSP_REG_A1+destreg]); - dsp_ccr_unnormalized(&dsp_core->registers[DSP_REG_A2+destreg], &dsp_core->registers[DSP_REG_A1+destreg]); - dsp_ccr_negative(&dsp_core->registers[DSP_REG_A2+destreg]); - dsp_ccr_zero(&dsp_core->registers[DSP_REG_A2+destreg], &dsp_core->registers[DSP_REG_A1+destreg], &dsp_core->registers[DSP_REG_A0+destreg]); + dsp_ccr_update_e_u_n_z( &dsp_core->registers[DSP_REG_A2+destreg], + &dsp_core->registers[DSP_REG_A1+destreg], + &dsp_core->registers[DSP_REG_A0+destreg]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_A1+destreg] = dest[1]; dsp_core->registers[DSP_REG_A0+destreg] = dest[2]; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_SR] |= (overflowed<registers[DSP_REG_A1+numreg] = dest[1]; dsp_core->registers[DSP_REG_A0+numreg] = dest[2]; - dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-(1<registers[DSP_REG_A1+destreg] = dest[1]; dsp_core->registers[DSP_REG_A0+destreg] = dest[2]; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; @@ -4464,10 +5022,7 @@ static void dsp_sub(void) dsp_core->registers[DSP_REG_A1+destreg] = dest[1]; dsp_core->registers[DSP_REG_A0+destreg] = dest[2]; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; @@ -4494,10 +5049,7 @@ static void dsp_subl(void) dsp_core->registers[DSP_REG_A1+numreg] = dest[1]; dsp_core->registers[DSP_REG_A0+numreg] = dest[2]; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; @@ -4524,10 +5076,7 @@ static void dsp_subr(void) dsp_core->registers[DSP_REG_A1+numreg] = dest[1]; dsp_core->registers[DSP_REG_A0+numreg] = dest[2]; - dsp_ccr_extension(&dest[0], &dest[1]); - dsp_ccr_unnormalized(&dest[0], &dest[1]); - dsp_ccr_negative(&dest[0]); - dsp_ccr_zero(&dest[0], &dest[1], &dest[2]); + dsp_ccr_update_e_u_n_z(&dest[0], &dest[1], &dest[2]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; @@ -4594,10 +5143,9 @@ static void dsp_tst(void) destreg = (cur_inst>>3) & 1; - dsp_ccr_extension(&dsp_core->registers[DSP_REG_A2+destreg], &dsp_core->registers[DSP_REG_A1+destreg]); - dsp_ccr_unnormalized(&dsp_core->registers[DSP_REG_A2+destreg], &dsp_core->registers[DSP_REG_A1+destreg]); - dsp_ccr_negative(&dsp_core->registers[DSP_REG_A2+destreg]); - dsp_ccr_zero(&dsp_core->registers[DSP_REG_A2+destreg], &dsp_core->registers[DSP_REG_A1+destreg], &dsp_core->registers[DSP_REG_A0+destreg]); + dsp_ccr_update_e_u_n_z( &dsp_core->registers[DSP_REG_A2+destreg], + &dsp_core->registers[DSP_REG_A1+destreg], + &dsp_core->registers[DSP_REG_A0+destreg]); dsp_core->registers[DSP_REG_SR] &= BITMASK(16)-(1<