diff options
| author | rajdakin <rajdakin@gmail.com> | 2023-02-12 19:32:06 +0100 |
|---|---|---|
| committer | rajdakin <rajdakin@gmail.com> | 2023-02-12 19:32:06 +0100 |
| commit | 0f914cf7470980511040f13ab19c7ff44dbe7c21 (patch) | |
| tree | 6a22bc820ce3e7bb37a938a83d92616e687d407e | |
| parent | 5fab7d29931ccf66ac41055042089be46e685abf (diff) | |
| download | box64-0f914cf7470980511040f13ab19c7ff44dbe7c21.tar.gz box64-0f914cf7470980511040f13ab19c7ff44dbe7c21.zip | |
[WRAPPER] Added the Windows calling convention support
| -rwxr-xr-x | rebuild_wrappers.py | 97 |
1 files changed, 66 insertions, 31 deletions
diff --git a/rebuild_wrappers.py b/rebuild_wrappers.py index e1e8961e..f41de8de 100755 --- a/rebuild_wrappers.py +++ b/rebuild_wrappers.py @@ -145,6 +145,14 @@ wrappedtestundefs.h: # TODO: Add /.F.*A/ automatic generation (and suppression) +class FunctionConvention(object): + def __init__(self, convname: str) -> None: + self.name = convname +conventions = { + 'F': FunctionConvention("System V"), + 'W': FunctionConvention("Windows") +} + # Free letters: B FG J QR T XYZab e gh jk mno qrst xyz class FunctionType(str): values: List[str] = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P', 'A'] @@ -163,11 +171,14 @@ class FunctionType(str): # TODO: change *FEv into true functions (right now they are redirected to *FE) #chk_type = s[0] + s[3:] - if s[1] not in ["F"]: + if s[1] not in conventions: raise NotImplementedError("Bad middle letter {0}{1}".format(s[1], post)) return all(c in FunctionType.values for c in chk_type) and (('v' not in chk_type[1:]) or (len(chk_type) == 2)) + def get_convention(self) -> FunctionConvention: + return conventions[self[1]] + def splitchar(self) -> List[int]: """ splitchar -- Sorting key function for function signatures @@ -1013,9 +1024,6 @@ def main(root: str, files: Iterable[Filename], ver: str): "\n#error Invalid return type: va_list\n", # A ] - # Name of the registers - reg_arg = ["R_RDI", "R_RSI", "R_RDX", "R_RCX", "R_R8", "R_R9"] - assert(len(reg_arg) == 6) # vreg: value is in a general register # E v c w i I C W u U f d D K l L p V O S N M H P A vreg = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2, 0, 1] @@ -1136,7 +1144,7 @@ def main(root: str, files: Iterable[Filename], ver: str): "*(void**)(R_RSP + {p}), ", # P "*(void**)(R_RSP + {p}), ", # A ] - + # Asserts if len(FunctionType.values) != len(vstack): raise NotImplementedError("len(values) = {lenval} != len(vstack) = {lenvstack}".format(lenval=len(FunctionType.values), lenvstack=len(vstack))) @@ -1176,7 +1184,7 @@ def main(root: str, files: Iterable[Filename], ver: str): raise NotImplementedError("Something can be in an XMM register but not in the stack") # Helper functions to write the function definitions - def function_args(args: FunctionType, d: int = 8, r: int = 0, x: int = 0) -> str: + def function_args(conv: FunctionConvention, args: FunctionType, d: int = 8, r: int = 0, x: int = 0) -> str: # args: string of argument types # d: delta (in the stack) # r: general register no @@ -1186,40 +1194,67 @@ def main(root: str, files: Iterable[Filename], ver: str): # Redirections if args[0] == "0": - return "0, " + function_args(args[1:], d, r, x) + return "0, " + function_args(conv, args[1:], d, r, x) elif args[0] == "1": - return "1, " + function_args(args[1:], d, r, x) + return "1, " + function_args(conv, args[1:], d, r, x) idx = FunctionType.values.index(args[0]) - if (r < 6) and (vreg[idx] > 0): - ret = "" - for _ in range(vreg[idx]): - # There may be values in multiple registers - if r < 6: - # Value is in a general register - ret = ret + arg_r[idx].format(p=reg_arg[r]) - r = r + 1 - else: - # Remaining is in the stack - ret = ret + arg_s[idx].format(p=d) - d = d + 8 - return ret + function_args(args[1:], d, r, x) - elif (x < 8) and (vxmm[idx] > 0): - # Value is in an XMM register - return arg_x[idx].format(p=x) + function_args(args[1:], d, r, x+1) - elif vstack[idx] > 0: - # Value is in the stack - return arg_s[idx].format(p=d) + function_args(args[1:], d+8*vstack[idx], r, x) - else: - # Value is somewhere else - return arg_o[idx].format(p=d) + function_args(args[1:], d, r, x) + if conv.name == "System V": + # Name of the registers + reg_arg = ["R_RDI", "R_RSI", "R_RDX", "R_RCX", "R_R8", "R_R9"] + if (r < len(reg_arg)) and (vreg[idx] > 0): + ret = "" + for _ in range(vreg[idx]): + # There may be values in multiple registers + if r < len(reg_arg): + # Value is in a general register + ret = ret + arg_r[idx].format(p=reg_arg[r]) + r = r + 1 + else: + # Remaining is in the stack + ret = ret + arg_s[idx].format(p=d) + d = d + 8 + return ret + function_args(conv, args[1:], d, r, x) + elif (x < 8) and (vxmm[idx] > 0): + # Value is in an XMM register + return arg_x[idx].format(p=x) + function_args(conv, args[1:], d, r, x+1) + elif vstack[idx] > 0: + # Value is in the stack + return arg_s[idx].format(p=d) + function_args(conv, args[1:], d+8*vstack[idx], r, x) + else: + # Value is somewhere else + return arg_o[idx].format(p=d) + function_args(conv, args[1:], d, r, x) + else: # Windows + reg_arg = ["R_RCX", "R_RDX", "R_R8", "R_R9"] + if (r < len(reg_arg)) and (vreg[idx] > 0): + ret = "" + for _ in range(vreg[idx]): + # There may be values in multiple registers + if r < len(reg_arg): + # Value is in a general register + ret = ret + arg_r[idx].format(p=reg_arg[r]) + r = r + 1 + else: + # Remaining is in the stack + ret = ret + arg_s[idx].format(p=d) + d = d + 8 + return ret + function_args(conv, args[1:], d, r, x) + elif (x < 4) and (vxmm[idx] > 0): + # Value is in an XMM register + return arg_x[idx].format(p=x) + function_args(conv, args[1:], d, r, x+1) + elif vstack[idx] > 0: + # Value is in the stack + return arg_s[idx].format(p=d) + function_args(conv, args[1:], d+8*vstack[idx], r, x) + else: + # Value is somewhere else + return arg_o[idx].format(p=d) + function_args(conv, args[1:], d, r, x) def function_writer(f, N: FunctionType, W: str) -> None: # Write to f the function type N (real type W) f.write("void {0}(x64emu_t *emu, uintptr_t fcn) {2} {1} fn = ({1})fcn; ".format(N, W, "{")) # Generic function - f.write(vals[FunctionType.values.index(N[0])].format(function_args(N[2:])[:-2]) + " }\n") + f.write(vals[FunctionType.values.index(N[0])].format(function_args(N.get_convention(), N[2:])[:-2]) + " }\n") for k in gbls: if k != str(Clauses()): |