// license:BSD-3-Clause // copyright-holders:Tony La Porta /**************************************************************************\ * Texas Instruments TMS32010 DSP Disassembler * * * * Copyright Tony La Porta * * To be used with TMS32010 DSP Emulator engine. * * You are not allowed to distribute this software commercially. * * Written for the MAME project. * * * * Many thanks to those involved in the i8039 Disassembler * * as this was based on it. * * * * * * * * A Memory address * * B Branch Address for Branch instructions (Requires next opcode read) * * D Immediate byte load * * K Immediate bit load * * W Immediate word load (Actually 13 bit) * * M AR[x] register modification type (for indirect addressing) * * N ARP register to change ARP pointer to (for indirect addressing) * * P I/O port address number * * R AR[R] register to use * * S Shift ALU left * * * \**************************************************************************/ #include "emu.h" #include "debugger.h" #include #include "tms32010.h" typedef unsigned char byte; typedef unsigned short int word; #define FMT(a,b) a, b #define PTRS_PER_FORMAT 2 static const char *const arith[4] = { "*" , "*-" , "*+" , "??" } ; static const char *const nextar[4] = { ",AR0" , ",AR1" , "" , "" } ; static const char *const TMS32010Formats[] = { FMT("0000ssss0aaaaaaa", "add %A%S"), FMT("0000ssss10mmn00n", "add %M%S%N"), FMT("0001ssss0aaaaaaa", "sub %A%S"), FMT("0001ssss10mmn00n", "sub %M%S%N"), FMT("0010ssss0aaaaaaa", "lac %A%S"), FMT("0010ssss10mmn00n", "lac %M%S%N"), FMT("0011000r0aaaaaaa", "sar %R,%A"), FMT("0011000r10mmn00n", "sar %R%M%N"), FMT("0011100r0aaaaaaa", "lar %R,%A"), FMT("0011100r10mmn00n", "lar %R%M%N"), FMT("01000ppp0aaaaaaa", "in %A,%P"), FMT("01000ppp10mmn00n", "in %M,%P%N"), FMT("01001ppp0aaaaaaa", "out %A,%P"), FMT("01001ppp10mmn00n", "out %M,%P%N"), FMT("01010sss0aaaaaaa", "sacl %A"), /* This instruction has a shift but */ FMT("01010sss10mmn00n", "sacl %M%N"), /* is documented as not performed */ FMT("01011sss0aaaaaaa", "sach %A%S"), FMT("01011sss10mmn00n", "sach %M%S%N"), FMT("011000000aaaaaaa", "addh %A"), FMT("0110000010mmn00n", "addh %M%N"), FMT("011000010aaaaaaa", "adds %A"), FMT("0110000110mmn00n", "adds %M%N"), FMT("011000100aaaaaaa", "subh %A"), FMT("0110001010mmn00n", "subh %M%N"), FMT("011000110aaaaaaa", "subs %A"), FMT("0110001110mmn00n", "subs %M%N"), FMT("011001000aaaaaaa", "subc %A"), FMT("0110010010mmn00n", "subc %M%N"), FMT("011001010aaaaaaa", "zalh %A"), FMT("0110010110mmn00n", "zalh %M%N"), FMT("011001100aaaaaaa", "zals %A"), FMT("0110011010mmn00n", "zals %M%N"), FMT("011001110aaaaaaa", "tblr %A"), FMT("0110011110mmn00n", "tblr %M%N"), FMT("011010001000000k", "larp %K"), FMT("011010000aaaaaaa", "mar %A"), /* Actually this is executed as a NOP */ /* FMT("0110100010mmn00n", "mar %M%N"), */ /* MAR indirect has been expanded out to all its variations because one of */ /* its opcodes is the same as LARP (actually performs the same function) */ FMT("0110100010001000", "mar *"), FMT("0110100010001001", "mar *"), FMT("0110100010010000", "mar *-,AR0"), FMT("0110100010010001", "mar *-,AR1"), FMT("0110100010011000", "mar *-"), FMT("0110100010011001", "mar *-"), FMT("0110100010100000", "mar *+,AR0"), FMT("0110100010100001", "mar *+,AR1"), FMT("0110100010101000", "mar *+"), FMT("0110100010101001", "mar *+"), FMT("0110100010110000", "mar ??,AR0"), FMT("0110100010110001", "mar ??,AR1"), FMT("0110100010111000", "mar ??"), FMT("0110100010111001", "mar ??"), FMT("011010010aaaaaaa", "dmov %A"), FMT("0110100110mmn00n", "dmov %M%N"), FMT("011010100aaaaaaa", "lt %A"), FMT("0110101010mmn00n", "lt %M%N"), FMT("011010110aaaaaaa", "ltd %A"), FMT("0110101110mmn00n", "ltd %M%N"), FMT("011011000aaaaaaa", "lta %A"), FMT("0110110010mmn00n", "lta %M%N"), FMT("011011010aaaaaaa", "mpy %A"), FMT("0110110110mmn00n", "mpy %M%N"), FMT("011011100000000k", "ldpk %K"), FMT("011011110aaaaaaa", "ldp %A"), FMT("0110111110mmn00n", "ldp %M%N"), FMT("0111000rdddddddd", "lark %R,%D"), FMT("011110000aaaaaaa", "xor %A"), FMT("0111100010mmn00n", "xor %M%N"), FMT("011110010aaaaaaa", "and %A"), FMT("0111100110mmn00n", "and %M%N"), FMT("011110100aaaaaaa", "or %A"), FMT("0111101010mmn00n", "or %M%N"), FMT("011110110aaaaaaa", "lst %A"), FMT("0111101110mmn00n", "lst %M%N"), FMT("011111000aaaaaaa", "sst %A"), FMT("0111110010mmn00n", "sst %M%N"), FMT("011111010aaaaaaa", "tblw %A"), FMT("0111110110mmn00n", "tblw %M%N"), FMT("01111110dddddddd", "lack %D"), FMT("0111111110000000", "nop"), /* 7F80 */ FMT("0111111110000001", "dint"), FMT("0111111110000010", "eint"), FMT("0111111110001000", "abs"), /* 7F88 */ FMT("0111111110001001", "zac"), FMT("0111111110001010", "rovm"), FMT("0111111110001011", "sovm"), FMT("0111111110001100", "cala"), FMT("0111111110001101", "ret"), FMT("0111111110001110", "pac"), FMT("0111111110001111", "apac"), FMT("0111111110010000", "spac"), FMT("0111111110011100", "push"), FMT("0111111110011101", "pop"), /* 7F9D */ FMT("100wwwwwwwwwwwww", "mpyk %W"), FMT("1111010000000000bbbbbbbbbbbbbbbb", "banz %B"), FMT("1111010100000000bbbbbbbbbbbbbbbb", "bv %B"), FMT("1111011000000000bbbbbbbbbbbbbbbb", "bioz %B"), FMT("1111100000000000bbbbbbbbbbbbbbbb", "call %B"), FMT("1111100100000000bbbbbbbbbbbbbbbb", "b %B"), FMT("1111101000000000bbbbbbbbbbbbbbbb", "blz %B"), FMT("1111101100000000bbbbbbbbbbbbbbbb", "blez %B"), FMT("1111110000000000bbbbbbbbbbbbbbbb", "bgz %B"), FMT("1111110100000000bbbbbbbbbbbbbbbb", "bgez %B"), FMT("1111111000000000bbbbbbbbbbbbbbbb", "bnz %B"), FMT("1111111100000000bbbbbbbbbbbbbbbb", "bz %B"), nullptr }; #define MAX_OPS ((ARRAY_LENGTH(TMS32010Formats) - 1) / PTRS_PER_FORMAT) struct TMS32010Opcode { word mask; /* instruction mask */ word bits; /* constant bits */ word extcode; /* value that gets extension code */ const char *parse; /* how to parse bits */ const char *fmt; /* instruction format */ }; static TMS32010Opcode Op[MAX_OPS+1]; static int OpInizialized = 0; static void InitDasm32010(void) { const char *p; const char *const *ops; word mask, bits; int bit; int i; ops = TMS32010Formats; i = 0; while (*ops) { p = *ops; mask = 0; bits = 0; bit = 15; while (*p && bit >= 0) { switch (*p++) { case '1': mask |= 1<= 0) { /* osd_printf_debug("{%c/%d}",*cp,bit); */ switch(*cp) { case 'a': a <<=1; a |= ((code & (1<