1 module gbaid.gba.assembly; 2 3 import std.algorithm.searching : find; 4 import std.exception : assumeUnique; 5 6 version (D_InlineAsm_X86_64) { 7 public enum string LINE_BACKGROUND_TEXT_ASM = "asm {" 8 ~ import("line_background_text_x64.s").convertToDASM() ~ 9 "}"; 10 public enum string LINE_BACKGROUND_AFFINE_ASM = "asm {" 11 ~ import("line_background_affine_x64.s").convertToDASM() ~ 12 "}"; 13 public enum string ADD_WITH_FLAGS_ASM = "asm {" 14 ~ import("add_with_flags_x64.s").convertToDASM() ~ 15 "}"; 16 public enum string SUB_WITH_FLAGS_ASM = "asm {" 17 ~ import("sub_with_flags_x64.s").convertToDASM() ~ 18 "}"; 19 } else version (D_InlineAsm_X86) { 20 public enum string LINE_BACKGROUND_TEXT_ASM = "asm {" 21 ~ import("line_background_text_x64.s").x64_to_x86().convertToDASM() ~ 22 "}"; 23 public enum string LINE_BACKGROUND_AFFINE_ASM = "asm {" 24 ~ import("line_background_affine_x64.s").x64_to_x86().convertToDASM() ~ 25 "}"; 26 public enum string ADD_WITH_FLAGS_ASM = "asm {" 27 ~ import("add_with_flags_x64.s").x64_to_x86().convertToDASM() ~ 28 "}"; 29 public enum string SUB_WITH_FLAGS_ASM = "asm {" 30 ~ import("sub_with_flags_x64.s").x64_to_x86().convertToDASM() ~ 31 "}"; 32 } 33 34 private string convertToDASM(string rawAsm) { 35 return rawAsm.removeComments().addSemiColons(); 36 } 37 38 private string removeComments(inout char[] asmStr) { 39 char[] noComments; 40 auto ignore = false; 41 foreach (c; asmStr) { 42 if (c == ';') { 43 ignore = true; 44 } else if (c == '\r' || c == '\n') { 45 ignore = false; 46 } 47 if (!ignore) { 48 noComments ~= c; 49 } 50 } 51 return noComments.assumeUnique(); 52 } 53 54 private string addSemiColons(inout char[] asmStr) { 55 char[] withSemiColons = [asmStr[0]]; 56 foreach (i, c; asmStr[1 .. $]) { 57 withSemiColons ~= c; 58 if (c == '\n' && asmStr[i - 1] != ':') { 59 withSemiColons ~= ';'; 60 } 61 } 62 return withSemiColons.assumeUnique(); 63 } 64 65 // Very basic conversion for the purpose of this project only 66 // Only converts 64 registers to 32 bit and pushfq to pusfd 67 private string x64_to_x86(inout char[] x64) { 68 size_t length = x64.length; 69 char[] x86; 70 x86.length = length; 71 foreach (i; 0 .. length - 2) { 72 if (x64[i] == 'R' && x64[i + 2] == 'X') { 73 char c = x64[i + 1]; 74 if (c == 'A' || c == 'B' || c == 'C' || c == 'D') { 75 x86[i] = 'E'; 76 continue; 77 } 78 } 79 x86[i] = x64[i]; 80 } 81 x86[length - 1] = x64[length - 1]; 82 x86[length - 2] = x64[length - 2]; 83 84 auto pushOp = x86.find("pushfq"); 85 if (pushOp.length > 0) { 86 pushOp[5] = 'd'; 87 } 88 89 return x86.assumeUnique; 90 }