Browse Source

winch: Implement new trampolines (#6358)

* winch: Implement new trampolines

This change is a follow-up to
https://github.com/bytecodealliance/wasmtime/pull/6262, in which the new
trampolines, described [here](https://github.com/bytecodealliance/rfcs/blob/main/accepted/tail-calls.md#new-trampolines-and-vmcallercheckedanyfunc-changes),
were introduced to Wasmtime.

This change, focuses on the `array-to-wasm`,
`native-to-wasm` and `wasm-to-native` trampolines to restore Winch's
working state prior to the introduction of the new trampolines. It's
worth noting that the new approach for trampolines make it easier to support
the `TypedFunc` API in Winch. Prior to the introduction of the new
trampolines, it was not obvious how to approach it.

This change also introduces a pinned register that will hold the
`VMContext` pointer, which is loaded in the `*-to-wasm`  trampolines;
the `VMContext`  register is a pre-requisite to this change to support
the `wasm-to-native` trampolines.

Lastly, with the introduction of the `VMContext` register and the
`wasm-to-native` trampolines, this change also introduces support for
calling function imports, which is a variation of the already existing
calls to locally defined functions.

The other notable piece of this change aside from the trampolines is
`winch-codegen`'s dependency on `wasmtime-environ`. Winch is so closely
tied to the concepts exposed by the wasmtime crates that it makes sense
to tie them together, even though the separation provides some
advantages like easier testing in some cases, in the long run, there's
probably going to be less need to test Winch in isolation and rather
we'd rely more on integration style tests which require all of Wasmtime
pieces anyway (fuzzing, spec tests, etc).

This change doesn't update the  existing implmenetation of
`winch_codegen::FuncEnv`, but the intention is to update that part after
this change.

prtest:full

* tests: Ignore miri in Winch integration tests

* Remove hardcoded alignment and addend
pull/6387/head
Saúl Cabrera 2 years ago
committed by GitHub
parent
commit
20c5836295
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      Cargo.lock
  2. 63
      crates/winch/src/compiler.rs
  3. 2
      scripts/publish.rs
  4. 140
      tests/all/winch.rs
  5. 1
      winch/codegen/Cargo.toml
  6. 8
      winch/codegen/src/abi/mod.rs
  7. 79
      winch/codegen/src/codegen/call.rs
  8. 84
      winch/codegen/src/codegen/mod.rs
  9. 18
      winch/codegen/src/frame/mod.rs
  10. 8
      winch/codegen/src/isa/aarch64/abi.rs
  11. 10
      winch/codegen/src/isa/aarch64/masm.rs
  12. 12
      winch/codegen/src/isa/aarch64/mod.rs
  13. 8
      winch/codegen/src/isa/aarch64/regs.rs
  14. 22
      winch/codegen/src/isa/mod.rs
  15. 8
      winch/codegen/src/isa/x64/abi.rs
  16. 2
      winch/codegen/src/isa/x64/address.rs
  17. 22
      winch/codegen/src/isa/x64/masm.rs
  18. 32
      winch/codegen/src/isa/x64/mod.rs
  19. 22
      winch/codegen/src/isa/x64/regs.rs
  20. 2
      winch/codegen/src/lib.rs
  21. 16
      winch/codegen/src/masm.rs
  22. 11
      winch/codegen/src/regalloc.rs
  23. 5
      winch/codegen/src/stack.rs
  24. 400
      winch/codegen/src/trampoline.rs
  25. 3
      winch/codegen/src/visitor.rs
  26. 8
      winch/environ/src/lib.rs
  27. 15
      winch/filetests/filetests/aarch64/i32_add/const.wat
  28. 33
      winch/filetests/filetests/aarch64/i32_add/locals.wat
  29. 15
      winch/filetests/filetests/aarch64/i32_add/max.wat
  30. 17
      winch/filetests/filetests/aarch64/i32_add/max_one.wat
  31. 15
      winch/filetests/filetests/aarch64/i32_add/mixed.wat
  32. 23
      winch/filetests/filetests/aarch64/i32_add/params.wat
  33. 17
      winch/filetests/filetests/aarch64/i32_add/signed.wat
  34. 15
      winch/filetests/filetests/aarch64/i32_add/unsigned_with_zero.wat
  35. 15
      winch/filetests/filetests/aarch64/i64_add/const.wat
  36. 35
      winch/filetests/filetests/aarch64/i64_add/locals.wat
  37. 17
      winch/filetests/filetests/aarch64/i64_add/max.wat
  38. 17
      winch/filetests/filetests/aarch64/i64_add/max_one.wat
  39. 15
      winch/filetests/filetests/aarch64/i64_add/mixed.wat
  40. 23
      winch/filetests/filetests/aarch64/i64_add/params.wat
  41. 17
      winch/filetests/filetests/aarch64/i64_add/signed.wat
  42. 15
      winch/filetests/filetests/aarch64/i64_add/unsigned_with_zero.wat
  43. 158
      winch/filetests/filetests/x64/call/params.wat
  44. 59
      winch/filetests/filetests/x64/call/simple.wat
  45. 11
      winch/filetests/filetests/x64/i32_add/const.wat
  46. 28
      winch/filetests/filetests/x64/i32_add/locals.wat
  47. 11
      winch/filetests/filetests/x64/i32_add/max.wat
  48. 11
      winch/filetests/filetests/x64/i32_add/max_one.wat
  49. 11
      winch/filetests/filetests/x64/i32_add/mixed.wat
  50. 21
      winch/filetests/filetests/x64/i32_add/params.wat
  51. 11
      winch/filetests/filetests/x64/i32_add/signed.wat
  52. 11
      winch/filetests/filetests/x64/i32_add/unsigned_with_zero.wat
  53. 21
      winch/filetests/filetests/x64/i32_divs/const.wat
  54. 21
      winch/filetests/filetests/x64/i32_divs/one_zero.wat
  55. 21
      winch/filetests/filetests/x64/i32_divs/overflow.wat
  56. 27
      winch/filetests/filetests/x64/i32_divs/params.wat
  57. 21
      winch/filetests/filetests/x64/i32_divs/zero_zero.wat
  58. 15
      winch/filetests/filetests/x64/i32_divu/const.wat
  59. 15
      winch/filetests/filetests/x64/i32_divu/one_zero.wat
  60. 21
      winch/filetests/filetests/x64/i32_divu/params.wat
  61. 15
      winch/filetests/filetests/x64/i32_divu/signed.wat
  62. 15
      winch/filetests/filetests/x64/i32_divu/zero_zero.wat
  63. 11
      winch/filetests/filetests/x64/i32_mul/const.wat
  64. 28
      winch/filetests/filetests/x64/i32_mul/locals.wat
  65. 11
      winch/filetests/filetests/x64/i32_mul/max.wat
  66. 11
      winch/filetests/filetests/x64/i32_mul/max_one.wat
  67. 11
      winch/filetests/filetests/x64/i32_mul/mixed.wat
  68. 21
      winch/filetests/filetests/x64/i32_mul/params.wat
  69. 11
      winch/filetests/filetests/x64/i32_mul/signed.wat
  70. 11
      winch/filetests/filetests/x64/i32_mul/unsigned_with_zero.wat
  71. 25
      winch/filetests/filetests/x64/i32_rems/const.wat
  72. 25
      winch/filetests/filetests/x64/i32_rems/one_zero.wat
  73. 25
      winch/filetests/filetests/x64/i32_rems/overflow.wat
  74. 31
      winch/filetests/filetests/x64/i32_rems/params.wat
  75. 25
      winch/filetests/filetests/x64/i32_rems/zero_zero.wat
  76. 17
      winch/filetests/filetests/x64/i32_remu/const.wat
  77. 17
      winch/filetests/filetests/x64/i32_remu/one_zero.wat
  78. 23
      winch/filetests/filetests/x64/i32_remu/params.wat
  79. 17
      winch/filetests/filetests/x64/i32_remu/signed.wat
  80. 17
      winch/filetests/filetests/x64/i32_remu/zero_zero.wat
  81. 11
      winch/filetests/filetests/x64/i32_sub/const.wat
  82. 28
      winch/filetests/filetests/x64/i32_sub/locals.wat
  83. 11
      winch/filetests/filetests/x64/i32_sub/max.wat
  84. 11
      winch/filetests/filetests/x64/i32_sub/max_one.wat
  85. 11
      winch/filetests/filetests/x64/i32_sub/mixed.wat
  86. 21
      winch/filetests/filetests/x64/i32_sub/params.wat
  87. 11
      winch/filetests/filetests/x64/i32_sub/signed.wat
  88. 11
      winch/filetests/filetests/x64/i32_sub/unsigned_with_zero.wat
  89. 11
      winch/filetests/filetests/x64/i64_add/const.wat
  90. 29
      winch/filetests/filetests/x64/i64_add/locals.wat
  91. 13
      winch/filetests/filetests/x64/i64_add/max.wat
  92. 11
      winch/filetests/filetests/x64/i64_add/max_one.wat
  93. 11
      winch/filetests/filetests/x64/i64_add/mixed.wat
  94. 21
      winch/filetests/filetests/x64/i64_add/params.wat
  95. 11
      winch/filetests/filetests/x64/i64_add/signed.wat
  96. 11
      winch/filetests/filetests/x64/i64_add/unsigned_with_zero.wat
  97. 21
      winch/filetests/filetests/x64/i64_divs/const.wat
  98. 21
      winch/filetests/filetests/x64/i64_divs/one_zero.wat
  99. 21
      winch/filetests/filetests/x64/i64_divs/overflow.wat
  100. 27
      winch/filetests/filetests/x64/i64_divs/params.wat

1
Cargo.lock

@ -4431,6 +4431,7 @@ dependencies = [
"smallvec",
"target-lexicon",
"wasmparser 0.104.0",
"wasmtime-environ",
]
[[package]]

63
crates/winch/src/compiler.rs

@ -6,9 +6,9 @@ use wasmparser::FuncValidatorAllocations;
use wasmtime_cranelift_shared::{CompiledFunction, ModuleTextBuilder};
use wasmtime_environ::{
CompileError, DefinedFuncIndex, FilePos, FuncIndex, FunctionBodyData, FunctionLoc,
ModuleTranslation, ModuleTypes, PrimaryMap, Tunables, WasmFunctionInfo,
ModuleTranslation, ModuleTypes, PrimaryMap, Tunables, VMOffsets, WasmFunctionInfo,
};
use winch_codegen::TargetIsa;
use winch_codegen::{TargetIsa, TrampolineKind};
use winch_environ::FuncEnv;
pub(crate) struct Compiler {
@ -67,10 +67,11 @@ impl wasmtime_environ::Compiler for Compiler {
.unwrap(),
);
let mut validator = validator.into_validator(self.take_allocations());
let env = FuncEnv::new(&translation.module, translation.get_types(), &self.isa);
let vmoffsets = VMOffsets::new(self.isa.pointer_bytes(), &translation.module);
let env = FuncEnv::new(&translation.module, translation.get_types());
let buffer = self
.isa
.compile_function(&sig, &body, &env, &mut validator)
.compile_function(&sig, &body, &vmoffsets, &env, &mut validator)
.map_err(|e| CompileError::Codegen(format!("{e:?}")));
self.save_allocations(validator.into_allocations());
let buffer = buffer?;
@ -92,8 +93,21 @@ impl wasmtime_environ::Compiler for Compiler {
types: &ModuleTypes,
index: DefinedFuncIndex,
) -> Result<Box<dyn Any + Send>, CompileError> {
let _ = (translation, types, index);
todo!()
let func_index = translation.module.func_index(index);
let sig = translation.module.functions[func_index].signature;
let ty = &types[sig];
let wasm_ty = wasmparser::FuncType::new(
ty.params().iter().copied().map(Into::into),
ty.returns().iter().copied().map(Into::into),
);
let buffer = self
.isa
.compile_trampoline(&wasm_ty, TrampolineKind::ArrayToWasm(func_index))
.map_err(|e| CompileError::Codegen(format!("{:?}", e)))?;
let compiled_function =
CompiledFunction::new(buffer, CompiledFuncEnv {}, self.isa.function_alignment());
Ok(Box::new(compiled_function))
}
fn compile_native_to_wasm_trampoline(
@ -102,17 +116,44 @@ impl wasmtime_environ::Compiler for Compiler {
types: &ModuleTypes,
index: DefinedFuncIndex,
) -> Result<Box<dyn Any + Send>, CompileError> {
let _ = (translation, types, index);
todo!()
let func_index = translation.module.func_index(index);
let sig = translation.module.functions[func_index].signature;
let ty = &types[sig];
let wasm_ty = wasmparser::FuncType::new(
ty.params().iter().copied().map(Into::into),
ty.returns().iter().copied().map(Into::into),
);
let buffer = self
.isa
.compile_trampoline(&wasm_ty, TrampolineKind::NativeToWasm(func_index))
.map_err(|e| CompileError::Codegen(format!("{:?}", e)))?;
let compiled_function =
CompiledFunction::new(buffer, CompiledFuncEnv {}, self.isa.function_alignment());
Ok(Box::new(compiled_function))
}
fn compile_wasm_to_native_trampoline(
&self,
translation: &ModuleTranslation<'_>,
_translation: &ModuleTranslation<'_>,
wasm_func_ty: &wasmtime_environ::WasmFuncType,
) -> Result<Box<dyn Any + Send>, CompileError> {
let _ = (translation, wasm_func_ty);
todo!()
let wasm_ty = wasmparser::FuncType::new(
wasm_func_ty.params().iter().copied().map(Into::into),
wasm_func_ty.returns().iter().copied().map(Into::into),
);
let buffer = self
.isa
.compile_trampoline(&wasm_ty, TrampolineKind::WasmToNative)
.map_err(|e| CompileError::Codegen(format!("{:?}", e)))?;
let compiled_function =
CompiledFunction::new(buffer, CompiledFuncEnv {}, self.isa.function_alignment());
Ok(Box::new(compiled_function))
}
fn append_code(

2
scripts/publish.rs

@ -42,7 +42,6 @@ const CRATES_TO_PUBLISH: &[&str] = &[
"wiggle-generate",
"wiggle-macro",
// winch
"winch-codegen",
"winch",
// wasmtime
"wasmtime-asm-macros",
@ -57,6 +56,7 @@ const CRATES_TO_PUBLISH: &[&str] = &[
"wasmtime-cranelift",
"wasmtime-jit",
"wasmtime-cache",
"winch-codegen",
"winch-environ",
"wasmtime-winch",
"wasmtime",

140
tests/all/winch.rs

@ -1,58 +1,12 @@
use anyhow::Result;
use wasmtime::*;
#[test]
#[ignore]
fn compiles_with_winch() -> Result<()> {
let mut c = Config::new();
c.strategy(Strategy::Winch);
let engine = Engine::new(&c)?;
// Winch only supports a very basic function signature for now while it's being developed.
let test_mod = r#"
const MODULE: &'static str = r#"
(module
(import "" "" (func $add (param i32 i32) (result i32)))
(func $test (result i32)
(i32.const 42)
)
(export "test" (func $test))
)
"#;
let mut store = Store::new(&engine, ());
let module = Module::new(&engine, test_mod)?;
let instance = Instance::new(&mut store, &module, &[])?;
let f = instance
.get_func(&mut store, "test")
.ok_or(anyhow::anyhow!("test function not found"))?;
let mut returns = vec![Val::null(); 1];
// Winch doesn't support calling typed functions at the moment.
f.call(&mut store, &[], &mut returns)?;
assert_eq!(returns.len(), 1);
assert_eq!(returns[0].unwrap_i32(), 42);
Ok(())
}
#[test]
#[ignore]
fn compiles_with_winch_stack_arguments() -> Result<()> {
let mut c = Config::new();
c.strategy(Strategy::Winch);
let engine = Engine::new(&c)?;
// Winch only supports a very basic function signature for now while it's being developed.
let test_mod = r#"
(module
(func $sum10 (param $arg_1 i32) (param $arg_2 i32) (param $arg_3 i32) (param $arg_4 i32) (param $arg_5 i32) (param $arg_6 i32) (param $arg_7 i32) (param $arg_8 i32) (param $arg_9 i32) (param $arg_10 i32) (result i32)
local.get $arg_1
local.get $arg_2
@ -73,30 +27,98 @@ fn compiles_with_winch_stack_arguments() -> Result<()> {
i32.add
local.get $arg_10
i32.add)
(func $call_add (param i32 i32) (result i32)
(local.get 0)
(local.get 1)
(call $add))
(export "42" (func $test))
(export "sum10" (func $sum10))
(export "call_add" (func $call_add))
)
"#;
fn add_fn(store: impl AsContextMut) -> Func {
Func::wrap(store, |a: i32, b: i32| a + b)
}
#[test]
#[cfg_attr(miri, ignore)]
fn array_to_wasm() {
let mut c = Config::new();
c.strategy(Strategy::Winch);
let engine = Engine::new(&c).unwrap();
let mut store = Store::new(&engine, ());
let module = Module::new(&engine, MODULE).unwrap();
let module = Module::new(&engine, test_mod)?;
let add_fn = add_fn(store.as_context_mut());
let instance = Instance::new(&mut store, &module, &[add_fn.into()]).unwrap();
let instance = Instance::new(&mut store, &module, &[])?;
let constant = instance
.get_func(&mut store, "42")
.ok_or(anyhow::anyhow!("test function not found"))
.unwrap();
let mut returns = vec![Val::null(); 1];
constant.call(&mut store, &[], &mut returns).unwrap();
let f = instance
.get_func(&mut store, "sum10")
.ok_or(anyhow::anyhow!("sum10 function not found"))?;
assert_eq!(returns.len(), 1);
assert_eq!(returns[0].unwrap_i32(), 42);
let sum = instance
.get_func(&mut store, "sum10")
.ok_or(anyhow::anyhow!("sum10 function not found"))
.unwrap();
let mut returns = vec![Val::null(); 1];
// create a new Val array with ten 1s
let args = vec![Val::I32(1); 10];
// Winch doesn't support calling typed functions at the moment.
f.call(&mut store, &args, &mut returns)?;
sum.call(&mut store, &args, &mut returns).unwrap();
assert_eq!(returns.len(), 1);
assert_eq!(returns[0].unwrap_i32(), 10);
}
#[test]
#[cfg_attr(miri, ignore)]
fn native_to_wasm() {
let mut c = Config::new();
c.strategy(Strategy::Winch);
let engine = Engine::new(&c).unwrap();
let mut store = Store::new(&engine, ());
let module = Module::new(&engine, MODULE).unwrap();
let add_fn = add_fn(store.as_context_mut());
let instance = Instance::new(&mut store, &module, &[add_fn.into()]).unwrap();
let f = instance
.get_typed_func::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), i32>(
&mut store, "sum10",
)
.unwrap();
let args = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
let result = f.call(&mut store, args).unwrap();
assert_eq!(result, 10);
}
#[test]
#[cfg_attr(miri, ignore)]
fn wasm_to_native() {
let mut c = Config::new();
c.strategy(Strategy::Winch);
let engine = Engine::new(&c).unwrap();
let mut store = Store::new(&engine, ());
let module = Module::new(&engine, MODULE).unwrap();
let add_fn = add_fn(store.as_context_mut());
let instance = Instance::new(&mut store, &module, &[add_fn.into()]).unwrap();
let f = instance
.get_typed_func::<(i32, i32), i32>(&mut store, "call_add")
.unwrap();
let args = (41, 1);
let result = f.call(&mut store, args).unwrap();
Ok(())
assert_eq!(result, 42);
}

1
winch/codegen/Cargo.toml

@ -19,6 +19,7 @@ target-lexicon = { workspace = true, features = ["std"] }
cranelift-codegen = { workspace = true }
regalloc2 = { workspace = true }
gimli = { workspace = true }
wasmtime-environ = { workspace = true }
[features]
x64 = ["cranelift-codegen/x86"]

8
winch/codegen/src/abi/mod.rs

@ -33,6 +33,7 @@
//! | |
//! | |
//! | Stack slots |
//! | + `VMContext` slot |
//! | + dynamic space |
//! | |
//! | |
@ -78,6 +79,13 @@ pub(crate) trait ABI {
/// Returns the designated scratch register.
fn scratch_reg() -> Reg;
/// Returns the frame pointer register.
fn fp_reg() -> Reg;
/// Returns the pinned register used to hold
/// the `VMContext`.
fn vmctx_reg() -> Reg;
/// Returns the callee-saved registers for the given
/// calling convention.
fn callee_saved_regs(call_conv: &CallingConvention) -> SmallVec<[Reg; 9]>;

79
winch/codegen/src/codegen/call.rs

@ -2,23 +2,21 @@
//! calling convention, see [ABI].
use super::CodeGenContext;
use crate::{
abi::{align_to, calculate_frame_adjustment, ABIArg, ABIResult, ABISig, ABI},
abi::{ABIArg, ABIResult, ABISig, ABI},
masm::{CalleeKind, MacroAssembler, OperandSize},
reg::Reg,
stack::Val,
};
use wasmtime_environ::FuncIndex;
/// All the information needed to emit a function call.
pub(crate) struct FnCall<'a> {
/// The total stack space in bytes used by the function call.
/// This amount includes the sum of:
/// The stack space consumed by the function call; that is,
/// the sum of:
///
/// 1. The amount of stack space that needs to be explicitly
/// allocated at the callsite for callee arguments that
/// go in the stack, plus any alignment.
/// 2. The amount of stack space created by saving any live
/// 1. The amount of stack space created by saving any live
/// registers at the callsite.
/// 3. The amount of space used by any memory entries in the value
/// 2. The amount of space used by any memory entries in the value
/// stack present at the callsite, that will be used as
/// arguments for the function call. Any memory values in the
/// value stack that are needed as part of the function
@ -33,17 +31,17 @@ pub(crate) struct FnCall<'a> {
/// assigned); it's more efficient to track the space needed by
/// those memory values and reclaim it at once.
///
/// The machine stack state that this amount is capturing, is the following:
/// The machine stack throghout the function call is as follows:
/// ┌──────────────────────────────────────────────────┐
/// │ │
/// │
/// │ 1
/// │ Stack space created by any previous spills │
/// │ from the value stack; and which memory values │
/// │ are used as function arguments. │
/// │ │
/// ├──────────────────────────────────────────────────┤ ---> The Wasm value stack at this point in time would look like:
/// │ │ [ Reg | Reg | Mem(offset) | Mem(offset) ]
/// │
/// │ 2
/// │ Stack space created by saving │
/// │ any live registers at the callsite. │
/// │ │
@ -60,7 +58,7 @@ pub(crate) struct FnCall<'a> {
/// │ │
/// └──────────────────────────────────────────────────┘ ------> Stack pointer when emitting the call
///
total_stack_space: u32,
call_stack_space: u32,
/// The total stack space needed for the callee arguments on the
/// stack, including any adjustments to the function's frame and
/// aligned to to the required ABI alignment.
@ -87,7 +85,6 @@ impl<'a> FnCall<'a> {
/// having saved any live registers, so that we can account for
/// any pushes generated by register spilling.
pub fn new<A: ABI, M: MacroAssembler>(
abi: &A,
callee_sig: &'a ABISig,
context: &mut CodeGenContext,
masm: &mut M,
@ -135,34 +132,56 @@ impl<'a> FnCall<'a> {
}
};
let delta = calculate_frame_adjustment(
masm.sp_offset(),
abi.arg_base_offset() as u32,
abi.call_stack_align() as u32,
);
let arg_stack_space = align_to(arg_stack_space + delta, abi.call_stack_align() as u32);
Self {
abi_sig: &callee_sig,
arg_stack_space,
total_stack_space: (spilled_regs * <A as ABI>::word_bytes())
+ (memory_values * <A as ABI>::word_bytes())
+ arg_stack_space,
call_stack_space: (spilled_regs * <A as ABI>::word_bytes())
+ (memory_values * <A as ABI>::word_bytes()),
sp_offset_at_callsite,
}
}
/// Emit the function call.
pub fn emit<M: MacroAssembler, A: ABI>(
/// Emit a direct function call, to a locally defined function.
pub fn direct<M: MacroAssembler, A: ABI>(
&self,
masm: &mut M,
context: &mut CodeGenContext,
callee: FuncIndex,
alignment: u32,
addend: u32,
) {
let reserved_stack = masm.call(alignment, addend, self.arg_stack_space, |masm| {
self.assign_args(context, masm, <A as ABI>::scratch_reg());
CalleeKind::Direct(callee.as_u32())
});
self.post_call::<M, A>(masm, context, reserved_stack);
}
/// Emit an indirect function call, using a raw address.
pub fn indirect<M: MacroAssembler, A: ABI>(
&self,
masm: &mut M,
context: &mut CodeGenContext,
addr: M::Address,
alignment: u32,
addend: u32,
) {
let reserved_stack = masm.call(alignment, addend, self.arg_stack_space, |masm| {
let scratch = <A as ABI>::scratch_reg();
self.assign_args(context, masm, scratch);
masm.load(addr, scratch, OperandSize::S64);
CalleeKind::Indirect(scratch)
});
self.post_call::<M, A>(masm, context, reserved_stack);
}
fn post_call<M: MacroAssembler, A: ABI>(
&self,
masm: &mut M,
context: &mut CodeGenContext,
callee: u32,
size: u32,
) {
masm.reserve_stack(self.arg_stack_space);
self.assign_args(context, masm, <A as ABI>::scratch_reg());
masm.call(CalleeKind::Direct(callee));
masm.free_stack(self.total_stack_space);
masm.free_stack(self.call_stack_space + size);
context.drop_last(self.abi_sig.params.len());
// The stack pointer at the end of the function call
// cannot be less than what it was when starting the

84
winch/codegen/src/codegen/mod.rs

@ -1,11 +1,15 @@
use crate::{
abi::{ABISig, ABI},
masm::{MacroAssembler, OperandSize},
stack::Val,
CallingConvention,
};
use anyhow::Result;
use call::FnCall;
use wasmparser::{BinaryReader, FuncValidator, ValType, ValidatorResources, VisitOperator};
use wasmparser::{
BinaryReader, FuncType, FuncValidator, ValType, ValidatorResources, VisitOperator,
};
use wasmtime_environ::{FuncIndex, VMOffsets};
mod context;
pub(crate) use context::*;
@ -33,6 +37,9 @@ where
/// A reference to the current ABI.
pub abi: &'a A,
/// Offsets used with the VM context pointer.
vmoffsets: &'a VMOffsets<u8>,
}
impl<'a, A, M> CodeGen<'a, A, M>
@ -46,6 +53,7 @@ where
context: CodeGenContext<'a>,
env: &'a dyn FuncEnv,
sig: ABISig,
vmoffsets: &'a VMOffsets<u8>,
) -> Self {
Self {
sig,
@ -53,6 +61,7 @@ where
masm,
abi,
env,
vmoffsets,
}
}
@ -89,6 +98,12 @@ where
&mut self.context.regalloc,
);
// Save the vmctx pointer to its local slot in case we need to reload it
// at any point.
let vmctx_addr = self.masm.local_address(&self.context.frame.vmctx_slot);
self.masm
.store(<A as ABI>::vmctx_reg().into(), vmctx_addr, OperandSize::S64);
while !body.eof() {
let offset = body.original_position();
body.visit_operator(&mut ValidateThenVisit(validator.visitor(offset), self))??;
@ -121,16 +136,61 @@ where
}
/// Emit a direct function call.
pub fn emit_call(&mut self, index: u32) {
let callee = self.env.callee_from_index(index);
if callee.import {
// TODO: Only locally defined functions for now.
unreachable!()
pub fn emit_call(&mut self, index: FuncIndex) {
let callee = self.env.callee_from_index(index.as_u32());
let (sig, callee_addr): (ABISig, Option<<M as MacroAssembler>::Address>) = if callee.import
{
let mut params = vec![ValType::I64, ValType::I64];
params.extend_from_slice(&callee.ty.params());
let sig = FuncType::new(params, callee.ty.results().to_owned());
let caller_vmctx = <A as ABI>::vmctx_reg();
let callee_vmctx = self.context.any_gpr(self.masm);
let callee_vmctx_offset = self.vmoffsets.vmctx_vmfunction_import_vmctx(index);
let callee_vmctx_addr = self.masm.address_at_reg(caller_vmctx, callee_vmctx_offset);
// FIXME Remove harcoded operand size, this will be needed
// once 32-bit architectures are supported.
self.masm
.load(callee_vmctx_addr, callee_vmctx, OperandSize::S64);
let callee_body_offset = self.vmoffsets.vmctx_vmfunction_import_wasm_call(index);
let callee_addr = self.masm.address_at_reg(caller_vmctx, callee_body_offset);
// Put the callee / caller vmctx at the start of the
// range of the stack so that they are used as first
// and second arguments.
let stack = &mut self.context.stack;
let location = stack.len() - (sig.params().len() - 2);
stack.insert(location as usize, Val::reg(caller_vmctx));
stack.insert(location as usize, Val::reg(callee_vmctx));
(
self.abi.sig(&sig, &CallingConvention::Default),
Some(callee_addr),
)
} else {
(self.abi.sig(&callee.ty, &CallingConvention::Default), None)
};
let fncall = FnCall::new::<A, M>(&sig, &mut self.context, self.masm);
let alignment = self.abi.call_stack_align();
let addend = self.abi.arg_base_offset();
if let Some(addr) = callee_addr {
fncall.indirect::<M, A>(
self.masm,
&mut self.context,
addr,
alignment.into(),
addend.into(),
);
} else {
fncall.direct::<M, A>(
self.masm,
&mut self.context,
index,
alignment.into(),
addend.into(),
);
}
let sig = self.abi.sig(&callee.ty, &CallingConvention::Default);
let fncall = FnCall::new(self.abi, &sig, &mut self.context, self.masm);
fncall.emit::<M, A>(self.masm, &mut self.context, index);
}
/// Emit the usual function end instruction sequence.
@ -141,10 +201,6 @@ where
}
fn spill_register_arguments(&mut self) {
// TODO
// Revisit this once the implicit VMContext argument is introduced;
// when that happens the mapping between local slots and abi args
// is not going to be symmetric.
self.sig
.params
.iter()

18
winch/codegen/src/frame/mod.rs

@ -20,7 +20,7 @@ impl DefinedLocalsRange {
}
}
/// An abstraction to read the defined locals from the WASM binary for a function.
/// An abstraction to read the defined locals from the Wasm binary for a function.
#[derive(Default)]
pub(crate) struct DefinedLocals {
/// The defined locals for a function.
@ -30,13 +30,13 @@ pub(crate) struct DefinedLocals {
}
impl DefinedLocals {
/// Compute the local slots for a WASM function.
/// Compute the local slots for a Wasm function.
pub fn new(
reader: &mut BinaryReader<'_>,
validator: &mut FuncValidator<ValidatorResources>,
) -> Result<Self> {
let mut next_stack = 0;
// The first 32 bits of a WASM binary function describe the number of locals
// The first 32 bits of a Wasm binary function describe the number of locals.
let local_count = reader.read_var_u32()?;
let mut slots: Locals = Default::default();
@ -74,6 +74,9 @@ pub(crate) struct Frame {
/// Locals get calculated when allocating a frame and are readonly
/// through the function compilation lifetime.
pub locals: Locals,
/// The offset to the slot containing the `VMContext`.
pub vmctx_slot: LocalSlot,
}
impl Frame {
@ -90,14 +93,15 @@ impl Frame {
.map(|l| LocalSlot::new(l.ty, l.offset + defined_locals_start)),
);
let locals_size = align_to(
defined_locals_start + defined_locals.stack_size,
abi.stack_align().into(),
);
let vmctx_slots_size = <A as ABI>::word_bytes();
let vmctx_offset = defined_locals_start + defined_locals.stack_size + vmctx_slots_size;
let locals_size = align_to(vmctx_offset, abi.stack_align().into());
Ok(Self {
locals,
locals_size,
vmctx_slot: LocalSlot::i64(vmctx_offset),
defined_locals_range: DefinedLocalsRange(
defined_locals_start..defined_locals.stack_size,
),

8
winch/codegen/src/isa/aarch64/abi.rs

@ -87,6 +87,14 @@ impl ABI for Aarch64ABI {
todo!()
}
fn fp_reg() -> Reg {
regs::fp()
}
fn vmctx_reg() -> Reg {
regs::xreg(9)
}
fn callee_saved_regs(_call_conv: &CallingConvention) -> SmallVec<[Reg; 9]> {
regs::callee_saved()
}

10
winch/codegen/src/isa/aarch64/masm.rs

@ -136,7 +136,13 @@ impl Masm for MacroAssembler {
self.asm.str(src, dst, size);
}
fn call(&mut self, _callee: CalleeKind) {
fn call(
&mut self,
_alignment: u32,
_addend: u32,
_stack_args_size: u32,
_load_callee: impl FnMut(&mut Self) -> CalleeKind,
) -> u32 {
todo!()
}
@ -195,7 +201,7 @@ impl Masm for MacroAssembler {
self.sp_offset
}
fn address_from_reg(&self, reg: Reg, offset: u32) -> Self::Address {
fn address_at_reg(&self, reg: Reg, offset: u32) -> Self::Address {
Address::offset(reg, offset as i64)
}
}

12
winch/codegen/src/isa/aarch64/mod.rs

@ -8,7 +8,7 @@ use crate::{
regalloc::RegAlloc,
regset::RegSet,
stack::Stack,
FuncEnv,
FuncEnv, TrampolineKind,
};
use anyhow::Result;
use cranelift_codegen::settings::{self, Flags};
@ -17,6 +17,7 @@ use cranelift_codegen::{MachTextSectionBuilder, TextSectionBuilder};
use masm::MacroAssembler as Aarch64Masm;
use target_lexicon::Triple;
use wasmparser::{FuncType, FuncValidator, FunctionBody, ValidatorResources};
use wasmtime_environ::VMOffsets;
mod abi;
mod address;
@ -85,6 +86,7 @@ impl TargetIsa for Aarch64 {
&self,
sig: &FuncType,
body: &FunctionBody,
vmoffsets: &VMOffsets<u8>,
env: &dyn FuncEnv,
validator: &mut FuncValidator<ValidatorResources>,
) -> Result<MachBufferFinalized<Final>> {
@ -99,7 +101,7 @@ impl TargetIsa for Aarch64 {
// TODO: Add floating point bitmask
let regalloc = RegAlloc::new(RegSet::new(ALL_GPR, 0), scratch());
let codegen_context = CodeGenContext::new(regalloc, stack, &frame);
let mut codegen = CodeGen::new(&mut masm, &abi, codegen_context, env, abi_sig);
let mut codegen = CodeGen::new(&mut masm, &abi, codegen_context, env, abi_sig, vmoffsets);
codegen.emit(&mut body, validator)?;
Ok(masm.finalize())
@ -116,7 +118,11 @@ impl TargetIsa for Aarch64 {
32
}
fn host_to_wasm_trampoline(&self, _ty: &FuncType) -> Result<MachBufferFinalized<Final>> {
fn compile_trampoline(
&self,
_ty: &FuncType,
_kind: TrampolineKind,
) -> Result<MachBufferFinalized<Final>> {
todo!()
}
}

8
winch/codegen/src/isa/aarch64/regs.rs

@ -53,6 +53,11 @@ pub(crate) const fn zero() -> Reg {
xreg(31)
}
/// The VM context register.
pub(crate) const fn vmctx() -> Reg {
xreg(9)
}
/// Stack pointer register.
///
/// In aarch64 the zero and stack pointer registers are contextually
@ -132,7 +137,8 @@ const NON_ALLOCATABLE_GPR: u32 = (1 << ip0().hw_enc())
| (1 << fp().hw_enc())
| (1 << lr().hw_enc())
| (1 << zero().hw_enc())
| (1 << shadow_sp().hw_enc());
| (1 << shadow_sp().hw_enc())
| (1 << vmctx().hw_enc());
/// Bitmask to represent the available general purpose registers.
pub(crate) const ALL_GPR: u32 = u32::MAX & !NON_ALLOCATABLE_GPR;

22
winch/codegen/src/isa/mod.rs

@ -1,3 +1,4 @@
use crate::{FuncEnv, TrampolineKind};
use anyhow::{anyhow, Result};
use core::fmt::Formatter;
use cranelift_codegen::isa::{CallConv, IsaBuilder};
@ -9,8 +10,7 @@ use std::{
};
use target_lexicon::{Architecture, Triple};
use wasmparser::{FuncType, FuncValidator, FunctionBody, ValidatorResources};
use crate::FuncEnv;
use wasmtime_environ::VMOffsets;
#[cfg(feature = "x64")]
pub(crate) mod x64;
@ -149,6 +149,7 @@ pub trait TargetIsa: Send + Sync {
&self,
sig: &FuncType,
body: &FunctionBody,
vmoffsets: &VMOffsets<u8>,
env: &dyn FuncEnv,
validator: &mut FuncValidator<ValidatorResources>,
) -> Result<MachBufferFinalized<Final>>;
@ -186,8 +187,21 @@ pub trait TargetIsa: Send + Sync {
/// See `cranelift_codegen::isa::TargetIsa::function_alignment`.
fn function_alignment(&self) -> u32;
/// Generate a trampoline that can be used to call a wasm function from wasmtime.
fn host_to_wasm_trampoline(&self, ty: &FuncType) -> Result<MachBufferFinalized<Final>>;
/// Compile a trampoline kind.
///
/// This function, internally dispatches to the right trampoline to emit
/// depending on the `kind` paramter.
fn compile_trampoline(
&self,
ty: &FuncType,
kind: TrampolineKind,
) -> Result<MachBufferFinalized<Final>>;
/// Returns the pointer width of the ISA in bytes.
fn pointer_bytes(&self) -> u8 {
let width = self.triple().pointer_width().unwrap();
width.bytes()
}
}
impl Debug for &dyn TargetIsa {

8
winch/codegen/src/isa/x64/abi.rs

@ -121,6 +121,14 @@ impl ABI for X64ABI {
regs::scratch()
}
fn fp_reg() -> Reg {
regs::rbp()
}
fn vmctx_reg() -> Reg {
regs::vmctx()
}
fn callee_saved_regs(call_conv: &CallingConvention) -> SmallVec<[Reg; 9]> {
regs::callee_saved(call_conv)
}

2
winch/codegen/src/isa/x64/address.rs

@ -10,7 +10,7 @@ pub(crate) enum Address {
}
impl Address {
/// Create an offset
/// Create an offset.
pub fn offset(base: Reg, offset: u32) -> Self {
Self::Offset { base, offset }
}

22
winch/codegen/src/isa/x64/masm.rs

@ -4,7 +4,11 @@ use super::{
regs::{self, rbp, rsp},
};
use crate::masm::{DivKind, MacroAssembler as Masm, OperandSize, RegImm, RemKind};
use crate::{abi::LocalSlot, codegen::CodeGenContext, stack::Val};
use crate::{
abi::{align_to, calculate_frame_adjustment, LocalSlot},
codegen::CodeGenContext,
stack::Val,
};
use crate::{isa::reg::Reg, masm::CalleeKind};
use cranelift_codegen::{isa::x64::settings as x64_settings, settings, Final, MachBufferFinalized};
@ -114,8 +118,20 @@ impl Masm for MacroAssembler {
self.decrement_sp(8);
}
fn call(&mut self, callee: CalleeKind) {
fn call(
&mut self,
alignment: u32,
addend: u32,
stack_args_size: u32,
mut load_callee: impl FnMut(&mut Self) -> CalleeKind,
) -> u32 {
let delta = calculate_frame_adjustment(self.sp_offset(), addend, alignment);
let aligned_args_size = align_to(stack_args_size, alignment);
let total_stack = delta + aligned_args_size;
self.reserve_stack(total_stack);
let callee = load_callee(self);
self.asm.call(callee);
total_stack
}
fn load(&mut self, src: Address, dst: Reg, size: OperandSize) {
@ -237,7 +253,7 @@ impl Masm for MacroAssembler {
self.asm.finalize()
}
fn address_from_reg(&self, reg: Reg, offset: u32) -> Self::Address {
fn address_at_reg(&self, reg: Reg, offset: u32) -> Self::Address {
Address::offset(reg, offset)
}
}

32
winch/codegen/src/isa/x64/mod.rs

@ -8,18 +8,19 @@ use crate::isa::{x64::masm::MacroAssembler as X64Masm, CallingConvention};
use crate::masm::MacroAssembler;
use crate::regalloc::RegAlloc;
use crate::stack::Stack;
use crate::trampoline::Trampoline;
use crate::FuncEnv;
use crate::{
isa::{Builder, TargetIsa},
regset::RegSet,
};
use crate::{Trampoline, TrampolineKind};
use anyhow::Result;
use cranelift_codegen::settings::{self, Flags};
use cranelift_codegen::{isa::x64::settings as x64_settings, Final, MachBufferFinalized};
use cranelift_codegen::{MachTextSectionBuilder, TextSectionBuilder};
use target_lexicon::Triple;
use wasmparser::{FuncType, FuncValidator, FunctionBody, ValidatorResources};
use wasmtime_environ::VMOffsets;
use self::regs::ALL_GPR;
@ -90,6 +91,7 @@ impl TargetIsa for X64 {
&self,
sig: &FuncType,
body: &FunctionBody,
vmoffsets: &VMOffsets<u8>,
env: &dyn FuncEnv,
validator: &mut FuncValidator<ValidatorResources>,
) -> Result<MachBufferFinalized<Final>> {
@ -104,7 +106,7 @@ impl TargetIsa for X64 {
// TODO Add in floating point bitmask
let regalloc = RegAlloc::new(RegSet::new(ALL_GPR, 0), regs::scratch());
let codegen_context = CodeGenContext::new(regalloc, stack, &frame);
let mut codegen = CodeGen::new(&mut masm, &abi, codegen_context, env, abi_sig);
let mut codegen = CodeGen::new(&mut masm, &abi, codegen_context, env, abi_sig, vmoffsets);
codegen.emit(&mut body, validator)?;
@ -120,15 +122,31 @@ impl TargetIsa for X64 {
16
}
fn host_to_wasm_trampoline(&self, ty: &FuncType) -> Result<MachBufferFinalized<Final>> {
fn compile_trampoline(
&self,
ty: &FuncType,
kind: TrampolineKind,
) -> Result<MachBufferFinalized<Final>> {
use TrampolineKind::*;
let abi = abi::X64ABI::default();
let mut masm = X64Masm::new(self.shared_flags.clone(), self.isa_flags.clone());
let call_conv = self.wasmtime_call_conv();
let mut trampoline =
Trampoline::new(&mut masm, &abi, regs::scratch(), regs::argv(), &call_conv);
trampoline.emit_host_to_wasm(ty);
let mut trampoline = Trampoline::new(
&mut masm,
&abi,
regs::scratch(),
regs::argv(),
&call_conv,
self.pointer_bytes(),
);
match kind {
ArrayToWasm(idx) => trampoline.emit_array_to_wasm(ty, idx)?,
NativeToWasm(idx) => trampoline.emit_native_to_wasm(ty, idx)?,
WasmToNative => trampoline.emit_wasm_to_native(ty)?,
}
Ok(masm.finalize())
}

22
winch/codegen/src/isa/x64/regs.rs

@ -51,18 +51,25 @@ pub(crate) fn r9() -> Reg {
pub(crate) fn r10() -> Reg {
gpr(ENC_R10)
}
pub(crate) fn r11() -> Reg {
gpr(ENC_R11)
}
pub(crate) fn r12() -> Reg {
gpr(ENC_R12)
}
pub(crate) fn r13() -> Reg {
gpr(ENC_R13)
}
/// Used as a pinned register to hold
/// the `VMContext`.
/// Non-allocatable in Winch's default
/// ABI, and callee-saved in SystemV and
/// Fastcall.
pub(crate) fn r14() -> Reg {
gpr(ENC_R14)
}
pub(crate) fn vmctx() -> Reg {
r14()
}
pub(crate) fn rbx() -> Reg {
gpr(ENC_RBX)
}
@ -78,6 +85,13 @@ pub(crate) fn rbp() -> Reg {
gpr(ENC_RBP)
}
/// Used as the scratch register.
/// Non-allocatable in Winch's default
/// ABI.
pub(crate) fn r11() -> Reg {
gpr(ENC_R11)
}
pub(crate) fn scratch() -> Reg {
r11()
}
@ -151,7 +165,7 @@ pub(crate) fn xmm15() -> Reg {
const GPR: u32 = 16;
const ALLOCATABLE_GPR: u32 = (1 << GPR) - 1;
const NON_ALLOCATABLE_GPR: u32 = (1 << ENC_RBP) | (1 << ENC_RSP) | (1 << ENC_R11);
const NON_ALLOCATABLE_GPR: u32 = (1 << ENC_RBP) | (1 << ENC_RSP) | (1 << ENC_R11) | (1 << ENC_R14);
/// Bitmask to represent the available general purpose registers.
pub(crate) const ALL_GPR: u32 = ALLOCATABLE_GPR & !NON_ALLOCATABLE_GPR;

2
winch/codegen/src/lib.rs

@ -17,4 +17,6 @@ mod regalloc;
mod regset;
mod stack;
mod trampoline;
pub use trampoline::TrampolineKind;
use trampoline::*;
mod visitor;

16
winch/codegen/src/masm.rs

@ -39,6 +39,7 @@ pub(crate) enum RegImm {
Imm(i64),
}
#[derive(Clone)]
pub(crate) enum CalleeKind {
/// A function call to a raw address.
Indirect(Reg),
@ -83,7 +84,7 @@ impl From<Reg> for RegImm {
pub(crate) trait MacroAssembler {
/// The addressing mode.
type Address;
type Address: Copy;
/// Emit the function prologue.
fn prologue(&mut self);
@ -109,11 +110,18 @@ pub(crate) trait MacroAssembler {
/// current position of the stack pointer (e.g. [sp + offset].
fn address_at_sp(&self, offset: u32) -> Self::Address;
/// Construct an address that is relative to the given register.
fn address_from_reg(&self, reg: Reg, offset: u32) -> Self::Address;
/// Construct an address that is absolute to the current position
/// of the given register.
fn address_at_reg(&self, reg: Reg, offset: u32) -> Self::Address;
/// Emit a function call to either a local or external function.
fn call(&mut self, callee: CalleeKind);
fn call(
&mut self,
alignment: u32,
addend: u32,
stack_args_size: u32,
f: impl FnMut(&mut Self) -> CalleeKind,
) -> u32;
/// Get stack pointer offset.
fn sp_offset(&self) -> u32;

11
winch/codegen/src/regalloc.rs

@ -46,6 +46,12 @@ impl RegAlloc {
where
F: FnMut(&mut RegAlloc),
{
// If the scratch register is explicitly requested
// just return it, it's usage should never cause spills.
if named == self.scratch {
return named;
}
self.regset.gpr(named).unwrap_or_else(|| {
spill(self);
self.regset
@ -56,6 +62,9 @@ impl RegAlloc {
/// Mark a particular general purpose register as available.
pub fn free_gpr(&mut self, reg: Reg) {
self.regset.free_gpr(reg);
// Never mark the designated scratch register as allocatable.
if reg != self.scratch {
self.regset.free_gpr(reg);
}
}
}

5
winch/codegen/src/stack.rs

@ -117,6 +117,11 @@ impl Stack {
}
}
/// Insert a new value at the specified index.
pub fn insert(&mut self, at: usize, val: Val) {
self.inner.insert(at, val);
}
/// Get the length of the stack.
pub fn len(&self) -> usize {
self.inner.len()

400
winch/codegen/src/trampoline.rs

@ -1,15 +1,41 @@
//! Trampoline implementation for Winch.
//!
//! This module contains all the necessary pieces to emit the various
//! trampolines required by Wasmtime to call JIT code.
//
// TODO
//
// * Remove the usage of hardcoded operand sizes (`OperandSize::S64`) when
// loading/storing the VM context pointer. The real value of the operand size
// and VM context type should be derived from the ABI's pointer size. This is
// going to be relevant once 32-bit architectures are supported.
//
// * Save the fp and pc for fast stack walking.
use crate::{
abi::{align_to, calculate_frame_adjustment, ABIArg, ABIResult, ABI},
abi::{ABIArg, ABIParams, ABIResult, ABISig, ABI},
isa::CallingConvention,
masm::{CalleeKind, MacroAssembler, OperandSize, RegImm},
reg::Reg,
};
use anyhow::{anyhow, Result};
use smallvec::SmallVec;
use std::mem;
use wasmparser::{FuncType, ValType};
use wasmtime_environ::{FuncIndex, PtrSize};
/// A trampoline to provide interopt between different calling
/// conventions.
/// The supported trampoline kinds.
/// See https://github.com/bytecodealliance/rfcs/blob/main/accepted/tail-calls.md#new-trampolines-and-vmcallercheckedanyfunc-changes
/// for more details.
pub enum TrampolineKind {
/// Calling from native to Wasm, using the array calling convention.
ArrayToWasm(FuncIndex),
/// Calling from native to Wasm.
NativeToWasm(FuncIndex),
/// Calling from Wasm to native.
WasmToNative,
}
/// The main trampoline abstraction.
pub(crate) struct Trampoline<'a, A, M>
where
A: ABI,
@ -26,12 +52,15 @@ where
/// callee, so it can only be used after the callee-saved
/// registers are on the stack.
alloc_scratch_reg: Reg,
/// Registers to be saved as part of the trampoline's prologue and epilogue.
/// Registers to be saved as part of the trampoline's prologue
/// and to be restored as part of the trampoline's epilogue.
callee_saved_regs: SmallVec<[Reg; 9]>,
/// The calling convention used by the trampoline,
/// which is the Wasmtime variant of the system ABI's
/// calling convention.
call_conv: &'a CallingConvention,
/// The pointer size of the current ISA.
pointer_size: u8,
}
impl<'a, A, M> Trampoline<'a, A, M>
@ -46,6 +75,7 @@ where
scratch_reg: Reg,
alloc_scratch_reg: Reg,
call_conv: &'a CallingConvention,
pointer_size: u8,
) -> Self {
Self {
masm,
@ -54,147 +84,320 @@ where
alloc_scratch_reg,
callee_saved_regs: <A as ABI>::callee_saved_regs(call_conv),
call_conv,
pointer_size,
}
}
/// Emit the host to wasm trampoline.
pub fn emit_host_to_wasm(&mut self, ty: &FuncType) {
// The host to wasm trampoline is currently hard coded (see vmcontext.rs
// in the wasmtime-runtime crate, `VMArrayCallFunction`). The first two
// parameters are VMContexts (not used at this time). The third
// parameter is the function pointer to call. The fourth parameter is
// an address to storage space for both the return value and the
// arguments to the function.
let trampoline_ty = FuncType::new(
/// Emit an array-to-wasm trampoline.
pub fn emit_array_to_wasm(&mut self, ty: &FuncType, callee_index: FuncIndex) -> Result<()> {
let native_ty = FuncType::new(
vec![ValType::I64, ValType::I64, ValType::I64, ValType::I64],
vec![],
);
let trampoline_sig = self.abi.sig(&trampoline_ty, self.call_conv);
let native_sig = self.native_sig(&native_ty);
let wasm_sig = self.wasm_sig(ty);
// Hard-coding the size in bytes of the trampoline arguments
// since it's static, based on the current signature we should
// always have 4 arguments, each of which is 8 bytes.
let trampoline_arg_size = 32;
let val_ptr = &native_sig.params[2]
.get_reg()
.map(RegImm::reg)
.ok_or_else(|| anyhow!("Expected value pointer to be in a register"))?;
let callee_sig = self.abi.sig(ty, &CallingConvention::Default);
self.prologue_with_callee_saved();
let val_ptr = if let ABIArg::Reg { reg, ty: _ty } = &trampoline_sig.params[3] {
Ok(RegImm::reg(*reg))
} else {
Err(anyhow::anyhow!("Expected the val ptr to be in a register"))
}
.unwrap();
// Get the VM context pointer and move it to the designated pinned
// register.
let vmctx_ptr = Self::vmctx(&native_sig.params)?;
self.masm
.mov(vmctx_ptr, <A as ABI>::vmctx_reg().into(), OperandSize::S64);
self.prologue();
let (offsets, spill_size) = self.spill(&native_sig.params);
let mut trampoline_arg_offsets: [u32; 4] = [0; 4];
let val_ptr_offset = offsets[2];
trampoline_sig
.params
.iter()
.enumerate()
.for_each(|(i, param)| {
if let ABIArg::Reg { reg, ty: _ty } = param {
let offset = self.masm.push(*reg);
trampoline_arg_offsets[i] = offset;
}
});
// Call the function that was passed into the trampoline.
let allocated_stack = self.masm.call(
self.abi.call_stack_align().into(),
self.abi.arg_base_offset().into(),
wasm_sig.stack_bytes,
|masm| {
masm.mov(*val_ptr, self.scratch_reg.into(), OperandSize::S64);
Self::assign_args_from_array(
masm,
&wasm_sig,
self.scratch_reg,
self.alloc_scratch_reg,
);
CalleeKind::Direct(callee_index.as_u32())
},
);
self.masm.free_stack(allocated_stack);
// Move the val ptr back into the scratch register so we can
// load the return values.
self.masm.load(
self.masm.address_from_sp(val_ptr_offset),
self.scratch_reg,
OperandSize::S64,
);
// Move the return values into the value ptr. We are only
// supporting a single return value at this time.
let ABIResult::Reg { reg, ty } = &wasm_sig.result;
if let Some(ty) = ty {
self.masm.store(
RegImm::reg(*reg),
self.masm.address_at_reg(self.scratch_reg, 0),
(*ty).into(),
);
}
self.epilogue_with_callee_saved_restore(spill_size);
Ok(())
}
let val_ptr_offset = trampoline_arg_offsets[3];
let func_ptr_offset = trampoline_arg_offsets[2];
/// Emit a native-to-wasm trampoline.
pub fn emit_native_to_wasm(&mut self, ty: &FuncType, callee_index: FuncIndex) -> Result<()> {
let native_sig = self.native_sig(&ty);
let wasm_sig = self.wasm_sig(&ty);
let vmctx_ptr = Self::vmctx(&native_sig.params)?;
self.prologue_with_callee_saved();
// Move the VM context pointer to the designated pinned register.
self.masm
.mov(val_ptr, RegImm::reg(self.scratch_reg), OperandSize::S64);
// How much we need to adjust the stack pointer by to account
// for the alignment required by the ISA.
let delta = calculate_frame_adjustment(
self.masm.sp_offset(),
self.abi.arg_base_offset() as u32,
self.abi.call_stack_align() as u32,
.mov(vmctx_ptr, <A as ABI>::vmctx_reg().into(), OperandSize::S64);
let (offsets, spill_size) = self.spill(&native_sig.params);
let reserved_stack = self.masm.call(
self.abi.call_stack_align().into(),
self.abi.arg_base_offset().into(),
wasm_sig.stack_bytes,
|masm| {
Self::assign_args(
masm,
&wasm_sig.params,
&native_sig.params[2..],
&offsets[2..],
self.scratch_reg,
self.abi.arg_base_offset().into(),
);
CalleeKind::Direct(callee_index.as_u32())
},
);
// The total amount of stack space we need to reserve for the
// arguments.
let total_arg_stack_space = align_to(
callee_sig.stack_bytes + delta,
self.abi.call_stack_align() as u32,
self.masm.free_stack(reserved_stack);
self.epilogue_with_callee_saved_restore(spill_size);
Ok(())
}
/// Emit a wasm-to-native trampoline.
pub fn emit_wasm_to_native(&mut self, ty: &FuncType) -> Result<()> {
let mut params = Self::callee_and_caller_vmctx();
params.extend_from_slice(ty.params());
let func_ty = FuncType::new(params, ty.results().to_owned());
let wasm_sig = self.wasm_sig(&func_ty);
let native_sig = self.native_sig(ty);
self.prologue();
let (offsets, spill_size) = self.spill(&wasm_sig.params);
let reserved_stack = self.masm.call(
self.abi.call_stack_align().into(),
self.abi.arg_base_offset().into(),
native_sig.stack_bytes,
|masm| {
// Move the VM context into one of the scratch registers.
let vmctx = Self::vmctx(&wasm_sig.params).unwrap();
masm.mov(
vmctx.into(),
self.alloc_scratch_reg.into(),
OperandSize::S64,
);
Self::assign_args(
masm,
&native_sig.params,
&wasm_sig.params,
&offsets,
self.scratch_reg,
self.abi.arg_base_offset().into(),
);
let body_offset = self.pointer_size.vmnative_call_host_func_context_func_ref()
+ self.pointer_size.vm_func_ref_native_call();
let callee_addr = masm.address_at_reg(self.alloc_scratch_reg, body_offset.into());
masm.load(callee_addr, self.scratch_reg, OperandSize::S64);
CalleeKind::Indirect(self.scratch_reg)
},
);
self.masm.reserve_stack(total_arg_stack_space);
self.masm.free_stack(reserved_stack);
self.epilogue(spill_size);
Ok(())
}
/// Perfom argument assignment, translating between
/// caller and callee calling conventions.
fn assign_args(
masm: &mut M,
callee_params: &[ABIArg],
caller_params: &[ABIArg],
caller_stack_offsets: &[u32],
scratch: Reg,
arg_base_offset: u32,
) {
assert!(callee_params.len() == caller_params.len());
let fp = <A as ABI>::fp_reg();
let mut offset_index = 0;
callee_params
.iter()
.zip(caller_params)
.for_each(
|(callee_param, caller_param)| match (callee_param, caller_param) {
(ABIArg::Reg { ty, reg: dst }, ABIArg::Reg { .. }) => {
let offset = caller_stack_offsets[offset_index];
let addr = masm.address_from_sp(offset);
masm.load(addr, *dst, (*ty).into());
offset_index += 1;
}
(ABIArg::Stack { ty, offset }, ABIArg::Reg { .. }) => {
let spill_offset = caller_stack_offsets[offset_index];
let addr = masm.address_from_sp(spill_offset);
masm.load(addr, scratch, (*ty).into());
let arg_addr = masm.address_at_sp(*offset);
masm.store(scratch.into(), arg_addr, (*ty).into());
offset_index += 1;
}
(ABIArg::Reg { ty, reg: dst }, ABIArg::Stack { ty: _, offset }) => {
let addr = masm.address_at_reg(fp, arg_base_offset + offset);
masm.load(addr, *dst, (*ty).into());
}
(
ABIArg::Stack {
ty,
offset: callee_offset,
},
ABIArg::Stack {
offset: caller_offset,
..
},
) => {
let addr = masm.address_at_reg(fp, arg_base_offset + caller_offset);
masm.load(addr, scratch, (*ty).into());
let arg_addr = masm.address_at_sp(*callee_offset);
masm.store(scratch.into(), arg_addr, (*ty).into());
}
},
)
}
/// Get the type of the caller and callee VM contexts.
fn callee_and_caller_vmctx() -> Vec<ValType> {
vec![ValType::I64, ValType::I64]
}
/// Returns a signature using the system's calling convention.
fn native_sig(&self, ty: &FuncType) -> ABISig {
let mut params = Self::callee_and_caller_vmctx();
params.extend_from_slice(ty.params());
let native_type = FuncType::new(params, ty.results().to_owned());
self.abi.sig(&native_type, self.call_conv)
}
/// Returns a signature using the Winch's default calling convention.
fn wasm_sig(&self, ty: &FuncType) -> ABISig {
self.abi.sig(ty, &CallingConvention::Default)
}
/// Returns the register containing the VM context pointer.
fn vmctx(params: &ABIParams) -> Result<RegImm> {
params[0]
.get_reg()
.map(RegImm::reg)
.ok_or_else(|| anyhow!("Expected vm context pointer to be in a register"))
}
/// Performs a spill of the register params.
fn spill(&mut self, params: &ABIParams) -> (SmallVec<[u32; 6]>, u32) {
let mut offsets = SmallVec::new();
let mut spilled = 0;
params.iter().for_each(|param| {
if let Some(reg) = param.get_reg() {
let offset = self.masm.push(reg);
offsets.push(offset);
spilled += 1;
}
});
// The stack size for the spill, calculated
// from the number of spilled register times
// the size of each push (8 bytes).
let size = spilled * <A as ABI>::word_bytes();
(offsets, size)
}
/// Assigns arguments for the callee, loading them from a register.
fn assign_args_from_array(masm: &mut M, callee_sig: &ABISig, values_reg: Reg, scratch: Reg) {
// The max size a value can be when reading from the params
// memory location.
let value_size = mem::size_of::<u128>();
callee_sig.params.iter().enumerate().for_each(|(i, param)| {
let value_offset = (i * value_size) as u32;
match param {
ABIArg::Reg { reg, ty } => self.masm.load(
self.masm.address_from_reg(self.scratch_reg, value_offset),
ABIArg::Reg { reg, ty } => masm.load(
masm.address_at_reg(values_reg, value_offset),
*reg,
(*ty).into(),
),
ABIArg::Stack { offset, ty } => {
self.masm.load(
self.masm.address_from_reg(self.scratch_reg, value_offset),
self.alloc_scratch_reg,
masm.load(
masm.address_at_reg(values_reg, value_offset),
scratch,
(*ty).into(),
);
self.masm.store(
RegImm::reg(self.alloc_scratch_reg),
self.masm.address_at_sp(*offset),
masm.store(
RegImm::reg(scratch),
masm.address_at_sp(*offset),
(*ty).into(),
);
}
}
});
// Move the function pointer from it's stack location into a
// scratch register.
self.masm.load(
self.masm.address_from_sp(func_ptr_offset),
self.scratch_reg,
OperandSize::S64,
);
// Call the function that was passed into the trampoline.
self.masm.call(CalleeKind::Indirect(self.scratch_reg));
self.masm.free_stack(total_arg_stack_space);
// Move the val ptr back into the scratch register so we can
// load the return values.
self.masm.load(
self.masm.address_from_sp(val_ptr_offset),
self.scratch_reg,
OperandSize::S64,
);
// Move the return values into the value ptr. We are only
// supporting a single return value at this time.
let ABIResult::Reg { reg, ty } = &callee_sig.result;
self.masm.store(
RegImm::reg(*reg),
self.masm.address_from_reg(self.scratch_reg, 0),
(*ty).unwrap().into(),
);
self.epilogue(trampoline_arg_size);
}
/// The trampoline's prologue.
fn prologue(&mut self) {
self.masm.prologue();
}
/// Similar to [Trampoline::prologue], but saves
/// callee-saved registers.
fn prologue_with_callee_saved(&mut self) {
self.masm.prologue();
// Save any callee-saved registers.
for r in &self.callee_saved_regs {
self.masm.push(*r);
}
}
/// The trampoline's epilogue.
fn epilogue(&mut self, arg_size: u32) {
/// Similar to [Trampoline::epilogue], but restores
/// callee-saved registers.
fn epilogue_with_callee_saved_restore(&mut self, arg_size: u32) {
// Free the stack space allocated by pushing the trampoline arguments.
self.masm.free_stack(arg_size);
// Restore the callee-saved registers.
@ -203,4 +406,11 @@ where
}
self.masm.epilogue(0);
}
/// The trampoline's epilogue.
fn epilogue(&mut self, arg_size: u32) {
// Free the stack space allocated by pushing the trampoline arguments.
self.masm.free_stack(arg_size);
self.masm.epilogue(0);
}
}

3
winch/codegen/src/visitor.rs

@ -10,6 +10,7 @@ use crate::masm::{DivKind, MacroAssembler, OperandSize, RegImm, RemKind};
use crate::stack::Val;
use wasmparser::ValType;
use wasmparser::VisitOperator;
use wasmtime_environ::FuncIndex;
/// A macro to define unsupported WebAssembly operators.
///
@ -198,7 +199,7 @@ where
}
fn visit_call(&mut self, index: u32) {
self.emit_call(index);
self.emit_call(FuncIndex::from_u32(index));
}
wasmparser::for_each_operator!(def_unsupported);

8
winch/environ/src/lib.rs

@ -5,7 +5,7 @@
use wasmparser::types::Types;
use wasmtime_environ::{FuncIndex, Module};
use winch_codegen::{self, Callee, TargetIsa};
use winch_codegen::{self, Callee};
/// Function environment containing module and runtime specific
/// information.
@ -14,8 +14,6 @@ pub struct FuncEnv<'a> {
pub module: &'a Module,
/// Type information about a module, once it has been validated.
pub types: &'a Types,
/// The current ISA.
pub isa: &'a Box<dyn TargetIsa>,
}
impl<'a> winch_codegen::FuncEnv for FuncEnv<'a> {
@ -35,7 +33,7 @@ impl<'a> winch_codegen::FuncEnv for FuncEnv<'a> {
impl<'a> FuncEnv<'a> {
/// Create a new function environment.
pub fn new(module: &'a Module, types: &'a Types, isa: &'a Box<dyn TargetIsa>) -> Self {
Self { module, types, isa }
pub fn new(module: &'a Module, types: &'a Types) -> Self {
Self { module, types }
}
}

15
winch/filetests/filetests/aarch64/i32_add/const.wat

@ -10,8 +10,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: 500180d2 mov x16, #0xa
;; 10: e003102a mov w0, w16
;; 14: 00500011 add w0, w0, #0x14
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 1c: c0035fd6 ret
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 890300f8 stur x9, [x28]
;; 18: 500180d2 mov x16, #0xa
;; 1c: e003102a mov w0, w16
;; 20: 00500011 add w0, w0, #0x14
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

33
winch/filetests/filetests/aarch64/i32_add/locals.wat

@ -19,21 +19,22 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: ff2300d1 sub sp, sp, #8
;; c: ff4300d1 sub sp, sp, #0x10
;; 10: fc030091 mov x28, sp
;; 14: 100080d2 mov x16, #0
;; 18: 900300f8 stur x16, [x28]
;; 1c: 500180d2 mov x16, #0xa
;; 20: e003102a mov w0, w16
;; 24: 804300b8 stur w0, [x28, #4]
;; 28: 900280d2 mov x16, #0x14
;; 2c: e003102a mov w0, w16
;; 30: 800300b8 stur w0, [x28]
;; 34: 800340b8 ldur w0, [x28]
;; 38: 814340b8 ldur w1, [x28, #4]
;; 3c: 2160200b add w1, w1, w0, uxtx
;; 40: e00301aa mov x0, x1
;; 44: ff230091 add sp, sp, #8
;; 48: fc030091 mov x28, sp
;; 4c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 50: c0035fd6 ret
;; 18: 908300f8 stur x16, [x28, #8]
;; 1c: 890300f8 stur x9, [x28]
;; 20: 500180d2 mov x16, #0xa
;; 24: e003102a mov w0, w16
;; 28: 80c300b8 stur w0, [x28, #0xc]
;; 2c: 900280d2 mov x16, #0x14
;; 30: e003102a mov w0, w16
;; 34: 808300b8 stur w0, [x28, #8]
;; 38: 808340b8 ldur w0, [x28, #8]
;; 3c: 81c340b8 ldur w1, [x28, #0xc]
;; 40: 2160200b add w1, w1, w0, uxtx
;; 44: e00301aa mov x0, x1
;; 48: ff430091 add sp, sp, #0x10
;; 4c: fc030091 mov x28, sp
;; 50: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 54: c0035fd6 ret

15
winch/filetests/filetests/aarch64/i32_add/max.wat

@ -9,8 +9,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: f07b40b2 orr x16, xzr, #0x7fffffff
;; 10: e003102a mov w0, w16
;; 14: 00040011 add w0, w0, #1
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 1c: c0035fd6 ret
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 890300f8 stur x9, [x28]
;; 18: f07b40b2 orr x16, xzr, #0x7fffffff
;; 1c: e003102a mov w0, w16
;; 20: 00040011 add w0, w0, #1
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

17
winch/filetests/filetests/aarch64/i32_add/max_one.wat

@ -10,9 +10,14 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: f08361b2 orr x16, xzr, #0xffffffff80000000
;; 10: e003102a mov w0, w16
;; 14: 10008092 mov x16, #-1
;; 18: 0060300b add w0, w0, w16, uxtx
;; 1c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 20: c0035fd6 ret
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 890300f8 stur x9, [x28]
;; 18: f08361b2 orr x16, xzr, #0xffffffff80000000
;; 1c: e003102a mov w0, w16
;; 20: 10008092 mov x16, #-1
;; 24: 0060300b add w0, w0, w16, uxtx
;; 28: ff230091 add sp, sp, #8
;; 2c: fc030091 mov x28, sp
;; 30: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 34: c0035fd6 ret

15
winch/filetests/filetests/aarch64/i32_add/mixed.wat

@ -10,8 +10,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: 10008092 mov x16, #-1
;; 10: e003102a mov w0, w16
;; 14: 00040011 add w0, w0, #1
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 1c: c0035fd6 ret
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 890300f8 stur x9, [x28]
;; 18: 10008092 mov x16, #-1
;; 1c: e003102a mov w0, w16
;; 20: 00040011 add w0, w0, #1
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

23
winch/filetests/filetests/aarch64/i32_add/params.wat

@ -10,15 +10,16 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: ff2300d1 sub sp, sp, #8
;; c: ff4300d1 sub sp, sp, #0x10
;; 10: fc030091 mov x28, sp
;; 14: 804300b8 stur w0, [x28, #4]
;; 18: 810300b8 stur w1, [x28]
;; 1c: 800340b8 ldur w0, [x28]
;; 20: 814340b8 ldur w1, [x28, #4]
;; 24: 2160200b add w1, w1, w0, uxtx
;; 28: e00301aa mov x0, x1
;; 2c: ff230091 add sp, sp, #8
;; 30: fc030091 mov x28, sp
;; 34: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 38: c0035fd6 ret
;; 14: 80c300b8 stur w0, [x28, #0xc]
;; 18: 818300b8 stur w1, [x28, #8]
;; 1c: 890300f8 stur x9, [x28]
;; 20: 808340b8 ldur w0, [x28, #8]
;; 24: 81c340b8 ldur w1, [x28, #0xc]
;; 28: 2160200b add w1, w1, w0, uxtx
;; 2c: e00301aa mov x0, x1
;; 30: ff430091 add sp, sp, #0x10
;; 34: fc030091 mov x28, sp
;; 38: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 3c: c0035fd6 ret

17
winch/filetests/filetests/aarch64/i32_add/signed.wat

@ -10,9 +10,14 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: 10008092 mov x16, #-1
;; 10: e003102a mov w0, w16
;; 14: 10008092 mov x16, #-1
;; 18: 0060300b add w0, w0, w16, uxtx
;; 1c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 20: c0035fd6 ret
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 890300f8 stur x9, [x28]
;; 18: 10008092 mov x16, #-1
;; 1c: e003102a mov w0, w16
;; 20: 10008092 mov x16, #-1
;; 24: 0060300b add w0, w0, w16, uxtx
;; 28: ff230091 add sp, sp, #8
;; 2c: fc030091 mov x28, sp
;; 30: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 34: c0035fd6 ret

15
winch/filetests/filetests/aarch64/i32_add/unsigned_with_zero.wat

@ -10,8 +10,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: 300080d2 mov x16, #1
;; 10: e003102a mov w0, w16
;; 14: 00000011 add w0, w0, #0
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 1c: c0035fd6 ret
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 890300f8 stur x9, [x28]
;; 18: 300080d2 mov x16, #1
;; 1c: e003102a mov w0, w16
;; 20: 00000011 add w0, w0, #0
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

15
winch/filetests/filetests/aarch64/i64_add/const.wat

@ -10,8 +10,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: 500180d2 mov x16, #0xa
;; 10: e00310aa mov x0, x16
;; 14: 00500091 add x0, x0, #0x14
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 1c: c0035fd6 ret
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 890300f8 stur x9, [x28]
;; 18: 500180d2 mov x16, #0xa
;; 1c: e00310aa mov x0, x16
;; 20: 00500091 add x0, x0, #0x14
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

35
winch/filetests/filetests/aarch64/i64_add/locals.wat

@ -19,22 +19,23 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: ff4300d1 sub sp, sp, #0x10
;; c: ff6300d1 sub sp, sp, #0x18
;; 10: fc030091 mov x28, sp
;; 14: 100080d2 mov x16, #0
;; 18: 908300f8 stur x16, [x28, #8]
;; 1c: 900300f8 stur x16, [x28]
;; 20: 500180d2 mov x16, #0xa
;; 24: e00310aa mov x0, x16
;; 28: 808300f8 stur x0, [x28, #8]
;; 2c: 900280d2 mov x16, #0x14
;; 30: e00310aa mov x0, x16
;; 34: 800300f8 stur x0, [x28]
;; 38: 800340f8 ldur x0, [x28]
;; 3c: 818340f8 ldur x1, [x28, #8]
;; 40: 2160208b add x1, x1, x0, uxtx
;; 44: e00301aa mov x0, x1
;; 48: ff430091 add sp, sp, #0x10
;; 4c: fc030091 mov x28, sp
;; 50: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 54: c0035fd6 ret
;; 18: 900301f8 stur x16, [x28, #0x10]
;; 1c: 908300f8 stur x16, [x28, #8]
;; 20: 890300f8 stur x9, [x28]
;; 24: 500180d2 mov x16, #0xa
;; 28: e00310aa mov x0, x16
;; 2c: 800301f8 stur x0, [x28, #0x10]
;; 30: 900280d2 mov x16, #0x14
;; 34: e00310aa mov x0, x16
;; 38: 808300f8 stur x0, [x28, #8]
;; 3c: 808340f8 ldur x0, [x28, #8]
;; 40: 810341f8 ldur x1, [x28, #0x10]
;; 44: 2160208b add x1, x1, x0, uxtx
;; 48: e00301aa mov x0, x1
;; 4c: ff630091 add sp, sp, #0x18
;; 50: fc030091 mov x28, sp
;; 54: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 58: c0035fd6 ret

17
winch/filetests/filetests/aarch64/i64_add/max.wat

@ -9,9 +9,14 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: 300080d2 mov x16, #1
;; 10: e00310aa mov x0, x16
;; 14: 1000f092 mov x16, #0x7fffffffffffffff
;; 18: 0060308b add x0, x0, x16, uxtx
;; 1c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 20: c0035fd6 ret
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 890300f8 stur x9, [x28]
;; 18: 300080d2 mov x16, #1
;; 1c: e00310aa mov x0, x16
;; 20: 1000f092 mov x16, #0x7fffffffffffffff
;; 24: 0060308b add x0, x0, x16, uxtx
;; 28: ff230091 add sp, sp, #8
;; 2c: fc030091 mov x28, sp
;; 30: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 34: c0035fd6 ret

17
winch/filetests/filetests/aarch64/i64_add/max_one.wat

@ -10,9 +10,14 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: 1000f0d2 mov x16, #-0x8000000000000000
;; 10: e00310aa mov x0, x16
;; 14: 10008092 mov x16, #-1
;; 18: 0060308b add x0, x0, x16, uxtx
;; 1c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 20: c0035fd6 ret
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 890300f8 stur x9, [x28]
;; 18: 1000f0d2 mov x16, #-0x8000000000000000
;; 1c: e00310aa mov x0, x16
;; 20: 10008092 mov x16, #-1
;; 24: 0060308b add x0, x0, x16, uxtx
;; 28: ff230091 add sp, sp, #8
;; 2c: fc030091 mov x28, sp
;; 30: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 34: c0035fd6 ret

15
winch/filetests/filetests/aarch64/i64_add/mixed.wat

@ -10,8 +10,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: 10008092 mov x16, #-1
;; 10: e00310aa mov x0, x16
;; 14: 00040091 add x0, x0, #1
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 1c: c0035fd6 ret
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 890300f8 stur x9, [x28]
;; 18: 10008092 mov x16, #-1
;; 1c: e00310aa mov x0, x16
;; 20: 00040091 add x0, x0, #1
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

23
winch/filetests/filetests/aarch64/i64_add/params.wat

@ -10,15 +10,16 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: ff4300d1 sub sp, sp, #0x10
;; c: ff6300d1 sub sp, sp, #0x18
;; 10: fc030091 mov x28, sp
;; 14: 808300f8 stur x0, [x28, #8]
;; 18: 810300f8 stur x1, [x28]
;; 1c: 800340f8 ldur x0, [x28]
;; 20: 818340f8 ldur x1, [x28, #8]
;; 24: 2160208b add x1, x1, x0, uxtx
;; 28: e00301aa mov x0, x1
;; 2c: ff430091 add sp, sp, #0x10
;; 30: fc030091 mov x28, sp
;; 34: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 38: c0035fd6 ret
;; 14: 800301f8 stur x0, [x28, #0x10]
;; 18: 818300f8 stur x1, [x28, #8]
;; 1c: 890300f8 stur x9, [x28]
;; 20: 808340f8 ldur x0, [x28, #8]
;; 24: 810341f8 ldur x1, [x28, #0x10]
;; 28: 2160208b add x1, x1, x0, uxtx
;; 2c: e00301aa mov x0, x1
;; 30: ff630091 add sp, sp, #0x18
;; 34: fc030091 mov x28, sp
;; 38: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 3c: c0035fd6 ret

17
winch/filetests/filetests/aarch64/i64_add/signed.wat

@ -10,9 +10,14 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: 10008092 mov x16, #-1
;; 10: e00310aa mov x0, x16
;; 14: 10008092 mov x16, #-1
;; 18: 0060308b add x0, x0, x16, uxtx
;; 1c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 20: c0035fd6 ret
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 890300f8 stur x9, [x28]
;; 18: 10008092 mov x16, #-1
;; 1c: e00310aa mov x0, x16
;; 20: 10008092 mov x16, #-1
;; 24: 0060308b add x0, x0, x16, uxtx
;; 28: ff230091 add sp, sp, #8
;; 2c: fc030091 mov x28, sp
;; 30: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 34: c0035fd6 ret

15
winch/filetests/filetests/aarch64/i64_add/unsigned_with_zero.wat

@ -10,8 +10,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp
;; c: 300080d2 mov x16, #1
;; 10: e00310aa mov x0, x16
;; 14: 00000091 add x0, x0, #0
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 1c: c0035fd6 ret
;; c: ff2300d1 sub sp, sp, #8
;; 10: fc030091 mov x28, sp
;; 14: 890300f8 stur x9, [x28]
;; 18: 300080d2 mov x16, #1
;; 1c: e00310aa mov x0, x16
;; 20: 00000091 add x0, x0, #0
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

158
winch/filetests/filetests/x64/call/params.wat

@ -37,85 +37,87 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8
;; 8: 897c2404 mov dword ptr [rsp + 4], edi
;; c: 893424 mov dword ptr [rsp], esi
;; f: 8b4c2404 mov ecx, dword ptr [rsp + 4]
;; 13: 8b0424 mov eax, dword ptr [rsp]
;; 16: 31d2 xor edx, edx
;; 18: f7f1 div ecx
;; 1a: 50 push rax
;; 1b: 4883ec20 sub rsp, 0x20
;; 1f: 8b7c2420 mov edi, dword ptr [rsp + 0x20]
;; 23: be01000000 mov esi, 1
;; 28: ba02000000 mov edx, 2
;; 2d: b903000000 mov ecx, 3
;; 32: 41b804000000 mov r8d, 4
;; 38: 41b905000000 mov r9d, 5
;; 3e: 41bb06000000 mov r11d, 6
;; 44: 44891c24 mov dword ptr [rsp], r11d
;; 48: 41bb07000000 mov r11d, 7
;; 4e: 44895c2408 mov dword ptr [rsp + 8], r11d
;; 53: 41bb08000000 mov r11d, 8
;; 59: 44895c2410 mov dword ptr [rsp + 0x10], r11d
;; 5e: e800000000 call 0x63
;; 63: 4883c428 add rsp, 0x28
;; 67: 50 push rax
;; 68: 448b5c2408 mov r11d, dword ptr [rsp + 8]
;; 6d: 4153 push r11
;; 6f: 448b5c2414 mov r11d, dword ptr [rsp + 0x14]
;; 74: 4153 push r11
;; 76: 59 pop rcx
;; 77: 58 pop rax
;; 78: 31d2 xor edx, edx
;; 7a: f7f1 div ecx
;; 7c: 50 push rax
;; 7d: 4883ec20 sub rsp, 0x20
;; 81: 8b7c2428 mov edi, dword ptr [rsp + 0x28]
;; 85: 8b742420 mov esi, dword ptr [rsp + 0x20]
;; 89: ba02000000 mov edx, 2
;; 8e: b903000000 mov ecx, 3
;; 93: 41b804000000 mov r8d, 4
;; 99: 41b905000000 mov r9d, 5
;; 9f: 41bb06000000 mov r11d, 6
;; a5: 44891c24 mov dword ptr [rsp], r11d
;; a9: 41bb07000000 mov r11d, 7
;; af: 44895c2408 mov dword ptr [rsp + 8], r11d
;; b4: 41bb08000000 mov r11d, 8
;; ba: 44895c2410 mov dword ptr [rsp + 0x10], r11d
;; bf: e800000000 call 0xc4
;; c4: 4883c430 add rsp, 0x30
;; c8: 4883c408 add rsp, 8
;; cc: 5d pop rbp
;; cd: c3 ret
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 89742408 mov dword ptr [rsp + 8], esi
;; 10: 4c893424 mov qword ptr [rsp], r14
;; 14: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 18: 8b442408 mov eax, dword ptr [rsp + 8]
;; 1c: 31d2 xor edx, edx
;; 1e: f7f1 div ecx
;; 20: 50 push rax
;; 21: 4883ec28 sub rsp, 0x28
;; 25: 8b7c2428 mov edi, dword ptr [rsp + 0x28]
;; 29: be01000000 mov esi, 1
;; 2e: ba02000000 mov edx, 2
;; 33: b903000000 mov ecx, 3
;; 38: 41b804000000 mov r8d, 4
;; 3e: 41b905000000 mov r9d, 5
;; 44: 41bb06000000 mov r11d, 6
;; 4a: 44891c24 mov dword ptr [rsp], r11d
;; 4e: 41bb07000000 mov r11d, 7
;; 54: 44895c2408 mov dword ptr [rsp + 8], r11d
;; 59: 41bb08000000 mov r11d, 8
;; 5f: 44895c2410 mov dword ptr [rsp + 0x10], r11d
;; 64: e800000000 call 0x69
;; 69: 4883c430 add rsp, 0x30
;; 6d: 50 push rax
;; 6e: 448b5c2410 mov r11d, dword ptr [rsp + 0x10]
;; 73: 4153 push r11
;; 75: 448b5c241c mov r11d, dword ptr [rsp + 0x1c]
;; 7a: 4153 push r11
;; 7c: 59 pop rcx
;; 7d: 58 pop rax
;; 7e: 31d2 xor edx, edx
;; 80: f7f1 div ecx
;; 82: 50 push rax
;; 83: 4883ec20 sub rsp, 0x20
;; 87: 8b7c2428 mov edi, dword ptr [rsp + 0x28]
;; 8b: 8b742420 mov esi, dword ptr [rsp + 0x20]
;; 8f: ba02000000 mov edx, 2
;; 94: b903000000 mov ecx, 3
;; 99: 41b804000000 mov r8d, 4
;; 9f: 41b905000000 mov r9d, 5
;; a5: 41bb06000000 mov r11d, 6
;; ab: 44891c24 mov dword ptr [rsp], r11d
;; af: 41bb07000000 mov r11d, 7
;; b5: 44895c2408 mov dword ptr [rsp + 8], r11d
;; ba: 41bb08000000 mov r11d, 8
;; c0: 44895c2410 mov dword ptr [rsp + 0x10], r11d
;; c5: e800000000 call 0xca
;; ca: 4883c430 add rsp, 0x30
;; ce: 4883c410 add rsp, 0x10
;; d2: 5d pop rbp
;; d3: c3 ret
;;
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec18 sub rsp, 0x18
;; 8: 897c2414 mov dword ptr [rsp + 0x14], edi
;; c: 89742410 mov dword ptr [rsp + 0x10], esi
;; 10: 8954240c mov dword ptr [rsp + 0xc], edx
;; 14: 894c2408 mov dword ptr [rsp + 8], ecx
;; 18: 4489442404 mov dword ptr [rsp + 4], r8d
;; 1d: 44890c24 mov dword ptr [rsp], r9d
;; 21: 8b442410 mov eax, dword ptr [rsp + 0x10]
;; 25: 8b4c2414 mov ecx, dword ptr [rsp + 0x14]
;; 29: 01c1 add ecx, eax
;; 2b: 8b44240c mov eax, dword ptr [rsp + 0xc]
;; 2f: 01c1 add ecx, eax
;; 31: 8b442408 mov eax, dword ptr [rsp + 8]
;; 35: 01c1 add ecx, eax
;; 37: 8b442404 mov eax, dword ptr [rsp + 4]
;; 3b: 01c1 add ecx, eax
;; 3d: 8b0424 mov eax, dword ptr [rsp]
;; 4: 4883ec20 sub rsp, 0x20
;; 8: 897c241c mov dword ptr [rsp + 0x1c], edi
;; c: 89742418 mov dword ptr [rsp + 0x18], esi
;; 10: 89542414 mov dword ptr [rsp + 0x14], edx
;; 14: 894c2410 mov dword ptr [rsp + 0x10], ecx
;; 18: 448944240c mov dword ptr [rsp + 0xc], r8d
;; 1d: 44894c2408 mov dword ptr [rsp + 8], r9d
;; 22: 4c893424 mov qword ptr [rsp], r14
;; 26: 8b442418 mov eax, dword ptr [rsp + 0x18]
;; 2a: 8b4c241c mov ecx, dword ptr [rsp + 0x1c]
;; 2e: 01c1 add ecx, eax
;; 30: 8b442414 mov eax, dword ptr [rsp + 0x14]
;; 34: 01c1 add ecx, eax
;; 36: 8b442410 mov eax, dword ptr [rsp + 0x10]
;; 3a: 01c1 add ecx, eax
;; 3c: 8b44240c mov eax, dword ptr [rsp + 0xc]
;; 40: 01c1 add ecx, eax
;; 42: 8b4510 mov eax, dword ptr [rbp + 0x10]
;; 45: 01c1 add ecx, eax
;; 47: 8b4518 mov eax, dword ptr [rbp + 0x18]
;; 4a: 01c1 add ecx, eax
;; 4c: 8b4520 mov eax, dword ptr [rbp + 0x20]
;; 4f: 01c1 add ecx, eax
;; 51: 4889c8 mov rax, rcx
;; 54: 4883c418 add rsp, 0x18
;; 58: 5d pop rbp
;; 59: c3 ret
;; 42: 8b442408 mov eax, dword ptr [rsp + 8]
;; 46: 01c1 add ecx, eax
;; 48: 8b4510 mov eax, dword ptr [rbp + 0x10]
;; 4b: 01c1 add ecx, eax
;; 4d: 8b4518 mov eax, dword ptr [rbp + 0x18]
;; 50: 01c1 add ecx, eax
;; 52: 8b4520 mov eax, dword ptr [rbp + 0x20]
;; 55: 01c1 add ecx, eax
;; 57: 4889c8 mov rax, rcx
;; 5a: 4883c420 add rsp, 0x20
;; 5e: 5d pop rbp
;; 5f: c3 ret

59
winch/filetests/filetests/x64/call/simple.wat

@ -15,35 +15,36 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8
;; 8: 48c7042400000000 mov qword ptr [rsp], 0
;; 10: 4883ec10 sub rsp, 0x10
;; 14: bf14000000 mov edi, 0x14
;; 19: be50000000 mov esi, 0x50
;; 1e: e800000000 call 0x23
;; 23: 4883c410 add rsp, 0x10
;; 27: b902000000 mov ecx, 2
;; 2c: 894c2404 mov dword ptr [rsp + 4], ecx
;; 30: 50 push rax
;; 31: 448b5c240c mov r11d, dword ptr [rsp + 0xc]
;; 36: 4153 push r11
;; 38: 59 pop rcx
;; 39: 58 pop rax
;; 3a: 31d2 xor edx, edx
;; 3c: f7f1 div ecx
;; 3e: 4883c408 add rsp, 8
;; 42: 5d pop rbp
;; 43: c3 ret
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 48c744240800000000
;; mov qword ptr [rsp + 8], 0
;; 11: 4c89742404 mov qword ptr [rsp + 4], r14
;; 16: bf14000000 mov edi, 0x14
;; 1b: be50000000 mov esi, 0x50
;; 20: e800000000 call 0x25
;; 25: b902000000 mov ecx, 2
;; 2a: 894c240c mov dword ptr [rsp + 0xc], ecx
;; 2e: 50 push rax
;; 2f: 448b5c2414 mov r11d, dword ptr [rsp + 0x14]
;; 34: 4153 push r11
;; 36: 59 pop rcx
;; 37: 58 pop rax
;; 38: 31d2 xor edx, edx
;; 3a: f7f1 div ecx
;; 3c: 4883c410 add rsp, 0x10
;; 40: 5d pop rbp
;; 41: c3 ret
;;
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8
;; 8: 897c2404 mov dword ptr [rsp + 4], edi
;; c: 893424 mov dword ptr [rsp], esi
;; f: 8b0424 mov eax, dword ptr [rsp]
;; 12: 8b4c2404 mov ecx, dword ptr [rsp + 4]
;; 16: 0fafc8 imul ecx, eax
;; 19: 4889c8 mov rax, rcx
;; 1c: 4883c408 add rsp, 8
;; 20: 5d pop rbp
;; 21: c3 ret
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 89742408 mov dword ptr [rsp + 8], esi
;; 10: 4c893424 mov qword ptr [rsp], r14
;; 14: 8b442408 mov eax, dword ptr [rsp + 8]
;; 18: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 1c: 0fafc8 imul ecx, eax
;; 1f: 4889c8 mov rax, rcx
;; 22: 4883c410 add rsp, 0x10
;; 26: 5d pop rbp
;; 27: c3 ret

11
winch/filetests/filetests/x64/i32_add/const.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b80a000000 mov eax, 0xa
;; 9: 83c014 add eax, 0x14
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b80a000000 mov eax, 0xa
;; 11: 83c014 add eax, 0x14
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

28
winch/filetests/filetests/x64/i32_add/locals.wat

@ -18,16 +18,18 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8
;; 8: 48c7042400000000 mov qword ptr [rsp], 0
;; 10: b80a000000 mov eax, 0xa
;; 15: 89442404 mov dword ptr [rsp + 4], eax
;; 19: b814000000 mov eax, 0x14
;; 1e: 890424 mov dword ptr [rsp], eax
;; 21: 8b0424 mov eax, dword ptr [rsp]
;; 24: 8b4c2404 mov ecx, dword ptr [rsp + 4]
;; 28: 01c1 add ecx, eax
;; 2a: 4889c8 mov rax, rcx
;; 2d: 4883c408 add rsp, 8
;; 31: 5d pop rbp
;; 32: c3 ret
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 48c744240800000000
;; mov qword ptr [rsp + 8], 0
;; 11: 4c893424 mov qword ptr [rsp], r14
;; 15: b80a000000 mov eax, 0xa
;; 1a: 8944240c mov dword ptr [rsp + 0xc], eax
;; 1e: b814000000 mov eax, 0x14
;; 23: 89442408 mov dword ptr [rsp + 8], eax
;; 27: 8b442408 mov eax, dword ptr [rsp + 8]
;; 2b: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 2f: 01c1 add ecx, eax
;; 31: 4889c8 mov rax, rcx
;; 34: 4883c410 add rsp, 0x10
;; 38: 5d pop rbp
;; 39: c3 ret

11
winch/filetests/filetests/x64/i32_add/max.wat

@ -8,7 +8,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffff7f mov eax, 0x7fffffff
;; 9: 83c001 add eax, 1
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b8ffffff7f mov eax, 0x7fffffff
;; 11: 83c001 add eax, 1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_add/max_one.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b800000080 mov eax, 0x80000000
;; 9: 83c0ff add eax, -1
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b800000080 mov eax, 0x80000000
;; 11: 83c0ff add eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_add/mixed.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffffff mov eax, 0xffffffff
;; 9: 83c001 add eax, 1
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b8ffffffff mov eax, 0xffffffff
;; 11: 83c001 add eax, 1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

21
winch/filetests/filetests/x64/i32_add/params.wat

@ -9,13 +9,14 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8
;; 8: 897c2404 mov dword ptr [rsp + 4], edi
;; c: 893424 mov dword ptr [rsp], esi
;; f: 8b0424 mov eax, dword ptr [rsp]
;; 12: 8b4c2404 mov ecx, dword ptr [rsp + 4]
;; 16: 01c1 add ecx, eax
;; 18: 4889c8 mov rax, rcx
;; 1b: 4883c408 add rsp, 8
;; 1f: 5d pop rbp
;; 20: c3 ret
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 89742408 mov dword ptr [rsp + 8], esi
;; 10: 4c893424 mov qword ptr [rsp], r14
;; 14: 8b442408 mov eax, dword ptr [rsp + 8]
;; 18: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 1c: 01c1 add ecx, eax
;; 1e: 4889c8 mov rax, rcx
;; 21: 4883c410 add rsp, 0x10
;; 25: 5d pop rbp
;; 26: c3 ret

11
winch/filetests/filetests/x64/i32_add/signed.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffffff mov eax, 0xffffffff
;; 9: 83c0ff add eax, -1
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b8ffffffff mov eax, 0xffffffff
;; 11: 83c0ff add eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_add/unsigned_with_zero.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b801000000 mov eax, 1
;; 9: 83c000 add eax, 0
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b801000000 mov eax, 1
;; 11: 83c000 add eax, 0
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

21
winch/filetests/filetests/x64/i32_divs/const.wat

@ -9,12 +9,15 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b90a000000 mov ecx, 0xa
;; 9: b814000000 mov eax, 0x14
;; e: 83f900 cmp ecx, 0
;; 11: 0f8405000000 je 0x1c
;; 17: 99 cdq
;; 18: f7f9 idiv ecx
;; 1a: 5d pop rbp
;; 1b: c3 ret
;; 1c: 0f0b ud2
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b90a000000 mov ecx, 0xa
;; 11: b814000000 mov eax, 0x14
;; 16: 83f900 cmp ecx, 0
;; 19: 0f8409000000 je 0x28
;; 1f: 99 cdq
;; 20: f7f9 idiv ecx
;; 22: 4883c408 add rsp, 8
;; 26: 5d pop rbp
;; 27: c3 ret
;; 28: 0f0b ud2

21
winch/filetests/filetests/x64/i32_divs/one_zero.wat

@ -9,12 +9,15 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0
;; 9: b801000000 mov eax, 1
;; e: 83f900 cmp ecx, 0
;; 11: 0f8405000000 je 0x1c
;; 17: 99 cdq
;; 18: f7f9 idiv ecx
;; 1a: 5d pop rbp
;; 1b: c3 ret
;; 1c: 0f0b ud2
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b900000000 mov ecx, 0
;; 11: b801000000 mov eax, 1
;; 16: 83f900 cmp ecx, 0
;; 19: 0f8409000000 je 0x28
;; 1f: 99 cdq
;; 20: f7f9 idiv ecx
;; 22: 4883c408 add rsp, 8
;; 26: 5d pop rbp
;; 27: c3 ret
;; 28: 0f0b ud2

21
winch/filetests/filetests/x64/i32_divs/overflow.wat

@ -9,12 +9,15 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b9ffffffff mov ecx, 0xffffffff
;; 9: b800000080 mov eax, 0x80000000
;; e: 83f900 cmp ecx, 0
;; 11: 0f8405000000 je 0x1c
;; 17: 99 cdq
;; 18: f7f9 idiv ecx
;; 1a: 5d pop rbp
;; 1b: c3 ret
;; 1c: 0f0b ud2
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b9ffffffff mov ecx, 0xffffffff
;; 11: b800000080 mov eax, 0x80000000
;; 16: 83f900 cmp ecx, 0
;; 19: 0f8409000000 je 0x28
;; 1f: 99 cdq
;; 20: f7f9 idiv ecx
;; 22: 4883c408 add rsp, 8
;; 26: 5d pop rbp
;; 27: c3 ret
;; 28: 0f0b ud2

27
winch/filetests/filetests/x64/i32_divs/params.wat

@ -9,16 +9,17 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8
;; 8: 897c2404 mov dword ptr [rsp + 4], edi
;; c: 893424 mov dword ptr [rsp], esi
;; f: 8b0c24 mov ecx, dword ptr [rsp]
;; 12: 8b442404 mov eax, dword ptr [rsp + 4]
;; 16: 83f900 cmp ecx, 0
;; 19: 0f8409000000 je 0x28
;; 1f: 99 cdq
;; 20: f7f9 idiv ecx
;; 22: 4883c408 add rsp, 8
;; 26: 5d pop rbp
;; 27: c3 ret
;; 28: 0f0b ud2
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 89742408 mov dword ptr [rsp + 8], esi
;; 10: 4c893424 mov qword ptr [rsp], r14
;; 14: 8b4c2408 mov ecx, dword ptr [rsp + 8]
;; 18: 8b44240c mov eax, dword ptr [rsp + 0xc]
;; 1c: 83f900 cmp ecx, 0
;; 1f: 0f8409000000 je 0x2e
;; 25: 99 cdq
;; 26: f7f9 idiv ecx
;; 28: 4883c410 add rsp, 0x10
;; 2c: 5d pop rbp
;; 2d: c3 ret
;; 2e: 0f0b ud2

21
winch/filetests/filetests/x64/i32_divs/zero_zero.wat

@ -9,12 +9,15 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0
;; 9: b800000000 mov eax, 0
;; e: 83f900 cmp ecx, 0
;; 11: 0f8405000000 je 0x1c
;; 17: 99 cdq
;; 18: f7f9 idiv ecx
;; 1a: 5d pop rbp
;; 1b: c3 ret
;; 1c: 0f0b ud2
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b900000000 mov ecx, 0
;; 11: b800000000 mov eax, 0
;; 16: 83f900 cmp ecx, 0
;; 19: 0f8409000000 je 0x28
;; 1f: 99 cdq
;; 20: f7f9 idiv ecx
;; 22: 4883c408 add rsp, 8
;; 26: 5d pop rbp
;; 27: c3 ret
;; 28: 0f0b ud2

15
winch/filetests/filetests/x64/i32_divu/const.wat

@ -9,9 +9,12 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b90a000000 mov ecx, 0xa
;; 9: b814000000 mov eax, 0x14
;; e: 31d2 xor edx, edx
;; 10: f7f1 div ecx
;; 12: 5d pop rbp
;; 13: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b90a000000 mov ecx, 0xa
;; 11: b814000000 mov eax, 0x14
;; 16: 31d2 xor edx, edx
;; 18: f7f1 div ecx
;; 1a: 4883c408 add rsp, 8
;; 1e: 5d pop rbp
;; 1f: c3 ret

15
winch/filetests/filetests/x64/i32_divu/one_zero.wat

@ -9,9 +9,12 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0
;; 9: b801000000 mov eax, 1
;; e: 31d2 xor edx, edx
;; 10: f7f1 div ecx
;; 12: 5d pop rbp
;; 13: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b900000000 mov ecx, 0
;; 11: b801000000 mov eax, 1
;; 16: 31d2 xor edx, edx
;; 18: f7f1 div ecx
;; 1a: 4883c408 add rsp, 8
;; 1e: 5d pop rbp
;; 1f: c3 ret

21
winch/filetests/filetests/x64/i32_divu/params.wat

@ -9,13 +9,14 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8
;; 8: 897c2404 mov dword ptr [rsp + 4], edi
;; c: 893424 mov dword ptr [rsp], esi
;; f: 8b0c24 mov ecx, dword ptr [rsp]
;; 12: 8b442404 mov eax, dword ptr [rsp + 4]
;; 16: 31d2 xor edx, edx
;; 18: f7f1 div ecx
;; 1a: 4883c408 add rsp, 8
;; 1e: 5d pop rbp
;; 1f: c3 ret
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 89742408 mov dword ptr [rsp + 8], esi
;; 10: 4c893424 mov qword ptr [rsp], r14
;; 14: 8b4c2408 mov ecx, dword ptr [rsp + 8]
;; 18: 8b44240c mov eax, dword ptr [rsp + 0xc]
;; 1c: 31d2 xor edx, edx
;; 1e: f7f1 div ecx
;; 20: 4883c410 add rsp, 0x10
;; 24: 5d pop rbp
;; 25: c3 ret

15
winch/filetests/filetests/x64/i32_divu/signed.wat

@ -9,9 +9,12 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b9ffffffff mov ecx, 0xffffffff
;; 9: b8ffffffff mov eax, 0xffffffff
;; e: 31d2 xor edx, edx
;; 10: f7f1 div ecx
;; 12: 5d pop rbp
;; 13: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b9ffffffff mov ecx, 0xffffffff
;; 11: b8ffffffff mov eax, 0xffffffff
;; 16: 31d2 xor edx, edx
;; 18: f7f1 div ecx
;; 1a: 4883c408 add rsp, 8
;; 1e: 5d pop rbp
;; 1f: c3 ret

15
winch/filetests/filetests/x64/i32_divu/zero_zero.wat

@ -9,9 +9,12 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0
;; 9: b800000000 mov eax, 0
;; e: 31d2 xor edx, edx
;; 10: f7f1 div ecx
;; 12: 5d pop rbp
;; 13: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b900000000 mov ecx, 0
;; 11: b800000000 mov eax, 0
;; 16: 31d2 xor edx, edx
;; 18: f7f1 div ecx
;; 1a: 4883c408 add rsp, 8
;; 1e: 5d pop rbp
;; 1f: c3 ret

11
winch/filetests/filetests/x64/i32_mul/const.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b80a000000 mov eax, 0xa
;; 9: 6bc014 imul eax, eax, 0x14
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b80a000000 mov eax, 0xa
;; 11: 6bc014 imul eax, eax, 0x14
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

28
winch/filetests/filetests/x64/i32_mul/locals.wat

@ -18,16 +18,18 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8
;; 8: 48c7042400000000 mov qword ptr [rsp], 0
;; 10: b80a000000 mov eax, 0xa
;; 15: 89442404 mov dword ptr [rsp + 4], eax
;; 19: b814000000 mov eax, 0x14
;; 1e: 890424 mov dword ptr [rsp], eax
;; 21: 8b0424 mov eax, dword ptr [rsp]
;; 24: 8b4c2404 mov ecx, dword ptr [rsp + 4]
;; 28: 0fafc8 imul ecx, eax
;; 2b: 4889c8 mov rax, rcx
;; 2e: 4883c408 add rsp, 8
;; 32: 5d pop rbp
;; 33: c3 ret
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 48c744240800000000
;; mov qword ptr [rsp + 8], 0
;; 11: 4c893424 mov qword ptr [rsp], r14
;; 15: b80a000000 mov eax, 0xa
;; 1a: 8944240c mov dword ptr [rsp + 0xc], eax
;; 1e: b814000000 mov eax, 0x14
;; 23: 89442408 mov dword ptr [rsp + 8], eax
;; 27: 8b442408 mov eax, dword ptr [rsp + 8]
;; 2b: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 2f: 0fafc8 imul ecx, eax
;; 32: 4889c8 mov rax, rcx
;; 35: 4883c410 add rsp, 0x10
;; 39: 5d pop rbp
;; 3a: c3 ret

11
winch/filetests/filetests/x64/i32_mul/max.wat

@ -8,7 +8,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffff7f mov eax, 0x7fffffff
;; 9: 6bc0ff imul eax, eax, -1
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b8ffffff7f mov eax, 0x7fffffff
;; 11: 6bc0ff imul eax, eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_mul/max_one.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b800000080 mov eax, 0x80000000
;; 9: 6bc0ff imul eax, eax, -1
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b800000080 mov eax, 0x80000000
;; 11: 6bc0ff imul eax, eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_mul/mixed.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffffff mov eax, 0xffffffff
;; 9: 6bc001 imul eax, eax, 1
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b8ffffffff mov eax, 0xffffffff
;; 11: 6bc001 imul eax, eax, 1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

21
winch/filetests/filetests/x64/i32_mul/params.wat

@ -9,13 +9,14 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8
;; 8: 897c2404 mov dword ptr [rsp + 4], edi
;; c: 893424 mov dword ptr [rsp], esi
;; f: 8b0424 mov eax, dword ptr [rsp]
;; 12: 8b4c2404 mov ecx, dword ptr [rsp + 4]
;; 16: 0fafc8 imul ecx, eax
;; 19: 4889c8 mov rax, rcx
;; 1c: 4883c408 add rsp, 8
;; 20: 5d pop rbp
;; 21: c3 ret
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 89742408 mov dword ptr [rsp + 8], esi
;; 10: 4c893424 mov qword ptr [rsp], r14
;; 14: 8b442408 mov eax, dword ptr [rsp + 8]
;; 18: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 1c: 0fafc8 imul ecx, eax
;; 1f: 4889c8 mov rax, rcx
;; 22: 4883c410 add rsp, 0x10
;; 26: 5d pop rbp
;; 27: c3 ret

11
winch/filetests/filetests/x64/i32_mul/signed.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffffff mov eax, 0xffffffff
;; 9: 6bc0ff imul eax, eax, -1
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b8ffffffff mov eax, 0xffffffff
;; 11: 6bc0ff imul eax, eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_mul/unsigned_with_zero.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b801000000 mov eax, 1
;; 9: 6bc000 imul eax, eax, 0
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b801000000 mov eax, 1
;; 11: 6bc000 imul eax, eax, 0
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

25
winch/filetests/filetests/x64/i32_rems/const.wat

@ -9,14 +9,17 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b905000000 mov ecx, 5
;; 9: b807000000 mov eax, 7
;; e: 99 cdq
;; f: 83f9ff cmp ecx, -1
;; 12: 0f850a000000 jne 0x22
;; 18: ba00000000 mov edx, 0
;; 1d: e902000000 jmp 0x24
;; 22: f7f9 idiv ecx
;; 24: 4889d0 mov rax, rdx
;; 27: 5d pop rbp
;; 28: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b905000000 mov ecx, 5
;; 11: b807000000 mov eax, 7
;; 16: 99 cdq
;; 17: 83f9ff cmp ecx, -1
;; 1a: 0f850a000000 jne 0x2a
;; 20: ba00000000 mov edx, 0
;; 25: e902000000 jmp 0x2c
;; 2a: f7f9 idiv ecx
;; 2c: 4889d0 mov rax, rdx
;; 2f: 4883c408 add rsp, 8
;; 33: 5d pop rbp
;; 34: c3 ret

25
winch/filetests/filetests/x64/i32_rems/one_zero.wat

@ -9,14 +9,17 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0
;; 9: b801000000 mov eax, 1
;; e: 99 cdq
;; f: 83f9ff cmp ecx, -1
;; 12: 0f850a000000 jne 0x22
;; 18: ba00000000 mov edx, 0
;; 1d: e902000000 jmp 0x24
;; 22: f7f9 idiv ecx
;; 24: 4889d0 mov rax, rdx
;; 27: 5d pop rbp
;; 28: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b900000000 mov ecx, 0
;; 11: b801000000 mov eax, 1
;; 16: 99 cdq
;; 17: 83f9ff cmp ecx, -1
;; 1a: 0f850a000000 jne 0x2a
;; 20: ba00000000 mov edx, 0
;; 25: e902000000 jmp 0x2c
;; 2a: f7f9 idiv ecx
;; 2c: 4889d0 mov rax, rdx
;; 2f: 4883c408 add rsp, 8
;; 33: 5d pop rbp
;; 34: c3 ret

25
winch/filetests/filetests/x64/i32_rems/overflow.wat

@ -9,14 +9,17 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b9ffffffff mov ecx, 0xffffffff
;; 9: b800000080 mov eax, 0x80000000
;; e: 99 cdq
;; f: 83f9ff cmp ecx, -1
;; 12: 0f850a000000 jne 0x22
;; 18: ba00000000 mov edx, 0
;; 1d: e902000000 jmp 0x24
;; 22: f7f9 idiv ecx
;; 24: 4889d0 mov rax, rdx
;; 27: 5d pop rbp
;; 28: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b9ffffffff mov ecx, 0xffffffff
;; 11: b800000080 mov eax, 0x80000000
;; 16: 99 cdq
;; 17: 83f9ff cmp ecx, -1
;; 1a: 0f850a000000 jne 0x2a
;; 20: ba00000000 mov edx, 0
;; 25: e902000000 jmp 0x2c
;; 2a: f7f9 idiv ecx
;; 2c: 4889d0 mov rax, rdx
;; 2f: 4883c408 add rsp, 8
;; 33: 5d pop rbp
;; 34: c3 ret

31
winch/filetests/filetests/x64/i32_rems/params.wat

@ -9,18 +9,19 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8
;; 8: 897c2404 mov dword ptr [rsp + 4], edi
;; c: 893424 mov dword ptr [rsp], esi
;; f: 8b0c24 mov ecx, dword ptr [rsp]
;; 12: 8b442404 mov eax, dword ptr [rsp + 4]
;; 16: 99 cdq
;; 17: 83f9ff cmp ecx, -1
;; 1a: 0f850a000000 jne 0x2a
;; 20: ba00000000 mov edx, 0
;; 25: e902000000 jmp 0x2c
;; 2a: f7f9 idiv ecx
;; 2c: 4889d0 mov rax, rdx
;; 2f: 4883c408 add rsp, 8
;; 33: 5d pop rbp
;; 34: c3 ret
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 89742408 mov dword ptr [rsp + 8], esi
;; 10: 4c893424 mov qword ptr [rsp], r14
;; 14: 8b4c2408 mov ecx, dword ptr [rsp + 8]
;; 18: 8b44240c mov eax, dword ptr [rsp + 0xc]
;; 1c: 99 cdq
;; 1d: 83f9ff cmp ecx, -1
;; 20: 0f850a000000 jne 0x30
;; 26: ba00000000 mov edx, 0
;; 2b: e902000000 jmp 0x32
;; 30: f7f9 idiv ecx
;; 32: 4889d0 mov rax, rdx
;; 35: 4883c410 add rsp, 0x10
;; 39: 5d pop rbp
;; 3a: c3 ret

25
winch/filetests/filetests/x64/i32_rems/zero_zero.wat

@ -9,14 +9,17 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0
;; 9: b800000000 mov eax, 0
;; e: 99 cdq
;; f: 83f9ff cmp ecx, -1
;; 12: 0f850a000000 jne 0x22
;; 18: ba00000000 mov edx, 0
;; 1d: e902000000 jmp 0x24
;; 22: f7f9 idiv ecx
;; 24: 4889d0 mov rax, rdx
;; 27: 5d pop rbp
;; 28: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b900000000 mov ecx, 0
;; 11: b800000000 mov eax, 0
;; 16: 99 cdq
;; 17: 83f9ff cmp ecx, -1
;; 1a: 0f850a000000 jne 0x2a
;; 20: ba00000000 mov edx, 0
;; 25: e902000000 jmp 0x2c
;; 2a: f7f9 idiv ecx
;; 2c: 4889d0 mov rax, rdx
;; 2f: 4883c408 add rsp, 8
;; 33: 5d pop rbp
;; 34: c3 ret

17
winch/filetests/filetests/x64/i32_remu/const.wat

@ -9,10 +9,13 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b905000000 mov ecx, 5
;; 9: b807000000 mov eax, 7
;; e: 31d2 xor edx, edx
;; 10: f7f1 div ecx
;; 12: 4889d0 mov rax, rdx
;; 15: 5d pop rbp
;; 16: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b905000000 mov ecx, 5
;; 11: b807000000 mov eax, 7
;; 16: 31d2 xor edx, edx
;; 18: f7f1 div ecx
;; 1a: 4889d0 mov rax, rdx
;; 1d: 4883c408 add rsp, 8
;; 21: 5d pop rbp
;; 22: c3 ret

17
winch/filetests/filetests/x64/i32_remu/one_zero.wat

@ -9,10 +9,13 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0
;; 9: b801000000 mov eax, 1
;; e: 31d2 xor edx, edx
;; 10: f7f1 div ecx
;; 12: 4889d0 mov rax, rdx
;; 15: 5d pop rbp
;; 16: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b900000000 mov ecx, 0
;; 11: b801000000 mov eax, 1
;; 16: 31d2 xor edx, edx
;; 18: f7f1 div ecx
;; 1a: 4889d0 mov rax, rdx
;; 1d: 4883c408 add rsp, 8
;; 21: 5d pop rbp
;; 22: c3 ret

23
winch/filetests/filetests/x64/i32_remu/params.wat

@ -9,14 +9,15 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8
;; 8: 897c2404 mov dword ptr [rsp + 4], edi
;; c: 893424 mov dword ptr [rsp], esi
;; f: 8b0c24 mov ecx, dword ptr [rsp]
;; 12: 8b442404 mov eax, dword ptr [rsp + 4]
;; 16: 31d2 xor edx, edx
;; 18: f7f1 div ecx
;; 1a: 4889d0 mov rax, rdx
;; 1d: 4883c408 add rsp, 8
;; 21: 5d pop rbp
;; 22: c3 ret
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 89742408 mov dword ptr [rsp + 8], esi
;; 10: 4c893424 mov qword ptr [rsp], r14
;; 14: 8b4c2408 mov ecx, dword ptr [rsp + 8]
;; 18: 8b44240c mov eax, dword ptr [rsp + 0xc]
;; 1c: 31d2 xor edx, edx
;; 1e: f7f1 div ecx
;; 20: 4889d0 mov rax, rdx
;; 23: 4883c410 add rsp, 0x10
;; 27: 5d pop rbp
;; 28: c3 ret

17
winch/filetests/filetests/x64/i32_remu/signed.wat

@ -9,10 +9,13 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b9ffffffff mov ecx, 0xffffffff
;; 9: b8ffffffff mov eax, 0xffffffff
;; e: 31d2 xor edx, edx
;; 10: f7f1 div ecx
;; 12: 4889d0 mov rax, rdx
;; 15: 5d pop rbp
;; 16: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b9ffffffff mov ecx, 0xffffffff
;; 11: b8ffffffff mov eax, 0xffffffff
;; 16: 31d2 xor edx, edx
;; 18: f7f1 div ecx
;; 1a: 4889d0 mov rax, rdx
;; 1d: 4883c408 add rsp, 8
;; 21: 5d pop rbp
;; 22: c3 ret

17
winch/filetests/filetests/x64/i32_remu/zero_zero.wat

@ -9,10 +9,13 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0
;; 9: b800000000 mov eax, 0
;; e: 31d2 xor edx, edx
;; 10: f7f1 div ecx
;; 12: 4889d0 mov rax, rdx
;; 15: 5d pop rbp
;; 16: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b900000000 mov ecx, 0
;; 11: b800000000 mov eax, 0
;; 16: 31d2 xor edx, edx
;; 18: f7f1 div ecx
;; 1a: 4889d0 mov rax, rdx
;; 1d: 4883c408 add rsp, 8
;; 21: 5d pop rbp
;; 22: c3 ret

11
winch/filetests/filetests/x64/i32_sub/const.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b80a000000 mov eax, 0xa
;; 9: 83e814 sub eax, 0x14
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b80a000000 mov eax, 0xa
;; 11: 83e814 sub eax, 0x14
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

28
winch/filetests/filetests/x64/i32_sub/locals.wat

@ -18,16 +18,18 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8
;; 8: 48c7042400000000 mov qword ptr [rsp], 0
;; 10: b80a000000 mov eax, 0xa
;; 15: 89442404 mov dword ptr [rsp + 4], eax
;; 19: b814000000 mov eax, 0x14
;; 1e: 890424 mov dword ptr [rsp], eax
;; 21: 8b0424 mov eax, dword ptr [rsp]
;; 24: 8b4c2404 mov ecx, dword ptr [rsp + 4]
;; 28: 29c1 sub ecx, eax
;; 2a: 4889c8 mov rax, rcx
;; 2d: 4883c408 add rsp, 8
;; 31: 5d pop rbp
;; 32: c3 ret
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 48c744240800000000
;; mov qword ptr [rsp + 8], 0
;; 11: 4c893424 mov qword ptr [rsp], r14
;; 15: b80a000000 mov eax, 0xa
;; 1a: 8944240c mov dword ptr [rsp + 0xc], eax
;; 1e: b814000000 mov eax, 0x14
;; 23: 89442408 mov dword ptr [rsp + 8], eax
;; 27: 8b442408 mov eax, dword ptr [rsp + 8]
;; 2b: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 2f: 29c1 sub ecx, eax
;; 31: 4889c8 mov rax, rcx
;; 34: 4883c410 add rsp, 0x10
;; 38: 5d pop rbp
;; 39: c3 ret

11
winch/filetests/filetests/x64/i32_sub/max.wat

@ -8,7 +8,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffff7f mov eax, 0x7fffffff
;; 9: 83e8ff sub eax, -1
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b8ffffff7f mov eax, 0x7fffffff
;; 11: 83e8ff sub eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_sub/max_one.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b800000080 mov eax, 0x80000000
;; 9: 83e801 sub eax, 1
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b800000080 mov eax, 0x80000000
;; 11: 83e801 sub eax, 1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_sub/mixed.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffffff mov eax, 0xffffffff
;; 9: 83e801 sub eax, 1
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b8ffffffff mov eax, 0xffffffff
;; 11: 83e801 sub eax, 1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

21
winch/filetests/filetests/x64/i32_sub/params.wat

@ -9,13 +9,14 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8
;; 8: 897c2404 mov dword ptr [rsp + 4], edi
;; c: 893424 mov dword ptr [rsp], esi
;; f: 8b0424 mov eax, dword ptr [rsp]
;; 12: 8b4c2404 mov ecx, dword ptr [rsp + 4]
;; 16: 29c1 sub ecx, eax
;; 18: 4889c8 mov rax, rcx
;; 1b: 4883c408 add rsp, 8
;; 1f: 5d pop rbp
;; 20: c3 ret
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 89742408 mov dword ptr [rsp + 8], esi
;; 10: 4c893424 mov qword ptr [rsp], r14
;; 14: 8b442408 mov eax, dword ptr [rsp + 8]
;; 18: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 1c: 29c1 sub ecx, eax
;; 1e: 4889c8 mov rax, rcx
;; 21: 4883c410 add rsp, 0x10
;; 25: 5d pop rbp
;; 26: c3 ret

11
winch/filetests/filetests/x64/i32_sub/signed.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffffff mov eax, 0xffffffff
;; 9: 83e8ff sub eax, -1
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b8ffffffff mov eax, 0xffffffff
;; 11: 83e8ff sub eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_sub/unsigned_with_zero.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: b801000000 mov eax, 1
;; 9: 83c000 add eax, 0
;; c: 5d pop rbp
;; d: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: b801000000 mov eax, 1
;; 11: 83c000 add eax, 0
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i64_add/const.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c00a000000 mov rax, 0xa
;; b: 4883c014 add rax, 0x14
;; f: 5d pop rbp
;; 10: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 48c7c00a000000 mov rax, 0xa
;; 13: 4883c014 add rax, 0x14
;; 17: 4883c408 add rsp, 8
;; 1b: 5d pop rbp
;; 1c: c3 ret

29
winch/filetests/filetests/x64/i64_add/locals.wat

@ -18,18 +18,19 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec10 sub rsp, 0x10
;; 4: 4883ec18 sub rsp, 0x18
;; 8: 4531db xor r11d, r11d
;; b: 4c895c2408 mov qword ptr [rsp + 8], r11
;; 10: 4c891c24 mov qword ptr [rsp], r11
;; 14: 48c7c00a000000 mov rax, 0xa
;; 1b: 4889442408 mov qword ptr [rsp + 8], rax
;; 20: 48c7c014000000 mov rax, 0x14
;; 27: 48890424 mov qword ptr [rsp], rax
;; 2b: 488b0424 mov rax, qword ptr [rsp]
;; 2f: 488b4c2408 mov rcx, qword ptr [rsp + 8]
;; 34: 4801c1 add rcx, rax
;; 37: 4889c8 mov rax, rcx
;; 3a: 4883c410 add rsp, 0x10
;; 3e: 5d pop rbp
;; 3f: c3 ret
;; b: 4c895c2410 mov qword ptr [rsp + 0x10], r11
;; 10: 4c895c2408 mov qword ptr [rsp + 8], r11
;; 15: 4c893424 mov qword ptr [rsp], r14
;; 19: 48c7c00a000000 mov rax, 0xa
;; 20: 4889442410 mov qword ptr [rsp + 0x10], rax
;; 25: 48c7c014000000 mov rax, 0x14
;; 2c: 4889442408 mov qword ptr [rsp + 8], rax
;; 31: 488b442408 mov rax, qword ptr [rsp + 8]
;; 36: 488b4c2410 mov rcx, qword ptr [rsp + 0x10]
;; 3b: 4801c1 add rcx, rax
;; 3e: 4889c8 mov rax, rcx
;; 41: 4883c418 add rsp, 0x18
;; 45: 5d pop rbp
;; 46: c3 ret

13
winch/filetests/filetests/x64/i64_add/max.wat

@ -8,9 +8,12 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c001000000 mov rax, 1
;; b: 49bbffffffffffffff7f
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 48c7c001000000 mov rax, 1
;; 13: 49bbffffffffffffff7f
;; movabs r11, 0x7fffffffffffffff
;; 15: 4c01d8 add rax, r11
;; 18: 5d pop rbp
;; 19: c3 ret
;; 1d: 4c01d8 add rax, r11
;; 20: 4883c408 add rsp, 8
;; 24: 5d pop rbp
;; 25: c3 ret

11
winch/filetests/filetests/x64/i64_add/max_one.wat

@ -9,8 +9,11 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 48b80000000000000080
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 48b80000000000000080
;; movabs rax, 0x8000000000000000
;; e: 4883c0ff add rax, -1
;; 12: 5d pop rbp
;; 13: c3 ret
;; 16: 4883c0ff add rax, -1
;; 1a: 4883c408 add rsp, 8
;; 1e: 5d pop rbp
;; 1f: c3 ret

11
winch/filetests/filetests/x64/i64_add/mixed.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c0ffffffff mov rax, 0xffffffffffffffff
;; b: 4883c001 add rax, 1
;; f: 5d pop rbp
;; 10: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 48c7c0ffffffff mov rax, 0xffffffffffffffff
;; 13: 4883c001 add rax, 1
;; 17: 4883c408 add rsp, 8
;; 1b: 5d pop rbp
;; 1c: c3 ret

21
winch/filetests/filetests/x64/i64_add/params.wat

@ -9,13 +9,14 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 48897c2408 mov qword ptr [rsp + 8], rdi
;; d: 48893424 mov qword ptr [rsp], rsi
;; 11: 488b0424 mov rax, qword ptr [rsp]
;; 15: 488b4c2408 mov rcx, qword ptr [rsp + 8]
;; 1a: 4801c1 add rcx, rax
;; 1d: 4889c8 mov rax, rcx
;; 20: 4883c410 add rsp, 0x10
;; 24: 5d pop rbp
;; 25: c3 ret
;; 4: 4883ec18 sub rsp, 0x18
;; 8: 48897c2410 mov qword ptr [rsp + 0x10], rdi
;; d: 4889742408 mov qword ptr [rsp + 8], rsi
;; 12: 4c893424 mov qword ptr [rsp], r14
;; 16: 488b442408 mov rax, qword ptr [rsp + 8]
;; 1b: 488b4c2410 mov rcx, qword ptr [rsp + 0x10]
;; 20: 4801c1 add rcx, rax
;; 23: 4889c8 mov rax, rcx
;; 26: 4883c418 add rsp, 0x18
;; 2a: 5d pop rbp
;; 2b: c3 ret

11
winch/filetests/filetests/x64/i64_add/signed.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c0ffffffff mov rax, 0xffffffffffffffff
;; b: 4883c0ff add rax, -1
;; f: 5d pop rbp
;; 10: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 48c7c0ffffffff mov rax, 0xffffffffffffffff
;; 13: 4883c0ff add rax, -1
;; 17: 4883c408 add rsp, 8
;; 1b: 5d pop rbp
;; 1c: c3 ret

11
winch/filetests/filetests/x64/i64_add/unsigned_with_zero.wat

@ -9,7 +9,10 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c001000000 mov rax, 1
;; b: 4883c000 add rax, 0
;; f: 5d pop rbp
;; 10: c3 ret
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 48c7c001000000 mov rax, 1
;; 13: 4883c000 add rax, 0
;; 17: 4883c408 add rsp, 8
;; 1b: 5d pop rbp
;; 1c: c3 ret

21
winch/filetests/filetests/x64/i64_divs/const.wat

@ -9,12 +9,15 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c10a000000 mov rcx, 0xa
;; b: 48c7c014000000 mov rax, 0x14
;; 12: 4883f900 cmp rcx, 0
;; 16: 0f8407000000 je 0x23
;; 1c: 4899 cqo
;; 1e: 48f7f9 idiv rcx
;; 21: 5d pop rbp
;; 22: c3 ret
;; 23: 0f0b ud2
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 48c7c10a000000 mov rcx, 0xa
;; 13: 48c7c014000000 mov rax, 0x14
;; 1a: 4883f900 cmp rcx, 0
;; 1e: 0f840b000000 je 0x2f
;; 24: 4899 cqo
;; 26: 48f7f9 idiv rcx
;; 29: 4883c408 add rsp, 8
;; 2d: 5d pop rbp
;; 2e: c3 ret
;; 2f: 0f0b ud2

21
winch/filetests/filetests/x64/i64_divs/one_zero.wat

@ -9,12 +9,15 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c100000000 mov rcx, 0
;; b: 48c7c001000000 mov rax, 1
;; 12: 4883f900 cmp rcx, 0
;; 16: 0f8407000000 je 0x23
;; 1c: 4899 cqo
;; 1e: 48f7f9 idiv rcx
;; 21: 5d pop rbp
;; 22: c3 ret
;; 23: 0f0b ud2
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 48c7c100000000 mov rcx, 0
;; 13: 48c7c001000000 mov rax, 1
;; 1a: 4883f900 cmp rcx, 0
;; 1e: 0f840b000000 je 0x2f
;; 24: 4899 cqo
;; 26: 48f7f9 idiv rcx
;; 29: 4883c408 add rsp, 8
;; 2d: 5d pop rbp
;; 2e: c3 ret
;; 2f: 0f0b ud2

21
winch/filetests/filetests/x64/i64_divs/overflow.wat

@ -9,13 +9,16 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c1ffffffff mov rcx, 0xffffffffffffffff
;; b: 48b80000000000000080
;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 48c7c1ffffffff mov rcx, 0xffffffffffffffff
;; 13: 48b80000000000000080
;; movabs rax, 0x8000000000000000
;; 15: 4883f900 cmp rcx, 0
;; 19: 0f8407000000 je 0x26
;; 1f: 4899 cqo
;; 21: 48f7f9 idiv rcx
;; 24: 5d pop rbp
;; 25: c3 ret
;; 26: 0f0b ud2
;; 1d: 4883f900 cmp rcx, 0
;; 21: 0f840b000000 je 0x32
;; 27: 4899 cqo
;; 29: 48f7f9 idiv rcx
;; 2c: 4883c408 add rsp, 8
;; 30: 5d pop rbp
;; 31: c3 ret
;; 32: 0f0b ud2

27
winch/filetests/filetests/x64/i64_divs/params.wat

@ -9,16 +9,17 @@
)
;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec10 sub rsp, 0x10
;; 8: 48897c2408 mov qword ptr [rsp + 8], rdi
;; d: 48893424 mov qword ptr [rsp], rsi
;; 11: 488b0c24 mov rcx, qword ptr [rsp]
;; 15: 488b442408 mov rax, qword ptr [rsp + 8]
;; 1a: 4883f900 cmp rcx, 0
;; 1e: 0f840b000000 je 0x2f
;; 24: 4899 cqo
;; 26: 48f7f9 idiv rcx
;; 29: 4883c410 add rsp, 0x10
;; 2d: 5d pop rbp
;; 2e: c3 ret
;; 2f: 0f0b ud2
;; 4: 4883ec18 sub rsp, 0x18
;; 8: 48897c2410 mov qword ptr [rsp + 0x10], rdi
;; d: 4889742408 mov qword ptr [rsp + 8], rsi
;; 12: 4c893424 mov qword ptr [rsp], r14
;; 16: 488b4c2408 mov rcx, qword ptr [rsp + 8]
;; 1b: 488b442410 mov rax, qword ptr [rsp + 0x10]
;; 20: 4883f900 cmp rcx, 0
;; 24: 0f840b000000 je 0x35
;; 2a: 4899 cqo
;; 2c: 48f7f9 idiv rcx
;; 2f: 4883c418 add rsp, 0x18
;; 33: 5d pop rbp
;; 34: c3 ret
;; 35: 0f0b ud2

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save