diff options
Diffstat (limited to 'src/devices/cpu/dsp56156/dsp56ops.hxx')
-rw-r--r-- | src/devices/cpu/dsp56156/dsp56ops.hxx | 2135 |
1 files changed, 1552 insertions, 583 deletions
diff --git a/src/devices/cpu/dsp56156/dsp56ops.hxx b/src/devices/cpu/dsp56156/dsp56ops.hxx index 52ff4f5560c..0a3c33a8f96 100644 --- a/src/devices/cpu/dsp56156/dsp56ops.hxx +++ b/src/devices/cpu/dsp56156/dsp56ops.hxx @@ -19,11 +19,16 @@ /* TODO: - - 0x01ee: should this move sign extend? otherwise the test-against-minus means nothing. - - Restore only the proper bits upon loop termination! - - BFCLR has some errata in the docs that may need to be applied. + - Restore only the proper SR/MR bits upon loop termination! */ +#define LOG_OUTPUT_FUNC cpustate->device->logerror +#define LOG_UNIMPLEMENTED (1U << 1) +#define LOG_CHECKS (1U << 2) + +#define VERBOSE (0) +#include "logmacro.h" + /************************/ /* Datatypes and macros */ /************************/ @@ -42,7 +47,10 @@ struct typed_pointer char data_type; }; -#define BITS(CUR,MASK) (Dsp56156OpMask(CUR,MASK)) +#define BITS(CUR,MASK) (dsp56156_op_mask(CUR,MASK)) + +static constexpr bool dsp56156_add_ovf_table[8] = { false, true, false, false, false, false, true, false }; +static constexpr bool dsp56156_sub_ovf_table[8] = { false, false, false, true, true, false, false, false }; /*********************/ /* Opcode prototypes */ @@ -169,6 +177,8 @@ static size_t dsp56156_op_tst2 (dsp56156_core* cpustate, const uint16_t op, static size_t dsp56156_op_wait (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles); static size_t dsp56156_op_zero (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles); +static bool dsp56156_value_is_unnormalized(dsp56156_core* cpustate, const uint64_t value); +static bool dsp56156_value_is_extended(dsp56156_core* cpustate, const uint64_t value); static void execute_register_to_register_data_move(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value); static void execute_address_register_update(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value); @@ -177,7 +187,7 @@ static void execute_x_memory_data_move2(dsp56156_core* cpustate, const uint16_t static void execute_dual_x_memory_data_read(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register); static void execute_x_memory_data_move_with_short_displacement(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2); -static uint16_t decode_BBB_bitmask(dsp56156_core* cpustate, uint16_t BBB, uint16_t *iVal); +static uint16_t decode_BBB_bitmask(dsp56156_core* cpustate, uint16_t BBB, uint16_t *iVal); static int decode_cccc_table(dsp56156_core* cpustate, uint16_t cccc); static void decode_DDDDD_table(dsp56156_core* cpustate, uint16_t DDDDD, typed_pointer* ret); static void decode_DD_table(dsp56156_core* cpustate, uint16_t DD, typed_pointer* ret); @@ -202,12 +212,11 @@ static void decode_Z_table(dsp56156_core* cpustate, uint16_t Z, typed_pointe static void execute_m_table(dsp56156_core* cpustate, int x, uint16_t m); static void execute_mm_table(dsp56156_core* cpustate, uint16_t rnum, uint16_t mm); static void execute_MM_table(dsp56156_core* cpustate, uint16_t rnum, uint16_t MM); -static uint16_t execute_q_table(dsp56156_core* cpustate, int RR, uint16_t q); +static uint16_t execute_q_table(dsp56156_core* cpustate, int RR, uint16_t q); static void execute_z_table(dsp56156_core* cpustate, int RR, uint16_t z); -static uint16_t assemble_address_from_Pppppp_table(dsp56156_core* cpustate, uint16_t P, uint16_t ppppp); -static uint16_t assemble_address_from_IO_short_address(dsp56156_core* cpustate, uint16_t pp); -static uint16_t assemble_address_from_6bit_signed_relative_short_address(dsp56156_core* cpustate, uint16_t srs); +static uint16_t assemble_address_from_Pppppp_table(dsp56156_core* cpustate, uint16_t P, uint16_t ppppp); +static uint16_t assemble_address_from_IO_short_address(dsp56156_core* cpustate, uint16_t pp); static void dsp56156_process_loop(dsp56156_core* cpustate); static void dsp56156_process_rep(dsp56156_core* cpustate, size_t repSize); @@ -217,13 +226,15 @@ static void dsp56156_process_rep(dsp56156_core* cpustate, size_t repSize); /********************/ /* Helper Functions */ /********************/ -static uint16_t Dsp56156OpMask(uint16_t op, uint16_t mask); +static uint16_t dsp56156_op_mask(uint16_t op, uint16_t mask); + +static uint64_t dsp56156_limit_long_to_long(dsp56156_core* cpustate, uint64_t val); /* These arguments are written source->destination to fall in line with the processor's paradigm. */ -static void SetDestinationValue(typed_pointer source, typed_pointer dest); +static void dsp56156_set_destination_value(dsp56156_core* cpustate, typed_pointer source, typed_pointer dest); -static void SetDataMemoryValue(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr); -static void SetProgramMemoryValue(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr); +static void dsp56156_set_data_memory_value(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr); +static void dsp56156_set_program_memory_value(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr); @@ -231,10 +242,763 @@ static void SetProgramMemoryValue(dsp56156_core* cpustate, typed_pointer source, IMPLEMENTATION ***************************************************************************/ +static size_t dsp56156_get_op_size(uint16_t op, uint16_t op2) +{ + /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/ + if ((op & 0xe000) == 0x6000) + { + /* ADD : 011m mKKK 0rru Fuuu : A-22 */ + /* SUB : 011m mKKK 0rru Fuuu : A-202 */ + /* Note: 0x0094 check allows command to drop through to MOVE and TFR */ + if (((op & 0xe080) == 0x6000) && ((op & 0x0094) != 0x0010)) + { + return 1; + } + /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */ + else if ((op & 0xe094) == 0x6084) + { + return 1; + } + /* MACR: 011m mKKK 1--1 F1QQ : A-124 */ + else if ((op & 0xe094) == 0x6094) + { + return 0; // Not yet implemented + } + /* TFR : 011m mKKK 0rr1 F0DD : A-212 */ + else if ((op & 0xe094) == 0x6010) + { + return 0; // Not yet implemented + } + /* MOVE : 011m mKKK 0rr1 x111 : A-128, Note: The displayed bitfield appears to be errata. */ + else if ((op & 0xe097) == 0x6017) + { + return 0; // Not yet implemented + } + /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */ + else if ((op & 0xe094) == 0x6080) + { + return 1; + } + /* MPYR : 011m mKKK 1--1 F0QQ : A-162 */ + else if ((op & 0xe094) == 0x6090) + { + return 0; // Not yet implemented + } + } + /* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */ + else if ((op & 0xfe00) == 0x1600) + { + /* MPY : 0001 0110 RRDD FQQQ : A-160 */ + if ((op & 0xff00) == 0x1600) + { + return 0; // Not yet implemented + } + /* MAC : 0001 0111 RRDD FQQQ : A-122 */ + else if ((op & 0xff00) == 0x1700) + { + return 0; // Not yet implemented + } + } + + /* Handle Other parallel types */ + else + { + /***************************************/ + /* 32 General parallel move operations */ + /***************************************/ + + enum pType { kNoParallelDataMove, + kRegisterToRegister, + kAddressRegister, + kXMemoryDataMove, + kXMemoryDataMove2, + kXMemoryDataMoveWithDisp }; + + int parallelType = -1; + + /* Note: it's important that NPDM comes before RtRDM here */ + /* No Parallel Data Move : 0100 1010 .... .... : A-131 */ + if ((op & 0xff00) == 0x4a00) + { + parallelType = kNoParallelDataMove; + } + /* Register to Register Data Move : 0100 IIII .... .... : A-133 */ + else if ((op & 0xf000) == 0x4000) + { + parallelType = kRegisterToRegister; + } + /* Address Register Update : 0011 0zRR .... .... : A-135 */ + else if ((op & 0xf800) == 0x3000) + { + parallelType = kAddressRegister; + } + /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */ + else if ((op & 0x8000) == 0x8000) + { + parallelType = kXMemoryDataMove; + } + /* X Memory Data Move : 0101 HHHW .... .... : A-137 */ + else if ((op & 0xf000) == 0x5000) + { + parallelType = kXMemoryDataMove2; + } + /* X Memory Data Move with short displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */ + else if ((op & 0xff00) == 0x0500) + { + /* Now check it against all the other potential collisions */ + /* This is necessary because "don't care bits" get in the way. */ + /* + MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 + MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 + MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 + */ + if (((op2 & 0xfe20) != 0x0200) && + ((op2 & 0xf810) != 0x3800) && + ((op2 & 0x00ff) != 0x0011)) + { + return 2; + } + } + + if (parallelType != -1) + { + /* Note: There is much overlap between opcodes down here */ + /* To this end, certain ops must come before others in the list */ + + /* CLR : .... .... 0000 F001 : A-60 */ + if ((op & 0x00f7) == 0x0001) + { + return 1; + } + /* ADD : .... .... 0000 FJJJ : A-22 */ + else if ((op & 0x00f0) == 0x0000) + { + return 1; + } + /* MOVE : .... .... 0001 0001 : A-128 */ + else if ((op & 0x00ff) == 0x0011) + { + return 1; + } + /* TFR : .... .... 0001 FJJJ : A-212 */ + else if ((op & 0x00f0) == 0x0010) + { + return 1; + } + /* RND : .... .... 0010 F000 : A-188 */ + else if ((op & 0x00f7) == 0x0020) + { + return 1; + } + /* TST : .... .... 0010 F001 : A-218 */ + else if ((op & 0x00f7) == 0x0021) + { + return 1; + } + /* INC : .... .... 0010 F010 : A-104 */ + else if ((op & 0x00f7) == 0x0022) + { + return 1; + } + /* INC24 : .... .... 0010 F011 : A-106 */ + else if ((op & 0x00f7) == 0x0023) + { + return 1; + } + /* OR : .... .... 0010 F1JJ : A-176 */ + else if ((op & 0x00f4) == 0x0024) + { + return 1; + } + /* ASR : .... .... 0011 F000 : A-32 */ + else if ((op & 0x00f7) == 0x0030) + { + return 1; + } + /* ASL : .... .... 0011 F001 : A-28 */ + else if ((op & 0x00f7) == 0x0031) + { + return 1; + } + /* LSR : .... .... 0011 F010 : A-120 */ + else if ((op & 0x00f7) == 0x0032) + { + return 1; + } + /* LSL : .... .... 0011 F011 : A-118 */ + else if ((op & 0x00f7) == 0x0033) + { + return 1; + } + /* EOR : .... .... 0011 F1JJ : A-94 */ + else if ((op & 0x00f4) == 0x0034) + { + return 1; + } + /* SUBL : .... .... 0100 F001 : A-204 */ + else if ((op & 0x00f7) == 0x0041) + { + return 1; + } + /* SUB : .... .... 0100 FJJJ : A-202 */ + else if ((op & 0x00f0) == 0x0040) + { + return 1; + } + /* CLR24 : .... .... 0101 F001 : A-62 */ + else if ((op & 0x00f7) == 0x0051) + { + return 1; + } + /* SBC : .... .... 0101 F01J : A-198 */ + else if ((op & 0x00f6) == 0x0052) + { + return 1; + } + /* CMP : .... .... 0101 FJJJ : A-64 */ + else if ((op & 0x00f0) == 0x0050) + { + return 1; + } + /* NEG : .... .... 0110 F000 : A-166 */ + else if ((op & 0x00f7) == 0x0060) + { + return 1; + } + /* NOT : .... .... 0110 F001 : A-174 */ + else if ((op & 0x00f7) == 0x0061) + { + return 1; + } + /* DEC : .... .... 0110 F010 : A-72 */ + else if ((op & 0x00f7) == 0x0062) + { + return 1; + } + /* DEC24 : .... .... 0110 F011 : A-74 */ + else if ((op & 0x00f7) == 0x0063) + { + return 1; + } + /* AND : .... .... 0110 F1JJ : A-24 */ + else if ((op & 0x00f4) == 0x0064) + { + return 1; + } + /* ABS : .... .... 0111 F001 : A-18 */ + if ((op & 0x00f7) == 0x0071) + { + return 1; + } + /* ROR : .... .... 0111 F010 : A-192 */ + else if ((op & 0x00f7) == 0x0072) + { + return 1; + } + /* ROL : .... .... 0111 F011 : A-190 */ + else if ((op & 0x00f7) == 0x0073) + { + return 1; + } + /* CMPM : .... .... 0111 FJJJ : A-66 */ + else if ((op & 0x00f0) == 0x0070) + { + return 1; + } + /* MPY : .... .... 1k00 FQQQ : A-160 -- CONFIRMED TYPO IN DOCS (HHHH vs HHHW) */ + else if ((op & 0x00b0) == 0x0080) + { + return 1; + } + /* MPYR : .... .... 1k01 FQQQ : A-162 */ + else if ((op & 0x00b0) == 0x0090) + { + return 1; + } + /* MAC : .... .... 1k10 FQQQ : A-122 */ + else if ((op & 0x00b0) == 0x00a0) + { + return 1; + } + /* MACR : .... .... 1k11 FQQQ : A-124 -- DRAMA - rr vs xx (805) */ + else if ((op & 0x00b0) == 0x00b0) + { + return 1; + } + } + } + + /******************************/ + /* Remaining non-parallel ops */ + /******************************/ + + /* ADC : 0001 0101 0000 F01J : A-20 */ + if ((op & 0xfff6) == 0x1502) + { + return 1; + } + /* ANDI : 0001 1EE0 iiii iiii : A-26 */ + /* (MoveP sneaks in here if you don't check 0x0600) */ + else if (((op & 0xf900) == 0x1800) & ((op & 0x0600) != 0x0000)) + { + return 1; + } + /* ASL4 : 0001 0101 0011 F001 : A-30 */ + else if ((op & 0xfff7) == 0x1531) + { + return 1; + } + /* ASR4 : 0001 0101 0011 F000 : A-34 */ + else if ((op & 0xfff7) == 0x1530) + { + return 1; + } + /* ASR16 : 0001 0101 0111 F000 : A-36 */ + else if ((op & 0xfff7) == 0x1570) + { + return 1; + } + /* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */ + else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x1200)) + { + return 2; + } + /* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */ + else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x1200)) + { + return 2; + } + /* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */ + else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x1200)) + { + return 2; + } + /* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */ + else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x0400)) + { + return 2; + } + /* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */ + else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x0400)) + { + return 2; + } + /* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */ + else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x0400)) + { + return 2; + } + /* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */ + else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x1800)) + { + return 2; + } + /* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */ + else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x1800)) + { + return 2; + } + /* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */ + else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x1800)) + { + return 2; + } + /* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */ + else if (((op & 0xffc0) == 0x1440) && ((op2 & 0x1f00) == 0x1000)) + { + return 2; + } + /* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */ + else if (((op & 0xffe0) == 0x1420) && ((op2 & 0x1f00) == 0x1000)) + { + return 2; + } + /* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */ + else if (((op & 0xffe0) == 0x1400) && ((op2 & 0x1f00) == 0x1000)) + { + return 2; + } + /* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */ + else if (((op & 0xffc0) == 0x1440) && ((op2 & 0x1f00) == 0x0000)) + { + return 2; + } + /* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */ + else if (((op & 0xffe0) == 0x1420) && ((op2 & 0x1f00) == 0x0000)) + { + return 2; + } + /* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */ + else if (((op & 0xffe0) == 0x1400) && ((op2 & 0x1f00) == 0x0000)) + { + return 2; + } + /* Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 */ + else if (((op & 0xff30) == 0x0730) && ((op2 & 0x0000) == 0x0000)) + { + return 2; + } + /* Bcc : 0010 11cc ccee eeee : A-48 */ + else if ((op & 0xfc00) == 0x2c00) + { + return 1; + } + /* Bcc : 0000 0111 RR10 cccc : A-48 */ + else if ((op & 0xff30) == 0x0720) + { + return 1; + } + /* BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 */ + else if (((op & 0xfffc) == 0x013c) && ((op2 & 0x0000) == 0x0000)) + { + return 2; + } + /* BRA : 0000 1011 aaaa aaaa : A-50 */ + else if ((op & 0xff00) == 0x0b00) + { + return 1; + } + /* BRA : 0000 0001 0010 11RR : A-50 */ + else if ((op & 0xfffc) == 0x012c) + { + return 1; + } + /* BRKc : 0000 0001 0001 cccc : A-52 */ + else if ((op & 0xfff0) == 0x0110) + { + return 1; + } + /* BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 */ + else if (((op & 0xff30) == 0x0710) && ((op2 & 0x0000) == 0x0000)) + { + return 2; + } + /* BScc : 0000 0111 RR00 cccc : A-54 */ + else if ((op & 0xff30) == 0x0700) + { + return 1; + } + /* BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 */ + else if (((op & 0xfffc) == 0x0138) && ((op2 & 0x0000) == 0x0000)) + { + return 2; + } + /* BSR : 0000 0001 0010 10RR : A-56 */ + else if ((op & 0xfffc) == 0x0128) + { + return 1; + } + /* CHKAAU : 0000 0000 0000 0100 : A-58 */ + else if ((op & 0xffff) == 0x0004) + { + return 1; + } + /* DEBUG : 0000 0000 0000 0001 : A-68 */ + else if ((op & 0xffff) == 0x0001) + { + return 1; + } + /* DEBUGcc : 0000 0000 0101 cccc : A-70 */ + else if ((op & 0xfff0) == 0x0050) + { + return 1; + } + /* DIV : 0001 0101 0--0 F1DD : A-76 */ + else if ((op & 0xff94) == 0x1504) + { + return 1; + } + /* DMAC : 0001 0101 10s1 FsQQ : A-80 */ + else if ((op & 0xffd0) == 0x1590) + { + return 1; + } + /* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */ + else if (((op & 0xffe0) == 0x00c0) && ((op2 & 0x0000) == 0x0000)) + { + return 2; + } + /* DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 */ + else if (((op & 0xff00) == 0x0e00) && ((op2 & 0x0000) == 0x0000)) + { + return 2; + } + /* DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 */ + else if (((op & 0xffe0) == 0x0400) && ((op2 & 0x0000) == 0x0000)) + { + return 2; + } + /* DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 */ + else if (((op & 0xffff) == 0x0002) && ((op2 & 0x0000) == 0x0000)) + { + return 2; + } + /* ENDDO : 0000 0000 0000 1001 : A-92 */ + else if ((op & 0xffff) == 0x0009) + { + return 1; + } + /* EXT : 0001 0101 0101 F010 : A-96 */ + else if ((op & 0xfff7) == 0x1552) + { + return 1; + } + /* ILLEGAL : 0000 0000 0000 1111 : A-98 */ + else if ((op & 0xffff) == 0x000f) + { + return 1; + } + /* IMAC : 0001 0101 1010 FQQQ : A-100 */ + else if ((op & 0xfff0) == 0x15a0) + { + return 1; + } + /* IMPY : 0001 0101 1000 FQQQ : A-102 */ + else if ((op & 0xfff0) == 0x1580) + { + return 1; + } + /* Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 */ + else if (((op & 0xff30) == 0x0630) && ((op2 & 0x0000) == 0x0000)) + { + return 2; + } + /* Jcc : 0000 0110 RR10 cccc : A-108 */ + else if ((op & 0xff30) == 0x0620 ) + { + return 1; + } + /* JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 */ + else if (((op & 0xfffc) == 0x0134) && ((op2 & 0x0000) == 0x0000)) + { + return 2; + } + /* JMP : 0000 0001 0010 01RR : A-110 */ + else if ((op & 0xfffc) == 0x0124) + { + return 1; + } + /* JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 */ + else if (((op & 0xff30) == 0x0610) && ((op2 & 0x0000) == 0x0000)) + { + return 2; + } + /* JScc : 0000 0110 RR00 cccc : A-112 */ + else if ((op & 0xff30) == 0x0600) + { + return 1; + } + /* JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 */ + else if (((op & 0xfffc) == 0x0130) && ((op2 & 0x0000) == 0x0000)) + { + return 2; + } + /* JSR : 0000 1010 AAAA AAAA : A-114 */ + else if ((op & 0xff00) == 0x0a00) + { + return 1; + } + /* JSR : 0000 0001 0010 00RR : A-114 */ + else if ((op & 0xfffc) == 0x0120) + { + return 1; + } + /* LEA : 0000 0001 11TT MMRR : A-116 */ + else if ((op & 0xffc0) == 0x01c0) + { + return 1; + } + /* LEA : 0000 0001 10NN MMRR : A-116 */ + else if ((op & 0xffc0) == 0x0180) + { + return 1; + } + /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */ + else if ((op & 0xfff0) == 0x15e0) + { + return 1; + } + /* MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 */ + else if (((op & 0xff00) == 0x0500) && ((op2 & 0x00ff) == 0x0011)) + { + return 2; + } + /* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */ + else if ((op & 0xf810) == 0x3800) + { + return 1; + } + /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */ + else if ((op & 0xf814) == 0x3810) + { + return 1; + } + /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */ + else if ((op & 0xf816) == 0x3816) + { + return 1; + } + /* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */ + else if (((op & 0xf816) == 0x3814) && ((op2 & 0x0000) == 0x0000)) + { + return 2; + } + /* MOVE(C) : 0010 10dd dddD DDDD : A-144 */ + else if ((op & 0xfc00) == 0x2800) + { + return 1; + } + /* MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 */ + else if (((op & 0xff00) == 0x0500) && ((op2 & 0xf810) == 0x3800)) + { + return 2; + } + /* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */ + else if ((op & 0xfc00) == 0x2000) + { + return 1; + } + /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */ + else if ((op & 0xfe20) == 0x0200) + { + return 1; + } + /* MOVE(M) : 0000 001W RR11 mmRR : A-152 */ + else if ((op & 0xfe30) == 0x0230) + { + return 1; + } + /* MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 */ + else if (((op & 0xff00) == 0x0500) && ((op2 & 0xfe20) == 0x0200)) + { + return 2; + } + /* MOVE(P) : 0001 100W HH1p pppp : A-156 */ + else if ((op & 0xfe20) == 0x1820) + { + return 1; + } + /* MOVE(P) : 0000 110W RRmp pppp : A-156 */ + else if ((op & 0xfe00) == 0x0c00) + { + return 1; + } + /* MOVE(S) : 0001 100W HH0a aaaa : A-158 */ + else if ((op & 0xfe20) == 0x1800) + { + return 1; + } + /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */ + else if ((op & 0xfff0) == 0x15c0) + { + return 1; + } + /* NEGC : 0001 0101 0110 F000 : A-168 */ + else if ((op & 0xfff7) == 0x1560) + { + return 1; + } + /* NOP : 0000 0000 0000 0000 : A-170 */ + else if ((op & 0xffff) == 0x0000) + { + return 1; + } + /* NORM : 0001 0101 0010 F0RR : A-172 */ + else if ((op & 0xfff4) == 0x1520) + { + return 1; + } + /* ORI : 0001 1EE1 iiii iiii : A-178 */ + else if ((op & 0xf900) == 0x1900) + { + return 1; + } + /* REP : 0000 0000 111- --RR : A-180 */ + else if ((op & 0xffe0) == 0x00e0) + { + return 1; + } + /* REP : 0000 1111 iiii iiii : A-180 */ + else if ((op & 0xff00) == 0x0f00) + { + return 1; + } + /* REP : 0000 0100 001D DDDD : A-180 */ + else if ((op & 0xffe0) == 0x0420) + { + return 1; + } + /* REPcc : 0000 0001 0101 cccc : A-184 */ + else if ((op & 0xfff0) == 0x0150) + { + return 1; + } + /* RESET : 0000 0000 0000 1000 : A-186 */ + else if ((op & 0xffff) == 0x0008) + { + return 1; + } + /* RTI : 0000 0000 0000 0111 : A-194 */ + else if ((op & 0xffff) == 0x0007) + { + return 1; + } + /* RTS : 0000 0000 0000 0110 : A-196 */ + else if ((op & 0xffff) == 0x0006) + { + return 1; + } + /* STOP : 0000 0000 0000 1010 : A-200 */ + else if ((op & 0xffff) == 0x000a) + { + return 1; + } + /* SWAP : 0001 0101 0111 F001 : A-206 */ + else if ((op & 0xfff7) == 0x1571) + { + return 1; + } + /* SWI : 0000 0000 0000 0101 : A-208 */ + else if ((op & 0xffff) == 0x0005) + { + return 1; + } + /* Tcc : 0001 00cc ccTT Fh0h : A-210 */ + else if ((op & 0xfc02) == 0x1000) + { + return 1; + } + /* TFR(2) : 0001 0101 0000 F00J : A-214 */ + else if ((op & 0xfff6) == 0x1500) + { + return 1; + } + /* TFR(3) : 0010 01mW RRDD FHHH : A-216 */ + else if ((op & 0xfc00) == 0x2400) + { + return 1; + } + /* TST(2) : 0001 0101 0001 -1DD : A-220 */ + else if ((op & 0xfff4) == 0x1514) + { + return 1; + } + /* WAIT : 0000 0000 0000 1011 : A-222 */ + else if ((op & 0xffff) == 0x000b) + { + return 1; + } + /* ZERO : 0001 0101 0101 F000 : A-224 */ + else if ((op & 0xfff7) == 0x1550) + { + return 1; + } + + return 1; +} + static void execute_one(dsp56156_core* cpustate) { - uint16_t op; - uint16_t op2; size_t size = 0x1337; uint8_t cycle_count = 0; @@ -245,9 +1009,8 @@ static void execute_one(dsp56156_core* cpustate) cpustate->op = ROPCODE(PC); /* The words we're going to be working with */ - op = ROPCODE(PC); - op2 = ROPCODE(PC + 1); - + uint16_t op = ROPCODE(PC); + uint16_t op2 = ROPCODE(PC + 1); /* DECODE */ /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/ @@ -280,15 +1043,9 @@ static void execute_one(dsp56156_core* cpustate) { size = dsp56156_op_tfr_2(cpustate, op_byte, &d_register, &cycle_count); } - /* MOVE : 011m mKKK 0rr1 0000 : A-128 */ - else if ((op & 0xe09f) == 0x6010) + /* MOVE : 011m mKKK 0rr1 x111 : A-128, Note: The displayed bitfield appears to be errata. */ + else if ((op & 0xe097) == 0x6017) { - /* Note: The opcode encoding : 011x xxxx 0xx1 0000 (move + double memory read) - is .identical. to (tfr X0,A + two parallel reads). This sparks the notion - that these 'move' opcodes don't actually exist and are just there as - documentation. Real-world examples would need to be examined to come - to a satisfactory conclusion, but as it stands, tfr will override this - move operation. */ size = dsp56156_op_move_1(cpustate, op_byte, &d_register, &cycle_count); } /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */ @@ -324,7 +1081,8 @@ static void execute_one(dsp56156_core* cpustate) /* Now evaluate the parallel data move */ /* TODO // decode_x_memory_data_write_and_register_data_move(op, parallel_move_str, parallel_move_str2); */ - cpustate->device->logerror("DSP56156: Unemulated Dual X Memory Data And Register Data Move @ 0x%x\n", PC); + LOGMASKED(LOG_UNIMPLEMENTED, "DSP56156: Unemulated Dual X Memory Data And Register Data Move @ 0x%x\n", PC); + cpustate->device->machine().debug_break(); } /* Handle Other parallel types */ @@ -344,7 +1102,7 @@ static void execute_one(dsp56156_core* cpustate) int parallelType = -1; uint16_t op_byte = 0x0000; typed_pointer d_register = {nullptr, DT_BYTE}; - uint64_t prev_accum_value = 0x0000000000000000U; + uint64_t prev_accum_value = 0x0000000000000000ULL; /* Note: it's important that NPDM comes before RtRDM here */ /* No Parallel Data Move : 0100 1010 .... .... : A-131 */ @@ -1089,8 +1847,8 @@ static void execute_one(dsp56156_core* cpustate) /* Not recognized? Nudge debugger onto the next word */ if (size == 0x1337) { - cpustate->device->logerror("DSP56156: Unimplemented opcode at 0x%04x : %04x\n", PC, op); - size = 1 ; /* Just to get the debugger past the bad opcode */ + LOGMASKED(LOG_UNIMPLEMENTED, "DSP56156: Unimplemented opcode at 0x%04x : %04x\n", PC, op); + size = 1; /* Just to get the debugger past the bad opcode */ } /* Must have been a good opcode */ @@ -1124,11 +1882,11 @@ static size_t dsp56156_op_addsub_2(dsp56156_core* cpustate, const uint16_t op_by decode_uuuuF_table(cpustate, BITS(op_byte,0x0017), BITS(op_byte,0x0008), op_type, &S, &D); - /* If you gave an invalid operation type, presume it's a nop and move on with the parallel move */ + /* If you gave an invalid operation type, presume it's a nop and move on with the parallel move, priming the accumulator as appropriate */ if (op_type == OP_OTHER) { - d_register->addr = nullptr; - d_register->data_type = DT_BYTE; + d_register->addr = BIT(op_byte, 3) ? &B : &A; + d_register->data_type = DT_LONG_WORD; cycles += 2; return 1; } @@ -1142,8 +1900,12 @@ static size_t dsp56156_op_addsub_2(dsp56156_core* cpustate, const uint16_t op_by } /* Sign-extend word for proper add/sub op */ - if ((S.data_type == DT_WORD) && (useVal & 0x0000000080000000U)) - useVal |= 0x000000ff00000000U; + if ((S.data_type != DT_LONG_WORD) && (useVal & 0x00000000'80000000ULL)) + useVal |= 0x000000ff'00000000ULL; + + /* Make sure they're both real 40-bit values */ + useVal &= 0x000000ff'ffffffffULL; + *((uint64_t*)D.addr) &= 0x000000ff'ffffffffULL; /* Operate*/ if (op_type == OP_ADD) @@ -1157,8 +1919,8 @@ static size_t dsp56156_op_addsub_2(dsp56156_core* cpustate, const uint16_t op_by /* S L E U N Z V C */ /* * * * * * * * * */ /* TODO S, L, E, U, V, C */ - if (*((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if (*((uint64_t*)D.addr) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); cycles += 2; /* TODO: + mv oscillator cycles */ return 1; @@ -1167,12 +1929,6 @@ static size_t dsp56156_op_addsub_2(dsp56156_core* cpustate, const uint16_t op_by /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */ static size_t dsp56156_op_mac_1(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles) { - int64_t opD = 0; - int64_t result = 0; - - int32_t s1 = 0; - int32_t s2 = 0; - void* D = nullptr; void* S1 = nullptr; void* S2 = nullptr; @@ -1180,24 +1936,20 @@ static size_t dsp56156_op_mac_1(dsp56156_core* cpustate, const uint16_t op_byte, decode_QQF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S1, &S2, &D); /* Cast both values as being signed */ - s1 = *((int16_t*)S1); - s2 = *((int16_t*)S2); + const int32_t s1 = *((int16_t*)S1); + const int32_t s2 = *((int16_t*)S2); /* Fixed-point 2's complement multiplication requires a shift */ - result = (s1 * s2) << 1; + int64_t result = (s1 * s2) << 1; /* Sign extend D into a temp variable */ - opD = (*((uint64_t*)D)); - if (opD & 0x0000008000000000U) - opD |= 0xffffff0000000000U; - else - opD &= 0x000000ffffffffffU; + int64_t opD = util::sext(*((uint64_t*)D), 40); /* Accumulate */ opD += result; /* And out the bits that don't live in the register */ - opD &= 0x000000ffffffffffU; + opD &= 0x000000ff'ffffffffULL; (*((uint64_t*)D)) = (uint64_t)opD; @@ -1208,8 +1960,8 @@ static size_t dsp56156_op_mac_1(dsp56156_core* cpustate, const uint16_t op_byte, /* S L E U N Z V C */ /* * * * * * * * - */ /* TODO: S, L, E, V */ - if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ( *((uint64_t*)D) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D) & 0x000000ff'ffffffffULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); cycles += 2; /* TODO: +mv oscillator cycles */ return 1; @@ -1220,6 +1972,7 @@ static size_t dsp56156_op_macr_1(dsp56156_core* cpustate, const uint16_t op_byte { /* S L E U N Z V C */ /* * * * * * * * - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_macr_1\n"); return 0; } @@ -1227,18 +1980,14 @@ static size_t dsp56156_op_macr_1(dsp56156_core* cpustate, const uint16_t op_byte static size_t dsp56156_op_move_1(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles) { /* S L E U N Z V C */ - /* * * - - - - - - */ + /* * * * * * * * - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_move_1\n"); return 0; } /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */ static size_t dsp56156_op_mpy_1(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles) { - int64_t result = 0; - - int32_t s1 = 0; - int32_t s2 = 0; - void* D = nullptr; void* S1 = nullptr; void* S2 = nullptr; @@ -1246,14 +1995,14 @@ static size_t dsp56156_op_mpy_1(dsp56156_core* cpustate, const uint16_t op_byte, decode_QQF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S1, &S2, &D); /* Cast both values as being signed */ - s1 = *((int16_t*)S1); - s2 = *((int16_t*)S2); + const int32_t s1 = *((int16_t*)S1); + const int32_t s2 = *((int16_t*)S2); /* Fixed-point 2's complement multiplication requires a shift */ - result = (s1 * s2) << 1; + int64_t result = (s1 * s2) << 1; /* And out the bits that don't live in the register */ - (*((uint64_t*)D)) = result & 0x000000ffffffffffU; + (*((uint64_t*)D)) = result & 0x000000ff'ffffffffULL; /* For the parallel move */ d_register->addr = D; @@ -1262,8 +2011,8 @@ static size_t dsp56156_op_mpy_1(dsp56156_core* cpustate, const uint16_t op_byte, /* S L E U N Z V C */ /* * * * * * * * - */ /* TODO: S, L, E, V */ - if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ( *((uint64_t*)D) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D) & 0x000000ff'ffffffffULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); cycles += 2; /* TODO: +mv oscillator cycles */ return 1; @@ -1274,6 +2023,7 @@ static size_t dsp56156_op_mpyr_1(dsp56156_core* cpustate, const uint16_t op_byte { /* S L E U N Z V C */ /* * * * * * * * - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_mpyr_1\n"); return 0; } @@ -1282,6 +2032,7 @@ static size_t dsp56156_op_tfr_2(dsp56156_core* cpustate, const uint16_t op_byte, { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_tfr_2\n"); return 0; } @@ -1290,6 +2041,7 @@ static size_t dsp56156_op_mpy_2(dsp56156_core* cpustate, const uint16_t op_byte, { /* S L E U N Z V C */ /* * * * * * * * - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_mpy_2\n"); return 0; } @@ -1298,6 +2050,7 @@ static size_t dsp56156_op_mac_2(dsp56156_core* cpustate, const uint16_t op_byte, { /* S L E U N Z V C */ /* * * * * * * * - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_mac_2\n"); return 0; } @@ -1306,7 +2059,7 @@ static size_t dsp56156_op_clr(dsp56156_core* cpustate, const uint16_t op_byte, t { typed_pointer D = {nullptr, DT_LONG_WORD}; typed_pointer clear = {nullptr, DT_LONG_WORD}; - uint64_t clear_val = 0x0000000000000000U; + uint64_t clear_val = 0x00000000'00000000ULL; decode_F_table(cpustate, BITS(op_byte,0x0008), &D); @@ -1314,7 +2067,7 @@ static size_t dsp56156_op_clr(dsp56156_core* cpustate, const uint16_t op_byte, t clear.addr = &clear_val; clear.data_type = DT_LONG_WORD; - SetDestinationValue(clear, D); + dsp56156_set_destination_value(cpustate, clear, D); d_register->addr = D.addr; d_register->data_type = D.data_type; @@ -1351,20 +2104,28 @@ static size_t dsp56156_op_add(dsp56156_core* cpustate, const uint16_t op_byte, t } /* Sign-extend word for proper add/sub op */ - if ((S.data_type == DT_WORD) && (addVal & 0x0000000080000000U)) - addVal |= 0x000000ff00000000U; + if ((S.data_type != DT_LONG_WORD) && (addVal & 0x00000000'80000000ULL)) + addVal |= 0x000000ff'00000000ULL; + + /* Make sure they're both real 40-bit values */ + addVal &= 0x000000ff'ffffffffULL; + *((uint64_t*)D.addr) &= 0x000000ff'ffffffffULL; /* Operate*/ - *((uint64_t*)D.addr) += addVal; + const uint64_t result = *((uint64_t*)D.addr) + addVal; + const uint8_t ovf_index = (BIT(*((uint64_t*)D.addr), 39) << 2) | (BIT(addVal, 39) << 1) | BIT(result, 39); + *((uint64_t*)D.addr) = result; d_register->addr = D.addr; d_register->data_type = D.data_type; /* S L E U N Z V C */ /* * * * * * * * * */ - /* TODO S, L, E, U, V, C */ - if (*((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + /* TODO S, L, E, U */ + if (*((uint64_t*)D.addr) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if (dsp56156_add_ovf_table[ovf_index]) DSP56156_V_SET(); else DSP56156_V_CLEAR(); + if ((*((uint64_t*)D.addr) & 0xffffff00'00000000ULL) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR(); cycles += 2; /* TODO: + mv oscillator cycles */ return 1; @@ -1373,8 +2134,8 @@ static size_t dsp56156_op_add(dsp56156_core* cpustate, const uint16_t op_byte, t /* MOVE : .... .... 0001 0001 : A-128 */ static size_t dsp56156_op_move(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles) { - /* Equivalent to a nop with a parallel move */ - /* These can't be used later. Hopefully compilers would pick this up. */ + // Equivalent to a nop with a parallel move + // These can't be used later. Hopefully compilers would pick this up. *p_accum = 0; d_register->addr = nullptr; d_register->data_type = DT_BYTE; @@ -1396,7 +2157,7 @@ static size_t dsp56156_op_tfr(dsp56156_core* cpustate, const uint16_t op_byte, t *p_accum = *((uint64_t*)D.addr); - SetDestinationValue(S, D); + dsp56156_set_destination_value(cpustate, S, D); d_register->addr = D.addr; d_register->data_type = D.data_type; @@ -1417,11 +2178,22 @@ static size_t dsp56156_op_rnd(dsp56156_core* cpustate, const uint16_t op_byte, t *p_accum = *((uint64_t*)D.addr); - /* WARNING : ROUNDING NOT FULLY IMPLEMENTED YET! */ - if ((*((uint64_t*)D.addr) & 0x000000000000ffffU) >= 0x8000) - *((uint64_t*)D.addr) += 0x0000000000010000U; + uint64_t *d_ptr = (uint64_t*)D.addr; + if (R_bit(cpustate)) + { + if ((*d_ptr & 0x00000000'0000ffffULL) >= 0x8000) + *d_ptr += 0x00000000'00010000ULL; + } + else + { + uint64_t lower = *d_ptr & 0x00000000'0000ffffULL; + if (lower > 0x8000) + *d_ptr += 0x00000000'00010000ULL; + else if (lower == 0x8000 && BIT(*d_ptr, 16)) + *d_ptr += 0x00000000'00010000ULL; + } - *((uint64_t*)D.addr) = *((uint64_t*)D.addr) & 0x000000ffffff0000U; + *((uint64_t*)D.addr) = *((uint64_t*)D.addr) & 0x000000ff'ffff0000ULL; d_register->addr = D.addr; d_register->data_type = D.data_type; @@ -1429,8 +2201,8 @@ static size_t dsp56156_op_rnd(dsp56156_core* cpustate, const uint16_t op_byte, t /* S L E U N Z V C */ /* * * * * * * * - */ /* TODO: S, L, E, U, V */ - if ((*((uint64_t*)D.addr)) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D.addr)) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ((*((uint64_t*)D.addr)) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D.addr)) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); cycles += 2; /* TODO: + mv oscillator clock cycles */ return 1; @@ -1451,8 +2223,8 @@ static size_t dsp56156_op_tst(dsp56156_core* cpustate, const uint16_t op_byte, t /* S L E U N Z V C */ /* 0 * * * * * 0 0 */ /* TODO: S, L, E, U */ - if ((*((uint64_t*)D.addr)) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D.addr)) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ((*((uint64_t*)D.addr)) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D.addr)) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); DSP56156_V_CLEAR(); DSP56156_C_CLEAR(); @@ -1470,7 +2242,7 @@ static size_t dsp56156_op_inc(dsp56156_core* cpustate, const uint16_t op_byte, t *p_accum = *((uint64_t*)D.addr); /* Make sure the destination is a real 40-bit value */ - *((uint64_t*)D.addr) &= 0x000000ffffffffffU; + *((uint64_t*)D.addr) &= 0x000000ff'ffffffffULL; /* Increment */ *((uint64_t*)D.addr) = *((uint64_t*)D.addr) + 1; @@ -1481,10 +2253,10 @@ static size_t dsp56156_op_inc(dsp56156_core* cpustate, const uint16_t op_byte, t /* S L E U N Z V C */ /* * * * * * * * * */ /* TODO: S, L, E, U */ - if ( *((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x000000ffffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); - if ((*((uint64_t*)D.addr) & 0xffffff0000000000U) != 0) DSP56156_V_SET(); else DSP56156_V_CLEAR(); - if ((*((uint64_t*)D.addr) & 0xffffff0000000000U) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR(); + if ( *((uint64_t*)D.addr) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D.addr) & 0x000000ff'ffffffffULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ((*((uint64_t*)D.addr) & 0xffffff00'00000000ULL) != 0) DSP56156_V_SET(); else DSP56156_V_CLEAR(); + if ((*((uint64_t*)D.addr) & 0xffffff00'00000000ULL) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR(); cycles += 2; /* TODO: +mv oscillator cycles */ return 1; @@ -1502,12 +2274,12 @@ static size_t dsp56156_op_inc24(dsp56156_core* cpustate, const uint16_t op_byte, *p_accum = *((uint64_t*)D.addr); /* TODO: I wonder if workBits24 should be signed? */ - workBits24 = ((*((uint64_t*)D.addr)) & 0x000000ffffff0000U) >> 16; + workBits24 = ((*((uint64_t*)D.addr)) & 0x000000ff'ffff0000ULL) >> 16; workBits24++; //workBits24 &= 0x00ffffff; /* Solves -x issues - TODO: huh? */ /* Set the D bits with the dec result */ - *((uint64_t*)D.addr) &= 0x000000000000ffffU; + *((uint64_t*)D.addr) &= 0x00000000'0000ffffULL; *((uint64_t*)D.addr) |= (((uint64_t)(workBits24)) << 16); d_register->addr = D.addr; @@ -1516,10 +2288,10 @@ static size_t dsp56156_op_inc24(dsp56156_core* cpustate, const uint16_t op_byte, /* S L E U N Z V C */ /* * * * * * ? * * */ /* TODO: S, L, E, U */ - if ( *((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x000000ffffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); - if ((workBits24 & 0xff000000) != 0) DSP56156_V_SET(); else DSP56156_V_CLEAR(); - if ((workBits24 & 0xff000000) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR(); + if ( *((uint64_t*)D.addr) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D.addr) & 0x000000ff'ffff0000ULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ((workBits24 & 0xff000000) != 0) DSP56156_V_SET(); else DSP56156_V_CLEAR(); + if ((workBits24 & 0xff000000) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR(); cycles += 2; /* TODO: + mv oscillator clock cycles */ return 1; @@ -1545,8 +2317,8 @@ static size_t dsp56156_op_or(dsp56156_core* cpustate, const uint16_t op_byte, ty /* S L E U N Z V C */ /* * * - - ? ? 0 - */ /* TODO: S, L */ - if ( *((uint64_t*)D.addr) & 0x0000000080000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x00000000ffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ( *((uint64_t*)D.addr) & 0x00000000'80000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D.addr) & 0x00000000'ffff0000ULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); DSP56156_V_CLEAR(); cycles += 2; /* TODO: + mv oscillator cycles */ @@ -1564,10 +2336,10 @@ static size_t dsp56156_op_asr(dsp56156_core* cpustate, const uint16_t op_byte, t *((uint64_t*)D.addr) = (*((uint64_t*)D.addr)) >> 1; /* Make sure the MSB is maintained */ - if (*p_accum & 0x0000008000000000U) - *((uint64_t*)D.addr) |= 0x0000008000000000U; + if (*p_accum & 0x00000080'00000000ULL) + *((uint64_t*)D.addr) |= 0x00000080'00000000ULL; else - *((uint64_t*)D.addr) &= (~u64(0x0000008000000000U)); + *((uint64_t*)D.addr) &= (~u64(0x00000080'00000000ULL)); /* For the parallel move */ d_register->addr = D.addr; @@ -1576,10 +2348,10 @@ static size_t dsp56156_op_asr(dsp56156_core* cpustate, const uint16_t op_byte, t /* S L E U N Z V C */ /* * * * * * * 0 ? */ /* TODO: S, L, E, U */ - if (*((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if (*((uint64_t*)D.addr) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); DSP56156_V_CLEAR(); - if (*p_accum & 0x0000000000000001U) DSP56156_C_SET(); else DSP56156_C_CLEAR(); + if (*p_accum & 0x00000000'00000001ULL) DSP56156_C_SET(); else DSP56156_C_CLEAR(); cycles += 2; /* TODO: + mv oscillator cycles */ return 1; @@ -1588,12 +2360,31 @@ static size_t dsp56156_op_asr(dsp56156_core* cpustate, const uint16_t op_byte, t /* ASL : .... .... 0011 F001 : A-28 */ static size_t dsp56156_op_asl(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles) { + typed_pointer D = {nullptr, DT_BYTE}; + decode_F_table(cpustate, BITS(op_byte,0x0008), &D); + + *p_accum = *((uint64_t*)D.addr); + + uint64_t dVal = *(uint64_t*)D.addr; + const uint64_t oldBit39 = BIT(dVal, 39); + dVal = (dVal << 1) & 0x000000ff'ffffffffULL; + *((uint64_t*)D.addr) = dVal; + const uint64_t newBit39 = BIT(dVal, 39); + + /* For the parallel move */ + d_register->addr = D.addr; + d_register->data_type = D.data_type; + /* S L E U N Z V C */ /* * * * * * * ? ? */ /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significant bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */ /* C - Set if bit 39 of source operand is set. Cleared otherwise. */ - return 0; + if (oldBit39 != newBit39) DSP56156_V_SET(); else DSP56156_V_CLEAR(); + if (newBit39) DSP56156_C_SET(); else DSP56156_C_CLEAR(); + + cycles += 2; /* TODO: + mv oscillator cycles */ + return 1; } /* LSR : .... .... 0011 F010 : A-120 */ @@ -1617,9 +2408,9 @@ static size_t dsp56156_op_lsr(dsp56156_core* cpustate, const uint16_t op_byte, t /* * * - - ? ? 0 ? */ /* TODO: S, L */ DSP56156_N_CLEAR(); - if (((PAIR64*)D.addr)->w.h == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if (((PAIR64*)D.addr)->w.h == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); DSP56156_V_CLEAR(); - if (*p_accum & 0x0000000000010000U) DSP56156_C_SET(); else DSP56156_C_CLEAR(); + if (*p_accum & 0x00000000'00010000ULL) DSP56156_C_SET(); else DSP56156_C_CLEAR(); cycles += 2; /* TODO: + mv oscillator cycles */ return 1; @@ -1633,17 +2424,38 @@ static size_t dsp56156_op_lsl(dsp56156_core* cpustate, const uint16_t op_byte, t /* N - Set if bit 31 of the result is set. Cleared otherwise. */ /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */ /* C - Set if bit 31 of the source operand is set. Cleared otherwise. */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_lsl\n"); return 0; } /* EOR : .... .... 0011 F1JJ : A-94 */ static size_t dsp56156_op_eor(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles) { + typed_pointer S = {nullptr, DT_BYTE}; + typed_pointer D = {nullptr, DT_BYTE}; + + decode_JJF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S, &D); + + /* Save some data for the parallel move */ + *p_accum = *((uint64_t*)D.addr); + + /* XOR a word of S with A1|B1 */ + ((PAIR64*)D.addr)->w.h = *((uint16_t*)S.addr) ^ ((PAIR64*)D.addr)->w.h; + + d_register->addr = D.addr; + d_register->data_type = D.data_type; + /* S L E U N Z V C */ /* * * - - ? ? 0 - */ + /* TODO: S, L */ /* N - Set if bit 31 of the result is set. Cleared otherwise. */ /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */ - return 0; + if ( *((uint64_t*)D.addr) & 0x00000000'80000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D.addr) & 0x00000000'ffff0000ULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + DSP56156_V_CLEAR(); + + cycles += 2; /* TODO: + mv oscillator cycles */ + return 1; } /* SUBL : .... .... 0100 F001 : A-204 */ @@ -1653,6 +2465,7 @@ static size_t dsp56156_op_subl(dsp56156_core* cpustate, const uint16_t op_byte, /* * * * * * * ? * */ /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significant bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_subl\n"); return 0; } @@ -1665,6 +2478,8 @@ static size_t dsp56156_op_sub(dsp56156_core* cpustate, const uint16_t op_byte, t decode_JJJF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S, &D); + *p_accum = *((uint64_t*)D.addr); + /* Get on with it. */ switch(S.data_type) { @@ -1674,15 +2489,17 @@ static size_t dsp56156_op_sub(dsp56156_core* cpustate, const uint16_t op_byte, t } /* Sign-extend word for proper sub op */ - if ((S.data_type == DT_WORD) && useVal & 0x0000000080000000U) - useVal |= 0x000000ff00000000U; + if ((S.data_type != DT_LONG_WORD) && (useVal & 0x00000000'80000000ULL)) + useVal |= 0x000000ff'00000000ULL; /* Make sure they're both real 40-bit values */ - useVal &= 0x000000ffffffffffU; - *((uint64_t*)D.addr) &= 0x000000ffffffffffU; + useVal &= 0x000000ff'ffffffffULL; + *((uint64_t*)D.addr) &= 0x000000ff'ffffffffULL; /* Operate*/ - *((uint64_t*)D.addr) -= useVal; + uint64_t result = *((uint64_t*)D.addr) - useVal; + const uint8_t ovf_index = (BIT(*((uint64_t*)D.addr), 39) << 2) | (BIT(useVal, 39) << 1) | BIT(result, 39); + *((uint64_t*)D.addr) = result; d_register->addr = D.addr; d_register->data_type = D.data_type; @@ -1690,10 +2507,10 @@ static size_t dsp56156_op_sub(dsp56156_core* cpustate, const uint16_t op_byte, t /* S L E U N Z V C */ /* * * * * * * * * */ /* TODO S, L, E, U */ - if ( *((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ( *((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); - if ((*((uint64_t*)D.addr) & 0xffffff0000000000U) != 0) DSP56156_V_SET(); else DSP56156_V_CLEAR(); - if ((*((uint64_t*)D.addr) & 0xffffff0000000000U) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR(); + if ( *((uint64_t*)D.addr) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ( *((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if (dsp56156_sub_ovf_table[ovf_index]) DSP56156_V_SET(); else DSP56156_V_CLEAR(); + if ((*((uint64_t*)D.addr) & 0xffffff00'00000000ULL) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR(); cycles += 2; /* TODO: + mv oscillator cycles */ return 1; @@ -1705,6 +2522,7 @@ static size_t dsp56156_op_clr24(dsp56156_core* cpustate, const uint16_t op_byte, /* S L E U N Z V C */ /* * * * * * ? 0 - */ /* Z - Set if the 24 most significant bits of the destination result are all zeroes. */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_clr24\n"); return 0; } @@ -1713,6 +2531,7 @@ static size_t dsp56156_op_sbc(dsp56156_core* cpustate, const uint16_t op_byte, t { /* S L E U N Z V C */ /* * * * * * * * * */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_sbc\n"); return 0; } @@ -1720,7 +2539,7 @@ static size_t dsp56156_op_sbc(dsp56156_core* cpustate, const uint16_t op_byte, t static size_t dsp56156_op_cmp(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles) { uint64_t cmpVal = 0; - uint64_t result = 0; + uint64_t dVal = 0; typed_pointer S = {nullptr, DT_BYTE}; typed_pointer D = {nullptr, DT_BYTE}; @@ -1728,36 +2547,38 @@ static size_t dsp56156_op_cmp(dsp56156_core* cpustate, const uint16_t op_byte, t decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D); *p_accum = *((uint64_t*)D.addr); + dVal = *((int64_t*)D.addr); switch(S.data_type) { - case DT_WORD: cmpVal = (uint64_t)*((uint16_t*)S.addr) << 16; break; - case DT_DOUBLE_WORD: cmpVal = (uint64_t)*((uint32_t*)S.addr); break; - case DT_LONG_WORD: cmpVal = (uint64_t)*((uint64_t*)S.addr); break; + case DT_WORD: cmpVal = (int64_t)*((uint16_t*)S.addr) << 16; break; + case DT_DOUBLE_WORD: cmpVal = (int64_t)*((uint32_t*)S.addr); break; + case DT_LONG_WORD: cmpVal = (int64_t)*((uint64_t*)S.addr); break; } - /* Sign-extend word for proper subtraction op */ - if ((S.data_type == DT_WORD) && cmpVal & 0x0000000080000000U) - cmpVal |= 0x000000ff00000000U; + /* Sign-extend word for proper add/sub op */ + if ((S.data_type != DT_LONG_WORD) && (cmpVal & 0x00000000'80000000ULL)) + cmpVal |= 0x000000ff'00000000ULL; /* Make sure they're both real 40-bit values */ - cmpVal &= 0x000000ffffffffffU; - *((uint64_t*)D.addr) &= 0x000000ffffffffffU; + cmpVal &= 0x000000ff'ffffffffULL; + dVal &= 0x000000ff'ffffffffULL; /* Operate */ - result = *((uint64_t*)D.addr) - cmpVal; + uint64_t result = dVal - cmpVal; + d_register->data_type = DT_LONG_WORD; d_register->addr = D.addr; - d_register->data_type = D.data_type; + + uint8_t ovf_index = (BIT(dVal, 39) << 2) | (BIT(cmpVal, 39) << 1) | BIT(result, 39); /* S L E U N Z V C */ /* * * * * * * * * */ /* TODO: S, L, E, U */ - if ( result & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ( result == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); - if ((result & 0xffffff0000000000U) != 0) DSP56156_V_SET(); else DSP56156_V_CLEAR(); - if ((result & 0xffffff0000000000U) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR(); - + if (result & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if (result == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if (dsp56156_sub_ovf_table[ovf_index]) DSP56156_V_SET(); else DSP56156_V_CLEAR(); + if ((result & 0xffffff00'00000000ULL) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR(); cycles += 2; /* TODO: + mv oscillator clock cycles */ return 1; @@ -1766,9 +2587,36 @@ static size_t dsp56156_op_cmp(dsp56156_core* cpustate, const uint16_t op_byte, t /* NEG : .... .... 0110 F000 : A-166 */ static size_t dsp56156_op_neg(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles) { + typed_pointer D = {nullptr, DT_LONG_WORD}; + typed_pointer neg = {nullptr, DT_LONG_WORD}; + + decode_F_table(cpustate, BITS(op_byte,0x0008), &D); + + const uint64_t sVal = *p_accum = *((uint64_t*)D.addr); + const uint64_t dVal = 0 - sVal; + uint64_t dMasked = dVal & 0x000000ff'ffffffffULL; + + neg.addr = &dMasked; + neg.data_type = DT_LONG_WORD; + dsp56156_set_destination_value(cpustate, neg, D); + + d_register->addr = D.addr; + d_register->data_type = D.data_type; + + const uint8_t ovf_index = (BIT(sVal, 39) << 1) | BIT(dVal, 39); + /* S L E U N Z V C */ /* * * * * * * * * */ - return 0; + /* TODO - S, L */ + if (dsp56156_value_is_unnormalized(cpustate, dVal)) DSP56156_U_SET(); else DSP56156_U_CLEAR(); + if (dsp56156_value_is_extended(cpustate, dVal)) DSP56156_E_SET(); else DSP56156_E_CLEAR(); + if (dVal & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if (dVal == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if (dsp56156_sub_ovf_table[ovf_index]) DSP56156_V_SET(); else DSP56156_V_CLEAR(); + if ((dVal & 0xffffff00'00000000ULL) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR(); + + cycles += 2; /* TODO: + mv oscillator clock cycles */ + return 1; } /* NOT : .... .... 0110 F001 : A-174 */ @@ -1788,8 +2636,8 @@ static size_t dsp56156_op_not(dsp56156_core* cpustate, const uint16_t op_byte, t /* S L E U N Z V C */ /* * * - - ? ? 0 - */ /* TODO: S?, L */ - if ( *((uint64_t*)D.addr) & 0x0000000080000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x00000000ffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ( *((uint64_t*)D.addr) & 0x00000000'80000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D.addr) & 0x00000000'ffff0000ULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); DSP56156_V_CLEAR(); cycles += 2; /* TODO: + mv oscillator cycles */ @@ -1801,6 +2649,7 @@ static size_t dsp56156_op_dec(dsp56156_core* cpustate, const uint16_t op_byte, t { /* S L E U N Z V C */ /* * * * * * * * * */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_dec\n"); return 0; } @@ -1816,22 +2665,24 @@ static size_t dsp56156_op_dec24(dsp56156_core* cpustate, const uint16_t op_byte, *p_accum = *((uint64_t*)D.addr); /* TODO: I wonder if workBits24 should be signed? */ - workBits24 = ((*((uint64_t*)D.addr)) & 0x000000ffffff0000U) >> 16; + workBits24 = ((*((uint64_t*)D.addr)) & 0x000000ff'ffff0000ULL) >> 16; workBits24--; + const bool carry = BIT(workBits24, 24); workBits24 &= 0x00ffffff; /* Solves -x issues */ /* Set the D bits with the dec result */ - *((uint64_t*)D.addr) &= 0x000000000000ffffU; - *((uint64_t*)D.addr) |= (((uint64_t)(workBits24)) << 16); + *((uint64_t*)D.addr) &= 0x00000000'0000ffffULL; + *((uint64_t*)D.addr) |= uint64_t(workBits24) << 16; d_register->addr = D.addr; d_register->data_type = D.data_type; /* S L E U N Z V C */ /* * * * * * ? * * */ - /* TODO: S, L, E, U, V, C */ - if ( *((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x000000ffffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + /* TODO: S, L, E, U, V */ + if ( *((uint64_t*)D.addr) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D.addr) & 0x000000ff'ffff0000ULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if (carry) DSP56156_C_SET(); else DSP56156_C_CLEAR(); cycles += 2; /* TODO: + mv oscillator clock cycles */ return 1; @@ -1857,8 +2708,8 @@ static size_t dsp56156_op_and(dsp56156_core* cpustate, const uint16_t op_byte, t /* S L E U N Z V C */ /* * * - - ? ? 0 - */ /* TODO: S, L */ - if ( *((uint64_t*)D.addr) & 0x0000000080000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x00000000ffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ( *((uint64_t*)D.addr) & 0x00000000'80000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D.addr) & 0x00000000'ffff0000ULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); DSP56156_V_CLEAR(); cycles += 2; /* TODO: + mv oscillator cycles */ @@ -1868,7 +2719,6 @@ static size_t dsp56156_op_and(dsp56156_core* cpustate, const uint16_t op_byte, t /* ABS : .... .... 0111 F001 : A-18 */ static size_t dsp56156_op_abs(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles) { - int64_t opD = 0; typed_pointer D = {nullptr, DT_LONG_WORD}; decode_F_table(cpustate, BITS(op_byte,0x0008), &D); @@ -1876,29 +2726,29 @@ static size_t dsp56156_op_abs(dsp56156_core* cpustate, const uint16_t op_byte, t *p_accum = *((uint64_t*)D.addr); /* Sign extend D into a temp variable */ - opD = *p_accum; - if (opD & 0x0000008000000000U) - opD |= 0xffffff0000000000U; - else - opD &= 0x000000ffffffffffU; + int64_t opD = util::sext(*p_accum, 40); /* Take the absolute value and clean up */ opD = (opD < 0) ? -opD : opD; - opD &= 0x000000ffffffffffU; + opD &= 0x000000ff'ffffffffULL; /* Reassign */ *((uint64_t*)D.addr) = opD; /* Special overflow case */ - if ((*p_accum) == 0x0000008000000000U) - *((uint64_t*)D.addr) = 0x0000007fffffffffU; + if ((*p_accum) == 0x00000080'00000000ULL) + *((uint64_t*)D.addr) = 0x0000007f'ffffffffULL; + + /* For the parallel move */ + d_register->addr = D.addr; + d_register->data_type = D.data_type; /* S L E U N Z V C */ /* * * * * * * * - */ /* TODO: S, L, E, U */ - if ( *((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); - if ((*p_accum) == 0x0000008000000000U) DSP56156_V_SET(); else DSP56156_V_CLEAR(); + if ( *((uint64_t*)D.addr) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D.addr) & 0x000000ff'ffffffffULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ((*p_accum) == 0x00000080'00000000ULL) DSP56156_V_SET(); else DSP56156_V_CLEAR(); cycles += 2; /* TODO: + mv oscillator clock cycles */ return 1; @@ -1912,27 +2762,50 @@ static size_t dsp56156_op_ror(dsp56156_core* cpustate, const uint16_t op_byte, t /* N - Set if bit 31 of the result is set. Cleared otherwise. */ /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */ /* C - Set if bit 16 of the source operand is set. Cleared otherwise. */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_ror\n"); return 0; } /* ROL : .... .... 0111 F011 : A-190 */ static size_t dsp56156_op_rol(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles) { + typed_pointer D = {nullptr, DT_BYTE}; + decode_F_table(cpustate, BITS(op_byte,0x0008), &D); + + *p_accum = *((uint64_t*)D.addr); + + uint64_t dVal = *(uint64_t*)D.addr; + uint16_t middle = (uint16_t)(dVal >> 16); + bool new_carry = BIT(middle, 15); + middle = (middle << 1) | C(); + dVal &= ~0x00000000'ffff0000ULL; + dVal |= middle << 16; + + /* For the parallel move */ + d_register->addr = D.addr; + d_register->data_type = D.data_type; + + *((uint64_t*)D.addr) = dVal; + /* S L E U N Z V C */ - /* * * - - ? ? 0 ? */ + /* * * - - * * 0 * */ + /* TODO: S, L, E, U */ /* N - Set if bit 31 of the result is set. Cleared otherwise. */ - /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */ - /* C - Set if bit 31 of the source operand is set. Cleared otherwise. */ - return 0; + /* Z - Set if bits 31-16 of the result are zero. Cleared otherwise. */ + /* V - Always cleared. */ + /* C - Set if bit 31 of the source operand was set. Cleared otherwise. */ + if (middle & 0x8000) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if (middle == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + DSP56156_V_CLEAR(); + if (new_carry) DSP56156_C_SET(); else DSP56156_C_CLEAR(); + + cycles += 2; /* TODO: + mv oscillator cycles */ + return 1; } /* CMPM : .... .... 0111 FJJJ : A-66 */ static size_t dsp56156_op_cmpm(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles) { - int64_t absS; - int64_t absD; - int64_t absResult; - typed_pointer S = {nullptr, DT_BYTE}; typed_pointer D = {nullptr, DT_BYTE}; @@ -1941,48 +2814,38 @@ static size_t dsp56156_op_cmpm(dsp56156_core* cpustate, const uint16_t op_byte, *p_accum = *((uint64_t*)D.addr); /* Sign extend and get absolute value of the source */ + uint64_t absS; if (S.addr == &A || S.addr == &B) - { - absS = *((uint64_t*)S.addr); - if (absS & 0x0000008000000000U) - absS |= 0xffffff8000000000U; - } + absS = std::abs(util::sext(*((uint64_t*)S.addr), 40)); else - { - absS = (*((uint16_t*)S.addr)) << 16; - if (absS & 0x0000000080000000U) - absS |= 0xffffffff80000000U; - } - absS = (absS < 0) ? -absS : absS; + absS = std::abs((int64_t)(int32_t)((*((uint16_t*)S.addr)) << 16)); /* Sign extend and get absolute value of the destination */ + uint64_t absD; if (D.addr == &A || D.addr == &B) - { - absD = *((uint64_t*)D.addr); - if (absD & 0x0000008000000000U) - absD |= 0xffffff8000000000U; - } + absD = std::abs(util::sext(*((uint64_t*)D.addr), 40)); else - { - absD = (*((uint16_t*)D.addr)) << 16; - if (absS & 0x0000000080000000U) - absS |= 0xffffffff80000000U; - } - absD = (absD < 0) ? -absD : absD; + absD = std::abs((int64_t)(int32_t)(*((uint16_t*)D.addr) << 16)); + + /* Make sure they're both real 40-bit values */ + absS &= 0x000000ff'ffffffffULL; + absD &= 0x000000ff'ffffffffULL; /* Compare */ - absResult = absD - absS; + const uint64_t absResult = absD - absS; d_register->addr = D.addr; d_register->data_type = D.data_type; + uint8_t ovf_index = (BIT(absD, 39) << 2) | (BIT(absS, 39) << 1) | BIT(absResult, 39); + /* S L E U N Z V C */ /* * * * * * * * * */ /* TODO: S, L, E, U */ - if ( (absResult) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if (((absResult) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); - if ( (absResult & 0xffffff0000000000U) != 0) DSP56156_V_SET(); else DSP56156_V_CLEAR(); - if ( (absResult & 0xffffff0000000000U) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR(); + if (absResult & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if (absResult == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if (dsp56156_sub_ovf_table[ovf_index]) DSP56156_V_SET(); else DSP56156_V_CLEAR(); + if ((absResult & 0xffffff00'00000000ULL) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR(); cycles += 2; /* TODO: +mv oscillator cycles */ return 1; @@ -1991,38 +2854,38 @@ static size_t dsp56156_op_cmpm(dsp56156_core* cpustate, const uint16_t op_byte, /* MPY : .... .... 1k00 FQQQ : A-160 -- CONFIRMED TYPO IN DOCS (HHHH vs HHHW) */ static size_t dsp56156_op_mpy(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles) { - uint16_t k = 0; - int64_t result = 0; - - int32_t s1 = 0; - int32_t s2 = 0; - void* D = nullptr; void* S1 = nullptr; void* S2 = nullptr; decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D); - k = BITS(op_byte,0x0040); + *p_accum = *((uint64_t*)D); + + const uint16_t k = BITS(op_byte,0x0040); /* Cast both values as being signed */ - s1 = *((int16_t*)S1); - s2 = *((int16_t*)S2); + const int32_t s1 = *((int16_t*)S1); + const int32_t s2 = *((int16_t*)S2); /* Fixed-point 2's complement multiplication requires a shift */ - result = (s1 * s2) << 1; + int64_t result = (s1 * s2) << 1; /* Negate the product if necessary */ if (k) result *= -1; - (*((uint64_t*)D)) = result & 0x000000ffffffffffU; + (*((uint64_t*)D)) = result & 0x000000ff'ffffffffULL; + + /* For the parallel move */ + d_register->addr = D; + d_register->data_type = DT_LONG_WORD; /* S L E U N Z V C */ /* * * * * * * * - */ /* TODO: S, L, E, V */ - if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ( *((uint64_t*)D) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D) & 0x000000ff'ffffffffULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); cycles += 2; /* TODO: +mv oscillator cycles */ return 1; @@ -2033,40 +2896,32 @@ static size_t dsp56156_op_mpyr(dsp56156_core* cpustate, const uint16_t op_byte, { /* S L E U N Z V C */ /* * * * * * * * - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_mpyr\n"); return 0; } /* MAC : .... .... 1k10 FQQQ : A-122 */ static size_t dsp56156_op_mac(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles) { - uint16_t k = 0; - int64_t opD = 0; - int64_t result = 0; - - int32_t s1 = 0; - int32_t s2 = 0; - void* D = nullptr; void* S1 = nullptr; void* S2 = nullptr; decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D); - k = BITS(op_byte,0x0040); + *p_accum = *((uint64_t*)D); + + const uint16_t k = BITS(op_byte,0x0040); /* Cast both values as being signed */ - s1 = *((int16_t*)S1); - s2 = *((int16_t*)S2); + const int32_t s1 = *((int16_t*)S1); + const int32_t s2 = *((int16_t*)S2); /* Fixed-point 2's complement multiplication requires a shift */ - result = (s1 * s2) << 1; + int64_t result = (s1 * s2) << 1; /* Sign extend D into a temp variable */ - opD = (*((uint64_t*)D)); - if (opD & 0x0000008000000000U) - opD |= 0xffffff0000000000U; - else - opD &= 0x000000ffffffffffU; + int64_t opD = util::sext(*((uint64_t*)D), 40); /* Negate if necessary */ if (k) @@ -2076,7 +2931,7 @@ static size_t dsp56156_op_mac(dsp56156_core* cpustate, const uint16_t op_byte, t opD += result; /* And out the bits that don't live in the register */ - opD &= 0x000000ffffffffffU; + opD &= 0x000000ff'ffffffffULL; (*((uint64_t*)D)) = (uint64_t)opD; @@ -2087,8 +2942,8 @@ static size_t dsp56156_op_mac(dsp56156_core* cpustate, const uint16_t op_byte, t /* S L E U N Z V C */ /* * * * * * * * - */ /* TODO: S, L, E, V */ - if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ( *((uint64_t*)D) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D) & 0x000000ff'ffffffffULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); cycles += 2; /* TODO: +mv oscillator cycles */ return 1; @@ -2097,34 +2952,25 @@ static size_t dsp56156_op_mac(dsp56156_core* cpustate, const uint16_t op_byte, t /* MACR : .... .... 1k11 FQQQ : A-124 -- DRAMA - rr vs xx (805) */ static size_t dsp56156_op_macr(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles) { - uint16_t k = 0; - int64_t opD = 0; - int64_t result = 0; - - int32_t s1 = 0; - int32_t s2 = 0; - void* D = nullptr; void* S1 = nullptr; void* S2 = nullptr; decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D); - k = BITS(op_byte,0x0040); + *p_accum = *((uint64_t*)D); + + const uint16_t k = BITS(op_byte,0x0040); /* Cast both values as being signed */ - s1 = *((int16_t*)S1); - s2 = *((int16_t*)S2); + const int32_t s1 = *((int16_t*)S1); + const int32_t s2 = *((int16_t*)S2); /* Fixed-point 2's complement multiplication requires a shift */ - result = (s1 * s2) << 1; + int64_t result = (s1 * s2) << 1; /* Sign extend D into a temp variable */ - opD = (*((uint64_t*)D)); - if (opD & 0x0000008000000000U) - opD |= 0xffffff0000000000U; - else - opD &= 0x000000ffffffffffU; + int64_t opD = util::sext(*((uint64_t*)D), 40); /* Negate if necessary */ if (k) @@ -2134,14 +2980,20 @@ static size_t dsp56156_op_macr(dsp56156_core* cpustate, const uint16_t op_byte, opD += result; /* Round the result */ - /* WARNING : ROUNDING NOT FULLY IMPLEMENTED YET! */ - if ((opD & 0x000000000000ffffU) >= 0x8000) - opD += 0x0000000000010000U; - - opD &= 0x000000ffffff0000U; - - /* And out the bits that don't live in the register */ - opD &= 0x000000ffffffffffU; + if (R_bit(cpustate)) + { + if ((opD & 0x00000000'0000ffffULL) >= 0x8000) + opD += 0x00000000'00010000ULL; + } + else + { + const uint64_t lower = opD & 0x00000000'0000ffffULL; + if (lower > 0x8000) + opD += 0x00000000'00010000ULL; + else if (lower == 0x8000 && BIT(opD, 16)) + opD += 0x00000000'00010000ULL; + } + opD &= 0x000000ffffff0000ULL; /* Store the result */ (*((uint64_t*)D)) = (uint64_t)opD; @@ -2153,8 +3005,8 @@ static size_t dsp56156_op_macr(dsp56156_core* cpustate, const uint16_t op_byte, /* S L E U N Z V C */ /* * * * * * * * - */ /* TODO: S, L, E, V */ - if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ( *((uint64_t*)D) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D) & 0x000000ff'ffffffffULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); cycles += 2; /* TODO: +mv oscillator cycles */ return 1; @@ -2170,6 +3022,7 @@ static size_t dsp56156_op_adc(dsp56156_core* cpustate, const uint16_t op, uint8_ { /* S L E U N Z V C */ /* - * * * * * * * */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_adc\n"); return 0; } @@ -2185,16 +3038,16 @@ static size_t dsp56156_op_andi(dsp56156_core* cpustate, const uint16_t op, uint8 SR &= ((immediate << 8) | 0x00ff); break; - case 0x02: /* CCR */ - SR &= (immediate | 0xff00); + case 0x02: /* OMR */ + OMR &= (uint8_t)(immediate); break; - case 0x03: /* OMR */ - OMR &= (uint8_t)(immediate); + case 0x03: /* CCR */ + SR &= (immediate | 0xff00); break; default: - fatalerror("DSP56156 - BAD EE value in andi operation\n") ; + fatalerror("DSP56156 - BAD EE value in andi operation\n"); } /* S L E U N Z V C */ @@ -2215,7 +3068,7 @@ static size_t dsp56156_op_asl4(dsp56156_core* cpustate, const uint16_t op, uint8 p_accum = *((uint64_t*)D.addr); *((uint64_t*)D.addr) = (*((uint64_t*)D.addr)) << 4; - *((uint64_t*)D.addr) = (*((uint64_t*)D.addr)) & 0x000000ffffffffffU; + *((uint64_t*)D.addr) = (*((uint64_t*)D.addr)) & 0x000000ff'ffffffffULL; /* S L E U N Z V C */ /* - ? * * * * ? ? */ @@ -2223,10 +3076,10 @@ static size_t dsp56156_op_asl4(dsp56156_core* cpustate, const uint16_t op, uint8 /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if bit 35 through 39 are not the same. */ /* C - Set if bit 36 of source operand is set. Cleared otherwise. */ - if (*((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); - if ( (*((uint64_t*)D.addr) & 0x000000ff00000000U) != (p_accum & 0x000000ff00000000U) ) DSP56156_V_SET(); else DSP56156_V_CLEAR(); - if (p_accum & 0x0000001000000000U) DSP56156_C_SET(); else DSP56156_C_CLEAR(); + if (*((uint64_t*)D.addr) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ((*((uint64_t*)D.addr) & 0x000000ff'00000000ULL) != (p_accum & 0x000000ff'00000000ULL)) DSP56156_V_SET(); else DSP56156_V_CLEAR(); + if (p_accum & 0x00000010'00000000ULL) DSP56156_C_SET(); else DSP56156_C_CLEAR(); cycles += 2; return 1; @@ -2242,22 +3095,22 @@ static size_t dsp56156_op_asr4(dsp56156_core* cpustate, const uint16_t op, uint8 p_accum = *((uint64_t*)D.addr); *((uint64_t*)D.addr) = (*((uint64_t*)D.addr)) >> 4; - *((uint64_t*)D.addr) = (*((uint64_t*)D.addr)) & 0x000000ffffffffffU; + *((uint64_t*)D.addr) = (*((uint64_t*)D.addr)) & 0x000000ff'ffffffffULL; /* The top 4 bits become the old bit 39 */ - if (p_accum & 0x0000008000000000U) - *((uint64_t*)D.addr) |= 0x000000f000000000U; + if (p_accum & 0x00000080'00000000ULL) + *((uint64_t*)D.addr) |= 0x000000f0'00000000ULL; else - *((uint64_t*)D.addr) &= (~u64(0x000000f000000000U)); + *((uint64_t*)D.addr) &= ~0x000000f0'00000000ULL; /* S L E U N Z V C */ /* - * * * * * 0 ? */ /* TODO: E, U */ /* C - Set if bit 3 of source operand is set. Cleared otherwise. */ - if (*((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if (*((uint64_t*)D.addr) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); DSP56156_V_CLEAR(); - if (p_accum & 0x0000000000000008U) DSP56156_C_SET(); else DSP56156_C_CLEAR(); + if (p_accum & 0x00000000'00000008ULL) DSP56156_C_SET(); else DSP56156_C_CLEAR(); cycles += 2; return 1; @@ -2275,18 +3128,18 @@ static size_t dsp56156_op_asr16(dsp56156_core* cpustate, const uint16_t op, uint *((uint64_t*)D.addr) = *((uint64_t*)D.addr) >> 16; - if (backupVal & 0x0000008000000000U) - *((uint64_t*)D.addr) |= 0x000000ffff000000U; + if (backupVal & 0x00000080'00000000ULL) + *((uint64_t*)D.addr) |= 0x000000ffff000000ULL; else - *((uint64_t*)D.addr) &= 0x0000000000ffffffU; + *((uint64_t*)D.addr) &= 0x00000000'00ffffffULL; /* S L E U N Z V C */ /* - * * * * * 0 ? */ /* TODO: E, U */ - if (*((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if (*((uint64_t*)D.addr) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); DSP56156_V_CLEAR(); - if (backupVal & 0x0000000000008000U) DSP56156_C_SET(); else DSP56156_C_CLEAR(); + if (backupVal & 0x00000000'00008000ULL) DSP56156_C_SET(); else DSP56156_C_CLEAR(); cycles += 2; return 1; @@ -2308,7 +3161,7 @@ static size_t dsp56156_op_bfop(dsp56156_core* cpustate, const uint16_t op, const decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal); workAddr = assemble_address_from_Pppppp_table(cpustate, BITS(op,0x0020), BITS(op,0x001f)); - previousValue = cpustate->data->read_word(workAddr); + previousValue = cpustate->data.read_word(workAddr); workingWord = previousValue; switch(BITS(op2, 0x1f00)) @@ -2332,7 +3185,7 @@ static size_t dsp56156_op_bfop(dsp56156_core* cpustate, const uint16_t op, const tempTP.addr = &workingWord; tempTP.data_type = DT_WORD; - SetDataMemoryValue(cpustate, tempTP, workAddr); + dsp56156_set_data_memory_value(cpustate, tempTP, workAddr); /* S L E U N Z V C */ /* - * - - - - - ? */ @@ -2342,7 +3195,7 @@ static size_t dsp56156_op_bfop(dsp56156_core* cpustate, const uint16_t op, const case 0x12: /* BFCHG */ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; case 0x04: /* BFCLR */ - if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; + if ((iVal & previousValue) == 0x0000) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; case 0x18: /* BFSET */ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; case 0x10: /* BFTSTH */ @@ -2374,7 +3227,7 @@ static size_t dsp56156_op_bfop_1(dsp56156_core* cpustate, const uint16_t op, con decode_RR_table(cpustate, BITS(op,0x0003), &R); workAddr = *((uint16_t*)R.addr); - previousValue = cpustate->data->read_word(workAddr); + previousValue = cpustate->data.read_word(workAddr); workingWord = previousValue; switch(BITS(op2, 0x1f00)) @@ -2398,7 +3251,7 @@ static size_t dsp56156_op_bfop_1(dsp56156_core* cpustate, const uint16_t op, con tempTP.addr = &workingWord; tempTP.data_type = DT_WORD; - SetDataMemoryValue(cpustate, tempTP, workAddr); + dsp56156_set_data_memory_value(cpustate, tempTP, workAddr); /* S L E U N Z V C */ /* - * - - - - - ? */ @@ -2408,7 +3261,7 @@ static size_t dsp56156_op_bfop_1(dsp56156_core* cpustate, const uint16_t op, con case 0x12: /* BFCHG */ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; case 0x04: /* BFCLR */ - if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; + if ((iVal & previousValue) == 0x0000) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; case 0x18: /* BFSET */ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; case 0x10: /* BFTSTH */ @@ -2428,8 +3281,9 @@ static size_t dsp56156_op_bfop_1(dsp56156_core* cpustate, const uint16_t op, con /* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */ static size_t dsp56156_op_bfop_2(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles) { - uint16_t workingWord = 0x0000; - uint16_t previousValue = 0x0000; + uint16_t workingWord = 0; + uint16_t previousWord = 0; + uint64_t previousAccum = 0; uint16_t iVal = op2 & 0x00ff; typed_pointer S = { nullptr, DT_BYTE }; @@ -2439,11 +3293,16 @@ static size_t dsp56156_op_bfop_2(dsp56156_core* cpustate, const uint16_t op, con /* A & B are special */ if (S.data_type == DT_LONG_WORD) - previousValue = ((PAIR64*)S.addr)->w.h; + { + previousAccum = dsp56156_limit_long_to_long(cpustate, ((PAIR64*)S.addr)->q); + previousWord = (uint16_t)(previousAccum >> 16); + } else - previousValue = *((uint16_t*)S.addr); + { + previousWord = *((uint16_t*)S.addr); + } - workingWord = previousValue; + workingWord = previousWord; switch(BITS(op2, 0x1f00)) { @@ -2466,9 +3325,13 @@ static size_t dsp56156_op_bfop_2(dsp56156_core* cpustate, const uint16_t op, con /* Put the data back where it belongs (A & B are special) */ if (S.data_type == DT_LONG_WORD) - ((PAIR64*)S.addr)->w.h = workingWord; + { + ((PAIR64*)S.addr)->q = (previousAccum & 0x000000ff'00000000ULL) | ((uint64_t)workingWord << 16); + } else - *((uint16_t*)S.addr) = workingWord; + { + *(uint16_t*)S.addr = workingWord; + } /* S L E U N Z V C */ /* - * - - - - - ? */ @@ -2476,15 +3339,15 @@ static size_t dsp56156_op_bfop_2(dsp56156_core* cpustate, const uint16_t op, con switch(BITS(op2, 0x1f00)) { case 0x12: /* BFCHG */ - if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; + if ((iVal & previousWord) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; case 0x04: /* BFCLR */ - if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; + if ((iVal & previousWord) == 0x0000) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; case 0x18: /* BFSET */ - if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; + if ((iVal & previousWord) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; case 0x10: /* BFTSTH */ - if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; + if ((iVal & previousWord) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; case 0x00: /* BFTSTL */ - if ((iVal & previousValue) == 0x0000) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; + if ((iVal & previousWord) == 0x0000) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break; } cycles += 4; /* TODO: + mvb oscillator clock cycles */ @@ -2523,7 +3386,7 @@ static size_t dsp56156_op_bcc_1(dsp56156_core* cpustate, const uint16_t op, uint if (shouldBranch) { - int16_t offset = (int16_t)assemble_address_from_6bit_signed_relative_short_address(cpustate, BITS(op,0x003f)); + int16_t offset = util::sext(op, 6); PC += offset + 1; @@ -2546,6 +3409,7 @@ static size_t dsp56156_op_bcc_2(dsp56156_core* cpustate, const uint16_t op, uint { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_bcc_2\n"); return 0; } @@ -2554,6 +3418,7 @@ static size_t dsp56156_op_bra(dsp56156_core* cpustate, const uint16_t op, const { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_bra\n"); return 0; } @@ -2580,6 +3445,7 @@ static size_t dsp56156_op_bra_2(dsp56156_core* cpustate, const uint16_t op, uint { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_bra_2\n"); return 0; } @@ -2593,25 +3459,22 @@ static size_t dsp56156_op_brkcc(dsp56156_core* cpustate, const uint16_t op, uint /* TODO: I think this PC = LA thing is off-by-1, but it's working this way because its consistently so */ PC = LA; - SR = SSL; /* TODO: A-83. I believe only the Loop Flag and Forever Flag come back here. */ + SR &= 0x3fff; + SR |= SSL & 0xc000; SP--; LA = SSH; LC = SSL; SP--; - cycles += 8; - return 0; - } - else - { cycles += 2; - return 1; + return 0; } /* S L E U N Z V C */ /* - - - - - - - - */ - return 0; + cycles += 2; + return 1; } /* BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 */ @@ -2626,7 +3489,7 @@ static size_t dsp56156_op_bscc(dsp56156_core* cpustate, const uint16_t op, const /* Push */ SP++; - SSH = PC; + SSH = (PC < 0x80) ? PC : PC; /* Long interrupt gets the previous PC, not the current one */ SSL = SR; /* Change */ @@ -2649,6 +3512,7 @@ static size_t dsp56156_op_bscc_1(dsp56156_core* cpustate, const uint16_t op, uin { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_bscc_1\n"); return 0; } @@ -2660,7 +3524,7 @@ static size_t dsp56156_op_bsr(dsp56156_core* cpustate, const uint16_t op, const /* Push */ SP++; - SSH = PC; + SSH = (PC < 0x80) ? PC : PC; /* Long interrupt gets the previous PC, not the current one */ SSL = SR; /* Change */ @@ -2677,6 +3541,7 @@ static size_t dsp56156_op_bsr_1(dsp56156_core* cpustate, const uint16_t op, uint { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_bsr_1\n"); return 0; } @@ -2691,6 +3556,7 @@ static size_t dsp56156_op_chkaau(dsp56156_core* cpustate, const uint16_t op, uin address ALU is positive. */ /* N - Set if the result of the last address ALU update is negative. Cleared if the result of the last address ALU is positive. */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_chkaau\n"); return 0; } @@ -2699,6 +3565,7 @@ static size_t dsp56156_op_debug(dsp56156_core* cpustate, const uint16_t op, uint { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_debug\n"); return 0; } @@ -2707,6 +3574,7 @@ static size_t dsp56156_op_debugcc(dsp56156_core* cpustate, const uint16_t op, ui { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_debugcc\n"); return 0; } @@ -2714,17 +3582,37 @@ static size_t dsp56156_op_debugcc(dsp56156_core* cpustate, const uint16_t op, ui /* WARNING : DOCS SAY THERE IS A PARALLEL MOVE HERE !!! */ static size_t dsp56156_op_div(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { - /* WARNING : THIS DOES NOT WORK. IT DOESN'T EVEN TRY !!! */ typed_pointer S = {nullptr, DT_BYTE}; typed_pointer D = {nullptr, DT_BYTE}; decode_DDF_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S, &D); + uint64_t dVal = *(uint64_t*)D.addr; + uint64_t sVal = *(uint16_t*)S.addr; + + const bool quotient_negative = BIT(dVal, 39) != BIT(sVal, 15); + + const uint64_t oldBit39 = BIT(dVal, 39); + dVal <<= 1; + const uint64_t newBit39 = BIT(dVal, 39); + dVal |= C(); + dVal &= 0x000000ffffffffffULL; + + if (quotient_negative) + dVal += (uint32_t(sVal) << 16) | (BIT(sVal, 15) ? 0xff'00000000ULL : 0ULL); + else + dVal -= (uint32_t(sVal) << 16) | (BIT(sVal, 15) ? 0xff'00000000ULL : 0ULL); + + *(uint64_t*)D.addr = dVal & 0x000000ff'ffffffffULL; /* S L E U N Z V C */ /* - * - - - - ? ? */ - /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significantst - bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */ + /* L - Set if overflow bit V is set. */ + /* V - Set if the most significant bit of the destination operand is changed as a result of the left + shift. Cleared otherwise. */ /* C - Set if bit 39 of the result is cleared. Cleared otherwise. */ + if (newBit39 != oldBit39) DSP56156_V_SET(); else DSP56156_V_CLEAR(); + if (!BIT(dVal, 39)) DSP56156_C_SET(); else DSP56156_C_CLEAR(); + cycles += 2; return 1; } @@ -2732,7 +3620,6 @@ static size_t dsp56156_op_div(dsp56156_core* cpustate, const uint16_t op, uint8_ /* DMAC : 0001 0101 10s1 FsQQ : A-80 */ static size_t dsp56156_op_dmac(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { - uint8_t ss = 0; int64_t result = 0; void* D = nullptr; @@ -2741,41 +3628,41 @@ static size_t dsp56156_op_dmac(dsp56156_core* cpustate, const uint16_t op, uint8 decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D); - ss = BITS(op,0x0024); + const uint8_t ss = BITS(op,0x0024); /* Fixed-point 2's complement multiplication requires a shift */ if (ss == 0x00 || ss == 0x01) { /* Signed * Signed */ - int32_t s1 = ((int32_t)(*((uint16_t*)S1))); - int32_t s2 = ((int32_t)(*((uint16_t*)S2))); - result = ( s1 * s2 ) << 1; + const int64_t s1 = int64_t(*((int16_t*)S1)); + const int32_t s2 = int32_t(*((int16_t*)S2)); + result = (s1 * s2) << 1; } else if (ss == 0x2) { /* Signed * Unsigned */ - /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */ - int32_t s1 = ((int32_t)(*((uint16_t*)S1))); - int32_t s2 = (uint32_t)(*((uint16_t*)S2)); - result = ( s1 * s2 ) << 1; + const int64_t s1 = int64_t(*((int16_t*)S1)); + const int32_t s2 = uint32_t(*((uint16_t*)S2)); + result = (s1 * s2) << 1; } else if (ss == 0x3) { /* Unsigned * Unsigned */ - uint32_t s1 = (uint32_t)(*((uint16_t*)S1)); - uint32_t s2 = (uint32_t)(*((uint16_t*)S2)); - result = ( s1 * s2 ) << 1; + const uint64_t s1 = uint64_t(*((uint16_t*)S1)); + const uint32_t s2 = uint32_t(*((uint16_t*)S2)); + result = (s1 * s2) << 1; } /* Shift right, then accumulate */ - (*((uint64_t*)D)) = (*((uint64_t*)D)) >> 16; - (*((uint64_t*)D)) += result; + + *((uint64_t*)D) = (uint64_t)((*(int64_t*)D << 24) >> 40); + *((uint64_t*)D) += result; /* S L E U N Z V C */ /* - * * * * * * - */ /* TODO: L, E, U, V */ - if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ( *((uint64_t*)D) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D) & 0x000000ff'ffffffffULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); cycles += 2; return 1; @@ -2786,6 +3673,7 @@ static size_t dsp56156_op_do(dsp56156_core* cpustate, const uint16_t op, const u { /* S L E U N Z V C */ /* - * - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_do\n"); return 0; } @@ -2793,7 +3681,7 @@ static size_t dsp56156_op_do(dsp56156_core* cpustate, const uint16_t op, const u static size_t dsp56156_op_do_1(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles) { uint8_t retSize = 0; - uint8_t iValue = BITS(op,0x00ff); + const uint8_t iValue = BITS(op,0x00ff); /* Don't execute if the loop counter == 0 */ if (iValue != 0x00) @@ -2852,20 +3740,13 @@ static size_t dsp56156_op_do_2(dsp56156_core* cpustate, const uint16_t op, const else if (S.addr == &B) lValue = *((uint16_t*)(&B1)); else lValue = *((uint16_t*)S.addr); - /* HACK */ - if (lValue >= 0xfff0) - { - cpustate->device->logerror("Dsp56156 : DO_2 operation changed %04x to 0000.\n", lValue); - lValue = 0x0000; - } - /* TODO: Fix for special cased SP S */ if (S.addr == &SP) - cpustate->device->logerror("DSP56156: do with SP as the source not properly implemented yet.\n"); + LOGMASKED(LOG_UNIMPLEMENTED, "DSP56156: do with SP as the source not properly implemented yet.\n"); /* TODO: Fix for special cased SSSL S */ if (S.addr == &SSL) - cpustate->device->logerror("DSP56156: do with SP as the source not properly implemented yet.\n"); + LOGMASKED(LOG_UNIMPLEMENTED, "DSP56156: do with SP as the source not properly implemented yet.\n"); /* Don't execute if the loop counter == 0 */ if (lValue != 0x00) @@ -2887,6 +3768,8 @@ static size_t dsp56156_op_do_2(dsp56156_core* cpustate, const uint16_t op, const /* Third instruction cycle */ LF_bit_set(cpustate, 1); + /* Undocumented, but it must be true to nest Dos in DoForevers */ + FV_bit_set(cpustate, 0); /* S L E U N Z V C */ /* - * - - - - - - */ @@ -2934,9 +3817,18 @@ static size_t dsp56156_op_doforever(dsp56156_core* cpustate, const uint16_t op, /* ENDDO : 0000 0000 0000 1001 : A-92 */ static size_t dsp56156_op_enddo(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { + SR &= 0x3fff; + SR |= SSL & 0xc000; + SP--; + + LA = SSH; + LC = SSL; + SP--; + /* S L E U N Z V C */ /* - - - - - - - - */ - return 0; + cycles += 8; + return 1; } /* EXT : 0001 0101 0101 F010 : A-96 */ @@ -2944,6 +3836,7 @@ static size_t dsp56156_op_ext(dsp56156_core* cpustate, const uint16_t op, uint8_ { /* S L E U N Z V C */ /* - * * * * * * - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_ext\n"); return 0; } @@ -2952,18 +3845,13 @@ static size_t dsp56156_op_illegal(dsp56156_core* cpustate, const uint16_t op, ui { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_illegal\n"); return 0; } /* IMAC : 0001 0101 1010 FQQQ : A-100 */ static size_t dsp56156_op_imac(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { - int64_t opD = 0; - int64_t result = 0; - - int32_t s1 = 0; - int32_t s2 = 0; - void* D = nullptr; void* S1 = nullptr; void* S2 = nullptr; @@ -2971,27 +3859,23 @@ static size_t dsp56156_op_imac(dsp56156_core* cpustate, const uint16_t op, uint8 decode_QQQF_table(cpustate, BITS(op,0x0007), BITS(op,0x0008), &S1, &S2, &D); /* Cast both values as being signed */ - s1 = *((int16_t*)S1); - s2 = *((int16_t*)S2); + const int32_t s1 = *((int16_t*)S1); + const int32_t s2 = *((int16_t*)S2); /* Integral multiply doesn't require the shift */ - result = (s1 * s2); + int64_t result = (s1 * s2); /* Shift result 16 bits to the left before adding to destination */ result = (result << 16) & 0xffff0000; /* Sign extend D into a temp variable */ - opD = (*((uint64_t*)D)); - if (opD & 0x0000008000000000U) - opD |= 0xffffff0000000000U; - else - opD &= 0x000000ffffffffffU; + int64_t opD = util::sext(*((uint64_t*)D), 40); /* Accumulate */ opD += result; /* And out the bits that don't live in the register */ - opD &= 0x000000ffffffffffU; + opD &= 0x000000ff'ffffffffULL; (*((uint64_t*)D)) = (uint64_t)opD; @@ -2999,8 +3883,8 @@ static size_t dsp56156_op_imac(dsp56156_core* cpustate, const uint16_t op, uint8 /* - * ? ? * ? ? - */ /* TODO: L */ /* U,E - Will not be set correctly by this instruction*/ - if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ( *((uint64_t*)D) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D) & 0x000000ff'ffff0000ULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); DSP56156_V_CLEAR(); cycles += 2; @@ -3015,6 +3899,7 @@ static size_t dsp56156_op_impy(dsp56156_core* cpustate, const uint16_t op, uint8 /* Z - Set if the 24 most significant bits of the destination result are all zeroes. */ /* U,E - Will not be set correctly by this instruction*/ /* V - Set to zero regardless of the overflow */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_impy\n"); return 0; } @@ -3023,6 +3908,7 @@ static size_t dsp56156_op_jcc(dsp56156_core* cpustate, const uint16_t op, const { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_jcc\n"); return 0; } @@ -3031,6 +3917,7 @@ static size_t dsp56156_op_jcc_1(dsp56156_core* cpustate, const uint16_t op, uint { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_jcc_1\n"); return 0; } @@ -3064,18 +3951,19 @@ static size_t dsp56156_op_jmp_1(dsp56156_core* cpustate, const uint16_t op, uint /* JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 */ static size_t dsp56156_op_jscc(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles) { - int shouldJump = decode_cccc_table(cpustate, BITS(op,0x000f)); + const int shouldJump = decode_cccc_table(cpustate, BITS(op,0x000f)); - if(shouldJump) + if (shouldJump) { /* TODO: It says "signed" absolute offset. Weird. */ - uint16_t branchOffset = op2; + const uint16_t branchOffset = op2; /* TODO: Verify, since it's not in the docs, but it must be true */ PC += 2; + /* Push */ SP++; - SSH = PC; + SSH = (PC < 0x80) ? PC : PC; /* Long interrupt gets the previous PC, not the current one */ SSL = SR; PC = branchOffset; @@ -3099,6 +3987,7 @@ static size_t dsp56156_op_jscc_1(dsp56156_core* cpustate, const uint16_t op, uin { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_jscc_1\n"); return 0; } @@ -3106,30 +3995,15 @@ static size_t dsp56156_op_jscc_1(dsp56156_core* cpustate, const uint16_t op, uin static size_t dsp56156_op_jsr(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles) { /* TODO: It says "signed" absolute offset. Weird. */ - uint16_t branchOffset = op2; + const uint16_t branchOffset = op2; - /* TODO: Verify, since it's not in the docs, but it must be true */ PC += 2; - /* TODO: This is a hacky implementation of Long vs Fast Interrupts. Do it right someday! */ - if (PC < 0x80) - { - /* Long interrupt gets the previous PC, not the current one */ - SP++; - SSH = cpustate->ppc; - SSL = SR; - - PC = branchOffset; - } - else - { - /* Normal operation */ - SP++; - SSH = PC; - SSL = SR; - - PC = branchOffset; - } + /* Push */ + SP++; + SSH = (PC < 0x80) ? IPC : PC; /* Long interrupt gets the previous PC, not the current one */ + SSL = SR; + PC = branchOffset; /* S L E U N Z V C */ /* - - - - - - - - */ @@ -3142,6 +4016,7 @@ static size_t dsp56156_op_jsr_1(dsp56156_core* cpustate, const uint16_t op, uint { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_jsr_1\n"); return 0; } @@ -3150,21 +4025,21 @@ static size_t dsp56156_op_jsr_2(dsp56156_core* cpustate, const uint16_t op, uint { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_jsr_2\n"); return 0; } /* LEA : 0000 0001 11TT MMRR : A-116 */ static size_t dsp56156_op_lea(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { - uint16_t ea = 0; - uint16_t *rX = nullptr; - uint16_t *nX = nullptr; typed_pointer D = {nullptr, DT_BYTE}; decode_TT_table(cpustate, BITS(op,0x0030), &D); /* TODO: change the execute_mm_functions to return values. Maybe */ /* Because this calculation isn't applied, do everything locally */ /* RR table */ + uint16_t *rX = nullptr; + uint16_t *nX = nullptr; switch(BITS(op,0x0003)) { case 0x0: rX = &R0; nX = &N0; break; @@ -3174,6 +4049,7 @@ static size_t dsp56156_op_lea(dsp56156_core* cpustate, const uint16_t op, uint8_ } /* MM table */ + uint16_t ea = 0; switch(BITS(op,0x000c)) { case 0x0: ea = *rX; break; @@ -3194,50 +4070,48 @@ static size_t dsp56156_op_lea_1(dsp56156_core* cpustate, const uint16_t op, uint { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_lea_1\n"); return 0; } /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */ static size_t dsp56156_op_macsuuu(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { - uint8_t s = 0; - int64_t result = 0; - void* D = nullptr; void* S1 = nullptr; void* S2 = nullptr; decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D); - s = BITS(op,0x0004); + const uint8_t s = BITS(op,0x0004); /* Fixed-point 2's complement multiplication requires a shift */ + int64_t result = 0; if (s) { /* Unsigned * Unsigned */ - uint32_t s1 = (uint32_t)(*((uint16_t*)S1)); - uint32_t s2 = (uint32_t)(*((uint16_t*)S2)); - result = ( s1 * s2 ) << 1; + const int64_t s1 = uint64_t(*((uint16_t*)S1)); + const int32_t s2 = uint32_t(*((uint16_t*)S2)); + result = (s1 * s2) << 1; } else { /* Signed * Unsigned */ - /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */ - int32_t s1 = ((int32_t)(*((uint16_t*)S1))); - int32_t s2 = (uint32_t)(*((uint16_t*)S2)); - result = ( s1 * s2 ) << 1; + const int64_t s1 = int64_t(*((uint16_t*)S1)); + const int32_t s2 = uint32_t(*((uint16_t*)S2)); + result = (s1 * s2) << 1; } (*((uint64_t*)D)) += result; /* And out the bits that don't live in the register */ - (*((uint64_t*)D)) &= 0x000000ffffffffffU; + (*((uint64_t*)D)) &= 0x000000ff'ffffffffULL; /* S L E U N Z V C */ /* - * * * * * * - */ /* TODO: L, E, U, V */ - if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ( *((uint64_t*)D) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D) & 0x000000ff'ffffffffULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); cycles += 2; return 1; @@ -3248,6 +4122,7 @@ static size_t dsp56156_op_move_2(dsp56156_core* cpustate, const uint16_t op, con { /* S L E U N Z V C */ /* * * - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_move_2\n"); return 0; } @@ -3265,15 +4140,15 @@ static size_t dsp56156_op_movec(dsp56156_core* cpustate, const uint16_t op, uint if (W) { /* Write D */ - uint16_t value = cpustate->data->read_word(*((uint16_t*)R.addr)) ; + uint16_t value = cpustate->data.read_word(*((uint16_t*)R.addr)); typed_pointer temp_src = { &value, DT_WORD }; - SetDestinationValue(temp_src, SD); + dsp56156_set_destination_value(cpustate, temp_src, SD); } else { /* Read S */ uint16_t dataMemOffset = *((uint16_t*)R.addr); - SetDataMemoryValue(cpustate, SD, dataMemOffset); + dsp56156_set_data_memory_value(cpustate, SD, dataMemOffset); } execute_MM_table(cpustate, BITS(op,0x0003), BITS(op,0x000c)); @@ -3296,27 +4171,40 @@ static size_t dsp56156_op_movec(dsp56156_core* cpustate, const uint16_t op, uint /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */ static size_t dsp56156_op_movec_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { - uint8_t W; - uint16_t memOffset; typed_pointer SD = {nullptr, DT_BYTE}; - W = BITS(op,0x0400); + const uint8_t W = BITS(op,0x0400); decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD); - memOffset = execute_q_table(cpustate, BITS(op,0x0003), BITS(op,0x0008)); + const uint16_t memOffset = execute_q_table(cpustate, BITS(op,0x0003), BITS(op,0x0008)); if (W) { /* Write D */ - uint16_t tempData = cpustate->data->read_word(memOffset); + uint16_t tempData = cpustate->data.read_word(memOffset); typed_pointer temp_src = { (void*)&tempData, DT_WORD }; - SetDestinationValue(temp_src, SD); + + /* A & B are special */ + if (SD.data_type == DT_LONG_WORD) + { + SD.data_type = DT_WORD; + SD.addr = &((PAIR64*)SD.addr)->w.h; + } + + dsp56156_set_destination_value(cpustate, temp_src, SD); } else { /* Read S */ uint16_t tempData = *((uint16_t*)SD.addr); + + /* A & B are special */ + if (SD.data_type == DT_LONG_WORD) + { + tempData = (uint16_t)(*((uint64_t*)SD.addr) >> 16); + } + typed_pointer temp_src = { (void*)&tempData, DT_WORD }; - SetDataMemoryValue(cpustate, temp_src, memOffset); + dsp56156_set_data_memory_value(cpustate, temp_src, memOffset); } /* S L E U N Z V C */ @@ -3337,30 +4225,28 @@ static size_t dsp56156_op_movec_1(dsp56156_core* cpustate, const uint16_t op, ui /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */ static size_t dsp56156_op_movec_2(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { - uint8_t W; - uint16_t memOffset; typed_pointer SD = {nullptr, DT_BYTE}; typed_pointer XMemOffset = {nullptr, DT_BYTE}; - W = BITS(op,0x0400); + const uint8_t W = BITS(op,0x0400); decode_Z_table(cpustate, BITS(op,0x0008), &XMemOffset); decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD); - memOffset = *((uint16_t*)XMemOffset.addr); + const uint16_t memOffset = *((uint16_t*)XMemOffset.addr); if (W) { /* Write D */ - uint16_t tempData = cpustate->data->read_word(memOffset); + uint16_t tempData = cpustate->data.read_word(memOffset); typed_pointer temp_src = { (void*)&tempData, DT_WORD }; - SetDestinationValue(temp_src, SD); + dsp56156_set_destination_value(cpustate, temp_src, SD); } else { /* Read S */ uint16_t tempData = *((uint16_t*)SD.addr); typed_pointer temp_src = { (void*)&tempData, DT_WORD }; - SetDataMemoryValue(cpustate, temp_src, memOffset); + dsp56156_set_data_memory_value(cpustate, temp_src, memOffset); } @@ -3382,14 +4268,17 @@ static size_t dsp56156_op_movec_2(dsp56156_core* cpustate, const uint16_t op, ui /* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */ static size_t dsp56156_op_movec_3(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles) { - uint8_t W; - uint8_t t; typed_pointer SD = { nullptr, DT_BYTE }; - W = BITS(op,0x0400); - t = BITS(op,0x0008); + const uint8_t W = BITS(op,0x0400); + const uint8_t t = BITS(op,0x0008); decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD); + // Useful Polygonet addresses: + // 0x255: cpustate->ALU.a.w.h contains model to draw, go to 0x628 to skip. Data RAM 0x2F6 contains address into which model spans are drawn + // 0x61F: R1 contains span-store pointer which is being stored + // 0x554: 0x2F6 contains span-store pointer which is being loaded + if (W) { /* Write D */ @@ -3397,14 +4286,14 @@ static size_t dsp56156_op_movec_3(dsp56156_core* cpustate, const uint16_t op, co { /* 16-bit long data */ typed_pointer temp_src = { (void*)&op2, DT_WORD }; - SetDestinationValue(temp_src, SD); + dsp56156_set_destination_value(cpustate, temp_src, SD); } else { /* 16-bit long address */ - uint16_t tempD = cpustate->data->read_word(op2); + uint16_t tempD = cpustate->data.read_word(op2); typed_pointer tempTP = {&tempD, DT_WORD}; - SetDestinationValue(tempTP, SD); + dsp56156_set_destination_value(cpustate, tempTP, SD); } } else @@ -3413,12 +4302,12 @@ static size_t dsp56156_op_movec_3(dsp56156_core* cpustate, const uint16_t op, co if (t) { /* 16-bit long data */ - cpustate->device->logerror("DSP56156: Movec - I don't think this exists?"); + LOGMASKED(LOG_UNIMPLEMENTED, "DSP56156: Potentially nonexistent movec_3 at %04x", PC); } else { /* 16-bit long address */ - SetDataMemoryValue(cpustate, SD, op2); + dsp56156_set_data_memory_value(cpustate, SD, op2); } } @@ -3446,7 +4335,29 @@ static size_t dsp56156_op_movec_4(dsp56156_core* cpustate, const uint16_t op, ui decode_DDDDD_table(cpustate, BITS(op,0x03e0), &S); decode_DDDDD_table(cpustate, BITS(op,0x001f), &D); - SetDestinationValue(S, D); + const bool both_accum = (S.data_type == DT_LONG_WORD && D.data_type == DT_LONG_WORD); + + if (S.data_type == DT_LONG_WORD && D.data_type == DT_WORD) + { + S.data_type = DT_WORD; + if (S.addr == &A) + S.addr = &A1; + else if (S.addr == &B) + S.addr = &B1; + dsp56156_set_destination_value(cpustate, S, D); + } + else if (both_accum) + { + typed_pointer tempTP; + uint64_t temp_val = dsp56156_limit_long_to_long(cpustate, *(uint64_t*)S.addr); + tempTP.addr = &temp_val; + tempTP.data_type = DT_LONG_WORD; + dsp56156_set_destination_value(cpustate, tempTP, D); + } + else + { + dsp56156_set_destination_value(cpustate, S, D); + } /* S L E U N Z V C */ /* * ? ? ? ? ? ? ? */ @@ -3466,30 +4377,27 @@ static size_t dsp56156_op_movec_4(dsp56156_core* cpustate, const uint16_t op, ui /* MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 */ static size_t dsp56156_op_movec_5(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles) { - int8_t xx; - uint8_t W; - uint16_t memOffset; typed_pointer SD = { nullptr, DT_BYTE }; - xx = (int8_t)(op & 0x00ff); - W = BITS(op2,0x0400); + const int8_t xx = int8_t(op & 0x00ff); + const uint8_t W = BITS(op2,0x0400); decode_DDDDD_table(cpustate, BITS(op2,0x03e0), &SD); - memOffset = R2 + (int16_t)xx; + const uint16_t memOffset = R2 + (int16_t)xx; if (W) { /* Write D */ - uint16_t tempData = cpustate->data->read_word(memOffset); + uint16_t tempData = cpustate->data.read_word(memOffset); typed_pointer temp_src = { (void*)&tempData, DT_WORD }; - SetDestinationValue(temp_src, SD); + dsp56156_set_destination_value(cpustate, temp_src, SD); } else { /* Read S */ uint16_t tempData = *((uint16_t*)SD.addr); typed_pointer temp_src = { (void*)&tempData, DT_WORD }; - SetDataMemoryValue(cpustate, temp_src, memOffset); + dsp56156_set_data_memory_value(cpustate, temp_src, memOffset); } /* S L E U N Z V C */ @@ -3514,13 +4422,13 @@ static size_t dsp56156_op_movei(dsp56156_core* cpustate, const uint16_t op, uint typed_pointer immTP = {nullptr, DT_BYTE}; /* Typecasting to int16_t sign-extends the BBBBBBBB operand */ - uint16_t immediateSignExtended = (int16_t)(op & 0x00ff); + uint16_t immediateSignExtended = int16_t(op & 0x00ff); immTP.addr = &immediateSignExtended; immTP.data_type = DT_WORD; decode_DD_table(cpustate, BITS(op,0x0300), &D); - SetDestinationValue(immTP, D); + dsp56156_set_destination_value(cpustate, immTP, D); /* S L E U N Z V C */ /* - - - - - - - - */ @@ -3531,11 +4439,10 @@ static size_t dsp56156_op_movei(dsp56156_core* cpustate, const uint16_t op, uint /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */ static size_t dsp56156_op_movem(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { - uint8_t W; typed_pointer R = { nullptr, DT_BYTE }; typed_pointer SD = { nullptr, DT_BYTE }; - W = BITS(op,0x0100); + const uint8_t W = BITS(op,0x0100); decode_RR_table(cpustate, BITS(op,0x00c0), &R); decode_HHH_table(cpustate, BITS(op,0x0007), &SD); @@ -3543,16 +4450,16 @@ static size_t dsp56156_op_movem(dsp56156_core* cpustate, const uint16_t op, uint { /* Read from Program Memory */ typed_pointer data; - uint16_t ldata = cpustate->program->read_word(*((uint16_t*)R.addr)); + uint16_t ldata = cpustate->program.read_word(*((uint16_t*)R.addr)); data.addr = &ldata; data.data_type = DT_WORD; - SetDestinationValue(data, SD) ; + dsp56156_set_destination_value(cpustate, data, SD); } else { /* Write to Program Memory */ - SetProgramMemoryValue(cpustate, SD, *((uint16_t*)R.addr)) ; + dsp56156_set_program_memory_value(cpustate, SD, *((uint16_t*)R.addr)); } execute_MM_table(cpustate, BITS(op,0x00c0), BITS(op,0x0018)); @@ -3569,6 +4476,7 @@ static size_t dsp56156_op_movem_1(dsp56156_core* cpustate, const uint16_t op, ui { /* S L E U N Z V C */ /* * * - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_movem_1\n"); return 0; } @@ -3577,37 +4485,35 @@ static size_t dsp56156_op_movem_2(dsp56156_core* cpustate, const uint16_t op, co { /* S L E U N Z V C */ /* * * - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_movem_2\n"); return 0; } /* MOVE(P) : 0001 100W HH1p pppp : A-156 */ static size_t dsp56156_op_movep(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { - uint16_t W; - uint16_t pp; typed_pointer SD = {nullptr, DT_BYTE}; decode_HH_table(cpustate, BITS(op,0x00c0), &SD); /* TODO: Special cases for A & B */ - pp = op & 0x001f; - pp = assemble_address_from_IO_short_address(cpustate, pp); + const uint16_t pp = assemble_address_from_IO_short_address(cpustate, op & 0x001f); - W = BITS(op,0x0100); + const uint16_t W = BITS(op,0x0100); if (W) { - uint16_t data = cpustate->data->read_word(pp); + uint16_t data = cpustate->data.read_word(pp); typed_pointer tempTP; tempTP.addr = &data; tempTP.data_type = DT_WORD; - SetDestinationValue(tempTP, SD); + dsp56156_set_destination_value(cpustate, tempTP, SD); } else { - SetDataMemoryValue(cpustate, SD, pp); + dsp56156_set_data_memory_value(cpustate, SD, pp); } /* S L E U N Z V C */ @@ -3622,32 +4528,29 @@ static size_t dsp56156_op_movep(dsp56156_core* cpustate, const uint16_t op, uint static size_t dsp56156_op_movep_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { /* X:<Rx> and X:<pp> */ - uint16_t W; - uint16_t pp; typed_pointer SD = {nullptr, DT_BYTE}; decode_RR_table(cpustate, BITS(op,0x00c0), &SD); - pp = op & 0x001f; - pp = assemble_address_from_IO_short_address(cpustate, pp); + const uint16_t pp = assemble_address_from_IO_short_address(cpustate, op & 0x001f); - W = BITS(op,0x0100); + const uint16_t W = BITS(op,0x0100); /* A little different than most W if's - opposite read and write */ if (W) { - uint16_t data = cpustate->data->read_word(*((uint16_t*)SD.addr)); + uint16_t data = cpustate->data.read_word(*((uint16_t*)SD.addr)); typed_pointer tempTP; tempTP.addr = &data; tempTP.data_type = DT_WORD; - SetDataMemoryValue(cpustate, tempTP, pp); + dsp56156_set_data_memory_value(cpustate, tempTP, pp); } else { /* TODO */ - fatalerror("dsp56156 : move(p) NOTHING HERE (yet)\n") ; + fatalerror("dsp56156 : move(p) NOTHING HERE (yet)\n"); } /* Postincrement */ @@ -3665,13 +4568,13 @@ static size_t dsp56156_op_moves(dsp56156_core* cpustate, const uint16_t op, uint { /* S L E U N Z V C */ /* * * - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_moves\n"); return 0; } /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */ static size_t dsp56156_op_mpysuuu(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { - uint8_t s = 0; int64_t result = 0; void* D = nullptr; @@ -3680,35 +4583,34 @@ static size_t dsp56156_op_mpysuuu(dsp56156_core* cpustate, const uint16_t op, ui decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D); - s = BITS(op,0x0004); + const uint8_t s = BITS(op,0x0004); /* Fixed-point 2's complement multiplication requires a shift */ if (s) { /* Unsigned * Unsigned */ - uint32_t s1 = (uint32_t)(*((uint16_t*)S1)); - uint32_t s2 = (uint32_t)(*((uint16_t*)S2)); - result = ( s1 * s2 ) << 1; + const int64_t s1 = uint64_t(*((uint16_t*)S1)); + const int32_t s2 = uint32_t(*((uint16_t*)S2)); + result = (s1 * s2) << 1; } else { /* Signed * Unsigned */ - /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */ - int32_t s1 = ((int32_t)(*((uint16_t*)S1))); - int32_t s2 = (uint32_t)(*((uint16_t*)S2)); - result = ( s1 * s2 ) << 1; + const int64_t s1 = int64_t(*((int16_t*)S1)); + const int32_t s2 = uint32_t(*((uint16_t*)S2)); + result = (s1 * s2) << 1; } (*((uint64_t*)D)) = result; /* And out the bits that don't live in the register */ - (*((uint64_t*)D)) &= 0x000000ffffffffffU; + (*((uint64_t*)D)) &= 0x000000ff'ffffffffULL; /* S L E U N Z V C */ /* - * * * * * * - */ /* TODO: L, E, U, V */ - if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + if ( *((uint64_t*)D) & 0x00000080'00000000ULL) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D) & 0x000000ff'ffffffffULL) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); cycles += 2; return 1; @@ -3719,6 +4621,7 @@ static size_t dsp56156_op_negc(dsp56156_core* cpustate, const uint16_t op, uint8 { /* S L E U N Z V C */ /* - * * * * * * * */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_negc\n"); return 0; } @@ -3737,6 +4640,7 @@ static size_t dsp56156_op_norm(dsp56156_core* cpustate, const uint16_t op, uint8 /* - * * * * * ? - */ /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significantst bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_norm\n"); return 0; } @@ -3747,6 +4651,7 @@ static size_t dsp56156_op_ori(dsp56156_core* cpustate, const uint16_t op, uint8_ /* - ? ? ? ? ? ? ? */ /* All ? bits - Set if the corresponding bit in the immediate data is set and if the operand is the CCR. Not affected otherwise. */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_ori\n"); return 0; } @@ -3755,14 +4660,15 @@ static size_t dsp56156_op_rep(dsp56156_core* cpustate, const uint16_t op, uint8_ { /* S L E U N Z V C */ /* - * - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_rep\n"); return 0; } /* REP : 0000 1111 iiii iiii : A-180 */ static size_t dsp56156_op_rep_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { - /* TODO: This is non-interruptable, probably have to turn off interrupts here */ - uint16_t iVal = op & 0x00ff; + /* TODO: This is non-interruptible, probably have to turn off interrupts here */ + const uint16_t iVal = op & 0x00ff; if (iVal != 0) { @@ -3776,7 +4682,10 @@ static size_t dsp56156_op_rep_1(dsp56156_core* cpustate, const uint16_t op, uint } else { + const uint16_t op1 = ROPCODE(PC + 1); + const uint16_t op2 = ROPCODE(PC + 2); cycles += 6; /* TODO: + mv oscillator clock cycles */ + return 1 + dsp56156_get_op_size(op1, op2); } @@ -3789,16 +4698,15 @@ static size_t dsp56156_op_rep_1(dsp56156_core* cpustate, const uint16_t op, uint /* REP : 0000 0100 001D DDDD : A-180 */ static size_t dsp56156_op_rep_2(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { - /* TODO: This is non-interruptable, probably have to turn off interrupts here */ - uint16_t repValue; + /* TODO: This is non-interruptible, probably have to turn off interrupts here */ typed_pointer D = {nullptr, DT_BYTE}; decode_DDDDD_table(cpustate, BITS(op,0x001f), &D); /* TODO: handle special A&B source cases */ if (D.addr == &A || D.addr == &B) - cpustate->device->logerror("DSP56156 ERROR : Rep with A or B instruction not implemented yet!\n"); + LOGMASKED(LOG_UNIMPLEMENTED, "DSP56156 ERROR: rep_2 with A or B instruction not implemented yet at %04x\n", PC); - repValue = *((uint16_t*)D.addr); + const uint16_t repValue = *((uint16_t*)D.addr); if (repValue != 0) { @@ -3812,7 +4720,10 @@ static size_t dsp56156_op_rep_2(dsp56156_core* cpustate, const uint16_t op, uint } else { + const uint16_t op1 = ROPCODE(PC + 1); + const uint16_t op2 = ROPCODE(PC + 2); cycles += 6; /* TODO: + mv oscillator clock cycles */ + return 1 + dsp56156_get_op_size(op1, op2); } /* S L E U N Z V C */ @@ -3826,6 +4737,7 @@ static size_t dsp56156_op_repcc(dsp56156_core* cpustate, const uint16_t op, uint { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_repcc\n"); return 0; } @@ -3834,6 +4746,7 @@ static size_t dsp56156_op_reset(dsp56156_core* cpustate, const uint16_t op, uint { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_reset\n"); return 0; } @@ -3880,6 +4793,7 @@ static size_t dsp56156_op_stop(dsp56156_core* cpustate, const uint16_t op, uint8 { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_stop\n"); return 0; } @@ -3888,6 +4802,7 @@ static size_t dsp56156_op_swap(dsp56156_core* cpustate, const uint16_t op, uint8 { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_swap\n"); return 0; } @@ -3896,13 +4811,14 @@ static size_t dsp56156_op_swi(dsp56156_core* cpustate, const uint16_t op, uint8_ { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_swi\n"); return 0; } /* Tcc : 0001 00cc ccTT Fh0h : A-210 */ static size_t dsp56156_op_tcc(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) { - int shouldTransfer = decode_cccc_table(cpustate, BITS(op,0x03c0)); + const int shouldTransfer = decode_cccc_table(cpustate, BITS(op,0x03c0)); if (shouldTransfer) { @@ -3912,11 +4828,11 @@ static size_t dsp56156_op_tcc(dsp56156_core* cpustate, const uint16_t op, uint8_ typed_pointer D2 = {nullptr, DT_BYTE}; decode_h0hF_table(cpustate, BITS(op,0x0007),BITS(op,0x0008), &S, &D); - SetDestinationValue(S, D); + dsp56156_set_destination_value(cpustate, S, D); /* TODO: What's up with that A,A* thing in the docs? Can you only ignore the R0->RX transfer if you do an A,A? */ decode_RR_table(cpustate, BITS(op,0x0030), &D2); /* TT is the same as RR */ - SetDestinationValue(S2, D2); + dsp56156_set_destination_value(cpustate, S2, D2); } /* S L E U N Z V C */ @@ -3933,7 +4849,7 @@ static size_t dsp56156_op_tfr2(dsp56156_core* cpustate, const uint16_t op, uint8 decode_JF_table(cpustate, BITS(op,0x0001), BITS(op,0x0008), &S, &D); - SetDestinationValue(S, D); + dsp56156_set_destination_value(cpustate, S, D); /* S L E U N Z V C */ /* - * - - - - - - */ @@ -3947,6 +4863,7 @@ static size_t dsp56156_op_tfr3(dsp56156_core* cpustate, const uint16_t op, uint8 { /* S L E U N Z V C */ /* * * - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_tfr3\n"); return 0; } @@ -3976,6 +4893,7 @@ static size_t dsp56156_op_wait(dsp56156_core* cpustate, const uint16_t op, uint8 { /* S L E U N Z V C */ /* - - - - - - - - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_wait\n"); return 0; } @@ -3984,6 +4902,7 @@ static size_t dsp56156_op_zero(dsp56156_core* cpustate, const uint16_t op, uint8 { /* S L E U N Z V C */ /* - * * * * * * - */ + LOGMASKED(LOG_UNIMPLEMENTED, "dsp56156_op_zero\n"); return 0; } @@ -4027,9 +4946,9 @@ static int decode_cccc_table(dsp56156_core* cpustate, uint16_t cccc) case 0x9: if((N() ^ V()) == 1) retVal = 1; break; /* lt */ case 0xb: if( N() == 1) retVal = 1; break; /* mi */ case 0x2: if( Z() == 0) retVal = 1; break; /* ne */ - case 0xc: if((Z() | ((!U()) & (!E()))) == 1) retVal = 1; break; /* nr */ + case 0xc: if((Z() || ((!U()) && (!E())))) retVal = 1; break; /* nr */ case 0x3: if( N() == 0) retVal = 1; break; /* pl */ - case 0x4: if((Z() | ((!U()) & (!E()))) == 0) retVal = 1; break; /* nn */ + case 0x4: if(!(Z() || ((!U()) && (!E())))) retVal = 1; break; /* nn */ } return retVal; @@ -4043,8 +4962,8 @@ static void decode_DDDDD_table(dsp56156_core* cpustate, uint16_t DDDDD, typed_po case 0x01: ret->addr = &Y0; ret->data_type = DT_WORD; break; case 0x02: ret->addr = &X1; ret->data_type = DT_WORD; break; case 0x03: ret->addr = &Y1; ret->data_type = DT_WORD; break; - case 0x04: ret->addr = &A ; ret->data_type = DT_LONG_WORD; break; - case 0x05: ret->addr = &B ; ret->data_type = DT_LONG_WORD; break; + case 0x04: ret->addr = &A; ret->data_type = DT_LONG_WORD; break; + case 0x05: ret->addr = &B; ret->data_type = DT_LONG_WORD; break; case 0x06: ret->addr = &A0; ret->data_type = DT_WORD; break; case 0x07: ret->addr = &B0; ret->data_type = DT_WORD; break; case 0x08: ret->addr = &LC; ret->data_type = DT_WORD; break; @@ -4114,7 +5033,7 @@ static void decode_F_table(dsp56156_core* cpustate, uint16_t F, typed_pointer* r static void decode_h0hF_table(dsp56156_core* cpustate, uint16_t h0h, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret) { - uint16_t switchVal = (h0h << 1) | F ; + uint16_t switchVal = (h0h << 1) | F; switch (switchVal) { @@ -4157,10 +5076,10 @@ static void decode_HHH_table(dsp56156_core* cpustate, uint16_t HHH, typed_pointe static void decode_IIII_table(dsp56156_core* cpustate, uint16_t IIII, typed_pointer* src_ret, typed_pointer* dst_ret, void *working) { - void *opposite = nullptr ; + void *opposite = nullptr; - if (working == &A) opposite = &B ; - else opposite = &A ; + if (working == &A) opposite = &B; + else opposite = &A; switch(IIII) { @@ -4168,14 +5087,16 @@ static void decode_IIII_table(dsp56156_core* cpustate, uint16_t IIII, typed_poin case 0x1: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; case 0x2: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; case 0x3: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; - case 0x4: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X0; dst_ret->data_type = DT_WORD; break; - case 0x5: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y0; dst_ret->data_type = DT_WORD; break; + case 0x4: src_ret->addr = &A1; src_ret->data_type = DT_WORD; dst_ret->addr = &X0; dst_ret->data_type = DT_WORD; break; + case 0x5: src_ret->addr = &B1; src_ret->data_type = DT_WORD; dst_ret->addr = &Y0; dst_ret->data_type = DT_WORD; break; case 0x6: src_ret->addr = &A0; src_ret->data_type = DT_WORD; dst_ret->addr = &X0; dst_ret->data_type = DT_WORD; break; case 0x7: src_ret->addr = &B0; src_ret->data_type = DT_WORD; dst_ret->addr = &Y0; dst_ret->data_type = DT_WORD; break; - case 0x8: src_ret->addr = working; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; + case 0x8: case 0x9: src_ret->addr = working; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; - case 0xc: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X1; dst_ret->data_type = DT_WORD; break; - case 0xd: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y1; dst_ret->data_type = DT_WORD; break; + //case 0x8: + //case 0x9: src_ret->addr = &((PAIR64*)working)->w.h; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; + case 0xc: src_ret->addr = &A1; src_ret->data_type = DT_WORD; dst_ret->addr = &X1; dst_ret->data_type = DT_WORD; break; + case 0xd: src_ret->addr = &B1; src_ret->data_type = DT_WORD; dst_ret->addr = &Y1; dst_ret->data_type = DT_WORD; break; case 0xe: src_ret->addr = &A0; src_ret->data_type = DT_WORD; dst_ret->addr = &X1; dst_ret->data_type = DT_WORD; break; case 0xf: src_ret->addr = &B0; src_ret->data_type = DT_WORD; dst_ret->addr = &Y1; dst_ret->data_type = DT_WORD; break; } @@ -4183,7 +5104,7 @@ static void decode_IIII_table(dsp56156_core* cpustate, uint16_t IIII, typed_poin static void decode_JJJF_table(dsp56156_core* cpustate, uint16_t JJJ, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret) { - uint16_t switchVal = (JJJ << 1) | F ; + uint16_t switchVal = (JJJ << 1) | F; switch(switchVal) { @@ -4206,7 +5127,7 @@ static void decode_JJJF_table(dsp56156_core* cpustate, uint16_t JJJ, uint16_t F, static void decode_JJF_table(dsp56156_core* cpustate, uint16_t JJ, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret) { - uint16_t switchVal = (JJ << 1) | F ; + uint16_t switchVal = (JJ << 1) | F; switch (switchVal) { @@ -4223,7 +5144,7 @@ static void decode_JJF_table(dsp56156_core* cpustate, uint16_t JJ, uint16_t F, t static void decode_JF_table(dsp56156_core* cpustate, uint16_t J, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret) { - uint16_t switchVal = (J << 1) | F ; + uint16_t switchVal = (J << 1) | F; switch (switchVal) { @@ -4236,10 +5157,10 @@ static void decode_JF_table(dsp56156_core* cpustate, uint16_t J, uint16_t F, typ static void decode_KKK_table(dsp56156_core* cpustate, uint16_t KKK, typed_pointer* dst_ret1, typed_pointer* dst_ret2, void* working) { - void *opposite = nullptr ; + void *opposite = nullptr; - if (working == &A) opposite = &B ; - else opposite = &A ; + if (working == &A) opposite = &B; + else opposite = &A; switch(KKK) { @@ -4256,7 +5177,7 @@ static void decode_KKK_table(dsp56156_core* cpustate, uint16_t KKK, typed_pointe static void decode_QQF_table(dsp56156_core* cpustate, uint16_t QQ, uint16_t F, void **S1, void **S2, void **D) { - uint16_t switchVal = (QQ << 1) | F ; + uint16_t switchVal = (QQ << 1) | F; switch(switchVal) { @@ -4273,7 +5194,7 @@ static void decode_QQF_table(dsp56156_core* cpustate, uint16_t QQ, uint16_t F, v static void decode_QQF_special_table(dsp56156_core* cpustate, uint16_t QQ, uint16_t F, void **S1, void **S2, void **D) { - uint16_t switchVal = (QQ << 1) | F ; + uint16_t switchVal = (QQ << 1) | F; switch(switchVal) { @@ -4422,8 +5343,8 @@ static void decode_Z_table(dsp56156_core* cpustate, uint16_t Z, typed_pointer* r static void execute_m_table(dsp56156_core* cpustate, int x, uint16_t m) { - uint16_t *rX = nullptr ; - uint16_t *nX = nullptr ; + uint16_t *rX = nullptr; + uint16_t *nX = nullptr; switch(x) { @@ -4464,8 +5385,8 @@ static void execute_mm_table(dsp56156_core* cpustate, uint16_t rnum, uint16_t mm static void execute_MM_table(dsp56156_core* cpustate, uint16_t rnum, uint16_t MM) { - uint16_t *rX = nullptr ; - uint16_t *nX = nullptr ; + uint16_t *rX = nullptr; + uint16_t *nX = nullptr; switch(rnum) { @@ -4478,9 +5399,9 @@ static void execute_MM_table(dsp56156_core* cpustate, uint16_t rnum, uint16_t MM switch(MM) { case 0x0: /* do nothing */ break; - case 0x1: (*rX)++ ; break; - case 0x2: (*rX)-- ; break; - case 0x3: (*rX) = (*rX)+(*nX) ; break; + case 0x1: (*rX)++; break; + case 0x2: (*rX)--; break; + case 0x3: (*rX) = (*rX)+(*nX); break; } } @@ -4500,8 +5421,8 @@ static uint16_t execute_q_table(dsp56156_core* cpustate, int RR, uint16_t q) switch(q) { - case 0x0: /* No permanent changes */ ; return (*rX)+(*nX); - case 0x1: (*rX)--; return (*rX); /* This one is special - it's a *PRE-decrement*! */ + case 0x0: /* No permanent changes */; return (*rX)+(*nX); + case 0x1: (*rX)--; return (*rX); /* This one is special - it's a *PRE-decrement*! */ } /* Should not get here */ @@ -4531,7 +5452,7 @@ static void execute_z_table(dsp56156_core* cpustate, int RR, uint16_t z) static uint16_t assemble_address_from_Pppppp_table(dsp56156_core* cpustate, uint16_t P, uint16_t ppppp) { - uint16_t destAddr = 0x00 ; + uint16_t destAddr = 0x00; switch (P) { @@ -4539,7 +5460,7 @@ static uint16_t assemble_address_from_Pppppp_table(dsp56156_core* cpustate, uint case 0x1: destAddr = assemble_address_from_IO_short_address(cpustate, ppppp); break; } - return destAddr ; + return destAddr; } static uint16_t assemble_address_from_IO_short_address(dsp56156_core* cpustate, uint16_t pp) @@ -4549,15 +5470,6 @@ static uint16_t assemble_address_from_IO_short_address(dsp56156_core* cpustate, return fullAddy; } -static uint16_t assemble_address_from_6bit_signed_relative_short_address(dsp56156_core* cpustate, uint16_t srs) -{ - uint16_t fullAddy = srs ; - if (fullAddy & 0x0020) - fullAddy |= 0xffc0 ; - - return fullAddy ; -} - static void dsp56156_process_loop(dsp56156_core* cpustate) { /* TODO: This might not work for dos nested in doForevers */ @@ -4619,6 +5531,34 @@ static void dsp56156_process_rep(dsp56156_core* cpustate, size_t repSize) /*************************************************************************** + Flag Utilities +***************************************************************************/ + +static bool dsp56156_value_is_unnormalized(dsp56156_core* cpustate, const uint64_t value) +{ + uint16_t S = (cpustate->PCU.sr >> 10) & 3; + if (S == 0 || S == 3) + return BIT(value, 31) == BIT(value, 30); + else if (S == 1) + return BIT(value, 32) == BIT(value, 31); + else + return BIT(value, 30) == BIT(value, 29); +} + +static bool dsp56156_value_is_extended(dsp56156_core* cpustate, const uint64_t value) +{ + uint16_t S = (cpustate->PCU.sr >> 10) & 3; + uint64_t extMask = 0x000000ffc0000000ULL; + if (S == 0 || S == 3) + extMask = 0x000000ff80000000ULL; + else if (S == 1) + extMask = 0x000000ff00000000ULL; + uint64_t extVal = value & extMask; + return extVal == extMask || extVal == 0; +} + + +/*************************************************************************** Parallel Memory Ops ***************************************************************************/ /* Register to Register Data Move : 0100 IIII .... .... : A-132 */ @@ -4629,17 +5569,40 @@ static void execute_register_to_register_data_move(dsp56156_core* cpustate, cons decode_IIII_table(cpustate, BITS(op,0x0f00), &S, &D, d_register->addr); + const bool opdest_is_a = d_register->addr == &A0 || d_register->addr == &A1; + const bool opdest_is_b = d_register->addr == &B0 || d_register->addr == &B1; + const bool s_is_a = S.addr == &A0 || S.addr == &A1; + const bool s_is_b = S.addr == &B0 || S.addr == &B1; + /* If the source is the same as the ALU destination, use the previous accumulator value */ - if (d_register->addr == S.addr) + if ((opdest_is_a && s_is_a) || (opdest_is_b && s_is_b)) { typed_pointer tempTP; - tempTP.addr = prev_accum_value; - tempTP.data_type = DT_LONG_WORD; - SetDestinationValue(tempTP, D); + uint64_t temp_long = 0ULL; + uint16_t temp_word = 0U; + if (S.addr == &A1 || S.addr == &B1) + { + temp_word = (uint16_t)(*prev_accum_value >> 16); + tempTP.addr = &temp_word; + tempTP.data_type = DT_WORD; + } + else if (S.data_type == DT_LONG_WORD) + { + temp_long = dsp56156_limit_long_to_long(cpustate, *prev_accum_value); + tempTP.addr = &temp_long; + tempTP.data_type = DT_LONG_WORD; + } + else + { + temp_word = (uint16_t)*prev_accum_value; + tempTP.addr = &temp_word; + tempTP.data_type = DT_WORD; + } + dsp56156_set_destination_value(cpustate, tempTP, D); } else { - SetDestinationValue(S, D); + dsp56156_set_destination_value(cpustate, S, D); } } @@ -4652,24 +5615,23 @@ static void execute_address_register_update(dsp56156_core* cpustate, const uint1 /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */ static void execute_x_memory_data_move(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value) { - uint16_t W; typed_pointer R = {nullptr, DT_BYTE}; typed_pointer SD = {nullptr, DT_BYTE}; - W = BITS(op,0x0100); + const uint16_t W = BITS(op,0x0100); decode_HHH_table(cpustate, BITS(op,0x0e00), &SD); decode_RR_table(cpustate, BITS(op,0x3000),&R); if (W) { /* From X:<ea> to SD */ - uint16_t data = cpustate->data->read_word(*((uint16_t*)R.addr)); + uint16_t data = cpustate->data.read_word(*((uint16_t*)R.addr)); typed_pointer tempTP; tempTP.addr = &data; tempTP.data_type = DT_WORD; - SetDestinationValue(tempTP, SD); + dsp56156_set_destination_value(cpustate, tempTP, SD); } else { @@ -4681,11 +5643,11 @@ static void execute_x_memory_data_move(dsp56156_core* cpustate, const uint16_t o tempTP.addr = prev_accum_value; tempTP.data_type = DT_LONG_WORD; - SetDataMemoryValue(cpustate, tempTP, *((uint16_t*)R.addr)) ; + dsp56156_set_data_memory_value(cpustate, tempTP, *((uint16_t*)R.addr)); } else { - SetDataMemoryValue(cpustate, SD, *((uint16_t*)R.addr)) ; + dsp56156_set_data_memory_value(cpustate, SD, *((uint16_t*)R.addr)); } } @@ -4696,59 +5658,51 @@ static void execute_x_memory_data_move(dsp56156_core* cpustate, const uint16_t o /* NOTE: previous accumulator value is not needed since ^F1 is always the opposite accumulator */ static void execute_x_memory_data_move2(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register) { - uint16_t W; - uint16_t* mem_offset = nullptr; typed_pointer SD = {nullptr, DT_BYTE}; - W = BITS(op,0x0100); + const uint16_t W = BITS(op,0x0100); decode_HHH_table(cpustate, BITS(op,0x0e000), &SD); - if (d_register->addr == &A) - mem_offset = &B1; - else - mem_offset = &A1; + uint16_t *const mem_offset = (d_register->addr == &A) ? &B1 : &A1; if (W) { /* Write D */ - uint16_t value = cpustate->data->read_word(*mem_offset); + uint16_t value = cpustate->data.read_word(*mem_offset); typed_pointer tempV = {&value, DT_WORD}; - SetDestinationValue(tempV, SD); + dsp56156_set_destination_value(cpustate, tempV, SD); } else { /* Read S */ - SetDataMemoryValue(cpustate, SD, *mem_offset); + dsp56156_set_data_memory_value(cpustate, SD, *mem_offset); } } /* X Memory Data Move With Short Displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */ static void execute_x_memory_data_move_with_short_displacement(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2) { - int8_t xx; - uint8_t W; - uint16_t memOffset; typed_pointer SD = { nullptr, DT_BYTE }; - xx = (int8_t)(op & 0x00ff); - W = BITS(op2,0x0100); + const int8_t xx = int8_t(op & 0x00ff); + const uint8_t W = BITS(op2,0x0100); decode_HHH_table(cpustate, BITS(op2,0x0e00), &SD); - memOffset = R2 + (int16_t)xx; + const uint16_t memOffset = R2 + (int16_t)xx; if (W) { /* Write D */ - uint16_t tempData = cpustate->data->read_word(memOffset); + uint16_t tempData = cpustate->data.read_word(memOffset); typed_pointer temp_src = { (void*)&tempData, DT_WORD }; - SetDestinationValue(temp_src, SD); + dsp56156_set_destination_value(cpustate, temp_src, SD); } else { /* Read S */ uint16_t tempData = *((uint16_t*)SD.addr); typed_pointer temp_src = { (void*)&tempData, DT_WORD }; - SetDataMemoryValue(cpustate, temp_src, memOffset); + dsp56156_set_data_memory_value(cpustate, temp_src, memOffset); } } @@ -4756,8 +5710,6 @@ static void execute_x_memory_data_move_with_short_displacement(dsp56156_core* cp static void execute_dual_x_memory_data_read(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register) { typed_pointer tempV; - uint16_t srcVal1 = 0x0000; - uint16_t srcVal2 = 0x0000; typed_pointer R = {nullptr, DT_BYTE}; typed_pointer D1 = {nullptr, DT_BYTE}; typed_pointer D2 = {nullptr, DT_BYTE}; @@ -4771,20 +5723,23 @@ static void execute_dual_x_memory_data_read(dsp56156_core* cpustate, const uint1 /* The note on A-142 is very interesting. You can effectively access external memory in the last 64 bytes of X data memory! */ - if (*((uint16_t*)D2.addr) >= 0xffc0) - fatalerror("Dsp56156: Unimplemented access to external X Data Memory >= 0xffc0 in Dual X Memory Data Read.\n"); + if (*((uint16_t*)R.addr) >= 0xffc0 || R3 >= 0xffc0) + { + cpustate->device->machine().debug_break(); + LOGMASKED(LOG_UNIMPLEMENTED, "Dsp56156: Unimplemented access to external X Data Memory >= 0xffc0 in Dual X Memory Data Read at %04x.\n", cpustate->PCU.pc); + } /* First memmove */ - srcVal1 = cpustate->data->read_word(*((uint16_t*)R.addr)); + uint16_t srcVal1 = cpustate->data.read_word(*((uint16_t*)R.addr)); tempV.addr = &srcVal1; tempV.data_type = DT_WORD; - SetDestinationValue(tempV, D1); + dsp56156_set_destination_value(cpustate, tempV, D1); /* Second memmove */ - srcVal2 = cpustate->data->read_word(R3); + uint16_t srcVal2 = cpustate->data.read_word(R3); tempV.addr = &srcVal2; tempV.data_type = DT_WORD; - SetDestinationValue(tempV, D2); + dsp56156_set_destination_value(cpustate, tempV, D2); /* Touch up the R regs after all the moves */ execute_mm_table(cpustate, BITS(op,0x0060), BITS(op,0x1800)); @@ -4793,30 +5748,38 @@ static void execute_dual_x_memory_data_read(dsp56156_core* cpustate, const uint1 /*************************************************************************** Helper Functions ***************************************************************************/ -static uint16_t Dsp56156OpMask(uint16_t cur, uint16_t mask) +static uint16_t dsp56156_op_mask(uint16_t cur, uint16_t mask) { - int i ; - - uint16_t retVal = (cur & mask) ; - uint16_t temp = 0x0000 ; - int offsetCount = 0 ; + uint16_t retVal = (cur & mask); + uint16_t temp = 0x0000; + int offsetCount = 0; /* Shift everything right, eliminating 'whitespace' */ - for (i = 0; i < 16; i++) + for (int i = 0; i < 16; i++) { - if (mask & (0x1<<i)) /* If mask bit is non-zero */ + if (BIT(mask, i)) /* If mask bit is non-zero */ { - temp |= (((retVal >> i) & 0x1) << offsetCount) ; - offsetCount++ ; + temp |= (BIT(retVal, i) << offsetCount); + offsetCount++; } } - return temp ; + return temp; } -static void SetDestinationValue(typed_pointer source, typed_pointer dest) +static uint64_t dsp56156_limit_long_to_long(dsp56156_core* /*cpustate*/, uint64_t val) { - uint64_t destinationValue = 0 ; + int32_t signed_upper = (int32_t)(val >> 8) >> 8; + if (signed_upper < -32768) + return 0x000000ff'80000000ULL; + else if (signed_upper > 32767) + return 0x00000000'7fff0000ULL; + return val & 0x000000ff'ffff0000ULL; +} + +static void dsp56156_set_destination_value(dsp56156_core* cpustate, typed_pointer source, typed_pointer dest) +{ + uint64_t destinationValue = 0; switch(dest.data_type) { @@ -4828,9 +5791,9 @@ static void SetDestinationValue(typed_pointer source, typed_pointer dest) case DT_BYTE: *((uint8_t*)dest.addr) = (*((uint8_t*) source.addr)) & 0xff; break; case DT_WORD: *((uint8_t*)dest.addr) = (*((uint16_t*)source.addr)) & 0x00ff; break; case DT_DOUBLE_WORD: *((uint8_t*)dest.addr) = (*((uint32_t*)source.addr)) & 0x000000ff; break; - case DT_LONG_WORD: *((uint8_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x00000000000000ffU; break; + case DT_LONG_WORD: *((uint8_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x00000000000000ffULL; break; } - break ; + break; /* Copying to a 16-bit value */ case DT_WORD: @@ -4839,9 +5802,15 @@ static void SetDestinationValue(typed_pointer source, typed_pointer dest) case DT_BYTE: *((uint16_t*)dest.addr) = (*((uint8_t*) source.addr)) & 0xff; break; case DT_WORD: *((uint16_t*)dest.addr) = (*((uint16_t*)source.addr)) & 0xffff; break; case DT_DOUBLE_WORD: *((uint16_t*)dest.addr) = (*((uint32_t*)source.addr)) & 0x0000ffff; break; - case DT_LONG_WORD: *((uint16_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x000000000000ffffU; break; /* TODO: Shift limiter action! A-147 */ + case DT_LONG_WORD: *((uint16_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x000000000000ffffULL; + /* TODO: Shift limiter action! A-147 */ + if (dest.addr == &A || dest.addr == &B) + { + LOGMASKED(LOG_CHECKS, "%04x: Double-check dsp56156_set_destination_value, writing A/B to a word.\n", cpustate->PCU.pc); + } + break; } - break ; + break; /* Copying to a 32-bit value */ case DT_DOUBLE_WORD: @@ -4850,9 +5819,9 @@ static void SetDestinationValue(typed_pointer source, typed_pointer dest) case DT_BYTE: *((uint32_t*)dest.addr) = (*((uint8_t*) source.addr)) & 0xff; break; case DT_WORD: *((uint32_t*)dest.addr) = (*((uint16_t*)source.addr)) & 0xffff; break; case DT_DOUBLE_WORD: *((uint32_t*)dest.addr) = (*((uint32_t*)source.addr)) & 0xffffffff; break; - case DT_LONG_WORD: *((uint32_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x00000000ffffffffU; break; + case DT_LONG_WORD: *((uint32_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x00000000'ffffffffULL; break; } - break ; + break; /* Copying to a 64-bit value */ case DT_LONG_WORD: @@ -4861,43 +5830,43 @@ static void SetDestinationValue(typed_pointer source, typed_pointer dest) case DT_BYTE: *((uint64_t*)dest.addr) = (*((uint8_t*)source.addr)) & 0xff; break; case DT_WORD: destinationValue = (*((uint16_t*)source.addr)) << 16; - if (destinationValue & 0x0000000080000000U) - destinationValue |= 0x000000ff00000000U; + if (destinationValue & 0x00000000'80000000ULL) + destinationValue |= 0x000000ff'00000000ULL; *((uint64_t*)dest.addr) = (uint64_t)destinationValue; break; /* Forget not, yon shift register */ case DT_DOUBLE_WORD: *((uint64_t*)dest.addr) = (*((uint32_t*)source.addr)) & 0xffffffff; break; - case DT_LONG_WORD: *((uint64_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x000000ffffffffffU; break; + case DT_LONG_WORD: *((uint64_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x000000ff'ffffffffULL; break; } - break ; + break; } } /* TODO: Wait-state timings! */ -static void SetDataMemoryValue(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr) +static void dsp56156_set_data_memory_value(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr) { switch(source.data_type) { - case DT_BYTE: cpustate->data->write_word(destinationAddr, (uint16_t)( (*((uint8_t*) source.addr) & 0xff) ) ) ; break ; - case DT_WORD: cpustate->data->write_word(destinationAddr, (uint16_t)( (*((uint16_t*)source.addr) & 0xffff) ) ) ; break ; - case DT_DOUBLE_WORD: cpustate->data->write_word(destinationAddr, (uint16_t)( (*((uint32_t*)source.addr) & 0x0000ffff) ) ) ; break ; + case DT_BYTE: cpustate->data.write_word(destinationAddr, (uint16_t)( (*((uint8_t*) source.addr) & 0xff))); break; + case DT_WORD: cpustate->data.write_word(destinationAddr, (uint16_t)( (*((uint16_t*)source.addr) & 0xffff))); break; + case DT_DOUBLE_WORD: cpustate->data.write_word(destinationAddr, (uint16_t)( (*((uint32_t*)source.addr) & 0x0000ffff))); break; /* !!! Is this universal ??? */ /* !!! Forget not, yon shift-limiter !!! */ - case DT_LONG_WORD: cpustate->data->write_word(destinationAddr, (uint16_t)( ((*((uint64_t*)source.addr)) & 0x00000000ffff0000U) >> 16) ) ; break ; + case DT_LONG_WORD: cpustate->data.write_word(destinationAddr, (uint16_t)(((*((uint64_t*)source.addr)) & 0x00000000'ffff0000ULL) >> 16)); break; } } /* TODO: Wait-state timings! */ -static void SetProgramMemoryValue(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr) +static void dsp56156_set_program_memory_value(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr) { switch(source.data_type) { - case DT_BYTE: cpustate->program->write_word(destinationAddr, (uint16_t)( (*((uint8_t*) source.addr) & 0xff) ) ) ; break ; - case DT_WORD: cpustate->program->write_word(destinationAddr, (uint16_t)( (*((uint16_t*)source.addr) & 0xffff) ) ) ; break ; - case DT_DOUBLE_WORD: cpustate->program->write_word(destinationAddr, (uint16_t)( (*((uint32_t*)source.addr) & 0x0000ffff) ) ) ; break ; + case DT_BYTE: cpustate->program.write_word(destinationAddr, (uint16_t)( (*((uint8_t*) source.addr) & 0xff))); break; + case DT_WORD: cpustate->program.write_word(destinationAddr, (uint16_t)( (*((uint16_t*)source.addr) & 0xffff))); break; + case DT_DOUBLE_WORD: cpustate->program.write_word(destinationAddr, (uint16_t)( (*((uint32_t*)source.addr) & 0x0000ffff))); break; /* !!! Is this universal ??? */ /* !!! Forget not, yon shift-limiter !!! */ - case DT_LONG_WORD: cpustate->program->write_word(destinationAddr, (uint16_t)( ((*((uint64_t*)source.addr)) & 0x00000000ffff0000U) >> 16) ) ; break ; + case DT_LONG_WORD: cpustate->program.write_word(destinationAddr, (uint16_t)(((*((uint64_t*)source.addr)) & 0x00000000'ffff0000ULL) >> 16)); break; } } |