DSP assembler: Error message improvements.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2956 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
e8b9e93465
commit
f6474b98a8
|
@ -601,13 +601,13 @@ const char *GetUserDirectory()
|
|||
return path;
|
||||
}
|
||||
|
||||
bool WriteStringToFile(bool text_file, const char *str, const char *filename)
|
||||
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename)
|
||||
{
|
||||
FILE *f = fopen(filename, text_file ? "w" : "wb");
|
||||
if (!f)
|
||||
return false;
|
||||
size_t len = strlen(str);
|
||||
if (len != fwrite(str, 1, strlen(str), f))
|
||||
size_t len = str.size();
|
||||
if (len != fwrite(str.data(), 1, str.size(), f))
|
||||
{
|
||||
fclose(f);
|
||||
return false;
|
||||
|
@ -616,7 +616,7 @@ bool WriteStringToFile(bool text_file, const char *str, const char *filename)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ReadStringFromFile(bool text_file, const char *filename, std::string *str)
|
||||
bool ReadFileToString(bool text_file, const char *filename, std::string *str)
|
||||
{
|
||||
FILE *f = fopen(filename, text_file ? "r" : "rb");
|
||||
if (!f)
|
||||
|
|
|
@ -99,8 +99,8 @@ char *GetConfigDirectory();
|
|||
std::string GetBundleDirectory();
|
||||
#endif
|
||||
|
||||
bool WriteStringToFile(bool text_file, const char *str, const char *filename);
|
||||
bool ReadStringFromFile(bool text_file, const char *filename, std::string *str);
|
||||
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename);
|
||||
bool ReadFileToString(bool text_file, const char *filename, std::string *str);
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
|
@ -82,12 +82,11 @@
|
|||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
|
@ -103,15 +102,16 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\Common\Src"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
|
@ -145,11 +145,12 @@
|
|||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
|
@ -165,16 +166,15 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories="..\Common\Src"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
|
@ -426,6 +426,14 @@
|
|||
RelativePath=".\Src\DSPAnalyzer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\DSPCodeUtil.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\DSPCodeUtil.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\DSPHost.h"
|
||||
>
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
#include "DSPCodeUtil.h"
|
||||
#include "assemble.h"
|
||||
#include "disassemble.h"
|
||||
|
||||
|
||||
bool Assemble(const char *text, std::vector<u16> *code)
|
||||
{
|
||||
const char *fname = "tmp.asm";
|
||||
gd_globals_t gdg;
|
||||
memset(&gdg, 0, sizeof(gdg));
|
||||
gdg.pc = 0;
|
||||
// gdg.decode_registers = false;
|
||||
// gdg.decode_names = false;
|
||||
gdg.print_tabs = false;
|
||||
gdg.ext_separator = '\'';
|
||||
gdg.buffer = 0;
|
||||
|
||||
if (!File::WriteStringToFile(true, text, fname))
|
||||
return false;
|
||||
|
||||
// TODO: fix the terrible api of the assembler.
|
||||
gd_ass_init_pass(1);
|
||||
if (!gd_ass_file(&gdg, fname, 1))
|
||||
return false;
|
||||
gd_ass_init_pass(2);
|
||||
if (!gd_ass_file(&gdg, fname, 2))
|
||||
return false;
|
||||
|
||||
code->resize(gdg.buffer_size);
|
||||
for (int i = 0; i < gdg.buffer_size; i++) {
|
||||
(*code)[i] = *(u16 *)(gdg.buffer + i * 2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Disassemble(const std::vector<u16> &code, std::string *text)
|
||||
{
|
||||
if (code.empty())
|
||||
return false;
|
||||
const char *tmp1 = "tmp1.bin";
|
||||
const char *tmp2 = "tmp.txt";
|
||||
|
||||
// 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);
|
||||
|
||||
FILE* t = fopen(tmp2, "w");
|
||||
if (t != NULL)
|
||||
{
|
||||
gd_globals_t gdg;
|
||||
memset(&gdg, 0, sizeof(gdg));
|
||||
|
||||
// These two prevent roundtripping.
|
||||
gdg.show_hex = false;
|
||||
gdg.show_pc = false;
|
||||
gdg.ext_separator = '\'';
|
||||
gdg.decode_names = false;
|
||||
gdg.decode_registers = true;
|
||||
bool success = gd_dis_file(&gdg, tmp1, t);
|
||||
fclose(t);
|
||||
|
||||
File::ReadFileToString(true, tmp2, text);
|
||||
return success;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
|
||||
{
|
||||
if (code1.size() != code2.size())
|
||||
printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
|
||||
int count_equal = 0;
|
||||
const int min_size = std::min(code1.size(), code2.size());
|
||||
for (int i = 0; i < min_size; i++)
|
||||
{
|
||||
if (code1[i] == code2[i])
|
||||
count_equal++;
|
||||
else
|
||||
printf("!! %04x : %04x vs %04x\n", i, code1[i], code2[i]);
|
||||
}
|
||||
printf("Equal instruction words: %i / %i\n", count_equal, min_size);
|
||||
}
|
||||
|
||||
void GenRandomCode(int size, std::vector<u16> *code)
|
||||
{
|
||||
code->resize(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
(*code)[i] = rand() ^ (rand() << 8);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeToHeader(std::vector<u16> *code, const char *name, std::string *header)
|
||||
{
|
||||
char buffer[1024];
|
||||
header->clear();
|
||||
header->reserve(code->size() * 4);
|
||||
header->append("#ifndef _MSCVER\n");
|
||||
sprintf(buffer, "const __declspec(align:64) unsigned short %s = {\n");
|
||||
header->append(buffer);
|
||||
header->append("#else\n");
|
||||
sprintf(buffer, "const unsigned short %s __attribute__(aligned:64) = {\n");
|
||||
header->append(buffer);
|
||||
header->append("#endif\n\n ");
|
||||
for (int i = 0; i < code->size(); i++)
|
||||
{
|
||||
if (((i + 1) & 15) == 0)
|
||||
header->append("\n ");
|
||||
sprintf(buffer, "%02x, ", code[i]);
|
||||
header->append(buffer);
|
||||
}
|
||||
header->append("\n};\n");
|
||||
}
|
||||
|
||||
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string *str)
|
||||
{
|
||||
str->resize(code.size() * 2);
|
||||
for (int i = 0; i < code.size(); i++)
|
||||
{
|
||||
(*str)[i * 2 + 0] = code[i] >> 8;
|
||||
(*str)[i * 2 + 1] = code[i] & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryStringBEToCode(const std::string &str, std::vector<u16> *code)
|
||||
{
|
||||
code->resize(str.size() / 2);
|
||||
for (int i = 0; i < code->size(); i++)
|
||||
{
|
||||
(*code)[i] = (str[i * 2 + 0] << 8) | (str[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
bool LoadBinary(const char *filename, std::vector<u16> *code)
|
||||
{
|
||||
std::string buffer;
|
||||
if (!File::ReadFileToString(false, filename, &buffer))
|
||||
return false;
|
||||
BinaryStringBEToCode(buffer, code);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SaveBinary(const std::vector<u16> &code, const char *filename)
|
||||
{
|
||||
std::string buffer;
|
||||
CodeToBinaryStringBE(code, &buffer);
|
||||
if (!File::WriteStringToFile(false, buffer, filename))
|
||||
return false;
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DSPCODEUTIL_H
|
||||
#define _DSPCODEUTIL_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
bool Assemble(const char *text, std::vector<u16> *code);
|
||||
bool Disassemble(const std::vector<u16> &code, std::string *text);
|
||||
void Compare(const std::vector<u16> &code1, const std::vector<u16> &code2);
|
||||
void GenRandomCode(int size, std::vector<u16> *code);
|
||||
void CodeToHeader(std::vector<u16> *code, const char *name, std::string *header);
|
||||
|
||||
// Big-endian, for writing straight to file using File::WriteStringToFile.
|
||||
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string *str);
|
||||
void BinaryStringBEToCode(const std::string &str, std::vector<u16> *code);
|
||||
|
||||
// Load code (big endian binary).
|
||||
bool LoadBinary(const char *filename, std::vector<u16> *code);
|
||||
bool SaveBinary(const std::vector<u16> &code, const char *filename);
|
||||
|
||||
#endif // _DSPCODEUTIL_H
|
|
@ -82,7 +82,8 @@ typedef struct fass_t
|
|||
label_t labels[10000];
|
||||
int labels_count = 0;
|
||||
|
||||
segment_t cur_segment;
|
||||
char cur_line[4096];
|
||||
|
||||
u32 cur_addr;
|
||||
u8 cur_pass;
|
||||
fass_t *cur_fa;
|
||||
|
@ -90,6 +91,7 @@ fass_t *cur_fa;
|
|||
typedef std::map<std::string, std::string> AliasMap;
|
||||
AliasMap aliases;
|
||||
|
||||
segment_t cur_segment;
|
||||
u32 segment_addr[SEGMENT_MAX];
|
||||
|
||||
int current_param = 0;
|
||||
|
@ -150,6 +152,7 @@ char *err_string[] =
|
|||
|
||||
void parse_error(err_t err_code, fass_t *fa, const char *extra_info = NULL)
|
||||
{
|
||||
fprintf(stderr, "%i : %s\n", fa->code_line, cur_line);
|
||||
fa->failed = true;
|
||||
if (!extra_info)
|
||||
extra_info = "-";
|
||||
|
@ -208,6 +211,11 @@ s32 strtoval(const char *str)
|
|||
const char *ptr = str;
|
||||
|
||||
if (ptr[0] == '#')
|
||||
{
|
||||
ptr++;
|
||||
negative = true; // Wow! Double # (needed one to get in here) ]negates???
|
||||
}
|
||||
if (ptr[0] == '-')
|
||||
{
|
||||
ptr++;
|
||||
negative = true; // Wow! # negates???
|
||||
|
@ -232,7 +240,7 @@ s32 strtoval(const char *str)
|
|||
case 'X': // hex
|
||||
for (int i = 2 ; ptr[i] != 0 ; i++)
|
||||
{
|
||||
val *=16;
|
||||
val <<= 4;
|
||||
if (ptr[i] >= 'a' && ptr[i] <= 'f')
|
||||
val += (ptr[i]-'a'+10);
|
||||
else if (ptr[i] >= 'A' && ptr[i] <= 'F')
|
||||
|
@ -331,7 +339,7 @@ char *find_brackets(char *src, char *dst)
|
|||
}
|
||||
else
|
||||
{
|
||||
if(first >= 0)
|
||||
if (first >= 0)
|
||||
dst[j++] = src[i];
|
||||
}
|
||||
}
|
||||
|
@ -529,7 +537,7 @@ const opc_t *find_opcode(const char *opcode, u32 par_count, const opc_t * const
|
|||
}
|
||||
|
||||
// weird...
|
||||
u16 get_mask(u16 mask)
|
||||
u16 get_mask_shifted_down(u16 mask)
|
||||
{
|
||||
while (!(mask & 1))
|
||||
mask >>= 1;
|
||||
|
@ -556,7 +564,7 @@ bool verify_params(const opc_t *opc, param_t *par, u32 count, fass_t *fa)
|
|||
//case P_REG1C:
|
||||
value = (opc->params[i].type >> 8) & 31;
|
||||
if ((int)par[i].val < value ||
|
||||
(int)par[i].val > value + get_mask(opc->params[i].mask))
|
||||
(int)par[i].val > value + get_mask_shifted_down(opc->params[i].mask))
|
||||
{
|
||||
parse_error(ERR_INVALID_REGISTER, fa);
|
||||
}
|
||||
|
@ -638,10 +646,10 @@ bool verify_params(const opc_t *opc, param_t *par, u32 count, fass_t *fa)
|
|||
else if ((opc->params[i].type & 3) != 0 && (par[i].type & 3) != 0)
|
||||
{
|
||||
// modified by Hermes: test NUMBER range
|
||||
value = get_mask(opc->params[i].mask);
|
||||
value = get_mask_shifted_down(opc->params[i].mask);
|
||||
|
||||
valueu = 0xffff & ~(value >> 1);
|
||||
if((int)par[i].val < 0)
|
||||
if ((int)par[i].val < 0)
|
||||
{
|
||||
if (value == 7) // value 7 por sbclr/sbset
|
||||
{
|
||||
|
@ -657,12 +665,14 @@ bool verify_params(const opc_t *opc, param_t *par, u32 count, fass_t *fa)
|
|||
|
||||
parse_error(ERR_OUT_RANGE_NUMBER, fa);
|
||||
}
|
||||
else if ((int)par[i].val < -((value>>1)+1))
|
||||
else if ((int)par[i].val < -((value >> 1) + 1))
|
||||
{
|
||||
if (value < 128)
|
||||
fprintf(stderr,"Value must be from -0x%x to 0x%x\n",((value>>1)+1), ((value>>1)));
|
||||
fprintf(stderr, "Value must be from -0x%x to 0x%x, is %i\n",
|
||||
(value >> 1) + 1, value >> 1, par[i].val);
|
||||
else
|
||||
fprintf(stderr,"Value must be from -0x%x to 0x%x or 0x0 to 0x%x\n",((value>>1)+1), ((value>>1)),value);
|
||||
fprintf(stderr, "Value must be from -0x%x to 0x%x or 0x0 to 0x%x, is %i\n",
|
||||
(value >> 1) + 1, value >> 1, value, par[i].val);
|
||||
|
||||
parse_error(ERR_OUT_RANGE_NUMBER, fa);
|
||||
}
|
||||
|
@ -673,7 +683,7 @@ bool verify_params(const opc_t *opc, param_t *par, u32 count, fass_t *fa)
|
|||
{
|
||||
if (par[i].val > (unsigned)value)
|
||||
{
|
||||
fprintf(stderr,"Value must be from 0x%x to 0x%x\n",valueu, value);
|
||||
fprintf(stderr,"Value must be from 0x%x to 0x%x, is %i\n",valueu, value, par[i].val);
|
||||
parse_error(ERR_OUT_RANGE_NUMBER, fa);
|
||||
}
|
||||
}
|
||||
|
@ -685,7 +695,7 @@ bool verify_params(const opc_t *opc, param_t *par, u32 count, fass_t *fa)
|
|||
(par[i].val < valueu || par[i].val > (unsigned)0xffff))
|
||||
{
|
||||
if (value < 256)
|
||||
fprintf(stderr,"Address value must be from 0x%x to 0x%x\n", valueu, value);
|
||||
fprintf(stderr,"Address value must be from 0x%x to 0x%x, is %04x\n", valueu, value, par[i].val);
|
||||
else
|
||||
fprintf(stderr,"Address value must be minor of 0x%x\n", value+1);
|
||||
parse_error(ERR_OUT_RANGE_NUMBER, fa);
|
||||
|
@ -698,9 +708,9 @@ bool verify_params(const opc_t *opc, param_t *par, u32 count, fass_t *fa)
|
|||
if (par[i].val > (unsigned)value)
|
||||
{
|
||||
if (value < 64)
|
||||
fprintf(stderr,"Value must be from -0x%x to 0x%x\n", (value + 1), value);
|
||||
fprintf(stderr,"Value must be from -0x%x to 0x%x, is %i\n", (value + 1), value, par[i].val);
|
||||
else
|
||||
fprintf(stderr,"Value must be minor of 0x%x\n", value + 1);
|
||||
fprintf(stderr,"Value must be minor of 0x%x, is %i\n", value + 1, par[i].val);
|
||||
parse_error(ERR_OUT_RANGE_NUMBER, fa);
|
||||
}
|
||||
}
|
||||
|
@ -719,6 +729,7 @@ void build_code(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf)
|
|||
outbuf[cur_addr] |= opc->opcode;
|
||||
for (u32 i = 0; i < par_count; i++)
|
||||
{
|
||||
// Ignore the "reverse" parameters since they are implicit.
|
||||
if (opc->params[i].type != P_ACC_D && opc->params[i].type != P_ACCM_D)
|
||||
{
|
||||
u16 t16 = outbuf[cur_addr + opc->params[i].loc];
|
||||
|
@ -790,6 +801,7 @@ bool gd_ass_file(gd_globals_t *gdg, const char *fname, int pass)
|
|||
memset(linebuffer, 0, LINEBUF_SIZE);
|
||||
if (!fgets(linebuffer, LINEBUF_SIZE, fa.fsrc))
|
||||
break;
|
||||
strcpy(cur_line, linebuffer);
|
||||
//printf("A: %s", linebuffer);
|
||||
fa.code_line++;
|
||||
|
||||
|
|
|
@ -256,7 +256,7 @@ void VertexShaderManager::SetConstants(bool proj_hax_1,bool SMG_hack)
|
|||
g_fProjectionMatrix[10] = xfregs.rawProjection[4];
|
||||
|
||||
if (SMG_hack) {
|
||||
g_fProjectionMatrix[11] = -(0.512505 + xfregs.rawProjection[5]) + (proj_hax_1 ? 0.1f : 0.0f);
|
||||
g_fProjectionMatrix[11] = -(0.512505f + xfregs.rawProjection[5]) + (proj_hax_1 ? 0.1f : 0.0f);
|
||||
}
|
||||
else {
|
||||
g_fProjectionMatrix[11] = xfregs.rawProjection[5] + (proj_hax_1 ? 0.1f : 0.0f);
|
||||
|
|
Loading…
Reference in New Issue