6.7.6 Special Memory Accesses

This section is about memory accesses useful for communicating with other software or other computers. This means that the accesses are of a certain bit width (independent of Gforth’s cell width), are possibly not naturally aligned and typically have a certain byte order that may be different from the native byte order of the system that Gforth runs on.

We use the following prefixes:

c

8 bits (character)

w

16 bits

l

32 bits

x

64 bits represented as one cell

xd

64 bits represented as two cells

The x-prefix words do not work properly on 32-bit systems, so for code that is intended to be portable to 32-bit systems you should use xd-prefix words. Note that xd-prefix words work on 64-bit systems: there the upper cell is just 0 (for unsigned values) or a sign extension of the lower cell.

The memory-access words below all work with arbitrarily (un)aligned addresses (unlike @, !, f@, f!, which require alignment on some hardware).

w@ ( c-addr – u ) gforth-0.5 “w-fetch”

u is the zero-extended 16-bit value stored at c_addr.

w! ( w c-addr – ) gforth-0.7 “w-store”

Store the bottom 16 bits of w at c_addr.

l@ ( c-addr – u ) gforth-0.7 “l-fetch”

u is the zero-extended 32-bit value stored at c_addr.

l! ( w c-addr – ) gforth-0.7 “l-store”

Store the bottom 32 bits of w at c_addr.

x@ ( c-addr – u ) gforth-1.0 “x-fetch”

u is the zero-extended 64-bit value stored at c_addr.

x! ( w c-addr – ) gforth-1.0 “x-store”

Store the bottom 64 bits of w at c_addr.

xd@ ( c-addr – ud ) gforth-1.0 “x-d-fetch”

ud is the zero-extended 64-bit value stored at c_addr.

xd! ( ud c-addr – ) gforth-1.0 “x-d-store”

Store the bottom 64 bits of ud at c_addr.

For accesses with a specific byte order, you have to perform byte-order adjustment immediately after a fetch (before the sign-extension), or immediately before the store. The results of these byte-order adjustment words are always zero-extended.

wbe ( u1 – u2  ) gforth-1.0 “wbe”

Convert 16-bit value in u1 from native byte order to big-endian or from big-endian to native byte order (the same operation)

wle ( u1 – u2  ) gforth-1.0 “wle”

Convert 16-bit value in u1 from native byte order to little-endian or from little-endian to native byte order (the same operation)

lbe ( u1 – u2  ) gforth-1.0 “lbe”

Convert 32-bit value in u1 from native byte order to big-endian or from big-endian to native byte order (the same operation)

lle ( u1 – u2  ) gforth-1.0 “lle”

Convert 32-bit value in u1 from native byte order to little-endian or from little-endian to native byte order (the same operation)

xbe ( u1 – u2  ) gforth-1.0 “xbe”

Convert 64-bit value in u1 from native byte order to big-endian or from big-endian to native byte order (the same operation)

xle ( u1 – u2  ) gforth-1.0 “xle”

Convert 64-bit value in u1 from native byte order to little-endian or from little-endian to native byte order (the same operation)

xdbe ( ud1 – ud2  ) gforth-1.0 “xdbe”

Convert 64-bit value in ud1 from native byte order to big-endian or from big-endian to native byte order (the same operation)

xdle ( ud1 – ud2  ) gforth-1.0 “xdle”

Convert 64-bit value in ud1 from native byte order to little-endian or from little-endian to native byte order (the same operation)

For signed fetches with a specific byte order, you have first have to perform an unsigned fetch and a byte-order correction, and finally use a sign-extension word:

c>s ( x – n ) gforth-1.0 “c-to-s”

Sign-extend the 8-bit value in x to cell n.

w>s ( x – n ) gforth-1.0 “w-to-s”

Sign-extend the 16-bit value in x to cell n.

l>s ( x – n ) gforth-1.0 “l-to-s”

Sign-extend the 32-bit value in x to cell n.

x>s ( x – n  ) gforth-1.0 “x>s”

Sign-extend the 64-bit value in x to cell n.

xd>s ( xd – d  ) gforth-1.0 “xd>s”

Sign-extend the 64-bit value in xd to double-cell d.

Overall, this leads to sequences like

w@ wbe w>s   \ 16-bit unaligned signed big-endian fetch
>r lle r> l! \ 32-bit unaligned little-endian store