fix(v4.0.0): MOVE follows FORTH-79
MOVE moves n cells, the cell at addr1 first, and nothing for n <= 0. v3's moved bytes like memmove; CMOVE and CMOVE> do that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
e178a76c36
commit
b137678691
@@ -334,7 +334,7 @@ Section numbers match the v3 primitive reference.
|
||||
| `C@` | CAP | See below (D-1). Call-free. Executed on the golden model (2026-10-03). Leaves its caller 8 data cells and 7 return entries. |
|
||||
| `C!` | CAP | See below (D-1). Call-free. Executed on the golden model (2026-10-03). |
|
||||
| `FILL` | CAP | `( baddr u c -- )`: the low byte of `c`. See below. Nothing for `u = 0`; for `u < 0` nothing is written and `NODE-ERROR` is set (v3 read a negative count as a huge unsigned one). Executed on the golden model (2026-10-03), including a transcript of the v3 binary. Leaves its caller 5 data cells and 5 return entries. Clobbers `A` and, on error, `B`. |
|
||||
| `MOVE` | CAP | `( src dst u -- )`, bytes: `push over over - -if UP drop pop jump CMOVE> UP: drop pop jump CMOVE` — `CMOVE>` when `src < dst`, else `CMOVE`, so overlapping bytes are read before they are overwritten, as v3's `memmove`. The test is the sign of `src - dst`, in line. Executed on the golden model (2026-10-03), including a transcript of the v3 binary. Leaves its caller 4 data cells and 5 return entries. |
|
||||
| `MOVE` | CAP | `( addr1 addr2 n -- )` — FORTH-79 (ruled 2026-10-04): `n` cells from `addr1` to `addr2`, the cell at `addr1` first; nothing for `n <= 0`. The addresses are word addresses (D-1). `-if OK drop drop drop ; OK: if DONE push over a! @ over a! ! 1 + push 1 + pop pop -1 + jump OK DONE: drop drop drop ;` v3's `MOVE` moved bytes, in whichever direction did not overwrite what it had yet to read; that is `CMOVE` and `CMOVE>`. Executed on the golden model (2026-10-04) against C, overlapping both ways. Leaves its caller 6 data cells and 6 return entries. Clobbers `A`. |
|
||||
| `ERASE` | CAP | `0 FILL`, as `0 jump FILL`. Executed on the golden model (2026-10-03), including a transcript of the v3 binary. |
|
||||
| `CELLS` | IN | Empty (word-addressed, D-1); v3 answers 24 for `3 CELLS`. Executed on the golden model (2026-10-03). |
|
||||
|
||||
|
||||
+33
-22
@@ -9,8 +9,11 @@
|
||||
* COUNT ( baddr -- baddr+1 c )
|
||||
* CMOVE ( src dst u -- ) low byte first
|
||||
* CMOVE> ( src dst u -- ) high byte first
|
||||
* MOVE ( src dst u -- ) whichever of the two does not overwrite
|
||||
* bytes it has yet to read
|
||||
* MOVE ( addr1 addr2 n -- ) FORTH-79 (ruled 2026-10-04): n cells
|
||||
* from addr1 to addr2, the cell at addr1
|
||||
* first; nothing for n <= 0. The addresses
|
||||
* are word addresses (D-1). v3's MOVE moved
|
||||
* bytes, either way round, like memmove.
|
||||
* FILL ( baddr u c -- ) the low byte of c
|
||||
* BLANK ERASE ( baddr u -- ) FILL with 32, with 0
|
||||
* -TRAILING ( baddr u -- baddr u' ) without its trailing spaces
|
||||
@@ -173,15 +176,22 @@ static void build(void)
|
||||
HERE_(b);
|
||||
O(DROP); O(DROP); O(DROP); O(SEMI);
|
||||
|
||||
/* : MOVE ( src dst u -- )
|
||||
* push over over - -if UP drop pop jump CMOVE> src < dst
|
||||
* UP: drop pop jump CMOVE
|
||||
* The sign of src - dst, the subtraction in line. */
|
||||
/* : MOVE ( addr1 addr2 n -- ) FORTH-79: cells, low address first
|
||||
* -if OK drop drop drop ; n < 0
|
||||
* OK: if DONE push addr1 addr2 R: n
|
||||
* over a! @ over a! ! 1 + push 1 + pop pop -1 + jump OK
|
||||
* DONE: drop drop drop ; */
|
||||
w_move = v4_asm_label(&as);
|
||||
O(PUSH); O(OVER); O(OVER); SUB_INLINE(); a = FWD(MINUS_IF);
|
||||
O(DROP); O(RPOP); JUMP(w_cmoveup);
|
||||
a = FWD(MINUS_IF);
|
||||
O(DROP); O(DROP); O(DROP); O(SEMI);
|
||||
HERE_(a);
|
||||
O(DROP); O(RPOP); JUMP(w_cmove);
|
||||
l = v4_asm_label(&as);
|
||||
b = FWD(IF);
|
||||
O(PUSH); O(OVER); O(BANG_A); O(FETCH_A); O(OVER); O(BANG_A); O(STORE_A);
|
||||
LIT(1); O(ADD); O(PUSH); LIT(1); O(ADD); O(RPOP); O(RPOP); LIT(-1); O(ADD);
|
||||
JUMP(l);
|
||||
HERE_(b);
|
||||
O(DROP); O(DROP); O(DROP); O(SEMI);
|
||||
|
||||
/* : FILL ( baddr u c -- )
|
||||
* -ROT c baddr u
|
||||
@@ -524,12 +534,10 @@ int main(void)
|
||||
* 20 20 20 20 2E 2E 2E 2E 00 00 00 2E 2E 2E 2E 2E
|
||||
* "ABCDEF" B 6 CMOVE B B 2 + 6 CMOVE> B B 1 + 6 CMOVE B 16 DUMP
|
||||
* 41 41 41 41 41 41 41 46 00 00 00 2E 2E 2E 2E 2E
|
||||
* B 3 + B 5 MOVE B 16 DUMP
|
||||
* 41 41 41 41 46 41 41 46 00 00 00 2E 2E 2E 2E 2E */
|
||||
* (v3 went on to B 3 + B 5 MOVE, a byte move; MOVE here is FORTH-79's and moves cells.) */
|
||||
{
|
||||
static const unsigned char d1[16] = { 0x20,0x20,0x20,0x20,0x2E,0x2E,0x2E,0x2E,0,0,0,0x2E,0x2E,0x2E,0x2E,0x2E };
|
||||
static const unsigned char d2[16] = { 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x46,0,0,0,0x2E,0x2E,0x2E,0x2E,0x2E };
|
||||
static const unsigned char d3[16] = { 0x41,0x41,0x41,0x41,0x46,0x41,0x41,0x46,0,0,0,0x2E,0x2E,0x2E,0x2E,0x2E };
|
||||
const v4_cell B = BUF + 21;
|
||||
#define STEP(word, argc, a, b, c) do { \
|
||||
CHECK(call(word, argc, a, b, c, 0) && clean() && !err(), "v3 block-copy step returns"); \
|
||||
@@ -544,8 +552,6 @@ int main(void)
|
||||
STEP(w_cmoveup, 3, B, B + 2, 6);
|
||||
STEP(w_cmove, 3, B, B + 1, 6);
|
||||
CHECK(memcmp(img + 21, d2, 16) == 0, "v3: CMOVE, CMOVE>, CMOVE");
|
||||
STEP(w_move, 3, B + 3, B, 5);
|
||||
CHECK(memcmp(img + 21, d3, 16) == 0, "v3: MOVE");
|
||||
for (i = 0; i < BUFLEN; i++)
|
||||
if ((i < 21 || i >= 37) && (i < 100 || i >= 106) && img[i] != 0x77) break;
|
||||
CHECK(i == BUFLEN, "nothing outside B was written");
|
||||
@@ -585,11 +591,16 @@ int main(void)
|
||||
if (t % 2) dst = rnd() % (BUFLEN - 48);
|
||||
else { int d = (int)(rnd() % 17) - 8; dst = (unsigned)((int)src + d < 0 ? 0 : (int)src + d); if (dst > BUFLEN - 48) dst = BUFLEN - 48; }
|
||||
random_img(0);
|
||||
CHECK(call(which == 0 ? w_cmove : which == 1 ? w_cmoveup : w_move, 3,
|
||||
BUF + (v4_cell)src, BUF + (v4_cell)dst, (v4_cell)len, 0) && clean(), "move returns [%u]", t);
|
||||
if (which == 0) for (k = 0; k < len; k++) img[dst + k] = img[src + k];
|
||||
else if (which == 1) for (k = len; k-- > 0; ) img[dst + k] = img[src + k];
|
||||
else memmove(img + dst, img + src, len);
|
||||
if (which == 2) { /* MOVE: cells, not bytes */
|
||||
len /= 4; src /= 4; dst /= 4;
|
||||
CHECK(call(w_move, 3, BUFW + (v4_cell)src, BUFW + (v4_cell)dst, (v4_cell)len, 0) && clean(), "MOVE returns [%u]", t);
|
||||
for (k = 0; k < 4 * len; k++) img[4 * dst + k] = img[4 * src + k];
|
||||
} else {
|
||||
CHECK(call(which == 0 ? w_cmove : w_cmoveup, 3,
|
||||
BUF + (v4_cell)src, BUF + (v4_cell)dst, (v4_cell)len, 0) && clean(), "move returns [%u]", t);
|
||||
if (which == 0) for (k = 0; k < len; k++) img[dst + k] = img[src + k];
|
||||
else for (k = len; k-- > 0; ) img[dst + k] = img[src + k];
|
||||
}
|
||||
CHECK(img_matches() && !err(), "%s [%u] src %u dst %u len %u",
|
||||
which == 0 ? "CMOVE" : which == 1 ? "CMOVE>" : "MOVE", t, src, dst, len);
|
||||
}
|
||||
@@ -601,8 +612,8 @@ int main(void)
|
||||
for (i = 0; i < 3; i++) {
|
||||
CHECK(call(w_cmove, 3, BUF, BUF + 50, neg[i], 0) && clean() && img_matches() && err(), "CMOVE negative count [%u]", i);
|
||||
CHECK(call(w_cmoveup, 3, BUF, BUF + 50, neg[i], 0) && clean() && img_matches() && err(), "CMOVE> negative count [%u]", i);
|
||||
CHECK(call(w_move, 3, BUF, BUF + 50, neg[i], 0) && clean() && img_matches() && err(), "MOVE negative count, up [%u]", i);
|
||||
CHECK(call(w_move, 3, BUF + 50, BUF, neg[i], 0) && clean() && img_matches() && err(), "MOVE negative count, down [%u]", i);
|
||||
CHECK(call(w_move, 3, BUFW, BUFW + 12, neg[i], 0) && clean() && img_matches() && !err(), "MOVE moves nothing for n < 0, up [%u]", i);
|
||||
CHECK(call(w_move, 3, BUFW + 12, BUFW, neg[i], 0) && clean() && img_matches() && !err(), "MOVE moves nothing for n < 0, down [%u]", i);
|
||||
CHECK(call(w_fill, 3, BUF, neg[i], 65, 0) && clean() && img_matches() && err(), "FILL negative count [%u]", i);
|
||||
CHECK(call(w_blank, 2, BUF, neg[i], 0, 0) && clean() && img_matches() && err(), "BLANK negative count [%u]", i);
|
||||
CHECK(call(w_erase, 2, BUF, neg[i], 0, 0) && clean() && img_matches() && err(), "ERASE negative count [%u]", i);
|
||||
@@ -690,7 +701,7 @@ int main(void)
|
||||
headroom("COUNT", w_count, 1, BUF + 3, 0, 0, 0, 2, 6, 6);
|
||||
headroom("CMOVE", w_cmove, 3, BUF + 3, BUF + 90, 9, 0, 0, 3, 5);
|
||||
headroom("CMOVE>", w_cmoveup, 3, BUF + 3, BUF + 90, 9, 0, 0, 3, 5);
|
||||
headroom("MOVE", w_move, 3, BUF + 3, BUF + 6, 9, 0, 0, 3, 5);
|
||||
headroom("MOVE", w_move, 3, BUFW + 1, BUFW + 9, 5, 0, 0, 4, 6);
|
||||
headroom("FILL", w_fill, 3, BUF + 3, 9, 65, 0, 0, 3, 5);
|
||||
headroom("BLANK", w_blank, 2, BUF + 3, 9, 0, 0, 0, 3, 5);
|
||||
headroom("-TRAILING", w_trailing, 2, BUF + 64, 8, 0, 0, 2, 4, 6);
|
||||
|
||||
Reference in New Issue
Block a user