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:
hrydgard 2009-04-12 13:12:42 +00:00
parent e8b9e93465
commit f6474b98a8
7 changed files with 267 additions and 35 deletions

View File

@ -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)

View File

@ -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

View File

@ -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"
>

View File

@ -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;
}

View File

@ -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

View File

@ -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++;

View File

@ -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);