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:
ThirstyWraith
2026-04-11 21:15:54 +02:00
committed by GitHub
parent e9f5847bb9
commit 62d64eb1d1
3 changed files with 399 additions and 204 deletions
+173 -41
View File
@@ -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
View File
@@ -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
View File
@@ -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);