From a02899bfe2de021109e86e6a343e98d873666d2a Mon Sep 17 00:00:00 2001 From: Christophe Diederichs Date: Tue, 13 Oct 2020 16:10:47 +0200 Subject: [PATCH] scalarmult internal loop in wasm --- fe25519_25/fe25519_mul.js | 3 +- fe25519_25/fe25519_mul.wat | 145 +-- fe25519_25/fe25519_sq.js | 2 +- fe25519_25/fe25519_sq.wat | 61 +- fe25519_25/scalarmult_curve25519.js | 61 ++ fe25519_25/scalarmult_curve25519.wat | 1434 ++++++++++++++++++++++++++ 6 files changed, 1610 insertions(+), 96 deletions(-) create mode 100644 fe25519_25/scalarmult_curve25519.js create mode 100644 fe25519_25/scalarmult_curve25519.wat diff --git a/fe25519_25/fe25519_mul.js b/fe25519_25/fe25519_mul.js index f53b10c..fd1852f 100644 --- a/fe25519_25/fe25519_mul.js +++ b/fe25519_25/fe25519_mul.js @@ -7,8 +7,7 @@ function loadWebAssembly (opts) { if (!loadWebAssembly.supported) return null var imp = opts && opts.imports -console.log(imp) - var wasm = toUint8Array('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') + var wasm = toUint8Array('AGFzbQEAAAABHwJgFX5+fn5+fn5+fn5+fn5+fn5+fn5+fwBgA39/fwACDgECanMFdGFibGUBcAABAwMCAAEFAwEAAQcYAgZtZW1vcnkCAAtmZTI1NTE5X211bAABCQcBAEEBCwEACv4QApAQAYYBfiAAp6whACABp6whASACp6whAiADp6whAyAEp6whBCAFp6whBSAGp6whBiAHp6whByAIp6whCCAJp6whCSAKp6whCiALp6whCyAMp6whDCANp6whDSAOp6whDiAPp6whDyAQp6whECARp6whESASp6whEiATp6whE0ITIAt+IAtCgICAgAiDQgGGQhN+fSEpQhMgDH4gDEKAgICACINCAYZCE359ISpCEyANfiANQoCAgIAIg0IBhkITfn0hK0ITIA5+IA5CgICAgAiDQgGGQhN+fSEsQhMgD34gD0KAgICACINCAYZCE359IS1CEyAQfiAQQoCAgIAIg0IBhkITfn0hLkITIBF+IBFCgICAgAiDQgGGQhN+fSEvQhMgEn4gEkKAgICACINCAYZCE359ITBCEyATfiATQoCAgIAIg0IBhkITfn0hMUICIAF+IAFCgICAgAiDQgGGQgJ+fSEyQgIgA34gA0KAgICACINCAYZCAn59ITNCAiAFfiAFQoCAgIAIg0IBhkICfn0hNEICIAd+IAdCgICAgAiDQgGGQgJ+fSE1QgIgCX4gCUKAgICACINCAYZCAn59ITYgKaesISkgKqesISogK6esISsgLKesISwgLaesIS0gLqesIS4gL6esIS8gMKesITAgMaesITEgMqesITIgM6esITMgNKesITQgNaesITUgNqesITYgACAKfiE3IAAgC34hOCAAIAx+ITkgACANfiE6IAAgDn4hOyAAIA9+ITwgACAQfiE9IAAgEX4hPiAAIBJ+IT8gACATfiFAIAEgCn4hQSAyIAt+IUIgASAMfiFDIDIgDX4hRCABIA5+IUUgMiAPfiFGIAEgEH4hRyAyIBF+IUggASASfiFJIDIgMX4hSiACIAp+IUsgAiALfiFMIAIgDH4hTSACIA1+IU4gAiAOfiFPIAIgD34hUCACIBB+IVEgAiARfiFSIAIgMH4hUyACIDF+IVQgAyAKfiFVIDMgC34hViADIAx+IVcgMyANfiFYIAMgDn4hWSAzIA9+IVogAyAQfiFbIDMgL34hXCADIDB+IV0gMyAxfiFeIAQgCn4hXyAEIAt+IWAgBCAMfiFhIAQgDX4hYiAEIA5+IWMgBCAPfiFkIAQgLn4hZSAEIC9+IWYgBCAwfiFnIAQgMX4haCAFIAp+IWkgNCALfiFqIAUgDH4hayA0IA1+IWwgBSAOfiFtIDQgLX4hbiAFIC5+IW8gNCAvfiFwIAUgMH4hcSA0IDF+IXIgBiAKfiFzIAYgC34hdCAGIAx+IXUgBiANfiF2IAYgLH4hdyAGIC1+IXggBiAufiF5IAYgL34heiAGIDB+IXsgBiAxfiF8IAcgCn4hfSA1IAt+IX4gByAMfiF/IDUgK34hgAEgByAsfiGBASA1IC1+IYIBIAcgLn4hgwEgNSAvfiGEASAHIDB+IYUBIDUgMX4hhgEgCCAKfiGHASAIIAt+IYgBIAggKn4hiQEgCCArfiGKASAIICx+IYsBIAggLX4hjAEgCCAufiGNASAIIC9+IY4BIAggMH4hjwEgCCAxfiGQASAJIAp+IZEBIDYgKX4hkgEgCSAqfiGTASA2ICt+IZQBIAkgLH4hlQEgNiAtfiGWASAJIC5+IZcBIDYgL34hmAEgCSAwfiGZASA2IDF+IZoBIDcgSiBTIFwgZSBuIHcggAEgiQEgkgF8fHx8fHx8fHwhFSA4IEEgVCBdIGYgbyB4IIEBIIoBIJMBfHx8fHx8fHx8IRYgOSBCIEsgXiBnIHAgeSCCASCLASCUAXx8fHx8fHx8fCEXIDogQyBMIFUgaCBxIHoggwEgjAEglQF8fHx8fHx8fHwhGCA7IEQgTSBWIF8gciB7IIQBII0BIJYBfHx8fHx8fHx8IRkgPCBFIE4gVyBgIGkgfCCFASCOASCXAXx8fHx8fHx8fCEaID0gRiBPIFggYSBqIHMghgEgjwEgmAF8fHx8fHx8fHwhGyA+IEcgUCBZIGIgayB0IH0gkAEgmQF8fHx8fHx8fHwhHCA/IEggUSBaIGMgbCB1IH4ghwEgmgF8fHx8fHx8fHwhHSBAIEkgUiBbIGQgbSB2IH8giAEgkQF8fHx8fHx8fHwhHiAVQgFCGYZ8QhqHIR8gFiAffCEWIBUgH0IBQhqGfn0hFSAZQgFCGYZ8QhqHISMgGiAjfCEaIBkgI0IBQhqGfn0hGSAWQgFCGIZ8QhmHISAgFyAgfCEXIBYgIEIBQhmGfn0hFiAaQgFCGIZ8QhmHISQgGyAkfCEbIBogJEIBQhmGfn0hGiAXQgFCGYZ8QhqHISEgGCAhfCEYIBcgIUIBQhqGfn0hFyAbQgFCGYZ8QhqHISUgHCAlfCEcIBsgJUIBQhqGfn0hGyAYQgFCGIZ8QhmHISIgGSAifCEZIBggIkIBQhmGfn0hGCAcQgFCGIZ8QhmHISYgHSAmfCEdIBwgJkIBQhmGfn0hHCAZQgFCGYZ8QhqHISMgGiAjfCEaIBkgI0IBQhqGfn0hGSAdQgFCGYZ8QhqHIScgHiAnfCEeIB0gJ0IBQhqGfn0hHSAeQgFCGIZ8QhmHISggFSAoQhN+fCEVIB4gKEIBQhmGfn0hHiAVQgFCGYZ8QhqHIR8gFiAffCEWIBUgH0IBQhqGfn0hFSAUIBU+AgAgFCAWPgIEIBQgFz4CCCAUIBg+AgwgFCAZPgIQIBQgGj4CFCAUIBs+AhggFCAcPgIcIBQgHT4CICAUIB4+AiQLagAgATUCACABNQIEIAE1AgggATUCDCABNQIQIAE1AhQgATUCGCABNQIcIAE1AiAgATUCJCACNQIAIAI1AgQgAjUCCCACNQIMIAI1AhAgAjUCFCACNQIYIAI1AhwgAjUCICACNQIkIAAQAAs=') var ready = null var mod = { diff --git a/fe25519_25/fe25519_mul.wat b/fe25519_25/fe25519_mul.wat index 998d4ba..41fa0f3 100644 --- a/fe25519_25/fe25519_mul.wat +++ b/fe25519_25/fe25519_mul.wat @@ -1,57 +1,62 @@ (module - (func $i32.log (import "debug" "log") (param i32)) - (func $i32.log_tee (import "debug" "log_tee") (param i32) (result i32)) - ;; No i64 interop with JS yet - but maybe coming with WebAssembly BigInt - ;; So we can instead fake this by splitting the i64 into two i32 limbs, - ;; however these are WASM functions using i32x2.log: - (func $i32x2.log (import "debug" "log") (param i32) (param i32)) - (func $f32.log (import "debug" "log") (param f32)) - (func $f32.log_tee (import "debug" "log_tee") (param f32) (result f32)) - (func $f64.log (import "debug" "log") (param f64)) - (func $f64.log_tee (import "debug" "log_tee") (param f64) (result f64)) + (import "js" "table" (table 1 anyfunc)) + (elem (i32.const 1) $fe_mul) + + ;; (func $i32.log (import "debug" "log") (param i32)) + ;; (func $i32.log_tee (import "debug" "log_tee") (param i32) (result i32)) + ;; ;; No i64 interop with JS yet - but maybe coming with WebAssembly BigInt + ;; ;; So we can instead fake this by splitting the i64 into two i32 limbs, + ;; ;; however these are WASM functions using i32x2.log: + ;; (func $i32x2.log (import "debug" "log") (param i32) (param i32)) + ;; (func $f32.log (import "debug" "log") (param f32)) + ;; (func $f32.log_tee (import "debug" "log_tee") (param f32) (result f32)) + ;; (func $f64.log (import "debug" "log") (param f64)) + ;; (func $f64.log_tee (import "debug" "log_tee") (param f64) (result f64)) (memory $0 1) (export "memory" (memory $0)) - ;; i64 logging by splitting into two i32 limbs - (func $i64.log - (param $0 i64) - (call $i32x2.log - ;; Upper limb - (i32.wrap/i64 - (i64.shr_s (get_local $0) - (i64.const 32))) - ;; Lower limb - (i32.wrap/i64 (get_local $0)))) + ;; ;; i64 logging by splitting into two i32 limbs + ;; (func $i64.log + ;; (param $0 i64) + ;; (call $i32x2.log + ;; ;; Upper limb + ;; (i32.wrap/i64 + ;; (i64.shr_s (get_local $0) + ;; (i64.const 32))) + ;; ;; Lower limb + ;; (i32.wrap/i64 (get_local $0)))) - (func $i64.log_tee - (param $0 i64) - (result i64) - (call $i64.log (get_local $0)) - (return (get_local $0))) + ;; (func $i64.log_tee + ;; (param $0 i64) + ;; (result i64) + ;; (call $i64.log (get_local $0)) + ;; (return (get_local $0))) - (func $mul (export "fe25519_mul") (param $h i32) (param $f i32) (param $g i32) - (local $f0 i64) - (local $f1 i64) - (local $f2 i64) - (local $f3 i64) - (local $f4 i64) - (local $f5 i64) - (local $f6 i64) - (local $f7 i64) - (local $f8 i64) - (local $f9 i64) + (func $fe_mul + (param $f0 i64) + (param $f1 i64) + (param $f2 i64) + (param $f3 i64) + (param $f4 i64) + (param $f5 i64) + (param $f6 i64) + (param $f7 i64) + (param $f8 i64) + (param $f9 i64) - (local $g0 i64) - (local $g1 i64) - (local $g2 i64) - (local $g3 i64) - (local $g4 i64) - (local $g5 i64) - (local $g6 i64) - (local $g7 i64) - (local $g8 i64) - (local $g9 i64) + (param $g0 i64) + (param $g1 i64) + (param $g2 i64) + (param $g3 i64) + (param $g4 i64) + (param $g5 i64) + (param $g6 i64) + (param $g7 i64) + (param $g8 i64) + (param $g9 i64) + + (param $h i32) (local $h0 i64) (local $h1 i64) @@ -191,28 +196,6 @@ (local $f9g8_19 i64) (local $f9g9_38 i64) - (set_local $f0 (i64.load32_u offset=0 (get_local $f))) - (set_local $f1 (i64.load32_u offset=4 (get_local $f))) - (set_local $f2 (i64.load32_u offset=8 (get_local $f))) - (set_local $f3 (i64.load32_u offset=12 (get_local $f))) - (set_local $f4 (i64.load32_u offset=16 (get_local $f))) - (set_local $f5 (i64.load32_u offset=20 (get_local $f))) - (set_local $f6 (i64.load32_u offset=24 (get_local $f))) - (set_local $f7 (i64.load32_u offset=28 (get_local $f))) - (set_local $f8 (i64.load32_u offset=32 (get_local $f))) - (set_local $f9 (i64.load32_u offset=36 (get_local $f))) - - (set_local $g0 (i64.load32_u offset=0 (get_local $g))) - (set_local $g1 (i64.load32_u offset=4 (get_local $g))) - (set_local $g2 (i64.load32_u offset=8 (get_local $g))) - (set_local $g3 (i64.load32_u offset=12 (get_local $g))) - (set_local $g4 (i64.load32_u offset=16 (get_local $g))) - (set_local $g5 (i64.load32_u offset=20 (get_local $g))) - (set_local $g6 (i64.load32_u offset=24 (get_local $g))) - (set_local $g7 (i64.load32_u offset=28 (get_local $g))) - (set_local $g8 (i64.load32_u offset=32 (get_local $g))) - (set_local $g9 (i64.load32_u offset=36 (get_local $g))) - (set_local $f0 (i64.extend_s/i32 (i32.wrap/i64 (get_local $f0)))) (set_local $f1 (i64.extend_s/i32 (i32.wrap/i64 (get_local $f1)))) (set_local $f2 (i64.extend_s/i32 (i32.wrap/i64 (get_local $f2)))) @@ -431,4 +414,28 @@ (i64.store32 offset=24 (get_local $h) (get_local $h6)) (i64.store32 offset=28 (get_local $h) (get_local $h7)) (i64.store32 offset=32 (get_local $h) (get_local $h8)) - (i64.store32 offset=36 (get_local $h) (get_local $h9)))) + (i64.store32 offset=36 (get_local $h) (get_local $h9))) + + (func $fe25519_mul (export "fe25519_mul") (param $h i32) (param $f i32) (param $g i32) + (i64.load32_u offset=0 (get_local $f)) + (i64.load32_u offset=4 (get_local $f)) + (i64.load32_u offset=8 (get_local $f)) + (i64.load32_u offset=12 (get_local $f)) + (i64.load32_u offset=16 (get_local $f)) + (i64.load32_u offset=20 (get_local $f)) + (i64.load32_u offset=24 (get_local $f)) + (i64.load32_u offset=28 (get_local $f)) + (i64.load32_u offset=32 (get_local $f)) + (i64.load32_u offset=36 (get_local $f)) + (i64.load32_u offset=0 (get_local $g)) + (i64.load32_u offset=4 (get_local $g)) + (i64.load32_u offset=8 (get_local $g)) + (i64.load32_u offset=12 (get_local $g)) + (i64.load32_u offset=16 (get_local $g)) + (i64.load32_u offset=20 (get_local $g)) + (i64.load32_u offset=24 (get_local $g)) + (i64.load32_u offset=28 (get_local $g)) + (i64.load32_u offset=32 (get_local $g)) + (i64.load32_u offset=36 (get_local $g)) + (get_local $h) + (call $fe_mul))) diff --git a/fe25519_25/fe25519_sq.js b/fe25519_25/fe25519_sq.js index d93d91a..6dae2d7 100644 --- a/fe25519_25/fe25519_sq.js +++ b/fe25519_25/fe25519_sq.js @@ -7,7 +7,7 @@ function loadWebAssembly (opts) { if (!loadWebAssembly.supported) return null var imp = opts && opts.imports - var wasm = toUint8Array('AGFzbQEAAAABCAFgBH9/f38AAwIBAAUDAQABBw8CBm1lbW9yeQIAAnNxAAAKzwoBzAoCAX9jfiABNQIAIQYgATUCBCEHIAE1AgghCCABNQIMIQkgATUCECEKIAE1AhQhCyABNQIYIQwgATUCHCENIAE1AiAhDiABNQIkIQ8CQANAIAanrCEGIAenrCEHIAinrCEIIAmnrCEJIAqnrCEKIAunrCELIAynrCEMIA2nrCENIA6nrCEOIA+nrCEPIAZCAn4hJCAHQgJ+ISUgCEICfiEmIAlCAn4hJyAKQgJ+ISggC0ICfiEpIAxCAn4hKiANQgJ+ISsgC0ImfiEsIAxCE34hLSANQiZ+IS4gDkITfiEvIA9CJn4hMCAGIAZ+ITEgJCAHfiEyICQgCH4hMyAkIAl+ITQgJCAKfiE1ICQgC34hNiAkIAx+ITcgJCANfiE4ICQgDn4hOSAkIA9+ITogJSAHfiE7ICUgCH4hPCAlICd+IT0gJSAKfiE+ICUgKX4hPyAlIAx+IUAgJSArfiFBICUgDn4hQiAlIDB+IUMgCCAIfiFEICYgCX4hRSAmIAp+IUYgJiALfiFHICYgDH4hSCAmIA1+IUkgJiAvfiFKIAggMH4hSyAnIAl+IUwgJyAKfiFNICcgKX4hTiAnIAx+IU8gJyAufiFQICcgL34hUSAnIDB+IVIgCiAKfiFTICggC34hVCAoIC1+IVUgCiAufiFWICggL34hVyAKIDB+IVggCyAsfiFZICkgLX4hWiApIC5+IVsgKSAvfiFcICkgMH4hXSAMIC1+IV4gDCAufiFfICogL34hYCAMIDB+IWEgDSAufiFiICsgL34hYyArIDB+IWQgDiAvfiFlIA4gMH4hZiAPIDB+IWcgMSBDIEogUCBVIFl8fHx8fCEQIDIgSyBRIFYgWnx8fHwhESAzIDsgUiBXIFsgXnx8fHx8IRIgNCA8IFggXCBffHx8fCETIDUgPSBEIF0gYCBifHx8fHwhFCA2ID4gRSBhIGN8fHx8IRUgNyA/IEYgTCBkIGV8fHx8fCEWIDggQCBHIE0gZnx8fHwhFyA5IEEgSCBOIFMgZ3x8fHx8IRggOiBCIEkgTyBUfHx8fCEZIAQgA0YNASAEQQFqIQQMAAsLIAJBAUYEQCAQIBB8IRAgESARfCERIBIgEnwhEiATIBN8IRMgFCAUfCEUIBUgFXwhFSAWIBZ8IRYgFyAXfCEXIBggGHwhGCAZIBl8IRkLIBBCAUIZhnxCGochGiARIBp8IREgECAaQgFCGoZ+fSEQIBRCAUIZhnxCGochHiAVIB58IRUgFCAeQgFCGoZ+fSEUIBFCAUIYhnxCGYchGyASIBt8IRIgESAbQgFCGYZ+fSERIBVCAUIYhnxCGYchHyAWIB98IRYgFSAfQgFCGYZ+fSEVIBJCAUIZhnxCGochHCATIBx8IRMgEiAcQgFCGoZ+fSESIBZCAUIZhnxCGochICAXICB8IRcgFiAgQgFCGoZ+fSEWIBNCAUIYhnxCGYchHSAUIB18IRQgEyAdQgFCGYZ+fSETIBdCAUIYhnxCGYchISAYICF8IRggFyAhQgFCGYZ+fSEXIBRCAUIZhnxCGochHiAVIB58IRUgFCAeQgFCGoZ+fSEUIBhCAUIZhnxCGochIiAZICJ8IRkgGCAiQgFCGoZ+fSEYIBlCAUIYhnxCGYchIyAQICNCE358IRAgGSAjQgFCGYZ+fSEZIBBCAUIZhnxCGochGiARIBp8IREgECAaQgFCGoZ+fSEQIAAgED4CACAAIBE+AgQgACASPgIIIAAgEz4CDCAAIBQ+AhAgACAVPgIUIAAgFj4CGCAAIBc+AhwgACAYPgIgIAAgGT4CJAs=') + var wasm = toUint8Array('AGFzbQEAAAABGAJgDX5+fn5+fn5+fn5/f38AYAR/f39/AAIOAQJqcwV0YWJsZQFwAAEDAwIAAQUDAQABBw8CBm1lbW9yeQIAAnNxAAEJBwEAQQILAQAKxgoChgoCAX9ZfgJAA0AgAKesIQAgAaesIQEgAqesIQIgA6esIQMgBKesIQQgBaesIQUgBqesIQYgB6esIQcgCKesIQggCaesIQkgAEICfiEjIAFCAn4hJCACQgJ+ISUgA0ICfiEmIARCAn4hJyAFQgJ+ISggBkICfiEpIAdCAn4hKiAFQiZ+ISsgBkITfiEsIAdCJn4hLSAIQhN+IS4gCUImfiEvIAAgAH4hMCAjIAF+ITEgIyACfiEyICMgA34hMyAjIAR+ITQgIyAFfiE1ICMgBn4hNiAjIAd+ITcgIyAIfiE4ICMgCX4hOSAkIAF+ITogJCACfiE7ICQgJn4hPCAkIAR+IT0gJCAofiE+ICQgBn4hPyAkICp+IUAgJCAIfiFBICQgL34hQiACIAJ+IUMgJSADfiFEICUgBH4hRSAlIAV+IUYgJSAGfiFHICUgB34hSCAlIC5+IUkgAiAvfiFKICYgA34hSyAmIAR+IUwgJiAofiFNICYgBn4hTiAmIC1+IU8gJiAufiFQICYgL34hUSAEIAR+IVIgJyAFfiFTICcgLH4hVCAEIC1+IVUgJyAufiFWIAQgL34hVyAFICt+IVggKCAsfiFZICggLX4hWiAoIC5+IVsgKCAvfiFcIAYgLH4hXSAGIC1+IV4gKSAufiFfIAYgL34hYCAHIC1+IWEgKiAufiFiICogL34hYyAIIC5+IWQgCCAvfiFlIAkgL34hZiAwIEIgSSBPIFQgWHx8fHx8IQ8gMSBKIFAgVSBZfHx8fCEQIDIgOiBRIFYgWiBdfHx8fHwhESAzIDsgVyBbIF58fHx8IRIgNCA8IEMgXCBfIGF8fHx8fCETIDUgPSBEIGAgYnx8fHwhFCA2ID4gRSBLIGMgZHx8fHx8IRUgNyA/IEYgTCBlfHx8fCEWIDggQCBHIE0gUiBmfHx8fHwhFyA5IEEgSCBOIFN8fHx8IRggDSALRg0BIA1BAWohDQwACwsgCkEBRgRAIA8gD3whDyAQIBB8IRAgESARfCERIBIgEnwhEiATIBN8IRMgFCAUfCEUIBUgFXwhFSAWIBZ8IRYgFyAXfCEXIBggGHwhGAsgD0IBQhmGfEIahyEZIBAgGXwhECAPIBlCAUIahn59IQ8gE0IBQhmGfEIahyEdIBQgHXwhFCATIB1CAUIahn59IRMgEEIBQhiGfEIZhyEaIBEgGnwhESAQIBpCAUIZhn59IRAgFEIBQhiGfEIZhyEeIBUgHnwhFSAUIB5CAUIZhn59IRQgEUIBQhmGfEIahyEbIBIgG3whEiARIBtCAUIahn59IREgFUIBQhmGfEIahyEfIBYgH3whFiAVIB9CAUIahn59IRUgEkIBQhiGfEIZhyEcIBMgHHwhEyASIBxCAUIZhn59IRIgFkIBQhiGfEIZhyEgIBcgIHwhFyAWICBCAUIZhn59IRYgE0IBQhmGfEIahyEdIBQgHXwhFCATIB1CAUIahn59IRMgF0IBQhmGfEIahyEhIBggIXwhGCAXICFCAUIahn59IRcgGEIBQhiGfEIZhyEiIA8gIkITfnwhDyAYICJCAUIZhn59IRggD0IBQhmGfEIahyEZIBAgGXwhECAPIBlCAUIahn59IQ8gDCAPPgIAIAwgED4CBCAMIBE+AgggDCASPgIMIAwgEz4CECAMIBQ+AhQgDCAVPgIYIAwgFj4CHCAMIBc+AiAgDCAYPgIkCzwAIAA1AgAgADUCBCAANQIIIAA1AgwgADUCECAANQIUIAA1AhggADUCHCAANQIgIAA1AiQgASACIAMQAAs=') var ready = null var mod = { diff --git a/fe25519_25/fe25519_sq.wat b/fe25519_25/fe25519_sq.wat index 2e14cf0..1cfba23 100644 --- a/fe25519_25/fe25519_sq.wat +++ b/fe25519_25/fe25519_sq.wat @@ -1,21 +1,29 @@ (module + (import "js" "table" (table 1 anyfunc)) + (elem (i32.const 2) $fe_sq) + (memory $0 1) (export "memory" (memory $0)) - (func $sq (export "sq") (param $h i32) (param $f i32) (param $double i32) (param $repeat i32) + (func $fe_sq + (param $f0 i64) + (param $f1 i64) + (param $f2 i64) + (param $f3 i64) + (param $f4 i64) + (param $f5 i64) + (param $f6 i64) + (param $f7 i64) + (param $f8 i64) + (param $f9 i64) + + (param $double i32) + (param $repeat i32) + + (param $h i32) + (local $count i32) (local $tmp i64) - - (local $f0 i64) - (local $f1 i64) - (local $f2 i64) - (local $f3 i64) - (local $f4 i64) - (local $f5 i64) - (local $f6 i64) - (local $f7 i64) - (local $f8 i64) - (local $f9 i64) (local $h0 i64) (local $h1 i64) @@ -110,17 +118,6 @@ (local $f8f9_38 i64) (local $f9f9_38 i64) - (set_local $f0 (i64.load32_u offset=0 (get_local $f))) - (set_local $f1 (i64.load32_u offset=4 (get_local $f))) - (set_local $f2 (i64.load32_u offset=8 (get_local $f))) - (set_local $f3 (i64.load32_u offset=12 (get_local $f))) - (set_local $f4 (i64.load32_u offset=16 (get_local $f))) - (set_local $f5 (i64.load32_u offset=20 (get_local $f))) - (set_local $f6 (i64.load32_u offset=24 (get_local $f))) - (set_local $f7 (i64.load32_u offset=28 (get_local $f))) - (set_local $f8 (i64.load32_u offset=32 (get_local $f))) - (set_local $f9 (i64.load32_u offset=36 (get_local $f))) - (block $end (loop $again (set_local $f0 (i64.extend_s/i32 (i32.wrap/i64 (get_local $f0)))) @@ -285,4 +282,20 @@ (i64.store32 offset=24 (get_local $h) (get_local $h6)) (i64.store32 offset=28 (get_local $h) (get_local $h7)) (i64.store32 offset=32 (get_local $h) (get_local $h8)) - (i64.store32 offset=36 (get_local $h) (get_local $h9)))) + (i64.store32 offset=36 (get_local $h) (get_local $h9))) + + (func $sq (export "sq") (param $f i32) (param $double i32) (param $repeat i32) (param $h i32) + (i64.load32_u offset=0 (get_local $f)) + (i64.load32_u offset=4 (get_local $f)) + (i64.load32_u offset=8 (get_local $f)) + (i64.load32_u offset=12 (get_local $f)) + (i64.load32_u offset=16 (get_local $f)) + (i64.load32_u offset=20 (get_local $f)) + (i64.load32_u offset=24 (get_local $f)) + (i64.load32_u offset=28 (get_local $f)) + (i64.load32_u offset=32 (get_local $f)) + (i64.load32_u offset=36 (get_local $f)) + (get_local $double) + (get_local $repeat) + (get_local $h) + (call $fe_sq))) diff --git a/fe25519_25/scalarmult_curve25519.js b/fe25519_25/scalarmult_curve25519.js new file mode 100644 index 0000000..c05f7ec --- /dev/null +++ b/fe25519_25/scalarmult_curve25519.js @@ -0,0 +1,61 @@ + +module.exports = loadWebAssembly + +loadWebAssembly.supported = typeof WebAssembly !== 'undefined' + +function loadWebAssembly (opts) { + if (!loadWebAssembly.supported) return null + + var imp = opts && opts.imports + var wasm = toUint8Array('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DCFWIBA1AhAhVyAQNQIUIVggEDUCGCFZIBA1AhwhWiAQNQIgIVsgEDUCJCFcID8gK3whNSBAICx8ITYgQSAtfCE3IEIgLnwhOCBDIC98ITkgRCAwfCE6IEUgMXwhOyBGIDJ8ITwgRyAzfCE9IEggNHwhPiA/ICt9ISsgQCAsfSEsIEEgLX0hLSBCIC59IS4gQyAvfSEvIEQgMH0hMCBFIDF9ITEgRiAyfSEyIEcgM30hMyBIIDR9ITQgUyBUIFUgViBXIFggWSBaIFsgXCBJIEogSyBMIE0gTiBPIFAgUSBSIA5BAxEAACBTIEl9IVMgVCBKfSFUIFUgS30hVSBWIEx9IVYgVyBNfSFXIFggTn0hWCBZIE99IVkgWiBQfSFaIFsgUX0hWyBcIFJ9IVwgKyAsIC0gLiAvIDAgMSAyIDMgNCANQQBBAEECEQEAQsK2B0IAQgBCAEIAQgBCAEIAQgBCACBTIFQgVSBWIFcgWCBZIFogWyBcIA5BAREAACA1IDYgNyA4IDkgOiA7IDwgPSA+IA9BAEEAQQIRAQAgDTUCACErIA01AgQhLCANNQIIIS0gDTUCDCEuIA01AhAhLyANNQIUITAgDTUCGCExIA01AhwhMiANNQIgITMgDTUCJCE0IA41AgAhPyAONQIEIUAgDjUCCCFBIA41AgwhQiAONQIQIUMgDjUCFCFEIA41AhghRSAONQIcIUYgDjUCICFHIA41AiQhSCAPNQIAITUgDzUCBCE2IA81AgghNyAPNQIMITggDzUCECE5IA81AhQhOiAPNQIYITsgDzUCHCE8IA81AiAhPSAPNQIkIT4gSSA/fCFJIEogQHwhSiBLIEF8IUsgTCBCfCFMIE0gQ3whTSBOIER8IU4gTyBFfCFPIFAgRnwhUCBRIEd8IVEgUiBIfCFSIBcgGCAZIBogGyAcIB0gHiAfICAgKyAsIC0gLiAvIDAgMSAyIDMgNCAOQQERAAAgSSBKIEsgTCBNIE4gTyBQIFEgUiBTIFQgVSBWIFcgWCBZIFogWyBcIA1BAREAACANNQIAISsgDTUCBCEsIA01AgghLSANNQIMIS4gDTUCECEvIA01AhQhMCANNQIYITEgDTUCHCEyIA01AiAhMyANNQIkITQgDjUCACE/IA41AgQhQCAONQIIIUEgDjUCDCFCIA41AhAhQyAONQIUIUQgDjUCGCFFIA41AhwhRiAONQIgIUcgDjUCJCFIIAxBAWshDAwACyAGICE+AgAgBiAiPgIEIAYgIz4CCCAGICQ+AgwgBiAlPgIQIAYgJj4CFCAGICc+AhggBiAoPgIcIAYgKT4CICAGICo+AiQgByA1PgIAIAcgNj4CBCAHIDc+AgggByA4PgIMIAcgOT4CECAHIDo+AhQgByA7PgIYIAcgPD4CHCAHID0+AiAgByA+PgIkIAggKz4CACAIICw+AgQgCCAtPgIIIAggLj4CDCAIIC8+AhAgCCAwPgIUIAggMT4CGCAIIDI+AhwgCCAzPgIgIAggND4CJCAJID8+AgAgCSBAPgIEIAkgQT4CCCAJIEI+AgwgCSBDPgIQIAkgRD4CFCAJIEU+AhggCSBGPgIcIAkgRz4CICAJIEg+AiQgCgs=') + var ready = null + + var mod = { + buffer: wasm, + memory: null, + exports: null, + realloc: realloc, + onload: onload + } + + onload(function () {}) + + return mod + + function realloc (size) { + mod.exports.memory.grow(Math.max(0, Math.ceil(Math.abs(size - mod.memory.length) / 65536))) + mod.memory = new Uint8Array(mod.exports.memory.buffer) + } + + function onload (cb) { + if (mod.exports) return cb() + + if (ready) { + ready.then(cb.bind(null, null)).catch(cb) + return + } + + try { + if (opts && opts.async) throw new Error('async') + setup({instance: new WebAssembly.Instance(new WebAssembly.Module(wasm), imp)}) + } catch (err) { + ready = WebAssembly.instantiate(wasm, imp).then(setup) + } + + onload(cb) + } + + function setup (w) { + mod.exports = w.instance.exports + mod.memory = mod.exports.memory && mod.exports.memory.buffer && new Uint8Array(mod.exports.memory.buffer) + } +} + +function toUint8Array (s) { + if (typeof atob === 'function') return new Uint8Array(atob(s).split('').map(charCodeAt)) + return (require('buf' + 'fer').Buffer).from(s, 'base64') +} + +function charCodeAt (c) { + return c.charCodeAt(0) +} diff --git a/fe25519_25/scalarmult_curve25519.wat b/fe25519_25/scalarmult_curve25519.wat new file mode 100644 index 0000000..2799750 --- /dev/null +++ b/fe25519_25/scalarmult_curve25519.wat @@ -0,0 +1,1434 @@ +(module + (import "js" "table" (table 1 anyfunc)) + (type $fe_mul (func + (param $f_0 i64) + (param $f_1 i64) + (param $f_2 i64) + (param $f_3 i64) + (param $f_4 i64) + (param $f_5 i64) + (param $f_6 i64) + (param $f_7 i64) + (param $f_8 i64) + (param $f_9 i64) + (param $g_0 i64) + (param $g_1 i64) + (param $g_2 i64) + (param $g_3 i64) + (param $g_4 i64) + (param $g_5 i64) + (param $g_6 i64) + (param $g_7 i64) + (param $g_8 i64) + (param $g_9 i64) + (param $res i32))) + + (type $fe_sq (func + (param $f_0 i64) + (param $f_1 i64) + (param $f_2 i64) + (param $f_3 i64) + (param $f_4 i64) + (param $f_5 i64) + (param $f_6 i64) + (param $f_7 i64) + (param $f_8 i64) + (param $f_9 i64) + (param $double i32) + (param $repeat i32) + (param $res i32))) + + (memory $0 1) + (export "memory" (memory $0)) + + (func $scalarmult (export "scalarmult") + (param $ptr_x1 i32) + (param $ptr_x2 i32) + (param $ptr_x3 i32) + (param $ptr_z2 i32) + (param $ptr_z3 i32) + + (param $ptr_t i32) + + (param $res_x2 i32) + (param $res_x3 i32) + (param $res_z2 i32) + (param $res_z3 i32) + + (result i32) + + (local $swap i32) + (local $b i32) + (local $pos i32) + + (local $ptr0 i32) + (local $ptr1 i32) + (local $ptr2 i32) + (local $ptr3 i32) + + (local $mask i64) + + (local $t i64) + (local $t_0 i64) + (local $t_1 i64) + (local $t_2 i64) + (local $t_3 i64) + + (local $x1_0 i64) + (local $x1_1 i64) + (local $x1_2 i64) + (local $x1_3 i64) + (local $x1_4 i64) + (local $x1_5 i64) + (local $x1_6 i64) + (local $x1_7 i64) + (local $x1_8 i64) + (local $x1_9 i64) + + (local $x2_0 i64) + (local $x2_1 i64) + (local $x2_2 i64) + (local $x2_3 i64) + (local $x2_4 i64) + (local $x2_5 i64) + (local $x2_6 i64) + (local $x2_7 i64) + (local $x2_8 i64) + (local $x2_9 i64) + + (local $z2_0 i64) + (local $z2_1 i64) + (local $z2_2 i64) + (local $z2_3 i64) + (local $z2_4 i64) + (local $z2_5 i64) + (local $z2_6 i64) + (local $z2_7 i64) + (local $z2_8 i64) + (local $z2_9 i64) + + (local $x3_0 i64) + (local $x3_1 i64) + (local $x3_2 i64) + (local $x3_3 i64) + (local $x3_4 i64) + (local $x3_5 i64) + (local $x3_6 i64) + (local $x3_7 i64) + (local $x3_8 i64) + (local $x3_9 i64) + + (local $z3_0 i64) + (local $z3_1 i64) + (local $z3_2 i64) + (local $z3_3 i64) + (local $z3_4 i64) + (local $z3_5 i64) + (local $z3_6 i64) + (local $z3_7 i64) + (local $z3_8 i64) + (local $z3_9 i64) + + (local $tmp0_0 i64) + (local $tmp0_1 i64) + (local $tmp0_2 i64) + (local $tmp0_3 i64) + (local $tmp0_4 i64) + (local $tmp0_5 i64) + (local $tmp0_6 i64) + (local $tmp0_7 i64) + (local $tmp0_8 i64) + (local $tmp0_9 i64) + + (local $tmp1_0 i64) + (local $tmp1_1 i64) + (local $tmp1_2 i64) + (local $tmp1_3 i64) + (local $tmp1_4 i64) + (local $tmp1_5 i64) + (local $tmp1_6 i64) + (local $tmp1_7 i64) + (local $tmp1_8 i64) + (local $tmp1_9 i64) + + (set_local $t_0 (i64.load offset=0 (get_local $ptr_t))) + (set_local $t_1 (i64.load offset=8 (get_local $ptr_t))) + (set_local $t_2 (i64.load offset=16 (get_local $ptr_t))) + (set_local $t_3 (i64.load offset=24 (get_local $ptr_t))) + + (set_local $x1_0 (i64.load32_u offset=0 (get_local $ptr_x1))) + (set_local $x1_1 (i64.load32_u offset=4 (get_local $ptr_x1))) + (set_local $x1_2 (i64.load32_u offset=8 (get_local $ptr_x1))) + (set_local $x1_3 (i64.load32_u offset=12 (get_local $ptr_x1))) + (set_local $x1_4 (i64.load32_u offset=16 (get_local $ptr_x1))) + (set_local $x1_5 (i64.load32_u offset=20 (get_local $ptr_x1))) + (set_local $x1_6 (i64.load32_u offset=24 (get_local $ptr_x1))) + (set_local $x1_7 (i64.load32_u offset=28 (get_local $ptr_x1))) + (set_local $x1_8 (i64.load32_u offset=32 (get_local $ptr_x1))) + (set_local $x1_9 (i64.load32_u offset=36 (get_local $ptr_x1))) + + (set_local $x2_0 (i64.load32_u offset=0 (get_local $ptr_x2))) + (set_local $x2_1 (i64.load32_u offset=4 (get_local $ptr_x2))) + (set_local $x2_2 (i64.load32_u offset=8 (get_local $ptr_x2))) + (set_local $x2_3 (i64.load32_u offset=12 (get_local $ptr_x2))) + (set_local $x2_4 (i64.load32_u offset=16 (get_local $ptr_x2))) + (set_local $x2_5 (i64.load32_u offset=20 (get_local $ptr_x2))) + (set_local $x2_6 (i64.load32_u offset=24 (get_local $ptr_x2))) + (set_local $x2_7 (i64.load32_u offset=28 (get_local $ptr_x2))) + (set_local $x2_8 (i64.load32_u offset=32 (get_local $ptr_x2))) + (set_local $x2_9 (i64.load32_u offset=36 (get_local $ptr_x2))) + + (set_local $x3_0 (i64.load32_u offset=0 (get_local $ptr_x3))) + (set_local $x3_1 (i64.load32_u offset=4 (get_local $ptr_x3))) + (set_local $x3_2 (i64.load32_u offset=8 (get_local $ptr_x3))) + (set_local $x3_3 (i64.load32_u offset=12 (get_local $ptr_x3))) + (set_local $x3_4 (i64.load32_u offset=16 (get_local $ptr_x3))) + (set_local $x3_5 (i64.load32_u offset=20 (get_local $ptr_x3))) + (set_local $x3_6 (i64.load32_u offset=24 (get_local $ptr_x3))) + (set_local $x3_7 (i64.load32_u offset=28 (get_local $ptr_x3))) + (set_local $x3_8 (i64.load32_u offset=32 (get_local $ptr_x3))) + (set_local $x3_9 (i64.load32_u offset=36 (get_local $ptr_x3))) + + (set_local $z2_0 (i64.load32_u offset=0 (get_local $ptr_z2))) + (set_local $z2_1 (i64.load32_u offset=4 (get_local $ptr_z2))) + (set_local $z2_2 (i64.load32_u offset=8 (get_local $ptr_z2))) + (set_local $z2_3 (i64.load32_u offset=12 (get_local $ptr_z2))) + (set_local $z2_4 (i64.load32_u offset=16 (get_local $ptr_z2))) + (set_local $z2_5 (i64.load32_u offset=20 (get_local $ptr_z2))) + (set_local $z2_6 (i64.load32_u offset=24 (get_local $ptr_z2))) + (set_local $z2_7 (i64.load32_u offset=28 (get_local $ptr_z2))) + (set_local $z2_8 (i64.load32_u offset=32 (get_local $ptr_z2))) + (set_local $z2_9 (i64.load32_u offset=36 (get_local $ptr_z2))) + + (set_local $z3_0 (i64.load32_u offset=0 (get_local $ptr_z3))) + (set_local $z3_1 (i64.load32_u offset=4 (get_local $ptr_z3))) + (set_local $z3_2 (i64.load32_u offset=8 (get_local $ptr_z3))) + (set_local $z3_3 (i64.load32_u offset=12 (get_local $ptr_z3))) + (set_local $z3_4 (i64.load32_u offset=16 (get_local $ptr_z3))) + (set_local $z3_5 (i64.load32_u offset=20 (get_local $ptr_z3))) + (set_local $z3_6 (i64.load32_u offset=24 (get_local $ptr_z3))) + (set_local $z3_7 (i64.load32_u offset=28 (get_local $ptr_z3))) + (set_local $z3_8 (i64.load32_u offset=32 (get_local $ptr_z3))) + (set_local $z3_9 (i64.load32_u offset=36 (get_local $ptr_z3))) + + (i32.const 254) + (set_local $pos) + + (loop $start + (i32.const 0) + (get_local $pos) + (i32.lt_s) + (br_if $start) + + ;; choose which limb of t + (block $break + (block $0 + (block $1 + (block $2 + (block $3 + (block $switch + (get_local $pos) + (i32.const 64) + (i32.div_u) + (br_table $3 $2 $1 $0)) + + (get_local $t_3) + (set_local $t) + (br $break)) + + (get_local $t_3) + (set_local $t) + (br $break)) + + (get_local $t_3) + (set_local $t) + (br $break)) + + (get_local $t_3) + (set_local $t) + (br $break))) + ;; end of switch statement + + (get_local $t) + (get_local $pos) + (i32.const 8) + (i32.div_u) + (i32.const 64) + (i32.rem_u) + (i64.extend_u/i32) + (i64.shr_u) + (i64.const 0xff) + (i64.and) + (get_local $pos) + (i32.const 7) + (i32.and) + (i64.extend_u/i32) + (i64.shr_u) + (i64.const 1) + (i64.and) + (i32.wrap/i64) + (set_local $b) + + (get_local $swap) + (get_local $b) + (i32.xor) + (set_local $swap) + + (i32.const 0) + (get_local $swap) + (i32.sub) + (i64.extend_u/i32) + (set_local $mask) + + (get_local $x2_0) + (get_local $x3_0) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_0) + + (get_local $x2_1) + (get_local $x3_1) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_1) + + (get_local $x2_2) + (get_local $x3_2) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_2) + + (get_local $x2_3) + (get_local $x3_3) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_3) + + (get_local $x2_4) + (get_local $x3_4) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_4) + + (get_local $x2_5) + (get_local $x3_5) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_5) + + (get_local $x2_6) + (get_local $x3_6) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_6) + + (get_local $x2_7) + (get_local $x3_7) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_7) + + (get_local $x2_8) + (get_local $x3_8) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_8) + + (get_local $x2_9) + (get_local $x3_9) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_9) + + + (get_local $x2_0) + (get_local $tmp0_0) + (i64.xor) + (set_local $x2_0) + + (get_local $x2_0) + (get_local $tmp0_0) + (i64.xor) + (set_local $x2_0) + + (get_local $x2_1) + (get_local $tmp0_1) + (i64.xor) + (set_local $x2_1) + + (get_local $x2_2) + (get_local $tmp0_2) + (i64.xor) + (set_local $x2_2) + + (get_local $x2_3) + (get_local $tmp0_3) + (i64.xor) + (set_local $x2_3) + + (get_local $x2_4) + (get_local $tmp0_4) + (i64.xor) + (set_local $x2_4) + + (get_local $x2_5) + (get_local $tmp0_5) + (i64.xor) + (set_local $x2_5) + + (get_local $x2_6) + (get_local $tmp0_6) + (i64.xor) + (set_local $x2_6) + + (get_local $x2_7) + (get_local $tmp0_7) + (i64.xor) + (set_local $x2_7) + + (get_local $x2_8) + (get_local $tmp0_8) + (i64.xor) + (set_local $x2_8) + + (get_local $x2_9) + (get_local $tmp0_9) + (i64.xor) + (set_local $x2_9) + + + (get_local $x3_0) + (get_local $tmp0_0) + (i64.xor) + (set_local $x3_0) + + (get_local $x3_0) + (get_local $tmp0_0) + (i64.xor) + (set_local $x3_0) + + (get_local $x3_1) + (get_local $tmp0_1) + (i64.xor) + (set_local $x3_1) + + (get_local $x3_2) + (get_local $tmp0_2) + (i64.xor) + (set_local $x3_2) + + (get_local $x3_3) + (get_local $tmp0_3) + (i64.xor) + (set_local $x3_3) + + (get_local $x3_4) + (get_local $tmp0_4) + (i64.xor) + (set_local $x3_4) + + (get_local $x3_5) + (get_local $tmp0_5) + (i64.xor) + (set_local $x3_5) + + (get_local $x3_6) + (get_local $tmp0_6) + (i64.xor) + (set_local $x3_6) + + (get_local $x3_7) + (get_local $tmp0_7) + (i64.xor) + (set_local $x3_7) + + (get_local $x3_8) + (get_local $tmp0_8) + (i64.xor) + (set_local $x3_8) + + (get_local $x3_9) + (get_local $tmp0_9) + (i64.xor) + (set_local $x3_9) + + + (get_local $z3_0) + (get_local $z2_0) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_0) + + (get_local $z3_1) + (get_local $z2_1) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_1) + + (get_local $z3_2) + (get_local $z2_2) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_2) + + (get_local $z3_3) + (get_local $z2_3) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_3) + + (get_local $z3_4) + (get_local $z2_4) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_4) + + (get_local $z3_5) + (get_local $z2_5) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_5) + + (get_local $z3_6) + (get_local $z2_6) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_6) + + (get_local $z3_7) + (get_local $z2_7) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_7) + + (get_local $z3_8) + (get_local $z2_8) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_8) + + (get_local $z3_9) + (get_local $z2_9) + (i64.xor) + (get_local $mask) + (i64.and) + (set_local $tmp0_9) + + + (get_local $z2_0) + (get_local $tmp0_0) + (i64.xor) + (set_local $z2_0) + + (get_local $z2_0) + (get_local $tmp0_0) + (i64.xor) + (set_local $z2_0) + + (get_local $z2_1) + (get_local $tmp0_1) + (i64.xor) + (set_local $z2_1) + + (get_local $z2_2) + (get_local $tmp0_2) + (i64.xor) + (set_local $z2_2) + + (get_local $z2_3) + (get_local $tmp0_3) + (i64.xor) + (set_local $z2_3) + + (get_local $z2_4) + (get_local $tmp0_4) + (i64.xor) + (set_local $z2_4) + + (get_local $z2_5) + (get_local $tmp0_5) + (i64.xor) + (set_local $z2_5) + + (get_local $z2_6) + (get_local $tmp0_6) + (i64.xor) + (set_local $z2_6) + + (get_local $z2_7) + (get_local $tmp0_7) + (i64.xor) + (set_local $z2_7) + + (get_local $z2_8) + (get_local $tmp0_8) + (i64.xor) + (set_local $z2_8) + + (get_local $z2_9) + (get_local $tmp0_9) + (i64.xor) + (set_local $z2_9) + + + (get_local $z3_0) + (get_local $tmp0_0) + (i64.xor) + (set_local $z3_0) + + (get_local $z3_0) + (get_local $tmp0_0) + (i64.xor) + (set_local $z3_0) + + (get_local $z3_1) + (get_local $tmp0_1) + (i64.xor) + (set_local $z3_1) + + (get_local $z3_2) + (get_local $tmp0_2) + (i64.xor) + (set_local $z3_2) + + (get_local $z3_3) + (get_local $tmp0_3) + (i64.xor) + (set_local $z3_3) + + (get_local $z3_4) + (get_local $tmp0_4) + (i64.xor) + (set_local $z3_4) + + (get_local $z3_5) + (get_local $tmp0_5) + (i64.xor) + (set_local $z3_5) + + (get_local $z3_6) + (get_local $tmp0_6) + (i64.xor) + (set_local $z3_6) + + (get_local $z3_7) + (get_local $tmp0_7) + (i64.xor) + (set_local $z3_7) + + (get_local $z3_8) + (get_local $tmp0_8) + (i64.xor) + (set_local $z3_8) + + (get_local $z3_9) + (get_local $tmp0_9) + (i64.xor) + (set_local $z3_9) + + (get_local $b) + (set_local $swap) + + ;; fe25519_sub(tmp0, x3, z3) + (get_local $x3_0) + (get_local $z3_0) + (i64.sub) + (set_local $tmp0_0) + + (get_local $x3_1) + (get_local $z3_1) + (i64.sub) + (set_local $tmp0_1) + + (get_local $x3_2) + (get_local $z3_2) + (i64.sub) + (set_local $tmp0_2) + + (get_local $x3_3) + (get_local $z3_3) + (i64.sub) + (set_local $tmp0_3) + + (get_local $x3_4) + (get_local $z3_4) + (i64.sub) + (set_local $tmp0_4) + + (get_local $x3_5) + (get_local $z3_5) + (i64.sub) + (set_local $tmp0_5) + + (get_local $x3_6) + (get_local $z3_6) + (i64.sub) + (set_local $tmp0_6) + + (get_local $x3_7) + (get_local $z3_7) + (i64.sub) + (set_local $tmp0_7) + + (get_local $x3_8) + (get_local $z3_8) + (i64.sub) + (set_local $tmp0_8) + + (get_local $x3_9) + (get_local $z3_9) + (i64.sub) + (set_local $tmp0_9) + + ;; fe25519_sub(tmp0, x3, z3) + (get_local $x2_0) + (get_local $z2_0) + (i64.sub) + (set_local $tmp1_0) + + (get_local $x2_1) + (get_local $z2_1) + (i64.sub) + (set_local $tmp1_1) + + (get_local $x2_2) + (get_local $z2_2) + (i64.sub) + (set_local $tmp1_2) + + (get_local $x2_3) + (get_local $z2_3) + (i64.sub) + (set_local $tmp1_3) + + (get_local $x2_4) + (get_local $z2_4) + (i64.sub) + (set_local $tmp1_4) + + (get_local $x2_5) + (get_local $z2_5) + (i64.sub) + (set_local $tmp1_5) + + (get_local $x2_6) + (get_local $z2_6) + (i64.sub) + (set_local $tmp1_6) + + (get_local $x2_7) + (get_local $z2_7) + (i64.sub) + (set_local $tmp1_7) + + (get_local $x2_8) + (get_local $z2_8) + (i64.sub) + (set_local $tmp1_8) + + (get_local $x2_9) + (get_local $z2_9) + (i64.sub) + (set_local $tmp1_9) + + ;; fe25519_add(x2, x2, z2) + (get_local $x2_0) + (get_local $z2_0) + (i64.add) + (set_local $x2_0) + + (get_local $x2_1) + (get_local $z2_1) + (i64.add) + (set_local $x2_1) + + (get_local $x2_2) + (get_local $z2_2) + (i64.add) + (set_local $x2_2) + + (get_local $x2_3) + (get_local $z2_3) + (i64.add) + (set_local $x2_3) + + (get_local $x2_4) + (get_local $z2_4) + (i64.add) + (set_local $x2_4) + + (get_local $x2_5) + (get_local $z2_5) + (i64.add) + (set_local $x2_5) + + (get_local $x2_6) + (get_local $z2_6) + (i64.add) + (set_local $x2_6) + + (get_local $x2_7) + (get_local $z2_7) + (i64.add) + (set_local $x2_7) + + (get_local $x2_8) + (get_local $z2_8) + (i64.add) + (set_local $x2_8) + + (get_local $x2_9) + (get_local $z2_9) + (i64.add) + (set_local $x2_9) + + ;; fe25519_add(z2, x3, z3) + (get_local $x3_0) + (get_local $z3_0) + (i64.add) + (set_local $z2_0) + + (get_local $x3_1) + (get_local $z3_1) + (i64.add) + (set_local $z2_1) + + (get_local $x3_2) + (get_local $z3_2) + (i64.add) + (set_local $z2_2) + + (get_local $x3_3) + (get_local $z3_3) + (i64.add) + (set_local $z2_3) + + (get_local $x3_4) + (get_local $z3_4) + (i64.add) + (set_local $z2_4) + + (get_local $x3_5) + (get_local $z3_5) + (i64.add) + (set_local $z2_5) + + (get_local $x3_6) + (get_local $z3_6) + (i64.add) + (set_local $z2_6) + + (get_local $x3_7) + (get_local $z3_7) + (i64.add) + (set_local $z2_7) + + (get_local $x3_8) + (get_local $z3_8) + (i64.add) + (set_local $z2_8) + + (get_local $x3_9) + (get_local $z3_9) + (i64.add) + (set_local $z2_9) + + ;; ptr0 <- z3 = x2 * tmp0 + (get_local $x2_0) + (get_local $x2_1) + (get_local $x2_2) + (get_local $x2_3) + (get_local $x2_4) + (get_local $x2_5) + (get_local $x2_6) + (get_local $x2_7) + (get_local $x2_8) + (get_local $x2_9) + (get_local $tmp0_0) + (get_local $tmp0_1) + (get_local $tmp0_2) + (get_local $tmp0_3) + (get_local $tmp0_4) + (get_local $tmp0_5) + (get_local $tmp0_6) + (get_local $tmp0_7) + (get_local $tmp0_8) + (get_local $tmp0_9) + (get_local $ptr0) + (i32.const 1) + (call_indirect (type $fe_mul)) + + ;; ptr1 <- z2 = z2 * tmp1 + (get_local $tmp1_0) + (get_local $tmp1_1) + (get_local $tmp1_2) + (get_local $tmp1_3) + (get_local $tmp1_4) + (get_local $tmp1_5) + (get_local $tmp1_6) + (get_local $tmp1_7) + (get_local $tmp1_8) + (get_local $tmp1_9) + (get_local $z2_0) + (get_local $z2_1) + (get_local $z2_2) + (get_local $z2_3) + (get_local $z2_4) + (get_local $z2_5) + (get_local $z2_6) + (get_local $z2_7) + (get_local $z2_8) + (get_local $z2_9) + (get_local $ptr1) + (i32.const 1) + (call_indirect (type $fe_mul)) + + ;; ptr2 <- tmp0 = tmp1 ^ 2 + (get_local $tmp1_0) + (get_local $tmp1_1) + (get_local $tmp1_2) + (get_local $tmp1_3) + (get_local $tmp1_4) + (get_local $tmp1_5) + (get_local $tmp1_6) + (get_local $tmp1_7) + (get_local $tmp1_8) + (get_local $tmp1_9) + (get_local $ptr2) + (i32.const 0) + (i32.const 0) + (i32.const 2) + (call_indirect (type $fe_sq)) + + ;; ptr3 <- tmp1 = x2 ^ 2 + (get_local $x2_0) + (get_local $x2_1) + (get_local $x2_2) + (get_local $x2_3) + (get_local $x2_4) + (get_local $x2_5) + (get_local $x2_6) + (get_local $x2_7) + (get_local $x2_8) + (get_local $x2_9) + (get_local $ptr3) + (i32.const 0) + (i32.const 0) + (i32.const 2) + (call_indirect (type $fe_sq)) + + ;; z3 <- load(ptr0) + (set_local $z3_0 (i64.load32_u offset=0 (get_local $ptr0))) + (set_local $z3_1 (i64.load32_u offset=4 (get_local $ptr0))) + (set_local $z3_2 (i64.load32_u offset=8 (get_local $ptr0))) + (set_local $z3_3 (i64.load32_u offset=12 (get_local $ptr0))) + (set_local $z3_4 (i64.load32_u offset=16 (get_local $ptr0))) + (set_local $z3_5 (i64.load32_u offset=20 (get_local $ptr0))) + (set_local $z3_6 (i64.load32_u offset=24 (get_local $ptr0))) + (set_local $z3_7 (i64.load32_u offset=28 (get_local $ptr0))) + (set_local $z3_8 (i64.load32_u offset=32 (get_local $ptr0))) + (set_local $z3_9 (i64.load32_u offset=36 (get_local $ptr0))) + + ;; z2 <- load(ptr1) + (set_local $z2_0 (i64.load32_u offset=0 (get_local $ptr1))) + (set_local $z2_1 (i64.load32_u offset=4 (get_local $ptr1))) + (set_local $z2_2 (i64.load32_u offset=8 (get_local $ptr1))) + (set_local $z2_3 (i64.load32_u offset=12 (get_local $ptr1))) + (set_local $z2_4 (i64.load32_u offset=16 (get_local $ptr1))) + (set_local $z2_5 (i64.load32_u offset=20 (get_local $ptr1))) + (set_local $z2_6 (i64.load32_u offset=24 (get_local $ptr1))) + (set_local $z2_7 (i64.load32_u offset=28 (get_local $ptr1))) + (set_local $z2_8 (i64.load32_u offset=32 (get_local $ptr1))) + (set_local $z2_9 (i64.load32_u offset=36 (get_local $ptr1))) + + ;; tmp0 <- load(ptr2) + (set_local $tmp0_0 (i64.load32_u offset=0 (get_local $ptr2))) + (set_local $tmp0_1 (i64.load32_u offset=4 (get_local $ptr2))) + (set_local $tmp0_2 (i64.load32_u offset=8 (get_local $ptr2))) + (set_local $tmp0_3 (i64.load32_u offset=12 (get_local $ptr2))) + (set_local $tmp0_4 (i64.load32_u offset=16 (get_local $ptr2))) + (set_local $tmp0_5 (i64.load32_u offset=20 (get_local $ptr2))) + (set_local $tmp0_6 (i64.load32_u offset=24 (get_local $ptr2))) + (set_local $tmp0_7 (i64.load32_u offset=28 (get_local $ptr2))) + (set_local $tmp0_8 (i64.load32_u offset=32 (get_local $ptr2))) + (set_local $tmp0_9 (i64.load32_u offset=36 (get_local $ptr2))) + + ;; tmp1 <- load(ptr3) + (set_local $tmp1_0 (i64.load32_u offset=0 (get_local $ptr3))) + (set_local $tmp1_1 (i64.load32_u offset=4 (get_local $ptr3))) + (set_local $tmp1_2 (i64.load32_u offset=8 (get_local $ptr3))) + (set_local $tmp1_3 (i64.load32_u offset=12 (get_local $ptr3))) + (set_local $tmp1_4 (i64.load32_u offset=16 (get_local $ptr3))) + (set_local $tmp1_5 (i64.load32_u offset=20 (get_local $ptr3))) + (set_local $tmp1_6 (i64.load32_u offset=24 (get_local $ptr3))) + (set_local $tmp1_7 (i64.load32_u offset=28 (get_local $ptr3))) + (set_local $tmp1_8 (i64.load32_u offset=32 (get_local $ptr3))) + (set_local $tmp1_9 (i64.load32_u offset=36 (get_local $ptr3))) + + ;; fe25519_add(x3, z3, z2) + (get_local $z3_0) + (get_local $z2_0) + (i64.add) + (set_local $x3_0) + + (get_local $z3_1) + (get_local $z2_1) + (i64.add) + (set_local $x3_1) + + (get_local $z3_2) + (get_local $z2_2) + (i64.add) + (set_local $x3_2) + + (get_local $z3_3) + (get_local $z2_3) + (i64.add) + (set_local $x3_3) + + (get_local $z3_4) + (get_local $z2_4) + (i64.add) + (set_local $x3_4) + + (get_local $z3_5) + (get_local $z2_5) + (i64.add) + (set_local $x3_5) + + (get_local $z3_6) + (get_local $z2_6) + (i64.add) + (set_local $x3_6) + + (get_local $z3_7) + (get_local $z2_7) + (i64.add) + (set_local $x3_7) + + (get_local $z3_8) + (get_local $z2_8) + (i64.add) + (set_local $x3_8) + + (get_local $z3_9) + (get_local $z2_9) + (i64.add) + (set_local $x3_9) + + ;; fe25519_sub(z2, z3, z2) + (get_local $z3_0) + (get_local $z2_0) + (i64.sub) + (set_local $z2_0) + + (get_local $z3_1) + (get_local $z2_1) + (i64.sub) + (set_local $z2_1) + + (get_local $z3_2) + (get_local $z2_2) + (i64.sub) + (set_local $z2_2) + + (get_local $z3_3) + (get_local $z2_3) + (i64.sub) + (set_local $z2_3) + + (get_local $z3_4) + (get_local $z2_4) + (i64.sub) + (set_local $z2_4) + + (get_local $z3_5) + (get_local $z2_5) + (i64.sub) + (set_local $z2_5) + + (get_local $z3_6) + (get_local $z2_6) + (i64.sub) + (set_local $z2_6) + + (get_local $z3_7) + (get_local $z2_7) + (i64.sub) + (set_local $z2_7) + + (get_local $z3_8) + (get_local $z2_8) + (i64.sub) + (set_local $z2_8) + + (get_local $z3_9) + (get_local $z2_9) + (i64.sub) + (set_local $z2_9) + + ;; ptr1 <- x2 = tmp0 * tmp1 + (get_local $tmp1_0) + (get_local $tmp1_1) + (get_local $tmp1_2) + (get_local $tmp1_3) + (get_local $tmp1_4) + (get_local $tmp1_5) + (get_local $tmp1_6) + (get_local $tmp1_7) + (get_local $tmp1_8) + (get_local $tmp1_9) + (get_local $tmp0_0) + (get_local $tmp0_1) + (get_local $tmp0_2) + (get_local $tmp0_3) + (get_local $tmp0_4) + (get_local $tmp0_5) + (get_local $tmp0_6) + (get_local $tmp0_7) + (get_local $tmp0_8) + (get_local $tmp0_9) + (get_local $ptr1) + (i32.const 3) + (call_indirect (type $fe_mul)) + + ;; tmp1 = tmp1 - tmp0 + (get_local $tmp1_0) + (get_local $tmp0_0) + (i64.sub) + (set_local $tmp1_0) + + (get_local $tmp1_1) + (get_local $tmp0_1) + (i64.sub) + (set_local $tmp1_1) + + (get_local $tmp1_2) + (get_local $tmp0_2) + (i64.sub) + (set_local $tmp1_2) + + (get_local $tmp1_3) + (get_local $tmp0_3) + (i64.sub) + (set_local $tmp1_3) + + (get_local $tmp1_4) + (get_local $tmp0_4) + (i64.sub) + (set_local $tmp1_4) + + (get_local $tmp1_5) + (get_local $tmp0_5) + (i64.sub) + (set_local $tmp1_5) + + (get_local $tmp1_6) + (get_local $tmp0_6) + (i64.sub) + (set_local $tmp1_6) + + (get_local $tmp1_7) + (get_local $tmp0_7) + (i64.sub) + (set_local $tmp1_7) + + (get_local $tmp1_8) + (get_local $tmp0_8) + (i64.sub) + (set_local $tmp1_8) + + (get_local $tmp1_9) + (get_local $tmp0_9) + (i64.sub) + (set_local $tmp1_9) + + ;; ptr0 <- z2 = z2 ^ 2 + (get_local $z2_0) + (get_local $z2_1) + (get_local $z2_2) + (get_local $z2_3) + (get_local $z2_4) + (get_local $z2_5) + (get_local $z2_6) + (get_local $z2_7) + (get_local $z2_8) + (get_local $z2_9) + (get_local $ptr0) + (i32.const 0) + (i32.const 0) + (i32.const 2) + (call_indirect (type $fe_sq)) + + ;; ptr1 <- z3 = tmp1 * _121666 + (i64.const 121666) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (get_local $tmp1_0) + (get_local $tmp1_1) + (get_local $tmp1_2) + (get_local $tmp1_3) + (get_local $tmp1_4) + (get_local $tmp1_5) + (get_local $tmp1_6) + (get_local $tmp1_7) + (get_local $tmp1_8) + (get_local $tmp1_9) + (get_local $ptr1) + (i32.const 1) + (call_indirect (type $fe_mul)) + + ;; ptr2 <- x3 = x3 ^ 2 + (get_local $x3_0) + (get_local $x3_1) + (get_local $x3_2) + (get_local $x3_3) + (get_local $x3_4) + (get_local $x3_5) + (get_local $x3_6) + (get_local $x3_7) + (get_local $x3_8) + (get_local $x3_9) + (get_local $ptr2) + (i32.const 0) + (i32.const 0) + (i32.const 2) + (call_indirect (type $fe_sq)) + + ;; tmp0 <- load(ptr2) + (set_local $z2_0 (i64.load32_u offset=0 (get_local $ptr0))) + (set_local $z2_1 (i64.load32_u offset=4 (get_local $ptr0))) + (set_local $z2_2 (i64.load32_u offset=8 (get_local $ptr0))) + (set_local $z2_3 (i64.load32_u offset=12 (get_local $ptr0))) + (set_local $z2_4 (i64.load32_u offset=16 (get_local $ptr0))) + (set_local $z2_5 (i64.load32_u offset=20 (get_local $ptr0))) + (set_local $z2_6 (i64.load32_u offset=24 (get_local $ptr0))) + (set_local $z2_7 (i64.load32_u offset=28 (get_local $ptr0))) + (set_local $z2_8 (i64.load32_u offset=32 (get_local $ptr0))) + (set_local $z2_9 (i64.load32_u offset=36 (get_local $ptr0))) + + ;; tmp0 <- load(ptr2) + (set_local $z3_0 (i64.load32_u offset=0 (get_local $ptr1))) + (set_local $z3_1 (i64.load32_u offset=4 (get_local $ptr1))) + (set_local $z3_2 (i64.load32_u offset=8 (get_local $ptr1))) + (set_local $z3_3 (i64.load32_u offset=12 (get_local $ptr1))) + (set_local $z3_4 (i64.load32_u offset=16 (get_local $ptr1))) + (set_local $z3_5 (i64.load32_u offset=20 (get_local $ptr1))) + (set_local $z3_6 (i64.load32_u offset=24 (get_local $ptr1))) + (set_local $z3_7 (i64.load32_u offset=28 (get_local $ptr1))) + (set_local $z3_8 (i64.load32_u offset=32 (get_local $ptr1))) + (set_local $z3_9 (i64.load32_u offset=36 (get_local $ptr1))) + + ;; tmp0 <- load(ptr2) + (set_local $x3_0 (i64.load32_u offset=0 (get_local $ptr2))) + (set_local $x3_1 (i64.load32_u offset=4 (get_local $ptr2))) + (set_local $x3_2 (i64.load32_u offset=8 (get_local $ptr2))) + (set_local $x3_3 (i64.load32_u offset=12 (get_local $ptr2))) + (set_local $x3_4 (i64.load32_u offset=16 (get_local $ptr2))) + (set_local $x3_5 (i64.load32_u offset=20 (get_local $ptr2))) + (set_local $x3_6 (i64.load32_u offset=24 (get_local $ptr2))) + (set_local $x3_7 (i64.load32_u offset=28 (get_local $ptr2))) + (set_local $x3_8 (i64.load32_u offset=32 (get_local $ptr2))) + (set_local $x3_9 (i64.load32_u offset=36 (get_local $ptr2))) + + (get_local $tmp0_0) + (get_local $z3_0) + (i64.add) + (set_local $tmp0_0) + + (get_local $tmp0_1) + (get_local $z3_1) + (i64.add) + (set_local $tmp0_1) + + (get_local $tmp0_2) + (get_local $z3_2) + (i64.add) + (set_local $tmp0_2) + + (get_local $tmp0_3) + (get_local $z3_3) + (i64.add) + (set_local $tmp0_3) + + (get_local $tmp0_4) + (get_local $z3_4) + (i64.add) + (set_local $tmp0_4) + + (get_local $tmp0_5) + (get_local $z3_5) + (i64.add) + (set_local $tmp0_5) + + (get_local $tmp0_6) + (get_local $z3_6) + (i64.add) + (set_local $tmp0_6) + + (get_local $tmp0_7) + (get_local $z3_7) + (i64.add) + (set_local $tmp0_7) + + (get_local $tmp0_8) + (get_local $z3_8) + (i64.add) + (set_local $tmp0_8) + + (get_local $tmp0_9) + (get_local $z3_9) + (i64.add) + (set_local $tmp0_9) + + ;; ptr1 <- z3 = x1 * z2 + (get_local $x1_0) + (get_local $x1_1) + (get_local $x1_2) + (get_local $x1_3) + (get_local $x1_4) + (get_local $x1_5) + (get_local $x1_6) + (get_local $x1_7) + (get_local $x1_8) + (get_local $x1_9) + (get_local $z2_0) + (get_local $z2_1) + (get_local $z2_2) + (get_local $z2_3) + (get_local $z2_4) + (get_local $z2_5) + (get_local $z2_6) + (get_local $z2_7) + (get_local $z2_8) + (get_local $z2_9) + (get_local $ptr1) + (i32.const 1) + (call_indirect (type $fe_mul)) + + ;; ptr0 <- z2 = tmp1 * tmp0 + (get_local $tmp0_0) + (get_local $tmp0_1) + (get_local $tmp0_2) + (get_local $tmp0_3) + (get_local $tmp0_4) + (get_local $tmp0_5) + (get_local $tmp0_6) + (get_local $tmp0_7) + (get_local $tmp0_8) + (get_local $tmp0_9) + (get_local $tmp1_0) + (get_local $tmp1_1) + (get_local $tmp1_2) + (get_local $tmp1_3) + (get_local $tmp1_4) + (get_local $tmp1_5) + (get_local $tmp1_6) + (get_local $tmp1_7) + (get_local $tmp1_8) + (get_local $tmp1_9) + (get_local $ptr0) + (i32.const 1) + (call_indirect (type $fe_mul)) + + ;; tmp0 <- load(ptr2) + (set_local $z2_0 (i64.load32_u offset=0 (get_local $ptr0))) + (set_local $z2_1 (i64.load32_u offset=4 (get_local $ptr0))) + (set_local $z2_2 (i64.load32_u offset=8 (get_local $ptr0))) + (set_local $z2_3 (i64.load32_u offset=12 (get_local $ptr0))) + (set_local $z2_4 (i64.load32_u offset=16 (get_local $ptr0))) + (set_local $z2_5 (i64.load32_u offset=20 (get_local $ptr0))) + (set_local $z2_6 (i64.load32_u offset=24 (get_local $ptr0))) + (set_local $z2_7 (i64.load32_u offset=28 (get_local $ptr0))) + (set_local $z2_8 (i64.load32_u offset=32 (get_local $ptr0))) + (set_local $z2_9 (i64.load32_u offset=36 (get_local $ptr0))) + + ;; tmp0 <- load(ptr2) + (set_local $z3_0 (i64.load32_u offset=0 (get_local $ptr1))) + (set_local $z3_1 (i64.load32_u offset=4 (get_local $ptr1))) + (set_local $z3_2 (i64.load32_u offset=8 (get_local $ptr1))) + (set_local $z3_3 (i64.load32_u offset=12 (get_local $ptr1))) + (set_local $z3_4 (i64.load32_u offset=16 (get_local $ptr1))) + (set_local $z3_5 (i64.load32_u offset=20 (get_local $ptr1))) + (set_local $z3_6 (i64.load32_u offset=24 (get_local $ptr1))) + (set_local $z3_7 (i64.load32_u offset=28 (get_local $ptr1))) + (set_local $z3_8 (i64.load32_u offset=32 (get_local $ptr1))) + (set_local $z3_9 (i64.load32_u offset=36 (get_local $ptr1))) + + (get_local $pos) + (i32.const 1) + (i32.sub) + (set_local $pos) + (br $start)) + + (i64.store32 offset=0 (get_local $res_x2) (get_local $x2_0)) + (i64.store32 offset=4 (get_local $res_x2) (get_local $x2_1)) + (i64.store32 offset=8 (get_local $res_x2) (get_local $x2_2)) + (i64.store32 offset=12 (get_local $res_x2) (get_local $x2_3)) + (i64.store32 offset=16 (get_local $res_x2) (get_local $x2_4)) + (i64.store32 offset=20 (get_local $res_x2) (get_local $x2_5)) + (i64.store32 offset=24 (get_local $res_x2) (get_local $x2_6)) + (i64.store32 offset=28 (get_local $res_x2) (get_local $x2_7)) + (i64.store32 offset=32 (get_local $res_x2) (get_local $x2_8)) + (i64.store32 offset=36 (get_local $res_x2) (get_local $x2_9)) + + (i64.store32 offset=0 (get_local $res_x3) (get_local $x3_0)) + (i64.store32 offset=4 (get_local $res_x3) (get_local $x3_1)) + (i64.store32 offset=8 (get_local $res_x3) (get_local $x3_2)) + (i64.store32 offset=12 (get_local $res_x3) (get_local $x3_3)) + (i64.store32 offset=16 (get_local $res_x3) (get_local $x3_4)) + (i64.store32 offset=20 (get_local $res_x3) (get_local $x3_5)) + (i64.store32 offset=24 (get_local $res_x3) (get_local $x3_6)) + (i64.store32 offset=28 (get_local $res_x3) (get_local $x3_7)) + (i64.store32 offset=32 (get_local $res_x3) (get_local $x3_8)) + (i64.store32 offset=36 (get_local $res_x3) (get_local $x3_9)) + + (i64.store32 offset=0 (get_local $res_z2) (get_local $z2_0)) + (i64.store32 offset=4 (get_local $res_z2) (get_local $z2_1)) + (i64.store32 offset=8 (get_local $res_z2) (get_local $z2_2)) + (i64.store32 offset=12 (get_local $res_z2) (get_local $z2_3)) + (i64.store32 offset=16 (get_local $res_z2) (get_local $z2_4)) + (i64.store32 offset=20 (get_local $res_z2) (get_local $z2_5)) + (i64.store32 offset=24 (get_local $res_z2) (get_local $z2_6)) + (i64.store32 offset=28 (get_local $res_z2) (get_local $z2_7)) + (i64.store32 offset=32 (get_local $res_z2) (get_local $z2_8)) + (i64.store32 offset=36 (get_local $res_z2) (get_local $z2_9)) + + (i64.store32 offset=0 (get_local $res_z3) (get_local $z3_0)) + (i64.store32 offset=4 (get_local $res_z3) (get_local $z3_1)) + (i64.store32 offset=8 (get_local $res_z3) (get_local $z3_2)) + (i64.store32 offset=12 (get_local $res_z3) (get_local $z3_3)) + (i64.store32 offset=16 (get_local $res_z3) (get_local $z3_4)) + (i64.store32 offset=20 (get_local $res_z3) (get_local $z3_5)) + (i64.store32 offset=24 (get_local $res_z3) (get_local $z3_6)) + (i64.store32 offset=28 (get_local $res_z3) (get_local $z3_7)) + (i64.store32 offset=32 (get_local $res_z3) (get_local $z3_8)) + (i64.store32 offset=36 (get_local $res_z3) (get_local $z3_9)) + + (get_local $swap)))