mirror of
https://github.com/encounter/mwccwrap.git
synced 2026-07-10 12:18:39 -07:00
correctly map cli paramters for all supported cc_mips versions (#1)
* correctly map cli paramters for all supported cc_mips versions * fix inconsistency with speed/space value
This commit is contained in:
+173
-41
@@ -282,41 +282,153 @@ typedef struct PPreprocessor {
|
||||
* MIPS preference panel structs
|
||||
* ============================================================ */
|
||||
|
||||
/* "MIPS CodeGen" panel (20 bytes) */
|
||||
typedef struct PMIPSCodeGen {
|
||||
SInt16 version; /* 0x00: ignored by DLL */
|
||||
UInt8 structalignment; /* 0x02: struct alignment (bulk-copied, not individually read) */
|
||||
UInt8 tracebacktables; /* 0x03: traceback tables (bulk-copied, not individually read) */
|
||||
SInt16 processor; /* 0x04: processor type (overridden to 0x1000 for PSX in init) */
|
||||
SInt16 fpuType; /* 0x06: FPU type: 0=none, 1=single, 2=double, 3=all */
|
||||
SInt16 isaLevel; /* 0x08: MIPS ISA level (I/II/III/IV) */
|
||||
UInt8 multibyteAware; /* 0x0A: multibyte string handling */
|
||||
UInt8 peephole; /* 0x0B: peephole optimization enable */
|
||||
UInt8 reserved_0C; /* 0x0C: unused */
|
||||
UInt8 useIntrinsics; /* 0x0D: inline intrinsics for strcpy/memcpy/etc */
|
||||
UInt8 reserved_0E; /* 0x0E: unused */
|
||||
UInt8 reserved_0F; /* 0x0F: unused */
|
||||
UInt32 reserved_10; /* 0x10: stored but never read */
|
||||
} PMIPSCodeGen;
|
||||
typedef struct MIPSCodeGenR3 {
|
||||
SInt16 version;
|
||||
SInt16 processor;
|
||||
SInt16 optimizationlevel;
|
||||
UInt8 readonlystrings;
|
||||
UInt8 floatgen;
|
||||
UInt8 isa_ii;
|
||||
UInt8 isa_iii;
|
||||
UInt8 isa_iv;
|
||||
UInt8 pad_0B;
|
||||
} MIPSCodeGenR3;
|
||||
|
||||
/* "MIPS Linker Panel" (340 bytes) */
|
||||
typedef struct PMIPSLinker {
|
||||
SInt16 version; /* 0x00 */
|
||||
UInt8 reserved_02; /* 0x02 */
|
||||
UInt8 reserved_03; /* 0x03 */
|
||||
UInt8 reserved_04; /* 0x04 */
|
||||
UInt8 genOutput; /* 0x05: controls linker output behavior */
|
||||
UInt8 reserved_06[334]; /* 0x06..0x153 */
|
||||
} PMIPSLinker;
|
||||
typedef struct MIPSCodeGenR4 {
|
||||
SInt16 version;
|
||||
SInt16 pad_02;
|
||||
SInt16 optimizationlevel;
|
||||
UInt8 readonlystrings;
|
||||
UInt8 pad_07;
|
||||
UInt8 pad_08; // always set
|
||||
UInt8 pad_09;
|
||||
UInt8 pad_0A;
|
||||
UInt8 pad_0B;
|
||||
UInt8 profiler;
|
||||
UInt8 pad_0D;
|
||||
} MIPSCodeGenR4;
|
||||
|
||||
/* "MIPS Project" (60 bytes) */
|
||||
typedef struct PMIPSProject {
|
||||
SInt16 version; /* 0x00 */
|
||||
UInt8 reserved_02; /* 0x02 */
|
||||
UInt8 reserved_03; /* 0x03 */
|
||||
SInt16 projectSetting; /* 0x04: project-level setting */
|
||||
UInt8 reserved_06[54]; /* 0x06..0x3B */
|
||||
} PMIPSProject;
|
||||
typedef struct MIPSCodeGenR5 {
|
||||
SInt16 version;
|
||||
SInt16 pad_02;
|
||||
SInt16 optimizationlevel;
|
||||
SInt16 pad_06;
|
||||
UInt8 pad_08; // always set
|
||||
UInt8 pad_09;
|
||||
UInt8 readonlystrings;
|
||||
UInt8 profiler;
|
||||
UInt8 pad_0C[8];
|
||||
} MIPSCodeGenR5;
|
||||
|
||||
typedef struct MIPSLinkerPanelR3 {
|
||||
SInt16 version;
|
||||
UInt8 listdwarf;
|
||||
UInt8 symfullpath;
|
||||
UInt8 linkmap;
|
||||
UInt8 nolinkwarnings;
|
||||
UInt8 genSrecFile;
|
||||
UInt8 linkunused;
|
||||
SInt32 codeaddr;
|
||||
SInt32 dataaddr;
|
||||
SInt32 smalldataaddr;
|
||||
SInt32 stackaddr;
|
||||
UInt8 mainname[64];
|
||||
UInt8 listclosure;
|
||||
UInt8 pad_0x59;
|
||||
SInt16 srecLength;
|
||||
UInt8 srecEOL;
|
||||
UInt8 pad_0x5D;
|
||||
} MIPSLinkerPanelR3;
|
||||
|
||||
typedef struct MIPSLinkerPanelR4 {
|
||||
SInt16 version;
|
||||
UInt8 listdwarf;
|
||||
UInt8 symfullpath;
|
||||
UInt8 linkmap;
|
||||
UInt8 nolinkwarnings;
|
||||
UInt8 genSrecFile;
|
||||
UInt8 linkunused;
|
||||
UInt8 mainname[64];
|
||||
UInt8 listclosure;
|
||||
UInt8 pad_0x49;
|
||||
SInt16 srecLength;
|
||||
UInt8 srecEOL;
|
||||
UInt8 outputformat;
|
||||
} MIPSLinkerPanelR4;
|
||||
|
||||
typedef struct MIPSLinkerPanelR5 {
|
||||
SInt16 version;
|
||||
SInt16 srecLength;
|
||||
UInt8 listdwarf;
|
||||
UInt8 symfullpath;
|
||||
UInt8 linkmap;
|
||||
UInt8 nolinkwarnings;
|
||||
UInt8 genSrecFile;
|
||||
UInt8 linkunused;
|
||||
UInt8 listclosure;
|
||||
UInt8 pad1;
|
||||
UInt8 srecEOL;
|
||||
UInt8 pad2;
|
||||
UInt8 nodeadstrip;
|
||||
UInt8 genelfsymtable;
|
||||
UInt8 pad3[4];
|
||||
UInt8 mainname[64];
|
||||
UInt8 forceactivesymbols[256];
|
||||
} MIPSLinkerPanelR5;
|
||||
|
||||
typedef struct MIPSProjectR3 {
|
||||
SInt16 version;
|
||||
SInt16 projtype;
|
||||
UInt8 outfile_name_length;
|
||||
char outfile_name[31];
|
||||
SInt32 heapsize;
|
||||
SInt32 stacksize;
|
||||
UInt8 bigendian;
|
||||
UInt8 pad2d;
|
||||
SInt16 datathreshold;
|
||||
SInt16 codeModel;
|
||||
UInt8 gprelative;
|
||||
UInt8 pcrelative;
|
||||
UInt8 data16bit;
|
||||
UInt8 pad35;
|
||||
} MIPSProjectR3;
|
||||
|
||||
typedef struct MIPSProjectR4 {
|
||||
SInt16 version;
|
||||
SInt16 projtype;
|
||||
UInt8 outfile_name_length;
|
||||
char outfile_name[31];
|
||||
SInt32 heapsize;
|
||||
SInt32 stacksize;
|
||||
UInt8 bigendian;
|
||||
UInt8 pad2d;
|
||||
SInt16 datathreshold;
|
||||
SInt16 codeModel;
|
||||
UInt8 gprelative;
|
||||
UInt8 pcrelative;
|
||||
UInt8 data16bit;
|
||||
UInt8 pad35;
|
||||
} MIPSProjectR4;
|
||||
|
||||
typedef struct MIPSProjectR5 {
|
||||
SInt16 version;
|
||||
SInt16 projtype;
|
||||
SInt16 datathreshold;
|
||||
SInt16 codeModel;
|
||||
UInt8 pad[4];
|
||||
SInt32 heapsize;
|
||||
SInt32 stacksize;
|
||||
UInt8 bigendian;
|
||||
UInt8 gprelative;
|
||||
UInt8 pcrelative;
|
||||
UInt8 data16bit_leftover;
|
||||
UInt8 pad2[4];
|
||||
UInt8 outfile_name_length;
|
||||
char outfile_name[31];
|
||||
} MIPSProjectR5;
|
||||
|
||||
/* Dummy struct for IR Optimizer request in older DLLs */
|
||||
typedef struct PIROptimizerDummy { UInt8 pad[12]; } PIROptimizerDummy;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
@@ -369,20 +481,40 @@ typedef struct CWPluginPrivateContext {
|
||||
PWarningC prefsWarnings;
|
||||
PGlobalOptimizer prefsOptimizer;
|
||||
|
||||
/* MIPS-specific panels */
|
||||
PMIPSCodeGen prefsMIPSCodeGen;
|
||||
PMIPSLinker prefsMIPSLinker;
|
||||
PMIPSProject prefsMIPSProject;
|
||||
UInt8 prefsMIPSCodeGenPanel[sizeof(PMIPSCodeGen)];
|
||||
UInt8 prefsMIPSLinkerPanel[sizeof(PMIPSLinker)];
|
||||
Boolean prefsMIPSCodeGenR4Compat;
|
||||
/* Safe scratchpad specifically for MIPS command-line flags */
|
||||
struct {
|
||||
int floatgen; /* -fp */
|
||||
int datathreshold; /* -sdata */
|
||||
int profiler; /* -profile */
|
||||
int readonlystrings; /* -rostr */
|
||||
} mips_cmdline;
|
||||
|
||||
/* PPC EABI-specific panels */
|
||||
PPCEABICodeGen prefsPPCCodeGen;
|
||||
PPCEABILinker prefsPPCLinker;
|
||||
PPCEABIProject prefsPPCProject;
|
||||
PPreprocessor prefsPreprocessor;
|
||||
|
||||
/* MIPS Binary Output Buffers */
|
||||
int mips_version; /* 3, 4, or 5 (0 if PowerPC) */
|
||||
union {
|
||||
struct {
|
||||
MIPSCodeGenR3 codegen;
|
||||
MIPSLinkerPanelR3 linker;
|
||||
MIPSProjectR3 project;
|
||||
PIROptimizerDummy ir_opt;
|
||||
} r3;
|
||||
struct {
|
||||
MIPSCodeGenR4 codegen;
|
||||
MIPSLinkerPanelR4 linker;
|
||||
MIPSProjectR4 project;
|
||||
PIROptimizerDummy ir_opt;
|
||||
} r4;
|
||||
struct {
|
||||
MIPSCodeGenR5 codegen;
|
||||
MIPSLinkerPanelR5 linker;
|
||||
MIPSProjectR5 project;
|
||||
} r5;
|
||||
} mips_panels;
|
||||
/* Define/pragma text exposed as a virtual prefix file */
|
||||
char* defineText; /* accumulated #define/#undef/#pragma/#include lines */
|
||||
SInt32 defineTextLen;
|
||||
|
||||
+91
-108
@@ -162,7 +162,6 @@ static void print_help(void) {
|
||||
" -opt off|on|all|full Optimization level\n"
|
||||
" -opt speed|space Optimization target\n"
|
||||
" -opt level=<N> Set optimization level (0-4)\n"
|
||||
" -opt [no]intrinsics Inline intrinsic functions\n"
|
||||
" -opt [no]peephole Peephole optimization\n"
|
||||
"\n"
|
||||
"Debug:\n"
|
||||
@@ -343,28 +342,28 @@ static int get_compiler_version_info(const char* dll_path, CompilerVersionInfo*
|
||||
free(info_blob);
|
||||
return found_any;
|
||||
}
|
||||
/*
|
||||
* Zero-I/O MIPS Version Detection using Opcode Fingerprinting.
|
||||
* Reads the instruction bytes exactly 16 bytes deep into PluginMain
|
||||
* to uniquely identify the CodeWarrior compiler version.
|
||||
*/
|
||||
static int detect_mips_version(void* plugin_main_ptr) {
|
||||
unsigned int* p;
|
||||
|
||||
if (!plugin_main_ptr) return 0;
|
||||
|
||||
p = (unsigned int*)plugin_main_ptr;
|
||||
|
||||
static int should_enable_mips_r4_compat(const CompilerVersionInfo* info) {
|
||||
unsigned int major, minor, patch, build;
|
||||
|
||||
if (!info || !info->has_fixed_version) return 0;
|
||||
|
||||
major = (unsigned int)HIWORD(info->version_ms);
|
||||
minor = (unsigned int)LOWORD(info->version_ms);
|
||||
patch = (unsigned int)HIWORD(info->version_ls);
|
||||
build = (unsigned int)LOWORD(info->version_ls);
|
||||
|
||||
if (!(major == 2 && minor == 44 && patch == 14 && build == 0)) return 0;
|
||||
|
||||
if (info->file_description[0] &&
|
||||
_stricmp(info->file_description, "MIPS Compiler for PlayStation") != 0)
|
||||
{
|
||||
return 0;
|
||||
/* Check the opcode block at offset 0x10 (p[4]) */
|
||||
switch (p[4]) {
|
||||
case 0x0025389F: return 30; /* R3 */
|
||||
case 0x0025AF26: return 40; /* R4 */
|
||||
case 0x885550D2: return 41; /* R4.1 */
|
||||
case 0x89000000: return 50; /* R5.0 */
|
||||
case 0xDEF0E855: return 52; /* R5.2 */
|
||||
default: return 0; /* Unknown or PowerPC */
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void format_version_line(const CompilerVersionInfo* info, char* out, size_t out_size) {
|
||||
unsigned int major, minor, patch, build;
|
||||
|
||||
@@ -713,86 +712,78 @@ static int set_ppc_alignment(PPCEABICodeGen* ppc, const char* value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apply_ppc_string_option(PFrontEndC* fe, PPCEABICodeGen* ppc, const char* token) {
|
||||
if (!fe || !ppc || !token || !token[0]) return 0;
|
||||
static int apply_string_option(CWPluginContext ctx, const char* token) {
|
||||
if (!ctx || !token || !token[0]) return 0;
|
||||
|
||||
if (_stricmp(token, "reuse") == 0) {
|
||||
fe->dontreusestrings = 0;
|
||||
ctx->prefsFrontEnd.dontreusestrings = 0;
|
||||
return 1;
|
||||
}
|
||||
if (_stricmp(token, "noreuse") == 0) {
|
||||
fe->dontreusestrings = 1;
|
||||
ctx->prefsFrontEnd.dontreusestrings = 1;
|
||||
return 1;
|
||||
}
|
||||
if (_stricmp(token, "pool") == 0) {
|
||||
fe->poolstrings = 1;
|
||||
ctx->prefsFrontEnd.poolstrings = 1;
|
||||
return 1;
|
||||
}
|
||||
if (_stricmp(token, "nopool") == 0) {
|
||||
fe->poolstrings = 0;
|
||||
ctx->prefsFrontEnd.poolstrings = 0;
|
||||
return 1;
|
||||
}
|
||||
if (_stricmp(token, "readonly") == 0) {
|
||||
ppc->readonlystrings = 1;
|
||||
ctx->prefsPPCCodeGen.readonlystrings = 1;
|
||||
ctx->mips_cmdline.readonlystrings = 1;
|
||||
return 1;
|
||||
}
|
||||
if (_stricmp(token, "noreadonly") == 0) {
|
||||
ppc->readonlystrings = 0;
|
||||
ctx->prefsPPCCodeGen.readonlystrings = 0;
|
||||
ctx->mips_cmdline.readonlystrings = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void apply_dash_o_token(const char* token,
|
||||
PGlobalOptimizer* opt,
|
||||
PMIPSCodeGen* mips,
|
||||
PPCEABICodeGen* ppc,
|
||||
int* handled)
|
||||
static void apply_dash_o_token(const char* token, CWPluginContext ctx, int* handled)
|
||||
{
|
||||
if (!token || !token[0]) return;
|
||||
|
||||
if (strcmp(token, "0") == 0) {
|
||||
opt->optimizationlevel = 0;
|
||||
ctx->prefsOptimizer.optimizationlevel = 0;
|
||||
return;
|
||||
}
|
||||
if (strcmp(token, "1") == 0) {
|
||||
opt->optimizationlevel = 1;
|
||||
ctx->prefsOptimizer.optimizationlevel = 1;
|
||||
return;
|
||||
}
|
||||
if (strcmp(token, "2") == 0) {
|
||||
opt->optimizationlevel = 2;
|
||||
mips->peephole = 1;
|
||||
ppc->peephole = 1;
|
||||
ctx->prefsOptimizer.optimizationlevel = 2;
|
||||
ctx->prefsPPCCodeGen.peephole = 1;
|
||||
return;
|
||||
}
|
||||
if (strcmp(token, "3") == 0) {
|
||||
opt->optimizationlevel = 3;
|
||||
mips->peephole = 1;
|
||||
ppc->peephole = 1;
|
||||
ctx->prefsOptimizer.optimizationlevel = 3;
|
||||
ctx->prefsPPCCodeGen.peephole = 1;
|
||||
return;
|
||||
}
|
||||
if (strcmp(token, "4") == 0) {
|
||||
opt->optimizationlevel = 4;
|
||||
mips->peephole = 1;
|
||||
ppc->peephole = 1;
|
||||
ppc->scheduling = 1;
|
||||
ctx->prefsOptimizer.optimizationlevel = 4;
|
||||
ctx->prefsPPCCodeGen.peephole = 1;
|
||||
ctx->prefsPPCCodeGen.scheduling = 1;
|
||||
return;
|
||||
}
|
||||
if (strcmp(token, "p") == 0) {
|
||||
opt->optfor = 2;
|
||||
ctx->prefsOptimizer.optfor = 2;
|
||||
return;
|
||||
}
|
||||
if (strcmp(token, "s") == 0) {
|
||||
opt->optfor = 1;
|
||||
ctx->prefsOptimizer.optfor = 1;
|
||||
return;
|
||||
}
|
||||
if (handled) *handled = 0;
|
||||
}
|
||||
|
||||
static int parse_dash_o_option(const char* arg,
|
||||
PGlobalOptimizer* opt,
|
||||
PMIPSCodeGen* mips,
|
||||
PPCEABICodeGen* ppc)
|
||||
static int parse_dash_o_option(const char* arg, CWPluginContext ctx)
|
||||
{
|
||||
const char* spec;
|
||||
int handled = 1;
|
||||
@@ -801,7 +792,7 @@ static int parse_dash_o_option(const char* arg,
|
||||
spec = arg + 2;
|
||||
|
||||
if (!spec[0]) {
|
||||
apply_dash_o_token("2", opt, mips, ppc, &handled);
|
||||
apply_dash_o_token("2", ctx, &handled);
|
||||
return handled;
|
||||
}
|
||||
|
||||
@@ -815,84 +806,68 @@ static int parse_dash_o_option(const char* arg,
|
||||
char* tok = strtok(tmp, ",");
|
||||
while (tok) {
|
||||
if (tok[0]) {
|
||||
apply_dash_o_token(tok, opt, mips, ppc, &handled);
|
||||
apply_dash_o_token(tok, ctx, &handled);
|
||||
}
|
||||
tok = strtok(NULL, ",");
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
apply_dash_o_token(spec, opt, mips, ppc, &handled);
|
||||
apply_dash_o_token(spec, ctx, &handled);
|
||||
return handled;
|
||||
}
|
||||
|
||||
static int apply_opt_keyword(const char* token,
|
||||
PGlobalOptimizer* opt,
|
||||
PMIPSCodeGen* mips,
|
||||
PPCEABICodeGen* ppc)
|
||||
static int apply_opt_keyword(const char* token, CWPluginContext ctx)
|
||||
{
|
||||
if (!token || !token[0]) return 0;
|
||||
|
||||
if (strcmp(token, "off") == 0 || strcmp(token, "none") == 0) {
|
||||
opt->optimizationlevel = 0;
|
||||
ctx->prefsOptimizer.optimizationlevel = 0;
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(token, "on") == 0) {
|
||||
opt->optimizationlevel = 2;
|
||||
mips->peephole = 1;
|
||||
ppc->peephole = 1;
|
||||
ctx->prefsOptimizer.optimizationlevel = 2;
|
||||
ctx->prefsPPCCodeGen.peephole = 1;
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(token, "all") == 0 || strcmp(token, "full") == 0) {
|
||||
opt->optimizationlevel = 4;
|
||||
opt->optfor = 1;
|
||||
mips->useIntrinsics = 1;
|
||||
mips->peephole = 1;
|
||||
ppc->peephole = 1;
|
||||
ppc->scheduling = 1;
|
||||
ctx->prefsOptimizer.optimizationlevel = 4;
|
||||
ctx->prefsOptimizer.optfor = 1;
|
||||
ctx->prefsPPCCodeGen.peephole = 1;
|
||||
ctx->prefsPPCCodeGen.scheduling = 1;
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(token, "speed") == 0) {
|
||||
opt->optfor = 2;
|
||||
ctx->prefsOptimizer.optfor = 2;
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(token, "space") == 0 || strcmp(token, "size") == 0) {
|
||||
opt->optfor = 1;
|
||||
ctx->prefsOptimizer.optfor = 1;
|
||||
return 1;
|
||||
}
|
||||
if (strncmp(token, "level=", 6) == 0 || strncmp(token, "l=", 2) == 0) {
|
||||
const char* num = strchr(token, '=') + 1;
|
||||
int lv = atoi(num);
|
||||
if (lv >= 0 && lv <= 4) {
|
||||
opt->optimizationlevel = (UInt8)lv;
|
||||
ctx->prefsOptimizer.optimizationlevel = (UInt8)lv;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(token, "intrinsics") == 0) {
|
||||
mips->useIntrinsics = 1;
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(token, "nointrinsics") == 0) {
|
||||
mips->useIntrinsics = 0;
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(token, "peephole") == 0 || strcmp(token, "peep") == 0) {
|
||||
mips->peephole = 1;
|
||||
ppc->peephole = 1;
|
||||
ctx->prefsPPCCodeGen.peephole = 1;
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(token, "nopeephole") == 0 || strcmp(token, "nopeep") == 0) {
|
||||
mips->peephole = 0;
|
||||
ppc->peephole = 0;
|
||||
ctx->prefsPPCCodeGen.peephole = 0;
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(token, "schedule") == 0) {
|
||||
ppc->scheduling = 1;
|
||||
ctx->prefsPPCCodeGen.scheduling = 1;
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(token, "noschedule") == 0) {
|
||||
ppc->scheduling = 0;
|
||||
ctx->prefsPPCCodeGen.scheduling = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -1314,11 +1289,9 @@ static void init_pref_defaults(CWPluginContext ctx) {
|
||||
memset(&ctx->prefsOptimizer, 0, sizeof(PGlobalOptimizer));
|
||||
|
||||
/* ---- MIPS-specific panels ---- */
|
||||
memset(&ctx->prefsMIPSCodeGen, 0, sizeof(PMIPSCodeGen));
|
||||
ctx->prefsMIPSCodeGen.fpuType = 1; /* -fp single (default) */
|
||||
|
||||
memset(&ctx->prefsMIPSLinker, 0, sizeof(PMIPSLinker));
|
||||
memset(&ctx->prefsMIPSProject, 0, sizeof(PMIPSProject));
|
||||
memset(&ctx->mips_cmdline, 0, sizeof(ctx->mips_cmdline));
|
||||
memset(&ctx->mips_panels, 0, sizeof(ctx->mips_panels));
|
||||
ctx->mips_cmdline.datathreshold = 8; /* -sdata 8 (default) */
|
||||
|
||||
/* ---- PPC EABI-specific panels ---- */
|
||||
memset(&ctx->prefsPPCCodeGen, 0, sizeof(PPCEABICodeGen));
|
||||
@@ -1404,8 +1377,6 @@ static int parse_args(int argc, char* argv[], CWPluginContext ctx,
|
||||
{
|
||||
PFrontEndC* fe = &ctx->prefsFrontEnd;
|
||||
PWarningC* warn = &ctx->prefsWarnings;
|
||||
PGlobalOptimizer* opt = &ctx->prefsOptimizer;
|
||||
PMIPSCodeGen* cg = &ctx->prefsMIPSCodeGen;
|
||||
PPCEABICodeGen* ppc = &ctx->prefsPPCCodeGen;
|
||||
const char* arg_val;
|
||||
|
||||
@@ -1717,16 +1688,17 @@ static int parse_args(int argc, char* argv[], CWPluginContext ctx,
|
||||
tok;
|
||||
tok = strtok(NULL, ","))
|
||||
{
|
||||
if (!apply_ppc_string_option(fe, ppc, tok)) {
|
||||
if (!apply_string_option(ctx, tok)) {
|
||||
fprintf(stderr, "warning: unknown -str value: %s\n", tok);
|
||||
}
|
||||
}
|
||||
} else if (!apply_ppc_string_option(fe, ppc, arg_val)) {
|
||||
} else if (!apply_string_option(ctx, arg_val)) {
|
||||
fprintf(stderr, "warning: unknown -str value: %s\n", arg_val);
|
||||
}
|
||||
}
|
||||
else if (strcmp(arg, "-rostr") == 0 || strcmp(arg, "-readonlystrings") == 0) {
|
||||
/* Deprecated alias for -str readonly. Does not imply [no]reuse. */
|
||||
ctx->mips_cmdline.readonlystrings = 1;
|
||||
ppc->readonlystrings = 1;
|
||||
}
|
||||
else if (strcmp(arg, "-multibyte") == 0 || strcmp(arg, "-multibyteaware") == 0) {
|
||||
@@ -1872,7 +1844,7 @@ static int parse_args(int argc, char* argv[], CWPluginContext ctx,
|
||||
|
||||
/* --- Optimizer --- */
|
||||
else if (arg[0] == '-' && arg[1] == 'O') {
|
||||
if (!parse_dash_o_option(arg, opt, cg, ppc)) {
|
||||
if (!parse_dash_o_option(arg, ctx)) {
|
||||
fprintf(stderr, "warning: unknown -O option: %s\n", arg);
|
||||
}
|
||||
}
|
||||
@@ -1888,11 +1860,11 @@ static int parse_args(int argc, char* argv[], CWPluginContext ctx,
|
||||
tok;
|
||||
tok = strtok(NULL, ","))
|
||||
{
|
||||
if (!apply_opt_keyword(tok, opt, cg, ppc)) {
|
||||
if (!apply_opt_keyword(tok, ctx)) {
|
||||
fprintf(stderr, "warning: unknown -opt value: %s\n", tok);
|
||||
}
|
||||
}
|
||||
} else if (!apply_opt_keyword(arg_val, opt, cg, ppc)) {
|
||||
} else if (!apply_opt_keyword(arg_val, ctx)) {
|
||||
fprintf(stderr, "warning: unknown -opt value: %s\n", arg_val);
|
||||
}
|
||||
}
|
||||
@@ -1901,13 +1873,15 @@ static int parse_args(int argc, char* argv[], CWPluginContext ctx,
|
||||
else if (strcmp(arg, "-fp") == 0) {
|
||||
NEXT_ARG(arg_val);
|
||||
if (_stricmp(arg_val, "off") == 0 || _stricmp(arg_val, "none") == 0) {
|
||||
cg->fpuType = 0;
|
||||
ctx->mips_cmdline.floatgen = 0;
|
||||
ppc->floatingpoint = 0;
|
||||
} else if (_stricmp(arg_val, "single") == 0) {
|
||||
cg->fpuType = 1;
|
||||
ctx->mips_cmdline.floatgen = 1;
|
||||
} else if (_stricmp(arg_val, "soft") == 0 || _stricmp(arg_val, "software") == 0) {
|
||||
ctx->mips_cmdline.floatgen = 0;
|
||||
ppc->floatingpoint = 1;
|
||||
} else if (_stricmp(arg_val, "hard") == 0 || _stricmp(arg_val, "hardware") == 0) {
|
||||
ctx->mips_cmdline.floatgen = 1;
|
||||
ppc->floatingpoint = 2;
|
||||
} else if (_stricmp(arg_val, "fmadd") == 0) {
|
||||
ppc->floatingpoint = 2;
|
||||
@@ -1948,7 +1922,9 @@ static int parse_args(int argc, char* argv[], CWPluginContext ctx,
|
||||
strcmp(arg, "-sdata") == 0 ||
|
||||
strcmp(arg, "-sdatathreshold") == 0) {
|
||||
NEXT_ARG(arg_val);
|
||||
ctx->prefsPPCProject.datathreshold = (SInt16)atoi(arg_val);
|
||||
SInt16 threshold = (SInt16)atoi(arg_val);
|
||||
ctx->prefsPPCProject.datathreshold = threshold;
|
||||
ctx->mips_cmdline.datathreshold = threshold;
|
||||
}
|
||||
else if (strcmp(arg, "-sdata2") == 0 ||
|
||||
strcmp(arg, "-sdata2threshold") == 0) {
|
||||
@@ -2014,7 +1990,8 @@ static int parse_args(int argc, char* argv[], CWPluginContext ctx,
|
||||
}
|
||||
}
|
||||
else if (strcmp(arg, "-profile") == 0) {
|
||||
/* profiler - stored but cc_mips.dll may not use it for PS1 */
|
||||
/* profiler */
|
||||
ctx->mips_cmdline.profiler = 1;
|
||||
ppc->profiler = 1;
|
||||
}
|
||||
else if (strcmp(arg, "-farcall") == 0) {
|
||||
@@ -2255,12 +2232,8 @@ int main(int argc, char* argv[]) {
|
||||
copy_cstr(loaded_dll_name, sizeof(loaded_dll_name), loaded_dll_path);
|
||||
}
|
||||
|
||||
has_active_version_info = get_compiler_version_info(loaded_dll_path, &active_version_info);
|
||||
ctx.prefsMIPSCodeGenR4Compat =
|
||||
has_active_version_info ? should_enable_mips_r4_compat(&active_version_info) : FALSE;
|
||||
if (ctx.verbose && ctx.prefsMIPSCodeGenR4Compat) {
|
||||
fprintf(stderr, "Enabled prefsMIPSCodeGenR4Compat based on compiler version metadata.\n");
|
||||
}
|
||||
/* Initialize to 0. It will be properly detected later when PluginMain is found. */
|
||||
ctx.mips_version = 0;
|
||||
|
||||
if (g_registered_pluginlib_version == 2) {
|
||||
plugin_api_version = 8;
|
||||
@@ -2303,6 +2276,16 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
if (ctx.verbose) fprintf(stderr, "Found plugin main at %p\n", (void*)plugin_main);
|
||||
|
||||
/* LATE DETECTION: Reuse the pointer mwccwrap already found */
|
||||
ctx.mips_version = detect_mips_version((void*)plugin_main);
|
||||
|
||||
if (ctx.verbose) {
|
||||
if (ctx.mips_version > 0) {
|
||||
fprintf(stderr, "Detected MIPS Compiler Version Scale: %d\n", ctx.mips_version);
|
||||
} else {
|
||||
fprintf(stderr, "Detected PowerPC/Legacy Compiler Mode.\n");
|
||||
}
|
||||
}
|
||||
ctx.apiVersion = plugin_api_version;
|
||||
ctx.numFiles = num_sources;
|
||||
|
||||
@@ -2529,4 +2512,4 @@ cleanup:
|
||||
if (ctx.defineText) free(ctx.defineText);
|
||||
|
||||
return (ctx.numErrors > 0 || had_compile_failure) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
+135
-55
@@ -1019,48 +1019,131 @@ CW_CALLBACK CWFreeObjectData(CWPluginContext ctx, SInt32 whichfile, CWMemHandle
|
||||
return CWFreeMemHandle(ctx, objectdata);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Preferences
|
||||
* ============================================================ */
|
||||
static CWResult MIPS_GetPreferences(CWPluginContext ctx, const char* prefsname, void** prefsdata) {
|
||||
const void* prefs = NULL;
|
||||
SInt32 prefsSize = 0;
|
||||
|
||||
static void build_mips_codegen_panel(CWPluginContext ctx) {
|
||||
memcpy(ctx->prefsMIPSCodeGenPanel,
|
||||
&ctx->prefsMIPSCodeGen,
|
||||
sizeof(ctx->prefsMIPSCodeGenPanel));
|
||||
|
||||
if (ctx->prefsMIPSCodeGenR4Compat) {
|
||||
/*
|
||||
* R4 reads PMIPSCodeGen with a different layout than R5/R5.2.
|
||||
* Keep a 20-byte panel, but patch overlapping bytes so both
|
||||
* layouts see sensible values.
|
||||
*/
|
||||
ctx->prefsMIPSCodeGenPanel[0x04] = (UInt8)(ctx->prefsMIPSCodeGen.processor & 0xFF);
|
||||
ctx->prefsMIPSCodeGenPanel[0x05] = 0;
|
||||
ctx->prefsMIPSCodeGenPanel[0x06] = (UInt8)(ctx->prefsMIPSCodeGen.fpuType & 0xFF);
|
||||
ctx->prefsMIPSCodeGenPanel[0x07] = (ctx->prefsMIPSCodeGen.fpuType != 0) ? 1 : 0;
|
||||
ctx->prefsMIPSCodeGenPanel[0x0C] = ctx->prefsMIPSCodeGen.useIntrinsics;
|
||||
if (strcmp(prefsname, "C/C++ Compiler") == 0) {
|
||||
prefs = &ctx->prefsFrontEnd;
|
||||
prefsSize = sizeof(ctx->prefsFrontEnd);
|
||||
if (ctx->mips_version >= 52) ctx->prefsFrontEnd.version = 13;
|
||||
else if (ctx->mips_version >= 40) ctx->prefsFrontEnd.version = 12;
|
||||
else ctx->prefsFrontEnd.version = 9;
|
||||
}
|
||||
else if (strcmp(prefsname, "C/C++ Warnings") == 0) {
|
||||
prefs = &ctx->prefsWarnings;
|
||||
prefsSize = sizeof(ctx->prefsWarnings);
|
||||
if (ctx->mips_version >= 52) ctx->prefsWarnings.version = 5;
|
||||
else if (ctx->mips_version >= 40) ctx->prefsWarnings.version = 4;
|
||||
else ctx->prefsWarnings.version = 3;
|
||||
}
|
||||
else if (strcmp(prefsname, "PS Global Optimizer") == 0) {
|
||||
|
||||
ctx->prefsOptimizer.version = 1;
|
||||
|
||||
/* Parser gives us: 1=Space, 2=Speed, 0=Default.
|
||||
* MIPS DLL wants: 1=Space, 0=Speed.
|
||||
* Default to Space (1) unless Speed (2) was explicitly requested.
|
||||
*/
|
||||
ctx->prefsOptimizer.optfor = (ctx->prefsOptimizer.optfor == 2) ? 0 : 1;
|
||||
|
||||
prefs = &ctx->prefsOptimizer;
|
||||
prefsSize = sizeof(PGlobalOptimizer);
|
||||
}
|
||||
else if (strcmp(prefsname, "MIPS Project") == 0) {
|
||||
if (ctx->mips_version >= 50) {
|
||||
MIPSProjectR5* p = &ctx->mips_panels.r5.project;
|
||||
p->version = 3;
|
||||
p->datathreshold = ctx->mips_cmdline.datathreshold;
|
||||
// "Absolute Addressing" Code Model
|
||||
p->codeModel = 1;
|
||||
prefs = p;
|
||||
prefsSize = sizeof(MIPSProjectR5);
|
||||
} else {
|
||||
MIPSProjectR4* p = &ctx->mips_panels.r4.project;
|
||||
p->version = 2;
|
||||
p->datathreshold = ctx->mips_cmdline.datathreshold;
|
||||
// "Absolute Addressing" Code Model
|
||||
p->codeModel = 1;
|
||||
prefs = p;
|
||||
prefsSize = sizeof(MIPSProjectR4);
|
||||
}
|
||||
}
|
||||
else if (strcmp(prefsname, "MIPS CodeGen") == 0) {
|
||||
if (ctx->mips_version >= 50) {
|
||||
MIPSCodeGenR5* p = &ctx->mips_panels.r5.codegen;
|
||||
p->version = 7;
|
||||
p->optimizationlevel = ctx->prefsOptimizer.optimizationlevel;
|
||||
p->readonlystrings = ctx->mips_cmdline.readonlystrings;
|
||||
p->profiler = ctx->mips_cmdline.profiler;
|
||||
// always set
|
||||
p->pad_08 = 1;
|
||||
prefs = p;
|
||||
prefsSize = sizeof(MIPSCodeGenR5);
|
||||
} else if (ctx->mips_version >= 40) {
|
||||
MIPSCodeGenR4* p = &ctx->mips_panels.r4.codegen;
|
||||
p->version = 5;
|
||||
p->optimizationlevel = ctx->prefsOptimizer.optimizationlevel;
|
||||
p->readonlystrings = ctx->mips_cmdline.readonlystrings;
|
||||
p->profiler = ctx->mips_cmdline.profiler;
|
||||
// always set
|
||||
p->pad_08 = 1;
|
||||
prefs = p;
|
||||
prefsSize = sizeof(MIPSCodeGenR4);
|
||||
} else {
|
||||
MIPSCodeGenR3* p = &ctx->mips_panels.r3.codegen;
|
||||
p->version = 2;
|
||||
p->optimizationlevel = ctx->prefsOptimizer.optimizationlevel;
|
||||
p->floatgen = ctx->mips_cmdline.floatgen;
|
||||
p->readonlystrings = ctx->mips_cmdline.readonlystrings;
|
||||
// TODO: possibly implement setting ISA Level, as the IDE lets you
|
||||
prefs = p;
|
||||
prefsSize = sizeof(MIPSCodeGenR3);
|
||||
}
|
||||
}
|
||||
else if (strcmp(prefsname, "MIPS Linker Panel") == 0) {
|
||||
if (ctx->mips_version >= 50) {
|
||||
MIPSLinkerPanelR5* p = &ctx->mips_panels.r5.linker;
|
||||
p->version = 6;
|
||||
//p->symfullpath = 1;
|
||||
prefs = p;
|
||||
prefsSize = sizeof(MIPSLinkerPanelR5);
|
||||
} else if (ctx->mips_version >= 40) {
|
||||
MIPSLinkerPanelR4* p = &ctx->mips_panels.r4.linker;
|
||||
p->version = 4;
|
||||
//p->symfullpath = 1;
|
||||
prefs = p;
|
||||
prefsSize = sizeof(MIPSLinkerPanelR4);
|
||||
} else {
|
||||
MIPSLinkerPanelR3* p = &ctx->mips_panels.r3.linker;
|
||||
p->version = 2;
|
||||
// in R3, passing -g with symfullpath = 1 causes a crash
|
||||
//p->symfullpath = 1;
|
||||
prefs = p;
|
||||
prefsSize = sizeof(MIPSLinkerPanelR3);
|
||||
}
|
||||
}
|
||||
else if (strcmp(prefsname, "IR Optimizer") == 0) {
|
||||
prefs = &ctx->mips_panels.r3.ir_opt;
|
||||
prefsSize = sizeof(PIROptimizerDummy);
|
||||
}
|
||||
else {
|
||||
LOG(" Unknown MIPS preference panel: %s", prefsname);
|
||||
prefsSize = 256;
|
||||
}
|
||||
|
||||
CWAllocMemHandle(ctx, prefsSize, FALSE, (CWMemHandle*)prefsdata);
|
||||
if (prefs && prefsSize > 0) {
|
||||
void* ptr = NULL;
|
||||
CWLockMemHandle(ctx, *(CWMemHandle*)prefsdata, FALSE, &ptr);
|
||||
if (ptr) memcpy(ptr, prefs, (size_t)prefsSize);
|
||||
CWUnlockMemHandle(ctx, *(CWMemHandle*)prefsdata);
|
||||
}
|
||||
return cwNoErr;
|
||||
}
|
||||
|
||||
static void build_mips_linker_panel(CWPluginContext ctx) {
|
||||
memcpy(ctx->prefsMIPSLinkerPanel,
|
||||
&ctx->prefsMIPSLinker,
|
||||
sizeof(ctx->prefsMIPSLinkerPanel));
|
||||
|
||||
/*
|
||||
* R4 reads genOutput at 0x03, R5/R5.2 reads 0x05.
|
||||
* Mirror to both offsets to avoid version branching.
|
||||
*/
|
||||
ctx->prefsMIPSLinkerPanel[0x03] = ctx->prefsMIPSLinker.genOutput;
|
||||
ctx->prefsMIPSLinkerPanel[0x05] = ctx->prefsMIPSLinker.genOutput;
|
||||
}
|
||||
|
||||
CW_CALLBACK CWSecretGetNamedPreferences(CWPluginContext ctx,
|
||||
const char* prefsname, void** prefsdata)
|
||||
{
|
||||
LOG("CWSecretGetNamedPreferences(\"%s\", %p)", prefsname ? prefsname : "NULL", prefsdata);
|
||||
if (!ctx || !prefsname || !prefsdata) return cwErrInvalidParameter;
|
||||
|
||||
/* Original PowerPC / Legacy layout mapping */
|
||||
static CWResult PPC_GetPreferences(CWPluginContext ctx, const char* prefsname, void** prefsdata) {
|
||||
const void* prefs = NULL;
|
||||
SInt32 prefsSize = 0;
|
||||
if (strcmp(prefsname, "C/C++ Compiler") == 0) {
|
||||
@@ -1074,23 +1157,7 @@ CW_CALLBACK CWSecretGetNamedPreferences(CWPluginContext ctx,
|
||||
strcmp(prefsname, "EPPC Global Optimizer") == 0) {
|
||||
prefs = &ctx->prefsOptimizer;
|
||||
prefsSize = sizeof(ctx->prefsOptimizer);
|
||||
} else if (strcmp(prefsname, "MIPS CodeGen") == 0) {
|
||||
build_mips_codegen_panel(ctx);
|
||||
prefs = ctx->prefsMIPSCodeGenPanel;
|
||||
prefsSize = sizeof(ctx->prefsMIPSCodeGenPanel);
|
||||
} else if (strcmp(prefsname, "MIPS Linker Panel") == 0) {
|
||||
build_mips_linker_panel(ctx);
|
||||
prefs = ctx->prefsMIPSLinkerPanel;
|
||||
prefsSize = sizeof(ctx->prefsMIPSLinkerPanel);
|
||||
} else if (strcmp(prefsname, "MIPS Project") == 0) {
|
||||
prefs = &ctx->prefsMIPSProject;
|
||||
prefsSize = sizeof(ctx->prefsMIPSProject);
|
||||
} else if (strcmp(prefsname, "IR Optimizer") == 0) {
|
||||
/* CW PS R4/R4.1 vestigial panel: data never read, just return zeros */
|
||||
prefsSize = 12;
|
||||
}
|
||||
/* ---- PPC EABI panels (GC/Wii target) ---- */
|
||||
else if (strcmp(prefsname, "PPC EABI CodeGen") == 0) {
|
||||
} else if (strcmp(prefsname, "PPC EABI CodeGen") == 0) {
|
||||
prefs = &ctx->prefsPPCCodeGen;
|
||||
prefsSize = sizeof(ctx->prefsPPCCodeGen);
|
||||
} else if (strcmp(prefsname, "PPC EABI Linker") == 0) {
|
||||
@@ -1120,6 +1187,19 @@ CW_CALLBACK CWSecretGetNamedPreferences(CWPluginContext ctx,
|
||||
return cwNoErr;
|
||||
}
|
||||
|
||||
CW_CALLBACK CWSecretGetNamedPreferences(CWPluginContext ctx,
|
||||
const char* prefsname, void** prefsdata)
|
||||
{
|
||||
LOG("CWSecretGetNamedPreferences(\"%s\", %p)", prefsname ? prefsname : "NULL", prefsdata);
|
||||
if (!ctx || !prefsname || !prefsdata) return cwErrInvalidParameter;
|
||||
|
||||
if (ctx->mips_version > 0) {
|
||||
return MIPS_GetPreferences(ctx, prefsname, prefsdata);
|
||||
} else {
|
||||
return PPC_GetPreferences(ctx, prefsname, prefsdata);
|
||||
}
|
||||
}
|
||||
|
||||
CW_CALLBACK CWGetNamedPreferences(CWPluginContext ctx, const char* prefsname, CWMemHandle* prefsdata) {
|
||||
LOG("CWGetNamedPreferences(\"%s\", %p)", prefsname ? prefsname : "NULL", prefsdata);
|
||||
return CWSecretGetNamedPreferences(ctx, prefsname, (void**)prefsdata);
|
||||
|
||||
Reference in New Issue
Block a user