, S{"+" }, [](auto) { fthp->top() += fthp->pop(); }, 0
, S{"-" }, [](auto) { fthp->top() -= fthp->pop(); }, 0
, S{"*" }, [](auto) { fthp->top() *= fthp->pop(); }, 0
+ , S{"M*" }, [](auto) {
+ dcell a = fthp->pop();
+ a *= fthp->pop();
+ fthp->push(a, a >> 8 * sizeof(cell)); }, 0
+ , S{"UM*" }, [](auto) {
+ daddr a = std::bit_cast<addr>(fthp->pop());
+ a *= std::bit_cast<addr>(fthp->pop());
+ fthp->push(a, a >> 8 * sizeof(addr)); }, 0
, S{"/" }, [](auto) { fthp->top() /= fthp->pop(); }, 0
, S{"MOD" }, [](auto) { fthp->top() %= fthp->pop(); }, 0
, S{"AND" }, [](auto) { fthp->top() &= fthp->pop(); }, 0
, S{"CHAR+" }, S{"1 +" }, 0
, S{"-ROT" }, S{"ROT ROT"}, 0
, S{"2DROP" }, S{"DROP DROP"}, 0
+ , S{"S>D" }, S{"DUP 0<"}, 0
, S{"0<" }, S{"0 <"}, 0
, S{"0<>" }, S{"0 <>"}, 0
, S{"<>" }, S{"= 0="}, 0
using addr = std::uintptr_t;
using func = void (*)(const void *);
+#if UINTPTR_MAX == 0xFFFF
+using dcell = std::int32_t;
+#elif UINTPTR_MAX == 0xFFFFFFFF
+using dcell = std::int64_t;
+#elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFF
+using dcell = __int128;
+#else
+#error "Cannot figure out size of double-cell integer"
+#endif
+
+#if UINTPTR_MAX == 0xFFFF
+using daddr = std::uint32_t;
+#elif UINTPTR_MAX == 0xFFFFFFFF
+using daddr = std::uint64_t;
+#elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFF
+using daddr = __uint128;
+#else
+#error "Cannot figure out size of double-address integer"
+#endif
+
struct word_base;
template<typename T>