diff --git a/src/xenia/cpu/sdb/symbol.h b/src/xenia/cpu/sdb/symbol.h index ab013ba27..e699186b7 100644 --- a/src/xenia/cpu/sdb/symbol.h +++ b/src/xenia/cpu/sdb/symbol.h @@ -108,6 +108,10 @@ public: enum Flags { kFlagSaveGprLr = 1 << 1, kFlagRestGprLr = 1 << 2, + kFlagSaveFpr = 1 << 3, + kFlagRestFpr = 1 << 4, + kFlagSaveVmx = 1 << 5, + kFlagRestVmx = 1 << 6, }; FunctionSymbol(); diff --git a/src/xenia/cpu/sdb/xex_symbol_database.cc b/src/xenia/cpu/sdb/xex_symbol_database.cc index 4220d8320..2e1de914d 100644 --- a/src/xenia/cpu/sdb/xex_symbol_database.cc +++ b/src/xenia/cpu/sdb/xex_symbol_database.cc @@ -64,8 +64,8 @@ XexSymbolDatabase::~XexSymbolDatabase() { int XexSymbolDatabase::Analyze() { const xe_xex2_header_t* header = xe_xex2_get_header(xex_); - // Find __savegprlr_* and __restgprlr_*. - FindGplr(); + // Find __savegprlr_* and __restgprlr_* and the others. + FindSaveRest(); // Add each import thunk. for (size_t n = 0; n < header->import_library_count; n++) { @@ -84,14 +84,14 @@ int XexSymbolDatabase::Analyze() { return SymbolDatabase::Analyze(); } -int XexSymbolDatabase::FindGplr() { +int XexSymbolDatabase::FindSaveRest() { // Special stack save/restore functions. - // __savegprlr_14 to __savegprlr_31 - // __restgprlr_14 to __restgprlr_31 // http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/ppc/xxx.s.htm // It'd be nice to stash these away and mark them as such to allow for // special codegen. - static const uint32_t code_values[] = { + // __savegprlr_14 to __savegprlr_31 + // __restgprlr_14 to __restgprlr_31 + static const uint32_t gprlr_code_values[] = { 0x68FFC1F9, // __savegprlr_14 0x70FFE1F9, // __savegprlr_15 0x78FF01FA, // __savegprlr_16 @@ -134,8 +134,395 @@ int XexSymbolDatabase::FindGplr() { 0xA603887D, 0x2000804E, }; + // __savefpr_14 to __savefpr_31 + // __restfpr_14 to __restfpr_31 + static const uint32_t fpr_code_values[] = { + 0x70FFCCD9, // __savefpr_14 + 0x78FFECD9, // __savefpr_15 + 0x80FF0CDA, // __savefpr_16 + 0x88FF2CDA, // __savefpr_17 + 0x90FF4CDA, // __savefpr_18 + 0x98FF6CDA, // __savefpr_19 + 0xA0FF8CDA, // __savefpr_20 + 0xA8FFACDA, // __savefpr_21 + 0xB0FFCCDA, // __savefpr_22 + 0xB8FFECDA, // __savefpr_23 + 0xC0FF0CDB, // __savefpr_24 + 0xC8FF2CDB, // __savefpr_25 + 0xD0FF4CDB, // __savefpr_26 + 0xD8FF6CDB, // __savefpr_27 + 0xE0FF8CDB, // __savefpr_28 + 0xE8FFACDB, // __savefpr_29 + 0xF0FFCCDB, // __savefpr_30 + 0xF8FFECDB, // __savefpr_31 + 0x2000804E, + 0x70FFCCC9, // __restfpr_14 + 0x78FFECC9, // __restfpr_15 + 0x80FF0CCA, // __restfpr_16 + 0x88FF2CCA, // __restfpr_17 + 0x90FF4CCA, // __restfpr_18 + 0x98FF6CCA, // __restfpr_19 + 0xA0FF8CCA, // __restfpr_20 + 0xA8FFACCA, // __restfpr_21 + 0xB0FFCCCA, // __restfpr_22 + 0xB8FFECCA, // __restfpr_23 + 0xC0FF0CCB, // __restfpr_24 + 0xC8FF2CCB, // __restfpr_25 + 0xD0FF4CCB, // __restfpr_26 + 0xD8FF6CCB, // __restfpr_27 + 0xE0FF8CCB, // __restfpr_28 + 0xE8FFACCB, // __restfpr_29 + 0xF0FFCCCB, // __restfpr_30 + 0xF8FFECCB, // __restfpr_31 + 0x2000804E, + }; + // __savevmx_14 to __savevmx_31 + // __savevmx_64 to __savevmx_127 + // __restvmx_14 to __restvmx_31 + // __restvmx_64 to __restvmx_127 + static const uint32_t vmx_code_values[] = { + 0xE0FE6039, // __savevmx_14 + 0xCE61CB7D, + 0xF0FE6039, + 0xCE61EB7D, + 0x00FF6039, + 0xCE610B7E, + 0x10FF6039, + 0xCE612B7E, + 0x20FF6039, + 0xCE614B7E, + 0x30FF6039, + 0xCE616B7E, + 0x40FF6039, + 0xCE618B7E, + 0x50FF6039, + 0xCE61AB7E, + 0x60FF6039, + 0xCE61CB7E, + 0x70FF6039, + 0xCE61EB7E, + 0x80FF6039, + 0xCE610B7F, + 0x90FF6039, + 0xCE612B7F, + 0xA0FF6039, + 0xCE614B7F, + 0xB0FF6039, + 0xCE616B7F, + 0xC0FF6039, + 0xCE618B7F, + 0xD0FF6039, + 0xCE61AB7F, + 0xE0FF6039, + 0xCE61CB7F, + 0xF0FF6039, // __savevmx_31 + 0xCE61EB7F, + 0x2000804E, + + 0x00FC6039, // __savevmx_64 + 0xCB610B10, + 0x10FC6039, + 0xCB612B10, + 0x20FC6039, + 0xCB614B10, + 0x30FC6039, + 0xCB616B10, + 0x40FC6039, + 0xCB618B10, + 0x50FC6039, + 0xCB61AB10, + 0x60FC6039, + 0xCB61CB10, + 0x70FC6039, + 0xCB61EB10, + 0x80FC6039, + 0xCB610B11, + 0x90FC6039, + 0xCB612B11, + 0xA0FC6039, + 0xCB614B11, + 0xB0FC6039, + 0xCB616B11, + 0xC0FC6039, + 0xCB618B11, + 0xD0FC6039, + 0xCB61AB11, + 0xE0FC6039, + 0xCB61CB11, + 0xF0FC6039, + 0xCB61EB11, + 0x00FD6039, + 0xCB610B12, + 0x10FD6039, + 0xCB612B12, + 0x20FD6039, + 0xCB614B12, + 0x30FD6039, + 0xCB616B12, + 0x40FD6039, + 0xCB618B12, + 0x50FD6039, + 0xCB61AB12, + 0x60FD6039, + 0xCB61CB12, + 0x70FD6039, + 0xCB61EB12, + 0x80FD6039, + 0xCB610B13, + 0x90FD6039, + 0xCB612B13, + 0xA0FD6039, + 0xCB614B13, + 0xB0FD6039, + 0xCB616B13, + 0xC0FD6039, + 0xCB618B13, + 0xD0FD6039, + 0xCB61AB13, + 0xE0FD6039, + 0xCB61CB13, + 0xF0FD6039, + 0xCB61EB13, + 0x00FE6039, + 0xCF610B10, + 0x10FE6039, + 0xCF612B10, + 0x20FE6039, + 0xCF614B10, + 0x30FE6039, + 0xCF616B10, + 0x40FE6039, + 0xCF618B10, + 0x50FE6039, + 0xCF61AB10, + 0x60FE6039, + 0xCF61CB10, + 0x70FE6039, + 0xCF61EB10, + 0x80FE6039, + 0xCF610B11, + 0x90FE6039, + 0xCF612B11, + 0xA0FE6039, + 0xCF614B11, + 0xB0FE6039, + 0xCF616B11, + 0xC0FE6039, + 0xCF618B11, + 0xD0FE6039, + 0xCF61AB11, + 0xE0FE6039, + 0xCF61CB11, + 0xF0FE6039, + 0xCF61EB11, + 0x00FF6039, + 0xCF610B12, + 0x10FF6039, + 0xCF612B12, + 0x20FF6039, + 0xCF614B12, + 0x30FF6039, + 0xCF616B12, + 0x40FF6039, + 0xCF618B12, + 0x50FF6039, + 0xCF61AB12, + 0x60FF6039, + 0xCF61CB12, + 0x70FF6039, + 0xCF61EB12, + 0x80FF6039, + 0xCF610B13, + 0x90FF6039, + 0xCF612B13, + 0xA0FF6039, + 0xCF614B13, + 0xB0FF6039, + 0xCF616B13, + 0xC0FF6039, + 0xCF618B13, + 0xD0FF6039, + 0xCF61AB13, + 0xE0FF6039, + 0xCF61CB13, + 0xF0FF6039, // __savevmx_127 + 0xCF61EB13, + 0x2000804E, + + 0xE0FE6039, // __restvmx_14 + 0xCE60CB7D, + 0xF0FE6039, + 0xCE60EB7D, + 0x00FF6039, + 0xCE600B7E, + 0x10FF6039, + 0xCE602B7E, + 0x20FF6039, + 0xCE604B7E, + 0x30FF6039, + 0xCE606B7E, + 0x40FF6039, + 0xCE608B7E, + 0x50FF6039, + 0xCE60AB7E, + 0x60FF6039, + 0xCE60CB7E, + 0x70FF6039, + 0xCE60EB7E, + 0x80FF6039, + 0xCE600B7F, + 0x90FF6039, + 0xCE602B7F, + 0xA0FF6039, + 0xCE604B7F, + 0xB0FF6039, + 0xCE606B7F, + 0xC0FF6039, + 0xCE608B7F, + 0xD0FF6039, + 0xCE60AB7F, + 0xE0FF6039, + 0xCE60CB7F, + 0xF0FF6039, // __restvmx_31 + 0xCE60EB7F, + 0x2000804E, + + 0x00FC6039, // __restvmx_64 + 0xCB600B10, + 0x10FC6039, + 0xCB602B10, + 0x20FC6039, + 0xCB604B10, + 0x30FC6039, + 0xCB606B10, + 0x40FC6039, + 0xCB608B10, + 0x50FC6039, + 0xCB60AB10, + 0x60FC6039, + 0xCB60CB10, + 0x70FC6039, + 0xCB60EB10, + 0x80FC6039, + 0xCB600B11, + 0x90FC6039, + 0xCB602B11, + 0xA0FC6039, + 0xCB604B11, + 0xB0FC6039, + 0xCB606B11, + 0xC0FC6039, + 0xCB608B11, + 0xD0FC6039, + 0xCB60AB11, + 0xE0FC6039, + 0xCB60CB11, + 0xF0FC6039, + 0xCB60EB11, + 0x00FD6039, + 0xCB600B12, + 0x10FD6039, + 0xCB602B12, + 0x20FD6039, + 0xCB604B12, + 0x30FD6039, + 0xCB606B12, + 0x40FD6039, + 0xCB608B12, + 0x50FD6039, + 0xCB60AB12, + 0x60FD6039, + 0xCB60CB12, + 0x70FD6039, + 0xCB60EB12, + 0x80FD6039, + 0xCB600B13, + 0x90FD6039, + 0xCB602B13, + 0xA0FD6039, + 0xCB604B13, + 0xB0FD6039, + 0xCB606B13, + 0xC0FD6039, + 0xCB608B13, + 0xD0FD6039, + 0xCB60AB13, + 0xE0FD6039, + 0xCB60CB13, + 0xF0FD6039, + 0xCB60EB13, + 0x00FE6039, + 0xCF600B10, + 0x10FE6039, + 0xCF602B10, + 0x20FE6039, + 0xCF604B10, + 0x30FE6039, + 0xCF606B10, + 0x40FE6039, + 0xCF608B10, + 0x50FE6039, + 0xCF60AB10, + 0x60FE6039, + 0xCF60CB10, + 0x70FE6039, + 0xCF60EB10, + 0x80FE6039, + 0xCF600B11, + 0x90FE6039, + 0xCF602B11, + 0xA0FE6039, + 0xCF604B11, + 0xB0FE6039, + 0xCF606B11, + 0xC0FE6039, + 0xCF608B11, + 0xD0FE6039, + 0xCF60AB11, + 0xE0FE6039, + 0xCF60CB11, + 0xF0FE6039, + 0xCF60EB11, + 0x00FF6039, + 0xCF600B12, + 0x10FF6039, + 0xCF602B12, + 0x20FF6039, + 0xCF604B12, + 0x30FF6039, + 0xCF606B12, + 0x40FF6039, + 0xCF608B12, + 0x50FF6039, + 0xCF60AB12, + 0x60FF6039, + 0xCF60CB12, + 0x70FF6039, + 0xCF60EB12, + 0x80FF6039, + 0xCF600B13, + 0x90FF6039, + 0xCF602B13, + 0xA0FF6039, + 0xCF604B13, + 0xB0FF6039, + 0xCF606B13, + 0xC0FF6039, + 0xCF608B13, + 0xD0FF6039, + 0xCF60AB13, + 0xE0FF6039, + 0xCF60CB13, + 0xF0FF6039, // __restvmx_127 + 0xCF60EB13, + 0x2000804E, + }; + + uint32_t gplr_start = 0; + uint32_t fpr_start = 0; + uint32_t vmx_start = 0; const xe_xex2_header_t* header = xe_xex2_get_header(xex_); for (size_t n = 0, i = 0; n < header->section_count; n++) { const xe_xex2_section_t* section = &header->sections[n]; @@ -144,40 +531,116 @@ int XexSymbolDatabase::FindGplr() { const size_t end_address = start_address + (section->info.page_count * xe_xex2_section_length); if (section->info.type == XEX_SECTION_CODE) { - gplr_start = xe_memory_search_aligned( - memory_, start_address, end_address, - code_values, XECOUNT(code_values)); - if (gplr_start) { + if (!gplr_start) { + gplr_start = xe_memory_search_aligned( + memory_, start_address, end_address, + gprlr_code_values, XECOUNT(gprlr_code_values)); + } + if (!fpr_start) { + fpr_start = xe_memory_search_aligned( + memory_, start_address, end_address, + fpr_code_values, XECOUNT(fpr_code_values)); + } + if (!vmx_start) { + vmx_start = xe_memory_search_aligned( + memory_, start_address, end_address, + vmx_code_values, XECOUNT(vmx_code_values)); + } + if (gplr_start && fpr_start && vmx_start) { break; } } i += section->info.page_count; } - if (!gplr_start) { - return 0; - } // Add function stubs. char name[32]; - uint32_t address = gplr_start; - for (int n = 14; n <= 31; n++) { - xesnprintfa(name, XECOUNT(name), "__savegprlr_%d", n); - FunctionSymbol* fn = GetOrInsertFunction(address); - fn->end_address = fn->start_address + (31 - n) * 4 + 2 * 4; - fn->set_name(name); - fn->type = FunctionSymbol::User; - fn->flags |= FunctionSymbol::kFlagSaveGprLr; - address += 4; + if (gplr_start) { + uint32_t address = gplr_start; + for (int n = 14; n <= 31; n++) { + xesnprintfa(name, XECOUNT(name), "__savegprlr_%d", n); + FunctionSymbol* fn = GetOrInsertFunction(address); + fn->end_address = fn->start_address + (31 - n) * 4 + 2 * 4; + fn->set_name(name); + fn->type = FunctionSymbol::User; + fn->flags |= FunctionSymbol::kFlagSaveGprLr; + address += 4; + } + address = gplr_start + 20 * 4; + for (int n = 14; n <= 31; n++) { + xesnprintfa(name, XECOUNT(name), "__restgprlr_%d", n); + FunctionSymbol* fn = GetOrInsertFunction(address); + fn->end_address = fn->start_address + (31 - n) * 4 + 3 * 4; + fn->set_name(name); + fn->type = FunctionSymbol::User; + fn->flags |= FunctionSymbol::kFlagRestGprLr; + address += 4; + } } - address = gplr_start + 20 * 4; - for (int n = 14; n <= 31; n++) { - xesnprintfa(name, XECOUNT(name), "__restgprlr_%d", n); - FunctionSymbol* fn = GetOrInsertFunction(address); - fn->end_address = fn->start_address + (31 - n) * 4 + 3 * 4; - fn->set_name(name); - fn->type = FunctionSymbol::User; - fn->flags |= FunctionSymbol::kFlagRestGprLr; + if (fpr_start) { + uint32_t address = fpr_start; + for (int n = 14; n <= 31; n++) { + xesnprintfa(name, XECOUNT(name), "__savefpr_%d", n); + FunctionSymbol* fn = GetOrInsertFunction(address); + fn->end_address = fn->start_address + (31 - n) * 4 + 1 * 4; + fn->set_name(name); + fn->type = FunctionSymbol::User; + fn->flags |= FunctionSymbol::kFlagSaveFpr; + address += 4; + } + address = fpr_start + (18 * 4) + (1 * 4); + for (int n = 14; n <= 31; n++) { + xesnprintfa(name, XECOUNT(name), "__restfpr_%d", n); + FunctionSymbol* fn = GetOrInsertFunction(address); + fn->end_address = fn->start_address + (31 - n) * 4 + 1 * 4; + fn->set_name(name); + fn->type = FunctionSymbol::User; + fn->flags |= FunctionSymbol::kFlagRestFpr; + address += 4; + } + } + if (vmx_start) { + // vmx is: + // 14-31 save + // 64-127 save + // 14-31 rest + // 64-127 rest + uint32_t address = vmx_start; + for (int n = 14; n <= 31; n++) { + xesnprintfa(name, XECOUNT(name), "__savevmx_%d", n); + FunctionSymbol* fn = GetOrInsertFunction(address); + fn->set_name(name); + fn->type = FunctionSymbol::User; + fn->flags |= FunctionSymbol::kFlagSaveVmx; + address += 2 * 4; + } address += 4; + for (int n = 64; n <= 127; n++) { + xesnprintfa(name, XECOUNT(name), "__savevmx_%d", n); + FunctionSymbol* fn = GetOrInsertFunction(address); + fn->set_name(name); + fn->type = FunctionSymbol::User; + fn->flags |= FunctionSymbol::kFlagSaveVmx; + address += 2 * 4; + } + address = vmx_start + (18 * 2 * 4) + (1 * 4) + (64 * 2 * 4) + (1 * 4); + for (int n = 14; n <= 31; n++) { + xesnprintfa(name, XECOUNT(name), "__restvmx_%d", n); + FunctionSymbol* fn = GetOrInsertFunction(address); + fn->set_name(name); + fn->type = FunctionSymbol::User; + fn->flags |= FunctionSymbol::kFlagRestVmx; + address += 2 * 4; + } + address += 4; + for (int n = 64; n <= 127; n++) { + xesnprintfa(name, XECOUNT(name), "__restvmx_%d", n); + FunctionSymbol* fn = GetOrInsertFunction(address); + fn->set_name(name); + fn->type = FunctionSymbol::User; + fn->flags |= FunctionSymbol::kFlagSaveVmx; + address += 2 * 4; + } } return 0; diff --git a/src/xenia/cpu/sdb/xex_symbol_database.h b/src/xenia/cpu/sdb/xex_symbol_database.h index 4bbde3f45..4c1795100 100644 --- a/src/xenia/cpu/sdb/xex_symbol_database.h +++ b/src/xenia/cpu/sdb/xex_symbol_database.h @@ -30,7 +30,7 @@ public: virtual int Analyze(); private: - int FindGplr(); + int FindSaveRest(); int AddImports(const xe_xex2_import_library_t *library); int AddMethodHints();