| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | /*====================================================================
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    filename:     disassemble.cpp | 
					
						
							|  |  |  |    project:      GameCube DSP Tool (gcdsp) | 
					
						
							|  |  |  |    created:      2005.03.04 | 
					
						
							|  |  |  |    mail:		  duddie@walla.com | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Copyright (c) 2005 Duddie | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |    modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |    as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |    of the License, or (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |    GNU General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |    along with this program; if not, write to the Free Software | 
					
						
							|  |  |  |    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    ====================================================================*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-12 10:21:40 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-12 21:58:32 +00:00
										 |  |  | #include "Common.h"
 | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | #include "FileUtil.h"
 | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | #include "disassemble.h"
 | 
					
						
							| 
									
										
										
										
											2009-04-01 20:22:43 +00:00
										 |  |  | #include "DSPTables.h"
 | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef _MSC_VER
 | 
					
						
							|  |  |  | #pragma warning(disable:4996)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-12 21:58:32 +00:00
										 |  |  | #ifndef MAX_PATH
 | 
					
						
							|  |  |  | #include <Windows.h> // For MAX_PATH
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | extern void nop(const UDSPInstruction opc); | 
					
						
							| 
									
										
										
										
											2009-04-05 15:46:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | DSPDisassembler::DSPDisassembler(const AssemblerSettings &settings) | 
					
						
							|  |  |  | 	: settings_(settings) | 
					
						
							| 
									
										
										
										
											2009-04-12 14:48:55 +00:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | DSPDisassembler::~DSPDisassembler() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// Some old code for logging unknown ops.
 | 
					
						
							|  |  |  | 	char filename[MAX_PATH]; | 
					
						
							| 
									
										
										
										
											2010-02-02 21:56:29 +00:00
										 |  |  | 	sprintf(filename, "%sUnkOps.txt", File::GetUserPath(D_DUMPDSP_IDX)); | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 	FILE *uo = fopen(filename, "w"); | 
					
						
							|  |  |  | 	if (!uo) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int count = 0; | 
					
						
							|  |  |  | 	for (std::map<u16, int>::const_iterator iter = unk_opcodes.begin(); | 
					
						
							|  |  |  | 		iter != unk_opcodes.end(); ++iter) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (iter->second > 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			count++; | 
					
						
							|  |  |  | 			fprintf(uo, "OP%04x\t%d", iter->first, iter->second); | 
					
						
							|  |  |  | 			for (int j = 15; j >= 0; j--)  // print op bits
 | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if ((j & 0x3) == 3) | 
					
						
							|  |  |  | 					fprintf(uo, "\tb"); | 
					
						
							|  |  |  | 				fprintf(uo, "%d", (iter->first >> j) & 0x1); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			fprintf(uo, "\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	fprintf(uo, "Unknown opcodes count: %d\n", count); | 
					
						
							|  |  |  | 	fclose(uo); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-07 11:06:40 +00:00
										 |  |  | bool DSPDisassembler::Disassemble(int start_pc, const std::vector<u16> &code, int base_addr, std::string &text) | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	const char *tmp1 = "tmp1.bin"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// First we have to dump the code to a bin file.
 | 
					
						
							|  |  |  | 	FILE *f = fopen(tmp1, "wb"); | 
					
						
							|  |  |  | 	fwrite(&code[0], 1, code.size() * 2, f); | 
					
						
							|  |  |  | 	fclose(f); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 	// Run the two passes.
 | 
					
						
							| 
									
										
										
										
											2009-06-21 08:39:21 +00:00
										 |  |  | 	return DisFile(tmp1, base_addr, 1, text) && DisFile(tmp1, base_addr, 2, text); | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char *DSPDisassembler::DisParams(const DSPOPCTemplate& opc, u16 op1, u16 op2, char *strbuf) | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 	char *buf = strbuf; | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 	for (int j = 0; j < opc.param_count; j++) | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		if (j > 0) | 
					
						
							| 
									
										
										
										
											2009-04-12 13:43:12 +00:00
										 |  |  | 			buf += sprintf(buf, ", "); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-21 18:55:00 +00:00
										 |  |  | 		u32 val = (opc.params[j].loc >= 1) ? op2 : op1; | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 		val &= opc.params[j].mask; | 
					
						
							|  |  |  | 		if (opc.params[j].lshift < 0) | 
					
						
							|  |  |  | 			val = val << (-opc.params[j].lshift); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 			val = val >> opc.params[j].lshift; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 		u32 type = opc.params[j].type; | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 		if ((type & 0xff) == 0x10) | 
					
						
							|  |  |  | 			type &= 0xff00; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 		if (type & P_REG) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 			// Check for _D parameter - if so flip.
 | 
					
						
							| 
									
										
										
										
											2009-12-08 22:44:11 +00:00
										 |  |  | 			if ((type == P_ACC_D) || (type == P_ACCM_D))  // Used to be P_ACCM_D TODO verify
 | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 				val = (~val & 0x1) | ((type & P_REGS_MASK) >> 8); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				val |= (type & P_REGS_MASK) >> 8; | 
					
						
							|  |  |  | 			type &= ~P_REGS_MASK; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch (type) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 		case P_REG: | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 			if (settings_.decode_registers) | 
					
						
							| 
									
										
										
										
											2009-04-12 10:21:40 +00:00
										 |  |  | 				sprintf(buf, "$%s", pdregname(val)); | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 			else | 
					
						
							|  |  |  | 				sprintf(buf, "$%d", val); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 		case P_PRG: | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 			if (settings_.decode_registers) | 
					
						
							| 
									
										
										
										
											2009-04-12 10:21:40 +00:00
										 |  |  | 				sprintf(buf, "@$%s", pdregname(val)); | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 			else | 
					
						
							|  |  |  | 				sprintf(buf, "@$%d", val); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 		case P_VAL: | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 		case P_ADDR_I: | 
					
						
							|  |  |  | 		case P_ADDR_D: | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 			if (settings_.decode_names) | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 				sprintf(buf, "%s", pdname(val)); | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 			else | 
					
						
							|  |  |  | 				sprintf(buf, "0x%04x", val); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 		case P_IMM: | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 			if (opc.params[j].size != 2) | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 				if (opc.params[j].mask == 0x003f) // LSL, LSR, ASL, ASR
 | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 					sprintf(buf, "#%d", (val & 0x20) ? (val | 0xFFFFFFC0) : val);  // 6-bit sign extension
 | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 				else | 
					
						
							|  |  |  | 					sprintf(buf, "#0x%02x", val); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 				sprintf(buf, "#0x%04x", val); | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 		case P_MEM: | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 			if (opc.params[j].size != 2) | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 				val = (u16)(s16)(s8)val; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 			if (settings_.decode_names) | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 				sprintf(buf, "@%s", pdname(val)); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				sprintf(buf, "@0x%04x", val); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 			ERROR_LOG(DSPLLE, "Unknown parameter type: %x", opc.params[j].type); | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		buf += strlen(buf); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 	return strbuf; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | static void MakeLowerCase(char *ptr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i = 0; | 
					
						
							|  |  |  | 	while (ptr[i]) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ptr[i] = tolower(ptr[i]); | 
					
						
							|  |  |  | 		i++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-21 08:39:21 +00:00
										 |  |  | bool DSPDisassembler::DisOpcode(const u16 *binbuf, int base_addr, int pass, u16 *pc, std::string &dest) | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 	char buffer[256]; | 
					
						
							|  |  |  | 	char *buf = buffer; | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Start with 8 spaces, if there's no label.
 | 
					
						
							| 
									
										
										
										
											2009-04-12 10:21:40 +00:00
										 |  |  | 	buf[0] = ' '; | 
					
						
							|  |  |  | 	buf[1] = '\0'; | 
					
						
							|  |  |  | 	buf++; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 	if ((*pc & 0x7fff) >= 0x1000) | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 		*pc++; | 
					
						
							| 
									
										
										
										
											2009-04-25 10:38:26 +00:00
										 |  |  | 		dest.append("; outside memory"); | 
					
						
							| 
									
										
										
										
											2009-06-21 08:39:21 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-21 08:39:21 +00:00
										 |  |  | 	const u32 op1 = binbuf[*pc & 0x0fff]; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-12 10:21:40 +00:00
										 |  |  | 	const DSPOPCTemplate *opc = NULL; | 
					
						
							|  |  |  | 	const DSPOPCTemplate *opc_ext = NULL; | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	// find opcode
 | 
					
						
							| 
									
										
										
										
											2009-04-12 10:21:40 +00:00
										 |  |  | 	for (int j = 0; j < opcodes_size; j++) | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-06 13:28:03 +00:00
										 |  |  | 		u16 mask = opcodes[j].opcode_mask; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if ((op1 & mask) == opcodes[j].opcode) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			opc = &opcodes[j]; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-04-07 15:04:45 +00:00
										 |  |  | 	const DSPOPCTemplate fake_op = {"CW",		0x0000, 0x0000, nop, NULL, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, false}; | 
					
						
							| 
									
										
										
										
											2009-04-05 15:46:47 +00:00
										 |  |  | 	if (!opc) | 
					
						
							|  |  |  | 		opc = &fake_op; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-06 13:28:03 +00:00
										 |  |  | 	bool extended = false; | 
					
						
							|  |  |  | 	bool only7bitext = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (((opc->opcode >> 12) == 0x3) && (op1 & 0x007f)) { | 
					
						
							|  |  |  | 		extended = true; | 
					
						
							|  |  |  | 		only7bitext = true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (((opc->opcode >> 12) > 0x3) && (op1 & 0x00ff)) | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 		extended = true; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		extended = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (extended) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// opcode has an extension
 | 
					
						
							|  |  |  | 		// find opcode
 | 
					
						
							| 
									
										
										
										
											2009-04-12 10:21:40 +00:00
										 |  |  | 		for (int j = 0; j < opcodes_ext_size; j++) | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-11-06 13:28:03 +00:00
										 |  |  | 			if (only7bitext) { | 
					
						
							|  |  |  | 				if (((op1 & 0x7f) & opcodes_ext[j].opcode_mask) == opcodes_ext[j].opcode) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					opc_ext = &opcodes_ext[j]; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				if ((op1 & opcodes_ext[j].opcode_mask) == opcodes_ext[j].opcode) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					opc_ext = &opcodes_ext[j]; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// printing
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 	if (settings_.show_pc) | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 		buf += sprintf(buf, "%04x ", *pc); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 	u32 op2; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 	// Size 2 - the op has a large immediate.
 | 
					
						
							| 
									
										
										
										
											2010-03-22 16:32:48 +00:00
										 |  |  | 	if (opc->size == 2) | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-06-21 08:39:21 +00:00
										 |  |  | 		op2 = binbuf[(*pc + 1) & 0x0fff]; | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 		if (settings_.show_hex) | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 			buf += sprintf(buf, "%04x %04x ", op1, op2); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		op2 = 0; | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 		if (settings_.show_hex) | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 			buf += sprintf(buf, "%04x      ", op1); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 	char opname[20]; | 
					
						
							|  |  |  | 	strcpy(opname, opc->name); | 
					
						
							|  |  |  | 	if (settings_.lower_case_ops) | 
					
						
							|  |  |  | 		MakeLowerCase(opname); | 
					
						
							|  |  |  | 	char ext_buf[20]; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	if (extended) | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 		sprintf(ext_buf, "%s%c%s", opname, settings_.ext_separator, opc_ext->name); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 		sprintf(ext_buf, "%s", opname); | 
					
						
							|  |  |  | 	if (settings_.lower_case_ops) | 
					
						
							|  |  |  | 		MakeLowerCase(ext_buf); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 	if (settings_.print_tabs) | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 		buf += sprintf(buf, "%s\t", ext_buf); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 		buf += sprintf(buf, "%-12s", ext_buf); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (opc->param_count > 0) | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 		DisParams(*opc, op1, op2, buf); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	buf += strlen(buf); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 	// Handle opcode extension.
 | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	if (extended) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (opc->param_count > 0) | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 			buf += sprintf(buf, " "); | 
					
						
							|  |  |  | 		buf += sprintf(buf, ": "); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 		if (opc_ext->param_count > 0) | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 			DisParams(*opc_ext, op1, op2, buf); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		buf += strlen(buf); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (opc->opcode_mask == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// unknown opcode
 | 
					
						
							|  |  |  | 		unk_opcodes[op1]++; | 
					
						
							|  |  |  | 		sprintf(buf, "\t\t; *** UNKNOWN OPCODE ***"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (extended) | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 		*pc += opc_ext->size; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2010-03-22 16:32:48 +00:00
										 |  |  | 		*pc += opc->size; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 	if (pass == 2) | 
					
						
							| 
									
										
										
										
											2009-04-25 10:38:26 +00:00
										 |  |  | 		dest.append(buffer); | 
					
						
							| 
									
										
										
										
											2009-06-21 08:39:21 +00:00
										 |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-21 08:39:21 +00:00
										 |  |  | bool DSPDisassembler::DisFile(const char* name, int base_addr, int pass, std::string &output) | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 	FILE* in = fopen(name, "rb"); | 
					
						
							|  |  |  | 	if (in == NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-04-12 10:21:40 +00:00
										 |  |  | 		printf("gd_dis_file: No input\n"); | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2009-04-12 10:21:40 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	fseek(in, 0, SEEK_END); | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 	int size = (int)ftell(in) & ~1; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	fseek(in, 0, SEEK_SET); | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 	u16 *binbuf = new u16[size / 2]; | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 	fread(binbuf, 1, size, in); | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 	fclose(in); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 	// Actually do the disassembly.
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 	for (u16 pc = 0; pc < (size / 2);) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-06-21 08:39:21 +00:00
										 |  |  | 		DisOpcode(binbuf, base_addr, pass, &pc, output); | 
					
						
							| 
									
										
										
										
											2009-04-18 11:31:37 +00:00
										 |  |  | 		if (pass == 2) | 
					
						
							| 
									
										
										
										
											2009-04-25 10:38:26 +00:00
										 |  |  | 			output.append("\n"); | 
					
						
							| 
									
										
										
										
											2009-04-14 20:44:03 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-04-14 22:30:31 +00:00
										 |  |  | 	delete [] binbuf; | 
					
						
							| 
									
										
										
										
											2009-04-03 06:21:45 +00:00
										 |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | } |