skip to content
==> src/ctx.c <==
1/* The instance's Ctx, built on first use (a wasm instance has one thread). Also memcpy, memset and
2 * memmove: freestanding wasm32 code may call them (struct and array copies). */
3#include "mesh/rt_wasm.h"
4
5static mesh_ctx ctx;
6static bool ready;
7
8const mesh_ctx *mesh_ctx_get(void) {
9    if (!ready) {
10        ctx.slot = mesh_sys_info(MESH_WASM_I_SLOT);
11        ctx.node = mesh_sys_info(MESH_WASM_I_NODE);
12        ctx.nodes = mesh_sys_info(MESH_WASM_I_NODES);
13        ctx.view.h = MESH_WASM_W_VIEW;
14        ctx.view.base = 0;
15        ctx.view.len = mesh_sys_info(MESH_WASM_I_VIEW_BYTES);
16        ctx.req_off = mesh_sys_info(MESH_WASM_I_REQ_OFF);
17        ctx.resp_off = mesh_sys_info(MESH_WASM_I_RESP_OFF);
18        ctx.resp_max = mesh_sys_info(MESH_WASM_I_RESP_MAX);
19        ctx.lockstep = mesh_sys_info(MESH_WASM_I_LOCKSTEP) != 0;
20        ready = true;
21    }
22    return &ctx;
23}
24
25void *memcpy(void *restrict dst, const void *restrict src, size_t n);
26void *memmove(void *dst, const void *src, size_t n);
27void *memset(void *dst, int c, size_t n);
28
29void *memcpy(void *restrict dst, const void *restrict src, size_t n) {
30    unsigned char *d = dst;
31    const unsigned char *s = src;
32    while (n--) *d++ = *s++;
33    return dst;
34}
35
36void *memmove(void *dst, const void *src, size_t n) {
37    unsigned char *d = dst;
38    const unsigned char *s = src;
39    if (d < s) {
40        while (n--) *d++ = *s++;
41    } else {
42        while (n--) d[n] = s[n];
43    }
44    return dst;
45}
46
47void *memset(void *dst, int c, size_t n) {
48    unsigned char *d = dst;
49    while (n--) *d++ = (unsigned char)c;
50    return dst;
51}
52
53/* compiler-rt's 128-bit multiply: clang calls it for u64 x u64 -> u128 products on wasm32 (nothing
54 * else here links compiler-rt). */
55__extension__ typedef __int128 mesh_ti;
56mesh_ti __multi3(mesh_ti a, mesh_ti b);
57mesh_ti __multi3(mesh_ti a, mesh_ti b) {
58    __extension__ typedef unsigned __int128 mesh_tu;
59    mesh_tu x = (mesh_tu)a, y = (mesh_tu)b;
60    uint64_t a0 = (uint64_t)x, a1 = (uint64_t)(x >> 64), b0 = (uint64_t)y, b1 = (uint64_t)(y >> 64);
61    /* a0 * b0 in full from 32-bit halves, then the cross terms into the high word. */
62    uint64_t l0 = a0 & 0xffffffffu, h0 = a0 >> 32, l1 = b0 & 0xffffffffu, h1 = b0 >> 32;
63    uint64_t ll = l0 * l1, lh = l0 * h1, hl = h0 * l1, hh = h0 * h1;
64    uint64_t mid = (ll >> 32) + (lh & 0xffffffffu) + (hl & 0xffffffffu);
65    uint64_t lo = (ll & 0xffffffffu) | mid << 32;
66    uint64_t hi = hh + (lh >> 32) + (hl >> 32) + (mid >> 32) + a0 * b1 + a1 * b0;
67    return (mesh_ti)((mesh_tu)hi << 64 | lo);
68}