Commit 8aa7ba36 authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

Merge branch 'develop' of gitlab.anu.edu.au:mu/mu-impl-fast into develop

parents 18d3368e b92de713
...@@ -26,16 +26,19 @@ doctest = false ...@@ -26,16 +26,19 @@ doctest = false
default = ["aot"] default = ["aot"]
aot = [] aot = []
jit = [] jit = []
sel4-rumprun = []
sel4-rumprun-target-side = []
[build-dependencies] [build-dependencies]
gcc = "*" gcc = "*"
built = "0.1" #built = "0.1"
[dependencies] [dependencies]
mu_ast = {path = "src/ast"} mu_ast = {path = "src/ast"}
mu_utils = {path = "src/utils"} mu_utils = {path = "src/utils"}
mu_gc = {path = "src/gc"} #mu_gc = {path = "src/gc"}
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" } rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" }
#rodal = { path = "../rodal_test/rodal", version = ">= 0.0.5" }
libc="*" libc="*"
field-offset = "*" field-offset = "*"
...@@ -55,4 +58,21 @@ docopt = "*" ...@@ -55,4 +58,21 @@ docopt = "*"
petgraph = "*" petgraph = "*"
extprim = "*" extprim = "*"
num-traits = "*" num-traits = "*"
#built = "0.1"
[target.x86_64-unknown-linux-gnu.dependencies]
mu_gc = { path = "src/gc", default-features = false}
built = "0.1"
[target.x86_64-apple-darwin.dependencies]
mu_gc = { path = "src/gc", default-features = false}
built = "0.1"
[target.x86_64-rumprun-netbsd.dependencies]
mu_gc = { path = "src/gc", default-features = false, features = ["sel4-rumprun-target-side"], target = "x86_64-rumprun-netbsd"}
[target.x86_64-unknown-linux-gnu.build-dependencies]
built = "0.1"
[target.x86_64-apple-darwin.build-dependencies]
built = "0.1" built = "0.1"
...@@ -12,9 +12,12 @@ ...@@ -12,9 +12,12 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#[cfg(not(feature = "sel4-rumprun-target-side"))]
extern crate built; extern crate built;
extern crate gcc; extern crate gcc;
#[cfg(not(feature = "sel4-rumprun-target-side"))]
#[cfg(any(target_os = "macos", target_os = "linux"))] #[cfg(any(target_os = "macos", target_os = "linux"))]
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn main() { fn main() {
...@@ -29,6 +32,7 @@ fn main() { ...@@ -29,6 +32,7 @@ fn main() {
built(); built();
} }
#[cfg(not(feature = "sel4-rumprun-target-side"))]
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
fn main() { fn main() {
...@@ -43,6 +47,34 @@ fn main() { ...@@ -43,6 +47,34 @@ fn main() {
built(); built();
} }
#[cfg(not(feature = "sel4-rumprun-target-side"))]
fn built() { fn built() {
built::write_built_file().expect("Failed to acquire build-time information"); built::write_built_file().expect("Failed to acquire build-time information");
} }
#[cfg(feature = "sel4-rumprun-target-side")]
#[cfg(target_arch = "x86_64")]
fn main() {
use std::path::Path;
let mut compiler_name = String::new();
compiler_name.push_str("x86_64-rumprun-netbsd-gcc");
gcc::Config::new()
.flag("-O3")
.flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("src/runtime/runtime_x64_sel4_rumprun_sysv.c")
.compile("libruntime_c.a");
gcc::Config::new()
.flag("-O3")
.flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("src/runtime/runtime_asm_x64_sel4_rumprun_sysv.S")
.compile("libruntime_asm.a");
gcc::Config::new()
.flag("-O3")
.flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("zebu_c_helpers.c")
.compile("libzebu_c_helpers.a");
}
#!/usr/bin/env bash
export ZEBU_TARGET=x86_64-rumprun-netbsd
cd ././../rumprun-sel4/
bash clean_and_build.sh
\ No newline at end of file
...@@ -26,3 +26,4 @@ lazy_static = "*" ...@@ -26,3 +26,4 @@ lazy_static = "*"
log = "*" log = "*"
simple_logger = "*" simple_logger = "*"
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" } rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" }
#rodal = { path = "../../../rodal_test/rodal", version = ">= 0.0.5" }
...@@ -3574,6 +3574,7 @@ fn write_const_value(f: &mut File, constant: P<Value>) { ...@@ -3574,6 +3574,7 @@ fn write_const_value(f: &mut File, constant: P<Value>) {
} }
} }
use std::collections::HashMap; use std::collections::HashMap;
pub fn emit_context_with_reloc( pub fn emit_context_with_reloc(
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#![allow(unused_variables)] #![allow(unused_variables)]
use compiler::backend::AOT_EMIT_CONTEXT_FILE; use compiler::backend::AOT_EMIT_CONTEXT_FILE;
use compiler::backend::AOT_EMIT_SYM_TABLE_FILE;
use compiler::backend::RegGroup; use compiler::backend::RegGroup;
use utils::ByteSize; use utils::ByteSize;
use utils::Address; use utils::Address;
...@@ -3792,6 +3793,7 @@ fn write_const_align(f: &mut File) { ...@@ -3792,6 +3793,7 @@ fn write_const_align(f: &mut File) {
} }
/// writes alignment in bytes for linux /// writes alignment in bytes for linux
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
fn write_align(f: &mut File, align: ByteSize) { fn write_align(f: &mut File, align: ByteSize) {
use std::io::Write; use std::io::Write;
...@@ -3801,6 +3803,7 @@ fn write_align(f: &mut File, align: ByteSize) { ...@@ -3801,6 +3803,7 @@ fn write_align(f: &mut File, align: ByteSize) {
/// writes alignment for macos. For macos, .align is followed by exponent /// writes alignment for macos. For macos, .align is followed by exponent
/// (e.g. 16 bytes is 2^4, writes .align 4 on macos) /// (e.g. 16 bytes is 2^4, writes .align 4 on macos)
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
fn write_align(f: &mut File, align: ByteSize) { fn write_align(f: &mut File, align: ByteSize) {
use std::io::Write; use std::io::Write;
...@@ -3815,6 +3818,14 @@ fn write_align(f: &mut File, align: ByteSize) { ...@@ -3815,6 +3818,14 @@ fn write_align(f: &mut File, align: ByteSize) {
f.write_fmt(format_args!("\t.align {}\n", n)).unwrap(); f.write_fmt(format_args!("\t.align {}\n", n)).unwrap();
} }
/// writes alignment in bytes for sel4-rumprun, which is exactly the same as Linux
#[cfg(feature = "sel4-rumprun")]
fn write_align(f: &mut File, align: ByteSize) {
use std::io::Write;
f.write_fmt(format_args!("\t.align {}\n", check_align(align)))
.unwrap();
}
/// writes a constant to assembly output /// writes a constant to assembly output
fn write_const(f: &mut File, constant: P<Value>, loc: P<Value>) { fn write_const(f: &mut File, constant: P<Value>, loc: P<Value>) {
use std::io::Write; use std::io::Write;
...@@ -3901,6 +3912,149 @@ fn write_const_value(f: &mut File, constant: P<Value>) { ...@@ -3901,6 +3912,149 @@ fn write_const_value(f: &mut File, constant: P<Value>) {
} }
} }
#[cfg(not(feature = "sel4-rumprun"))]
pub fn emit_sym_table(vm: &VM) {
debug!("Currently nothing to emit for --!");
}
fn mangle_all(name_vec: &mut Vec<String>) {
for i in 0..name_vec.len() {
name_vec[i] = name_vec[i]
.replace('.', "Zd")
.replace('-', "Zh")
.replace(':', "Zc")
.replace('#', "Za");
name_vec[i] = "__mu_".to_string() + &name_vec[i];
}
}
#[cfg(feature = "sel4-rumprun")]
pub fn emit_sym_table(vm: &VM) {
use std::path;
use std::io::Write;
// Here goes the code to generate an asm file to resolve symbol addresses at link time
// in this stage, a single sym_file is generated for the test
// these sym_files will be compiled in build.rs in the parent directory of sel4 side
//**************************************************
// first create the asm file in the correct path
// _st added file name and path stands for _SymTable
//*************************************************
debug!("Going to emit Sym table for sel4-rumprun");
let mut file_path_st = path::PathBuf::new();
file_path_st.push(&vm.vm_options.flag_aot_emit_dir);
// vm file name is: "mu_sym_table.s"
file_path_st.push(format!("{}", AOT_EMIT_SYM_TABLE_FILE));
let mut file_st = match File::create(file_path_st.as_path()) {
Err(why) => {
panic!(
"couldn't create SYM TABLE file {}: {}",
file_path_st.to_str().unwrap(),
why
)
}
Ok(file) => file
};
// **************************************************
// mu_sym_table.s content generation
// *************************************************
// Code for exporting all of the required symbols \
// in vm, using the following fields:
// compiled_funcs.CompiledFunction.start
// compiled_funcs.CompiledFunction.end
// compiled_funcs.CompiledFunction.Frame. \
// exception_callsites[iter](src,_)
// compiled_funcs.CompiledFunction.Frame. \
// exception_callsites[iter](_,dest)
// ret
// *************************************************
let mut sym_vec: Vec<String> = Vec::new();
let compiled_funcs: &HashMap<_, _> = &vm.compiled_funcs().read().unwrap();
for (theID, theCFs) in compiled_funcs.iter() {
let theCF: &CompiledFunction = &theCFs.read().unwrap();
match theCF.start {
// CF.start can only be relocatable , otherwise panic
ValueLocation::Relocatable(_, ref symbol) => {
// debug!("theCF.start, symbol = {}\n", *symbol);
sym_vec.push((*symbol).clone());
}
// CF.start can't reach this state
_ => {
panic!(
"Sym_Table_start: expecting Relocatable location, found {}",
theCF.start
)
}
}
match theCF.end {
// CF.start can only be relocatable , otherwise panic
ValueLocation::Relocatable(_, ref symbol) => {
// debug!("theCF.end, symbol = {}\n", *symbol);
sym_vec.push((*symbol).clone());
}
// CF.end can't reach this state
_ => {
panic!(
"Sym_Table_end: expecting Relocatable location, found {}",
theCF.end
)
}
}
// for &(ref callsite, ref dest) in theCF.frame.get_exception_callsites().iter(){
// match *callsite {
// ValueLocation::Relocatable(_, ref symbol) => {
// sym_vec.push((*symbol).clone());
// },
// // can't reach this state
// _ => panic!("Sym_Table_callsite: expecting Relocatable location, found {}",
// callsite)
// }
// match *dest {
// ValueLocation::Relocatable(_, ref symbol) => {
// sym_vec.push((*symbol).clone());
// },
// // can't reach this state
// _ => panic!("Sym_Table_callsite: expecting Relocatable location, found {}",
// dest)
// }
// }
}
mangle_all(&mut sym_vec);
file_st.write("\t.data\n".as_bytes()).unwrap();
file_st
.write_fmt(format_args!(
"\t{}\n",
directive_globl("mu_sym_table".to_string())
))
.unwrap();
file_st.write_fmt(format_args!("mu_sym_table:\n")).unwrap();
file_st
.write_fmt(format_args!(".quad {}\n", sym_vec.len()))
.unwrap();
for i in 0..sym_vec.len() {
file_st
.write_fmt(format_args!(".quad {}\n", sym_vec[i].len()))
.unwrap();
file_st
.write_fmt(format_args!(".ascii \"{}\"\n", sym_vec[i]))
.unwrap();
file_st
.write_fmt(format_args!(".quad {}\n", sym_vec[i]))
.unwrap();
}
}
use std::collections::HashMap; use std::collections::HashMap;
use compiler::backend::code_emission::emit_mu_types; use compiler::backend::code_emission::emit_mu_types;
...@@ -4094,6 +4248,8 @@ pub fn emit_context_with_reloc( ...@@ -4094,6 +4248,8 @@ pub fn emit_context_with_reloc(
dumper.finish(); dumper.finish();
emit_sym_table(vm);
debug!("---finish---"); debug!("---finish---");
} }
...@@ -4142,27 +4298,43 @@ fn directive_comm(name: String, size: ByteSize, align: ByteSize) -> String { ...@@ -4142,27 +4298,43 @@ fn directive_comm(name: String, size: ByteSize, align: ByteSize) -> String {
} }
/// returns symbol for a string (on linux, returns the same string) /// returns symbol for a string (on linux, returns the same string)
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub fn symbol(name: String) -> String { pub fn symbol(name: String) -> String {
name name
} }
/// returns symbol for a string (on macos, prefixes it with a understore (_)) /// returns symbol for a string (on macos, prefixes it with a understore (_))
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub fn symbol(name: String) -> String { pub fn symbol(name: String) -> String {
format!("_{}", name) format!("_{}", name)
} }
/// returns symbol for a string (on sel4-rumprun, returns the same string)
#[cfg(feature = "sel4-rumprun")]
pub fn symbol(name: String) -> String {
name
}
/// returns a position-indepdent symbol for a string (on linux, postfixes it with @GOTPCREL) /// returns a position-indepdent symbol for a string (on linux, postfixes it with @GOTPCREL)
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub fn pic_symbol(name: String) -> String { pub fn pic_symbol(name: String) -> String {
format!("{}@GOTPCREL", name) format!("{}@GOTPCREL", name)
} }
/// returns a position-indepdent symbol for a string (on macos, returns the same string) /// returns a position-indepdent symbol for a string (on macos, returns the same string)
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub fn pic_symbol(name: String) -> String { pub fn pic_symbol(name: String) -> String {
symbol(name) symbol(name)
} }
/// returns a position-indepdent symbol for a string (on sel4-rumprun, postfixes it with @GOTPCREL)
#[cfg(feature = "sel4-rumprun")]
pub fn pic_symbol(name: String) -> String {
format!("{}@GOTPCREL", name)
}
use compiler::machine_code::CompiledFunction; use compiler::machine_code::CompiledFunction;
/// rewrites the machine code of a function version for spilling. /// rewrites the machine code of a function version for spilling.
......
...@@ -4729,7 +4729,11 @@ impl<'a> InstructionSelection { ...@@ -4729,7 +4729,11 @@ impl<'a> InstructionSelection {
&Constant::FuncRef(func_id) => { &Constant::FuncRef(func_id) => {
// our code for linux has one more level of indirection // our code for linux has one more level of indirection
// so we need a load for linux // so we need a load for linux
if cfg!(target_os = "macos") { // sel4-rumprun is the same as Linux here
if cfg!(feature = "sel4-rumprun") {
let mem = self.get_mem_for_funcref(func_id, vm);
self.backend.emit_mov_r_mem(&tmp, &mem);
} else if cfg!(target_os = "macos") {
let mem = self.get_mem_for_funcref(func_id, vm); let mem = self.get_mem_for_funcref(func_id, vm);
self.backend.emit_lea_r64(&tmp, &mem); self.backend.emit_lea_r64(&tmp, &mem);
} else if cfg!(target_os = "linux") { } else if cfg!(target_os = "linux") {
...@@ -4957,7 +4961,33 @@ impl<'a> InstructionSelection { ...@@ -4957,7 +4961,33 @@ impl<'a> InstructionSelection {
unimplemented!() unimplemented!()
} else { } else {
// symbolic // symbolic
if cfg!(target_os = "macos") { if cfg!(feature = "sel4-rumprun") {
// Same as Linux:
// for a(%RIP), we need to load its address from a@GOTPCREL(%RIP)
// then load from the address.
// asm_backend will emit a@GOTPCREL(%RIP) for a(%RIP)
let got_loc = P(Value {
hdr: MuEntityHeader::unnamed(vm.next_id()),
ty: pv.ty.clone(),
v: Value_::Memory(MemoryLocation::Symbolic {
base: Some(x86_64::RIP.clone()),
label: pv.name(),
is_global: true,
is_native: false
})
});
// mov (got_loc) -> actual_loc
let actual_loc = self.make_temporary(f_context, pv.ty.clone(), vm);
self.emit_move_value_to_value(&actual_loc, &got_loc);
self.make_memory_op_base_offset(
&actual_loc,
0,
pv.ty.get_referent_ty().unwrap(),
vm
)
} else if cfg!(target_os = "macos") {
P(Value { P(Value {
hdr: MuEntityHeader::unnamed(vm.next_id()), hdr: MuEntityHeader::unnamed(vm.next_id()),
ty: pv.ty.get_referent_ty().unwrap(), ty: pv.ty.get_referent_ty().unwrap(),
...@@ -5823,7 +5853,8 @@ impl<'a> InstructionSelection { ...@@ -5823,7 +5853,8 @@ impl<'a> InstructionSelection {
}; };
self.current_constants.insert(id, val.clone()); self.current_constants.insert(id, val.clone());
self.current_constants_locs.insert(id, const_mem_val.clone()); self.current_constants_locs
.insert(id, const_mem_val.clone());
const_mem_val const_mem_val
} }
......
...@@ -34,6 +34,8 @@ use num::integer::lcm; ...@@ -34,6 +34,8 @@ use num::integer::lcm;
#[cfg(feature = "aot")] #[cfg(feature = "aot")]
pub const AOT_EMIT_CONTEXT_FILE: &'static str = "context.S"; pub const AOT_EMIT_CONTEXT_FILE: &'static str = "context.S";
pub const AOT_EMIT_SYM_TABLE_FILE: &'static str = "mu_sym_table.S";
// type alias to make backend code more readable // type alias to make backend code more readable
pub type Reg<'a> = &'a P<Value>; pub type Reg<'a> = &'a P<Value>;
pub type Mem<'a> = &'a P<Value>; pub type Mem<'a> = &'a P<Value>;
......
...@@ -24,6 +24,8 @@ crate-type = ["rlib"] ...@@ -24,6 +24,8 @@ crate-type = ["rlib"]
[features] [features]
default = [] default = []
use-sidemap = [] use-sidemap = []
sel4-rumprun = []
sel4-rumprun-target-side = []
[build-dependencies] [build-dependencies]
gcc = "*" gcc = "*"
...@@ -38,3 +40,4 @@ aligned_alloc = "*" ...@@ -38,3 +40,4 @@ aligned_alloc = "*"
crossbeam = "*" crossbeam = "*"
field-offset = "*" field-offset = "*"
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" } rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" }
#rodal = { path = "../../../rodal_test/rodal", version = ">= 0.0.5" }
...@@ -16,19 +16,49 @@ extern crate gcc; ...@@ -16,19 +16,49 @@ extern crate gcc;
#[cfg(any(target_os = "macos", target_os = "linux"))] #[cfg(any(target_os = "macos", target_os = "linux"))]
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn main() { fn build_libgc() {
gcc::compile_library("libgc_clib_x64.a", &["src/heap/gc/clib_x64.c"]); gcc::compile_library("libgc_clib_x64.a", &["src/heap/gc/clib_x64.c"]);
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
fn main() { fn build_libgc() {
gcc::compile_library("libgc_clib_aarch64.a", &["src/heap/gc/clib_aarch64.S"]); gcc::compile_library("libgc_clib_aarch64.a", &["src/heap/gc/clib_aarch64.S"]);
} }
// This is here to enable cross compiling from windows/x86_64 to linux/aarch64 // This is here to enable cross compiling from windows/x86_64 to linux/aarch64
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn main() { fn build_libgc() {
gcc::compile_library("libgc_clib_aarch64.a", &["src/heap/gc/clib_aarch64.S"]); gcc::compile_library("libgc_clib_aarch64.a", &["src/heap/gc/clib_aarch64.S"]);
} }
// Due to bugs, it is currently not possible to use conditional compilation \
// using features or target_..., so instead we use env variables
fn main() {
use std::env;
// For this variable: 1 means rumprun-sel4 and 0 means others
let mut gc_target = 0;
for (key, value) in env::vars() {
if key == "ZEBU_TARGET" {
if value == "x86_64-rumprun-netbsd" {
gc_target = 1;
break;
} else {
gc_target = 0;
break;
}
}
}
// for sel4-rumprun, do (if)
// otherwise, call the related target function
if gc_target == 1 {
use std::path::Path;
let mut compiler_name = String::new();
compiler_name.push_str("x86_64-rumprun-netbsd-gcc");
gcc::Config::new().flag("-O3").flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("src/heap/gc/clib_x64_sel4_rumprun.c")
.compile("libgc_clib_x64.a");
} else { build_libgc(); }
}
// Copyright 2017 The Australian National University
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
void* malloc_zero(size_t size) {
void* ret = malloc(size);
memset(ret, 0, size);
return ret;
}
uintptr_t immmix_get_stack_ptr() {
uintptr_t rsp;
// get current rsp, rbp (this C func frame)
__asm__(
"mov %%rsp, %0 \n"
: "=rm" (rsp)
);
return rsp;
}
int get_registers_count() {
return 16;
}
uintptr_t* get_registers () {
uintptr_t rax, rbx, rcx, rdx, rbp, rsp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
__asm__(
"mov %%rax, %0 \n"
"mov %%rbx, %1 \n"
"mov %%rcx, %2 \n"
"mov %%rdx, %3 \n"
"mov %%rbp, %4 \n"
"mov %%rsp, %5 \n"
"mov %%rsi, %5 \n"
"mov %%rdi, %6 \n"
"mov %%r8, %7 \n"
"mov %%r9, %8 \n"
"mov %%r10, %10\n"
"mov %%r11, %11\n"
"mov %%r12, %12\n"
"mov %%r13, %13\n"
"mov %%r14, %14\n"
"mov %%r15, %15\n"
: "=m" (rax),
"=m" (rbx),
"=m" (rcx),
"=m" (rdx),
"=m" (rbp),
"=m" (rsp),
"=m" (rsi),
"=m" (rdi),
"=m" (r8),
"=m" (r9),
"=m" (r10),
"=m" (r11),
"=m" (r12),
"=m" (r13),
"=m" (r14),
"=m" (r15)
:
:
);
uintptr_t* ret = (uintptr_t*) malloc(sizeof(uintptr_t) * 16);
ret[0] = rax;
ret[1] = rbx;
ret[2] = rcx;
ret[3] = rdx;
ret[4] = rbp;
ret[5] = rsp;
ret[6] = rsi;
ret[7] = rdi;
ret[8] = r8;
ret[9] = r9;
ret[10] = r10;
ret[11] = r11;
ret[12] = r12;
ret[13] = r13;
ret[14] = r14;