mirror of
				https://github.com/hedge-dev/XenonRecomp.git
				synced 2025-10-30 07:11:38 +00:00 
			
		
		
		
	Move C emit code to PowerRecomp
This commit is contained in:
		
							parent
							
								
									267e19b854
								
							
						
					
					
						commit
						cbfcdc3ebc
					
				
					 6 changed files with 149 additions and 100 deletions
				
			
		|  | @ -3,4 +3,9 @@ | |||
| project("PowerAnalyse") | ||||
| 
 | ||||
| add_executable(PowerAnalyse "main.cpp" "function.h"  "function.cpp") | ||||
| add_library(LibPowerAnalyse "function.h"  "function.cpp") | ||||
| 
 | ||||
| target_include_directories(LibPowerAnalyse PUBLIC .) | ||||
| target_link_libraries(LibPowerAnalyse PUBLIC PowerUtils) | ||||
| 
 | ||||
| target_link_libraries(PowerAnalyse PRIVATE PowerUtils) | ||||
|  |  | |||
|  | @ -131,6 +131,7 @@ Function Function::Analyze(const void* code, size_t size, size_t base) | |||
|                     const auto branchBase = insn.operands[0] - base; | ||||
|                     const auto branchBlock = fn.SearchBlock(insn.operands[0]); | ||||
| 
 | ||||
|                     // carry over our projection if blocks are next to each other
 | ||||
|                     const auto isContinious = branchBase == curBlock.base + curBlock.size; | ||||
|                     auto sizeProjection = (size_t)-1; | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ | |||
| 
 | ||||
| int main() | ||||
| { | ||||
|     const auto file = LoadFile("cond-fall.elf"); | ||||
|     const auto file = LoadFile("cond-fall.elf").value(); | ||||
|     auto image = Image::ParseImage(file.data(), file.size()).value(); | ||||
| 
 | ||||
|     for (const auto& section : image.sections) | ||||
|  | @ -72,99 +72,5 @@ int main() | |||
|     } | ||||
| 
 | ||||
|     std::println(""); | ||||
| 
 | ||||
|     FILE* f = fopen("add.elf.cpp", "w"); | ||||
|     for (const auto& fn : functions) | ||||
|     { | ||||
|         auto base = fn.base; | ||||
|         auto end = base + fn.size; | ||||
|         auto* data = (uint32_t*)image.Find(base); | ||||
| 
 | ||||
|         std::string name = ""; | ||||
|         auto symbol = image.symbols.find(base); | ||||
|         if (symbol != image.symbols.end()) | ||||
|         { | ||||
|             name = symbol->name; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             name = std::format("sub_{:X}", base); | ||||
|         } | ||||
| 
 | ||||
|         std::println(f, "void {}() {{", name); | ||||
| 
 | ||||
|         ppc_insn insn; | ||||
|         while (base < end) | ||||
|         { | ||||
|             ppc::Disassemble(data, 4, base, insn); | ||||
| 
 | ||||
|             base += 4; | ||||
|             ++data; | ||||
|             if (insn.opcode == nullptr) | ||||
|             { | ||||
|                 std::println(f, "\t// {:x} {}", base - 4, insn.op_str); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 std::println(f, "\t// {:x} {} {}", base - 4, insn.opcode->name, insn.op_str); | ||||
|                 switch (insn.opcode->id) | ||||
|                 { | ||||
|                 case PPC_INST_ADD: | ||||
|                     std::println(f, "\tr{} = r{} + r{};", insn.operands[0], insn.operands[1], insn.operands[2]); | ||||
|                     break; | ||||
|                 case PPC_INST_ADDI: | ||||
|                     std::println(f, "\tr{} = r{} + {};", insn.operands[0], insn.operands[1], insn.operands[2]); | ||||
|                     break; | ||||
|                 case PPC_INST_STWU: | ||||
|                     std::println(f, "\tea = r{} + {};", insn.operands[2], static_cast<int32_t>(insn.operands[1])); | ||||
|                     std::println(f, "\t*ea = byteswap(r{});", insn.operands[0]); | ||||
|                     std::println(f, "\tr{} = ea;", insn.operands[2]); | ||||
|                     break; | ||||
|                 case PPC_INST_STW: | ||||
|                     std::println(f, "\t*(r{} + {}) = byteswap(r{});", insn.operands[2], static_cast<int32_t>(insn.operands[1]), insn.operands[0]); | ||||
|                     break; | ||||
|                 case PPC_INST_MR: | ||||
|                     std::println(f, "\tr{} = r{};", insn.operands[0], insn.operands[1]); | ||||
|                     break; | ||||
|                 case PPC_INST_LWZ: | ||||
|                     std::println(f, "\tr{} = *(r{} + {});", insn.operands[0], insn.operands[2], insn.operands[1]); | ||||
|                     break; | ||||
|                 case PPC_INST_LI: | ||||
|                     std::println(f, "\tr{} = {};", insn.operands[0], insn.operands[1]); | ||||
|                     break; | ||||
|                 case PPC_INST_MFLR: | ||||
|                     std::println(f, "\tr{} = lr;", insn.operands[0]); | ||||
|                     break; | ||||
|                 case PPC_INST_MTLR: | ||||
|                     std::println(f, "\tlr = r{};", insn.operands[0]); | ||||
|                     break; | ||||
|                 case PPC_INST_BLR: | ||||
|                     std::println(f, "\treturn;"); | ||||
|                     break; | ||||
|                 case PPC_INST_BL: | ||||
|                     { | ||||
|                         std::string targetName = ""; | ||||
|                         auto targetSymbol = image.symbols.find(insn.operands[0]); | ||||
|                         if (targetSymbol != image.symbols.end() && targetSymbol->type == Symbol_Function) | ||||
|                         { | ||||
|                             targetName = targetSymbol->name; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             targetName = std::format("sub_{:X}", insn.operands[0]); | ||||
|                         } | ||||
|                         std::println(f, "\tlr = 0x{:x};", base); | ||||
|                         std::println(f, "\t{}();", targetName); | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         std::println(f, "}}\n"); | ||||
|     } | ||||
| 
 | ||||
|     fclose(f); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| cmake_minimum_required (VERSION 3.8) | ||||
| 
 | ||||
| project("PowerRecomp") | ||||
| add_executable(PowerRecomp "main.cpp") | ||||
| 
 | ||||
| set_property(TARGET PowerRecomp PROPERTY CXX_STANDARD 20) | ||||
| add_executable(PowerRecomp "main.cpp") | ||||
| target_link_libraries(PowerRecomp PRIVATE LibPowerAnalyse) | ||||
|  |  | |||
|  | @ -1,4 +1,140 @@ | |||
| #include <file.h> | ||||
| #include <image.h> | ||||
| #include <function.h> | ||||
| #include <format> | ||||
| #include <print> | ||||
| #include <disasm.h> | ||||
| #include <filesystem> | ||||
| 
 | ||||
| #define TEST_FILE "add.elf" | ||||
| 
 | ||||
| int main() | ||||
| { | ||||
|     const auto file = LoadFile(TEST_FILE).value(); | ||||
|     auto image = Image::ParseImage(file.data(), file.size()).value(); | ||||
| 
 | ||||
|     // TODO: Load functions from an existing database
 | ||||
|     std::vector<Function> functions; | ||||
|     for (const auto& section : image.sections) | ||||
|     { | ||||
|         if (!(section.flags & SectionFlags_Code)) | ||||
|         { | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         size_t base = section.base; | ||||
|         uint8_t* data = section.data; | ||||
|         uint8_t* dataEnd = section.data + section.size; | ||||
|         while (data < dataEnd) | ||||
|         { | ||||
|             if (*(uint32_t*)data == 0) | ||||
|             { | ||||
|                 data += 4; | ||||
|                 base += 4; | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             const auto& fn = functions.emplace_back(Function::Analyze(data, dataEnd - data, base)); | ||||
|             data += fn.size; | ||||
|             base += fn.size; | ||||
| 
 | ||||
|             image.symbols.emplace(std::format("sub_{:X}", fn.base), fn.base, fn.size, Symbol_Function); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::filesystem::create_directory("out"); | ||||
|     FILE* f = fopen("out/" TEST_FILE ".cpp", "w"); | ||||
|     for (const auto& fn : functions) | ||||
|     { | ||||
|         auto base = fn.base; | ||||
|         auto end = base + fn.size; | ||||
|         auto* data = (uint32_t*)image.Find(base); | ||||
| 
 | ||||
|         std::string name = ""; | ||||
|         auto symbol = image.symbols.find(base); | ||||
|         if (symbol != image.symbols.end()) | ||||
|         { | ||||
|             name = symbol->name; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             name = std::format("sub_{:X}", base); | ||||
|         } | ||||
| 
 | ||||
|         std::println(f, "void {}() {{", name); | ||||
| 
 | ||||
|         ppc_insn insn; | ||||
|         while (base < end) | ||||
|         { | ||||
|             ppc::Disassemble(data, 4, base, insn); | ||||
| 
 | ||||
|             base += 4; | ||||
|             ++data; | ||||
|             if (insn.opcode == nullptr) | ||||
|             { | ||||
|                 std::println(f, "\t// {:x} {}", base - 4, insn.op_str); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 std::println(f, "\t// {:x} {} {}", base - 4, insn.opcode->name, insn.op_str); | ||||
|                 switch (insn.opcode->id) | ||||
|                 { | ||||
|                 case PPC_INST_ADD: | ||||
|                     std::println(f, "\tr{} = r{} + r{};", insn.operands[0], insn.operands[1], insn.operands[2]); | ||||
|                     break; | ||||
|                 case PPC_INST_ADDI: | ||||
|                     std::println(f, "\tr{} = r{} + {};", insn.operands[0], insn.operands[1], insn.operands[2]); | ||||
|                     break; | ||||
|                 case PPC_INST_STWU: | ||||
|                     std::println(f, "\tea = r{} + {};", insn.operands[2], static_cast<int32_t>(insn.operands[1])); | ||||
|                     std::println(f, "\t*ea = byteswap(r{});", insn.operands[0]); | ||||
|                     std::println(f, "\tr{} = ea;", insn.operands[2]); | ||||
|                     break; | ||||
|                 case PPC_INST_STW: | ||||
|                     std::println(f, "\t*(r{} + {}) = byteswap(r{});", insn.operands[2], static_cast<int32_t>(insn.operands[1]), insn.operands[0]); | ||||
|                     break; | ||||
|                 case PPC_INST_MR: | ||||
|                     std::println(f, "\tr{} = r{};", insn.operands[0], insn.operands[1]); | ||||
|                     break; | ||||
|                 case PPC_INST_LWZ: | ||||
|                     std::println(f, "\tr{} = *(r{} + {});", insn.operands[0], insn.operands[2], insn.operands[1]); | ||||
|                     break; | ||||
|                 case PPC_INST_LI: | ||||
|                     std::println(f, "\tr{} = {};", insn.operands[0], insn.operands[1]); | ||||
|                     break; | ||||
|                 case PPC_INST_MFLR: | ||||
|                     std::println(f, "\tr{} = lr;", insn.operands[0]); | ||||
|                     break; | ||||
|                 case PPC_INST_MTLR: | ||||
|                     std::println(f, "\tlr = r{};", insn.operands[0]); | ||||
|                     break; | ||||
|                 case PPC_INST_BLR: | ||||
|                     std::println(f, "\treturn;"); | ||||
|                     break; | ||||
|                 case PPC_INST_BL: | ||||
|                 { | ||||
|                     std::string targetName = ""; | ||||
|                     auto targetSymbol = image.symbols.find(insn.operands[0]); | ||||
|                     if (targetSymbol != image.symbols.end() && targetSymbol->type == Symbol_Function) | ||||
|                     { | ||||
|                         targetName = targetSymbol->name; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         targetName = std::format("sub_{:X}", insn.operands[0]); | ||||
|                     } | ||||
|                     std::println(f, "\tlr = 0x{:x};", base); | ||||
|                     std::println(f, "\t{}();", targetName); | ||||
|                     break; | ||||
|                 } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         std::println(f, "}}\n"); | ||||
|     } | ||||
| 
 | ||||
|     fclose(f); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -1,13 +1,14 @@ | |||
| #pragma once | ||||
| #include <expected> | ||||
| #include <vector> | ||||
| 
 | ||||
| inline static std::vector<uint8_t> LoadFile(const char* path) | ||||
| inline static std::expected<std::vector<uint8_t>, int> LoadFile(const char* path) | ||||
| { | ||||
|     std::vector<uint8_t> data{}; | ||||
|     auto* stream = fopen(path, "rb"); | ||||
|     if (stream == nullptr) | ||||
|     { | ||||
|         return data; | ||||
|         return std::unexpected(1); | ||||
|     } | ||||
| 
 | ||||
|     fseek(stream, 0, SEEK_END); | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Sajid
						Sajid