From 35bfa34c0a446f3c9b29063db63e0a298e5427ff Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Wed, 29 Apr 2026 10:37:41 -0700 Subject: [PATCH 01/48] paging: add fetch and store macros use macros in @ ! w@ w! c@ c! and +! --- csrc/paging/dmpaging.h | 110 +++++++++++++++++++++++++++++++++++++++++ csrc/pf_all.h | 1 + csrc/pf_inner.c | 30 ++++++----- 3 files changed, 129 insertions(+), 12 deletions(-) create mode 100644 csrc/paging/dmpaging.h diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h new file mode 100644 index 0000000..807d5ab --- /dev/null +++ b/csrc/paging/dmpaging.h @@ -0,0 +1,110 @@ +#ifndef _pf_dmpaging_h +#define _pf_dmpaging_h + +/*************************************************************** +** Include file for PForth Demand Paging +** +** Author: Phil Burk +** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom +** +** Permission to use, copy, modify, and/or distribute this +** software for any purpose with or without fee is hereby granted. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +** THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +** FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +** +***************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef cell_t vm_address_t; + +/* Basic memory access macros. */ +#define DP_FETCH_CELL(address) (*((cell_t *)(address))) +#define DP_FETCH_U8(address) (*((uint8_t *)(address))) +#define DP_FETCH_U16(address) (*((uint16_t *)(address))) + +#define DP_STORE_CELL(address, value) *((cell_t *)(address)) = (cell_t)(value) +#define DP_STORE_U8(address, value) *((uint8_t *)(address)) = (uint8_t)(value) +#define DP_STORE_U16(address, value) *((uint16_t *)(address)) = (uint16_t)(value) + +/* Memory region locking and unlocking + * A maximum of DP_MAX_REGIONS can be locked at one time. The regions cannot overlap. + * Adjacent virtual regions will not be adjacent in physical memory! + */ + +/* maximum number of locked regions */ +#define DP_MAX_REGIONS (4) +/* maximum number of bytes per region */ +#define DP_MAX_REGION_SIZE (256) + +/** + * Lock a read-only region of demand paging in physical memory. + * Load the data from demand paging if not already loaded. + * A region should only be locked temporarily, for example within + * a single primitive. + * A physical address will be passed through. + * @return physical address that can be used by normal C code as “const” memory. + */ +#define DP_LOCK_READ_ONLY(virtual_address, numbytes) + +/** + * Lock a read-write region of demand paging in physical memory. + * Load the data from demand paging if not already loaded. + * @return physical address that can be used by normal C code as “const” memory. + */ +#define DP_LOCK_READ_WRITE(virtual_address, numbytes) + +/** + * Release a previously locked region of memory. + * Writable regions will be written back to serial memory. + * Regions may be kept in physical memory on an LRU basis + * to improve performance. + */ +#define DP_UNLOCK(virtual_address) + +/* Serial Memory Access + * A demand paging simulator is provided for testing the framework on a host. + * The actual demand paging interface must be provided by the user. + */ + +/** Free demand paged memory. */ +int pfIsAddressInPagedMemory(vm_address_t p); + +/** Allocate demand paged memory from SPI or other storage. + */ +vm_address_t pfAllocatePagedMemory(size_t numBytes); + +/** Free demand paging */ +void pfFreePagedMemory(vm_address_t p); + +/** Read from virtual to physical memory. + * Only one async read can be pending at a time. + */ +int pfReadPagedMemory(uint8_t *destination, + vm_address_t source, + size_t numBytes, + int sync); + +/* Wait for asynchronous virtual read to complete. + * This is useful for read-ahead buffering. */ +int pfWaitPendingVirtualRead(void); + +int pfWritePagedMemory(vm_address_t destination, + uint8_t *source, + size_t numBytes); + +#ifdef __cplusplus +} +#endif + + +#endif /* _pf_dmpaging_h */ diff --git a/csrc/pf_all.h b/csrc/pf_all.h index cfa3bca..4be0694 100644 --- a/csrc/pf_all.h +++ b/csrc/pf_all.h @@ -50,6 +50,7 @@ #include "pforth.h" #include "pf_types.h" +#include "paging/dmpaging.h" #include "pf_io.h" #include "pf_guts.h" #include "pf_text.h" diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 7ade2d2..1e72f3e 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -547,7 +547,7 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); TOS = TOS * sizeof(cell_t); endcase; - case ID_CFETCH: TOS = *((uint8_t *) TOS); endcase; + case ID_CFETCH: TOS = DP_FETCH_U8(TOS); endcase; case ID_CMOVE: /* ( src dst n -- ) */ { @@ -647,7 +647,8 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); endcase; case ID_CSTORE: /* ( c caddr -- ) */ - *((uint8_t *) TOS) = (uint8_t) M_POP; + /* *((uint8_t *) TOS) = (uint8_t) M_POP; */ + DP_STORE_U8(TOS, M_POP); M_DROP; endcase; @@ -959,10 +960,10 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); } else { - TOS = *((cell_t *)TOS); + TOS = DP_FETCH_CELL(TOS); } #else - TOS = *((cell_t *)TOS); + TOS = DP_FETCH_CELL(TOS); #endif endcase; @@ -1460,10 +1461,14 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); } else { - *((cell_t *)TOS) += M_POP; + Scratch = DP_FETCH_CELL(TOS); + Scratch += M_POP; + DP_STORE_CELL(TOS, Scratch); } #else - *((cell_t *)TOS) += M_POP; + Scratch = DP_FETCH_CELL(TOS); + Scratch += M_POP; + DP_STORE_CELL(TOS, Scratch); #endif M_DROP; endcase; @@ -1665,10 +1670,10 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); } else { - *((cell_t *)TOS) = M_POP; + DP_STORE_CELL(TOS, M_POP); } #else - *((cell_t *)TOS) = M_POP; + DP_STORE_CELL(TOS, M_POP); #endif M_DROP; endcase; @@ -1830,10 +1835,10 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); } else { - TOS = *((uint16_t *)TOS); + TOS = DP_FETCH_U16(TOS); } #else - TOS = *((uint16_t *)TOS); + TOS = DP_FETCH_U16(TOS); #endif endcase; @@ -1846,10 +1851,10 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); } else { - *((uint16_t *)TOS) = (uint16_t) M_POP; + DP_STORE_U16(TOS, (uint16_t) M_POP); } #else - *((uint16_t *)TOS) = (uint16_t) M_POP; + DP_STORE_U16(TOS, (uint16_t) M_POP); #endif M_DROP; endcase; @@ -1913,3 +1918,4 @@ DBUGX(("After 0Branch: IP = 0x%x\n", InsPtr )); return ExceptionReturnCode; } + From 36e14fc114171aad683cec9320d0df437c871c34 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Wed, 29 Apr 2026 17:02:19 -0700 Subject: [PATCH 02/48] paging: use lock and unlock macro stubs --- csrc/paging/dmpaging.h | 6 +++--- csrc/pf_inner.c | 21 ++++++++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index 807d5ab..b648f51 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -54,14 +54,14 @@ typedef cell_t vm_address_t; * A physical address will be passed through. * @return physical address that can be used by normal C code as “const” memory. */ -#define DP_LOCK_READ_ONLY(virtual_address, numbytes) +#define DP_LOCK_READ_ONLY(address, numbytes) ((const uint8_t *)(address)) /** * Lock a read-write region of demand paging in physical memory. * Load the data from demand paging if not already loaded. * @return physical address that can be used by normal C code as “const” memory. */ -#define DP_LOCK_READ_WRITE(virtual_address, numbytes) +#define DP_LOCK_READ_WRITE(address, numbytes) ((uint8_t *)(address)) /** * Release a previously locked region of memory. @@ -69,7 +69,7 @@ typedef cell_t vm_address_t; * Regions may be kept in physical memory on an LRU basis * to improve performance. */ -#define DP_UNLOCK(virtual_address) +#define DP_UNLOCK(address) ((void)(address)) /* Serial Memory Access * A demand paging simulator is provided for testing the framework on a host. diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 1e72f3e..e1e5871 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -446,8 +446,10 @@ DBUG(("pfCatch: Token = 0x%x\n", Token )); endcase; case ID_ACCEPT_P: /* ( c-addr +n1 -- +n2 ) */ - CharPtr = (char *) M_POP; + Temp = M_POP; + CharPtr = (char *) DP_LOCK_READ_WRITE((vm_address_t) Temp, TOS); TOS = ioAccept( CharPtr, TOS ); + DP_UNLOCK((vm_address_t) Temp); endcase; #ifndef PF_NO_SHELL @@ -588,11 +590,16 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); case ID_COMPARE: { const char *s1, *s2; + vm_address_t v1, v2; cell_t len1; - s2 = (const char *) M_POP; + v2 = (vm_address_t) M_POP; len1 = M_POP; - s1 = (const char *) M_POP; + v1 = (vm_address_t) M_POP; + s2 = (const char *) DP_LOCK_READ_ONLY(v2, TOS); + s1 = (const char *) DP_LOCK_READ_ONLY(v1, len); TOS = ffCompare( s1, len1, s2, TOS ); + DP_UNLOCK(v1); + DP_UNLOCK(v2); } endcase; @@ -898,7 +905,9 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_DUMP: Scratch = M_POP; - DumpMemory( (char *) Scratch, TOS ); + CharPtr = (char *) DP_LOCK_READ_ONLY((vm_address_t) Scratch, TOS); + DumpMemory( (char *) CharPtr, TOS ); + DP_UNLOCK((vm_address_t) Scratch); M_DROP; endcase; @@ -1790,7 +1799,9 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_TYPE: Scratch = M_POP; /* addr */ - ioType( (char *) Scratch, TOS ); + CharPtr = (char *) DP_LOCK_READ_ONLY((vm_address_t) Scratch, TOS); + ioType( (char *) CharPtr, TOS ); + DP_UNLOCK((vm_address_t) Scratch); M_DROP; endcase; From 585402417ba79773961dd51c57b4d7c34847cd10 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Thu, 30 Apr 2026 18:44:22 -0700 Subject: [PATCH 03/48] paging: add VM simulator and unit tests add QA macros from PortAudio --- csrc/paging/dmpaging.h | 51 ++++++++++++++++----- csrc/paging/pagedmem.c | 73 +++++++++++++++++++++++++++++ csrc/paging/qadmpage.c | 85 ++++++++++++++++++++++++++++++++++ csrc/paging/unittest.h | 102 +++++++++++++++++++++++++++++++++++++++++ csrc/pf_cglue.c | 2 +- csrc/pf_guts.h | 7 +-- csrc/pf_inner.c | 42 ++++++++++++----- csrc/pf_main.c | 4 ++ csrc/pfcompil.c | 4 +- 9 files changed, 342 insertions(+), 28 deletions(-) create mode 100644 csrc/paging/pagedmem.c create mode 100644 csrc/paging/qadmpage.c create mode 100644 csrc/paging/unittest.h diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index b648f51..d36fd60 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -25,7 +25,7 @@ extern "C" { #endif -typedef cell_t vm_address_t; +typedef uint8_t *vm_address_t; /* Basic memory access macros. */ #define DP_FETCH_CELL(address) (*((cell_t *)(address))) @@ -63,6 +63,12 @@ typedef cell_t vm_address_t; */ #define DP_LOCK_READ_WRITE(address, numbytes) ((uint8_t *)(address)) +/** + * Convert a physical address to a virtual address within the locked region. + * @return virtual address + */ +#define DP_LOCKED_ADDRESS_TO_VIRTUAL(address) ((vm_address_t)(address)) + /** * Release a previously locked region of memory. * Writable regions will be written back to serial memory. @@ -75,32 +81,55 @@ typedef cell_t vm_address_t; * A demand paging simulator is provided for testing the framework on a host. * The actual demand paging interface must be provided by the user. */ +#define DP_ALIGNMENT_SIZE (16) -/** Free demand paged memory. */ -int pfIsAddressInPagedMemory(vm_address_t p); +/** Is the given address associated in the paged memory. + * @return 1 if in paged memory, else 0 + */ +int pfIsAddressInPagedMemory(void *p); + +/** + * Reset the memory allocator. + * This may or may not clear the memory. + */ +void pfResetPagedMemory(void); /** Allocate demand paged memory from SPI or other storage. + * Memory blocks will be aligned on DP_ALIGNMENT_SIZE byte boundaries. */ -vm_address_t pfAllocatePagedMemory(size_t numBytes); +vm_address_t pfAllocatePagedMemory(cell_t numBytes); -/** Free demand paging */ +/** Free demand paged memory. + * This may simply be a NOOP. So just allocate + * what you need at the beginning and don't rely on being able to free it. + */ void pfFreePagedMemory(vm_address_t p); /** Read from virtual to physical memory. - * Only one async read can be pending at a time. + * Only one async read or write can be pending at a time. + * @param micros if zero then issue an async transfer, else timeout in micros + * @return number of bytes read or 0 if timed out */ int pfReadPagedMemory(uint8_t *destination, vm_address_t source, size_t numBytes, - int sync); + int micros); -/* Wait for asynchronous virtual read to complete. - * This is useful for read-ahead buffering. */ -int pfWaitPendingVirtualRead(void); +/* Wait for asynchronous paged memory read or write to complete. + * This is useful for read-ahead buffering. + * return 0 if finished in under the specified microseconds + */ +int pfWaitAsyncPagedMemoryAccess(int micros); +/** Read from virtual to physical memory. + * Only one async read or write can be pending at a time. + * @param micros if zero then issue an async transfer, else timeout in micros + * @return number of bytes written or 0 if timed out + */ int pfWritePagedMemory(vm_address_t destination, uint8_t *source, - size_t numBytes); + size_t numBytes, + int micros); #ifdef __cplusplus } diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c new file mode 100644 index 0000000..55658b2 --- /dev/null +++ b/csrc/paging/pagedmem.c @@ -0,0 +1,73 @@ +/*************************************************************** +** Demand Paged Memory Simulator +** +** Author: Phil Burk +** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom +** +** Permission to use, copy, modify, and/or distribute this +** software for any purpose with or without fee is hereby granted. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +** THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +** FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +** +***************************************************************/ + +#include "../pf_all.h" +#include "dmpaging.h" + +#define PF_DP_AVAILABLE_SPACE (256*1024) +static uint8_t sFakeSerialRAM[PF_DP_AVAILABLE_SPACE]; +static cell_t sDpNextAvailable = 0; +#define DP_ALIGNMENT_MASK (DP_ALIGNMENT_SIZE - 1) + + +void pfResetPagedMemory(void) { + sDpNextAvailable = 0; +} + +int pfIsAddressInPagedMemory(void * p) { + cell_t offset = (uint8_t *)p - sFakeSerialRAM; + return (offset >= 0) && (offset < PF_DP_AVAILABLE_SPACE); +} + +vm_address_t pfAllocatePagedMemory(const cell_t numBytes) { + cell_t alignedNumBytes = (numBytes + DP_ALIGNMENT_MASK) & (~DP_ALIGNMENT_MASK); + cell_t finalAvailable = sDpNextAvailable + alignedNumBytes; + if (finalAvailable > PF_DP_AVAILABLE_SPACE) { + printf("ERROR - Out of Demand Paged Memory!\n"); + return 0; + } + vm_address_t virtualAddress = (vm_address_t) &sFakeSerialRAM[sDpNextAvailable]; + sDpNextAvailable = finalAvailable; + return virtualAddress; +} + +void pfFreePagedMemory(vm_address_t p) {} + +int pfReadPagedMemory(uint8_t *destination, + vm_address_t source, + size_t numBytes, + int async) { + /* TODO check boundaries? */ + pfCopyMemory(destination, source, numBytes); + return numBytes; +} + +int pfWaitPendingVirtualRead(void) { + return 0; +} + +int pfWritePagedMemory(vm_address_t destination, + uint8_t *source, + size_t numBytes, + int async) { + /* TODO check boundaries? */ + pfCopyMemory(destination, source, numBytes); + return numBytes; + } diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c new file mode 100644 index 0000000..c66344a --- /dev/null +++ b/csrc/paging/qadmpage.c @@ -0,0 +1,85 @@ + +/*************************************************************** +** Unit Tests file for pForth Demand Paging +** +** Author: Phil Burk +** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom +** +** Permission to use, copy, modify, and/or distribute this +** software for any purpose with or without fee is hereby granted. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +** THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +** FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +** +***************************************************************/ + +#include "../pf_all.h" +#include "unittest.h" + +PFQA_INSTANTIATE_GLOBALS; + +static int pfQaTestAllocate(void) { + printf("pfQaDemandPaging : pfQaTestAllocate\n"); + pfResetPagedMemory(); + vm_address_t vm1 = pfAllocatePagedMemory(1); + ASSERT_NE(vm1, 0); + vm_address_t vm2 = pfAllocatePagedMemory(128); + ASSERT_NE(vm2, 0); + /* Check alignment. */ + ASSERT_EQ((vm2 - vm1), DP_ALIGNMENT_SIZE); + + int x = 0; + ASSERT_EQ(pfIsAddressInPagedMemory(&x), 0); + ASSERT_EQ(pfIsAddressInPagedMemory((void *)(vm2 + 5)), 1); + return 0; +error: + return 1; +} + +static int pfQaTestReadWrite(void) { + printf("pfQaDemandPaging : pfQaTestReadWrite\n"); + uint8_t buffer1[73]; + uint8_t buffer2[sizeof(buffer1)]; + const int kBufferSize = sizeof(buffer1); + for (int i = 0; i < kBufferSize; i++) { + buffer1[i] = i; + } + pfResetPagedMemory(); + vm_address_t vm1 = pfAllocatePagedMemory(kBufferSize); + ASSERT_NE(vm1, 0); + cell_t written = pfWritePagedMemory(vm1, buffer1, kBufferSize, 0); + ASSERT_EQ(written, kBufferSize); + cell_t numRead = pfReadPagedMemory(buffer2, vm1, kBufferSize, 0); + ASSERT_EQ(numRead, kBufferSize); + for (int i = 0; i < kBufferSize; i++) { + ASSERT_EQ(buffer2[i], buffer1[i]); + } + + return 0; +error: + return 1; +} + +int pfQaDemandPaging(void) { + printf("pfQaDemandPaging\n"); + int x = 4; + int y = 4; + ASSERT_EQ(x,y); + + ASSERT_EQ(sizeof(vm_address_t), sizeof(cell_t)); + + ASSERT_EQ(pfQaTestAllocate(), 0); + ASSERT_EQ(pfQaTestReadWrite(), 0); + + printf("pfQaDemandPaging ended\n"); + +error: + PFQA_PRINT_RESULT; + return PFQA_EXIT_RESULT; +} diff --git a/csrc/paging/unittest.h b/csrc/paging/unittest.h new file mode 100644 index 0000000..d158a7e --- /dev/null +++ b/csrc/paging/unittest.h @@ -0,0 +1,102 @@ +#ifndef _pf_unittest_h +#define _pf_unittest_h +/*************************************************************** +** Unit Tests support for pForth +** +** Author: Phil Burk +** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom +** +** Permission to use, copy, modify, and/or distribute this +** software for any purpose with or without fee is hereby granted. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +** THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +** FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +** +***************************************************************/ + +extern int pfQaNumPassed; +extern int pfQaNumFailed; + +/* You must use this macro exactly once in each test program. */ +#define PFQA_INSTANTIATE_GLOBALS\ + int pfQaNumPassed = 0;\ + int pfQaNumFailed = 0; + +#define CELL_FORMAT "%l" +/*------------------- Macros ------------------------------*/ +/* Print ERROR if it fails. Tally success or failure. Odd */ +/* do-while wrapper seems to be needed for some compilers. */ +#define CHECK_TRUE(_exp, _on_error) \ + do \ + { \ + if (_exp) {\ + pfQaNumPassed++; \ + } \ + else { \ + printf("ERROR at %s:%d, (%s) not true\n", \ + __FILE__, __LINE__, #_exp ); \ + pfQaNumFailed++; \ + _on_error; \ + } \ + } while(0) + +#define ASSERT_TRUE(_exp) CHECK_TRUE(_exp, goto error) +#define EXPECT_TRUE(_exp) CHECK_TRUE(_exp, (void)0) + +#define CHECK_AB(_a, _b, _op, _opn, _on_error) \ + do \ + { \ + cell_t mA = (cell_t)(_a); \ + cell_t mB = (cell_t)(_b); \ + if (mA _op mB) {\ + pfQaNumPassed++; \ + } \ + else { \ + printf("ERROR at %s:%d, (%s) %s (%s), %ld %s %ld\n", \ + __FILE__, __LINE__, #_a, #_opn, #_b, mA, #_opn, mB ); \ + pfQaNumFailed++; \ + _on_error; \ + } \ + } while(0) + +#define ASSERT_AB(_a, _b, _op, _opn) CHECK_AB(_a, _b, _op, _opn, goto error) +#define ASSERT_EQ(_a, _b) ASSERT_AB(_a, _b, ==, !=) +#define ASSERT_NE(_a, _b) ASSERT_AB(_a, _b, !=, ==) +#define ASSERT_GT(_a, _b) ASSERT_AB(_a, _b, >, <=) +#define ASSERT_GE(_a, _b) ASSERT_AB(_a, _b, >=, <) +#define ASSERT_LT(_a, _b) ASSERT_AB(_a, _b, <, >=) +#define ASSERT_LE(_a, _b) ASSERT_AB(_a, _b, <=, >) + +#define EXPECT_AB(_a, _b, _op, _opn) CHECK_AB(_a, _b, _op, _opn, (void)0) +#define EXPECT_EQ(_a, _b) EXPECT_AB(_a, _b, ==, !=) +#define EXPECT_NE(_a, _b) EXPECT_AB(_a, _b, !=, ==) +#define EXPECT_GT(_a, _b) EXPECT_AB(_a, _b, >, <=) +#define EXPECT_GE(_a, _b) EXPECT_AB(_a, _b, >=, <) +#define EXPECT_LT(_a, _b) EXPECT_AB(_a, _b, <, >=) +#define EXPECT_LE(_a, _b) EXPECT_AB(_a, _b, <=, >) + +#define HOPEFOR(_exp) \ + do \ + { \ + if ((_exp)) {\ + pfQaNumPassed++; \ + } \ + else { \ + printf("\nERROR - 0x%x - %s for %s\n", result, Pa_GetErrorText(result), #_exp ); \ + pfQaNumFailed++; \ + } \ + } while(0) + +#define PFQA_PRINT_RESULT \ + printf("QA Report: %d passed, %d failed.\n", pfQaNumPassed, pfQaNumFailed ) + +#define PFQA_EXIT_RESULT \ + (((pfQaNumFailed > 0) || (pfQaNumPassed == 0)) ? EXIT_FAILURE : EXIT_SUCCESS) + +#endif /* _pf_unittest_h */ diff --git a/csrc/pf_cglue.c b/csrc/pf_cglue.c index c2b65e5..6c6ab0b 100644 --- a/csrc/pf_cglue.c +++ b/csrc/pf_cglue.c @@ -86,7 +86,7 @@ DBUG(("CallUserFunction: Index = %d, ReturnMode = %d, NumParams = %d\n", Err CreateGlueToC( const char *CName, ucell_t Index, cell_t ReturnMode, int32_t NumParams ) { ucell_t Packed; - char FName[LONGEST_WORD_NAME+9]; /* +1 for length, up to +9 should not be used, but is here for safety */ + char FName[PF_NAME_SIZE_SAFE]; CStringToForth( FName, CName, sizeof(FName) ); Packed = (Index & 0xFFFF) | 0 | (NumParams << 24) | diff --git a/csrc/pf_guts.h b/csrc/pf_guts.h index 1a49647..94fd1cf 100644 --- a/csrc/pf_guts.h +++ b/csrc/pf_guts.h @@ -88,14 +88,15 @@ #ifdef PF_SUPPORT_LONG_NAMES #define FLAG_SMUDGE (0x80) -#define MASK_NAME_SIZE (0x3F) +#define PF_NAME_SIZE (0x40) #else #define FLAG_SMUDGE (0x20) -#define MASK_NAME_SIZE (0x1F) +#define PF_NAME_SIZE (0x20) #endif /* these the same, but have different names for clarity */ -#define LONGEST_WORD_NAME MASK_NAME_SIZE +#define MASK_NAME_SIZE (PF_NAME_SIZE - 1) +#define PF_NAME_SIZE_SAFE (PF_NAME_SIZE + 8) /* Debug TRACE flags */ #define TRACE_INNER (0x0002) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index e1e5871..386011f 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1192,12 +1192,19 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); #ifndef PF_NO_SHELL case ID_FIND: /* ( $addr -- $addr 0 | xt +-1 ) */ - TOS = ffFind( (char *) TOS, (ExecToken *) &Temp ); + Scratch = DP_FETCH_U8((vm_address_t) TOS) + 1; /* length including count */ + CharPtr = (char *) DP_LOCK_READ_ONLY((vm_address_t) TOS, Scratch); + TOS = ffFind( (char *) CharPtr, (ExecToken *) &Temp ); + DP_UNLOCK((vm_address_t) TOS); M_PUSH( Temp ); endcase; case ID_FINDNFA: - TOS = ffFindNFA( (const ForthString *) TOS, (const ForthString **) &Temp ); + Scratch = DP_FETCH_U8((vm_address_t) TOS) + 1; /* length including count */ + Temp = (cell_t) DP_LOCK_READ_ONLY((vm_address_t) TOS, Scratch); + TOS = ffFindNFA( (const ForthString *) Temp, (const ForthString **) &CellPtr ); + DP_UNLOCK((vm_address_t) TOS); + Temp = (cell_t) CellPtr; M_PUSH( (cell_t) Temp ); endcase; #endif /* !PF_NO_SHELL */ @@ -1241,7 +1248,10 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); /* Convert using number converter in 'C'. ** Only supports single precision for bootstrap. */ - TOS = (cell_t) ffNumberQ( (char *) TOS, &Temp ); + Scratch = MASK_NAME_SIZE & DP_FETCH_U8((vm_address_t) TOS); /* Length of string. */ + CharPtr = (char *) DP_LOCK_READ_ONLY((vm_address_t) TOS, Scratch); + TOS = (cell_t) ffNumberQ( (char *) CharPtr, &Temp ); + DP_UNLOCK((vm_address_t) TOS); if( TOS == NUM_TYPE_SINGLE) { M_PUSH( Temp ); /* Push single number */ @@ -1688,10 +1698,15 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); endcase; case ID_SCAN: /* ( addr cnt char -- addr' cnt' ) */ - Scratch = M_POP; /* cnt */ - Temp = M_POP; /* addr */ - TOS = ffScan( (char *) Temp, Scratch, (char) TOS, &CharPtr ); - M_PUSH((cell_t) CharPtr); + { + Scratch = M_POP; /* cnt */ + Temp = M_POP; /* addr */ + CharPtr = (char *) DP_LOCK_READ_ONLY((vm_address_t) Temp, Scratch); + TOS = ffScan( (char *) CharPtr, Scratch, (char) TOS, &CharPtr ); + vm_address_t vaddr = DP_LOCKED_ADDRESS_TO_VIRTUAL(CharPtr); + DP_UNLOCK((vm_address_t) Temp); + M_PUSH((cell_t) vaddr); + } endcase; #ifndef PF_NO_SHELL @@ -1704,10 +1719,15 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); #endif /* !PF_NO_SHELL */ case ID_SKIP: /* ( addr cnt char -- addr' cnt' ) */ - Scratch = M_POP; /* cnt */ - Temp = M_POP; /* addr */ - TOS = ffSkip( (char *) Temp, Scratch, (char) TOS, &CharPtr ); - M_PUSH((cell_t) CharPtr); + { + Scratch = M_POP; /* cnt */ + Temp = M_POP; /* addr */ + CharPtr = (char *) DP_LOCK_READ_ONLY((vm_address_t) Temp, Scratch); + TOS = ffSkip( (char *) CharPtr, Scratch, (char) TOS, &CharPtr ); + vm_address_t vaddr = DP_LOCKED_ADDRESS_TO_VIRTUAL(CharPtr); + DP_UNLOCK((vm_address_t) Temp); + M_PUSH((cell_t) vaddr); + } endcase; case ID_SOURCE: /* ( -- c-addr num ) */ diff --git a/csrc/pf_main.c b/csrc/pf_main.c index 1d9fa08..b129859 100644 --- a/csrc/pf_main.c +++ b/csrc/pf_main.c @@ -58,6 +58,8 @@ int main( void ) } #else +int pfQaDemandPaging(); + int main( int argc, char **argv ) { #ifdef PF_STATIC_DIC @@ -140,6 +142,8 @@ int main( int argc, char **argv ) } #endif + Result = pfQaDemandPaging(); + Result = pfDoForth( DicName, SourceName, IfInit); on_error: diff --git a/csrc/pfcompil.c b/csrc/pfcompil.c index 87ba056..fd93fd6 100644 --- a/csrc/pfcompil.c +++ b/csrc/pfcompil.c @@ -99,7 +99,7 @@ void CreateDicEntry( ExecToken XT, const ForthStringPtr FName, ucell_t Flags ) */ void CreateDicEntryC( ExecToken XT, const char *CName, ucell_t Flags ) { - ForthString FName[LONGEST_WORD_NAME+9]; /* +1 for length, up to +9 should not be used, but is here for safety */ + ForthString FName[PF_NAME_SIZE_SAFE]; CStringToForth( FName, CName, sizeof(FName) ); CreateDicEntry( XT, FName, Flags ); } @@ -656,7 +656,7 @@ void ffStringDefer( const ForthStringPtr FName, ExecToken DefaultXT ) /* Convert name then create deferred dictionary entry. */ static void CreateDeferredC( ExecToken DefaultXT, const char *CName ) { - char FName[LONGEST_WORD_NAME+9]; /* +1 for length, up to +9 should not be used, but is here for safety */ + char FName[PF_NAME_SIZE_SAFE]; CStringToForth( FName, CName, sizeof(FName) ); ffStringDefer( FName, DefaultXT ); } From 7f76ff3423015858feca35cff4426d008b66af73 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Fri, 1 May 2026 13:58:07 -0700 Subject: [PATCH 04/48] paging: add region locking Add more unit tests. --- csrc/paging/dmpaging.h | 30 ++++---- csrc/paging/lockpage.c | 149 ++++++++++++++++++++++++++++++++++++++++ csrc/paging/pagedmem.c | 3 + csrc/paging/qadmpage.c | 43 +++++++++++- csrc/pf_core.c | 1 + csrc/pf_inner.c | 91 ++++++++++++++---------- platforms/unix/Makefile | 5 +- 7 files changed, 271 insertions(+), 51 deletions(-) create mode 100644 csrc/paging/lockpage.c diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index d36fd60..8e94764 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -25,6 +25,10 @@ extern "C" { #endif +#ifndef PF_DEMAND_PAGING +#define PF_DEMAND_PAGING 1 +#endif + typedef uint8_t *vm_address_t; /* Basic memory access macros. */ @@ -37,7 +41,8 @@ typedef uint8_t *vm_address_t; #define DP_STORE_U16(address, value) *((uint16_t *)(address)) = (uint16_t)(value) /* Memory region locking and unlocking - * A maximum of DP_MAX_REGIONS can be locked at one time. The regions cannot overlap. + * A maximum of DP_MAX_REGIONS can be locked at one time. + * The regions cannot overlap. * Adjacent virtual regions will not be adjacent in physical memory! */ @@ -46,36 +51,37 @@ typedef uint8_t *vm_address_t; /* maximum number of bytes per region */ #define DP_MAX_REGION_SIZE (256) + +void pfResetLockedMemory(void); + /** * Lock a read-only region of demand paging in physical memory. * Load the data from demand paging if not already loaded. * A region should only be locked temporarily, for example within * a single primitive. - * A physical address will be passed through. + * If the virtual memory address is not in paged memory then it will be passed through. * @return physical address that can be used by normal C code as “const” memory. */ -#define DP_LOCK_READ_ONLY(address, numbytes) ((const uint8_t *)(address)) +const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, cell_t numBytes); /** * Lock a read-write region of demand paging in physical memory. * Load the data from demand paging if not already loaded. + * If the virtual memory address is not in paged memory then it will be passed through. * @return physical address that can be used by normal C code as “const” memory. */ -#define DP_LOCK_READ_WRITE(address, numbytes) ((uint8_t *)(address)) - -/** - * Convert a physical address to a virtual address within the locked region. - * @return virtual address - */ -#define DP_LOCKED_ADDRESS_TO_VIRTUAL(address) ((vm_address_t)(address)) +uint8_t *pfLockMemoryReadWrite(vm_address_t vp, cell_t numBytes); /** * Release a previously locked region of memory. * Writable regions will be written back to serial memory. * Regions may be kept in physical memory on an LRU basis * to improve performance. + * @param vp virtual memory address + * @param pp physical memory address + * @return negative code if an error occured */ -#define DP_UNLOCK(address) ((void)(address)) +int pfUnlockMemory(vm_address_t vp, const uint8_t *pp); /* Serial Memory Access * A demand paging simulator is provided for testing the framework on a host. @@ -83,7 +89,7 @@ typedef uint8_t *vm_address_t; */ #define DP_ALIGNMENT_SIZE (16) -/** Is the given address associated in the paged memory. +/** Is the given address associated in the paged memory? * @return 1 if in paged memory, else 0 */ int pfIsAddressInPagedMemory(void *p); diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c new file mode 100644 index 0000000..b113af5 --- /dev/null +++ b/csrc/paging/lockpage.c @@ -0,0 +1,149 @@ +/*************************************************************** +** Demand Paged Memory Region Locking +** +** Author: Phil Burk +** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom +** +** Permission to use, copy, modify, and/or distribute this +** software for any purpose with or without fee is hereby granted. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +** THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +** FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +** +***************************************************************/ + +#include "../pf_all.h" +#include "dmpaging.h" + +#ifndef PF_DEMAND_PAGING + +void pfResetLockedMemory(void) { +} + +const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, cell_t numBytes) { + return ((const uint8_t *)(vp)); +} + +uint8_t *pfLockMemoryReadWrite(vm_address_t vp, cell_t numBytes) { + return ((uint8_t *)(vp)); +} + +void pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { +} + +vm_address_t pfConvertPhysicalToVirtual(const uint8_t *p) { + return (vm_address_t) p; +} + +void pfUnlockMemory(vm_address_t vp, const uint8_t *pp); +#else + +#define DP_MAGIC (0x5A9E) + +struct RegionControlBlock { + vm_address_t virtual; + uint32_t magic; + uint32_t length; + uint8_t writable; + uint8_t locked; + uint8_t pad1; + uint8_t pad2; + uint8_t physical[DP_MAX_REGION_SIZE]; +}; + +struct RegionControlBlock sLockedRegions[DP_MAX_REGIONS]; + +void pfResetLockedMemory(void) { + pfSetMemory(sLockedRegions, 0, sizeof(sLockedRegions)); + for (int i = 0; i < DP_MAX_REGIONS; i++) { + struct RegionControlBlock *region = &sLockedRegions[i]; + region->magic = DP_MAGIC; + } +} + +uint8_t *pfLockMemoryInternal(vm_address_t vp, cell_t numBytes, int writable) { + struct RegionControlBlock *region = NULL; + if (pfIsAddressInPagedMemory(vp) == 0) { /* not in paged memory so locking not needed */ + return (uint8_t *) vp; + } + /* Find an empty region. */ + for (int i = 0; i < DP_MAX_REGIONS; i++) { + if (sLockedRegions[i].locked == 0) { + region = &sLockedRegions[i]; + break; + } + } + if (region == NULL) { + printf("ERROR: no available region!"); + return NULL; + } + /* Read serial data into the buffer. */ + cell_t numRead = pfReadPagedMemory(®ion->physical[0], vp, numBytes, 0); + if (numRead != numBytes) { + printf("ERROR: could not read data for region!"); + return NULL; + } + + region->virtual = vp; + region->length = (uint32_t) numBytes; + region->locked = 1; + region->writable = writable; + return ®ion->physical[0]; +} + +const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, cell_t numBytes) { + return ((const uint8_t *)(pfLockMemoryInternal(vp, numBytes, 0))); +} + +uint8_t *pfLockMemoryReadWrite(vm_address_t vp, cell_t numBytes) { + return ((uint8_t *)(pfLockMemoryInternal(vp, numBytes, 1))); +} + +int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { + if (vp == pp ) { + return 0; /* not paged memory */ + } + const size_t kPhysicalOffset = (((void *)&sLockedRegions[0].physical[0]) - ((void *)&sLockedRegions[0])); + struct RegionControlBlock *region = (struct RegionControlBlock *)(pp - kPhysicalOffset); + if (region->magic != DP_MAGIC) { + printf("ERROR: physical address was not in a region!\n"); + return -1; + } + if (region->locked == 0) { + printf("ERROR: physical address was not locked!\n"); + return -1; + } + if (region->virtual != vp) { + printf("ERROR: virtual address did not match region, %p != %p!\n", + region->virtual, vp); + return -1; + } + if (region->writable != 0) { + /* write back to serial memory */ + cell_t numWritten = pfWritePagedMemory(vp, ®ion->physical[0], region->length, 0); + + if (numWritten != region->length) { + printf("ERROR: virtual could not be written back, only wrote %d bytes\n", + region->length); + return -1; + } + } + region->virtual = NULL; + region->length = 0; + region->locked = 0; + region->writable = 0; + return 0; +} + +vm_address_t pfConvertPhysicalToVirtual(const uint8_t *p) { + return (vm_address_t) p; +} + +#endif + diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index 55658b2..94c18e9 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -1,5 +1,8 @@ /*************************************************************** ** Demand Paged Memory Simulator +** This should be replaced by a hardware specific implementation +** when doing actual demand paging. The real code may, for example, +** access SPI RAM. ** ** Author: Phil Burk ** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index c66344a..b30cb16 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -47,7 +47,8 @@ static int pfQaTestReadWrite(void) { uint8_t buffer1[73]; uint8_t buffer2[sizeof(buffer1)]; const int kBufferSize = sizeof(buffer1); - for (int i = 0; i < kBufferSize; i++) { + int i; + for (i = 0; i < kBufferSize; i++) { buffer1[i] = i; } pfResetPagedMemory(); @@ -57,7 +58,7 @@ static int pfQaTestReadWrite(void) { ASSERT_EQ(written, kBufferSize); cell_t numRead = pfReadPagedMemory(buffer2, vm1, kBufferSize, 0); ASSERT_EQ(numRead, kBufferSize); - for (int i = 0; i < kBufferSize; i++) { + for (i = 0; i < kBufferSize; i++) { ASSERT_EQ(buffer2[i], buffer1[i]); } @@ -66,6 +67,43 @@ static int pfQaTestReadWrite(void) { return 1; } +static int pfQaTestRegionLock(void) { + printf("pfQaDemandPaging : pfQaTestRegionLock\n"); + pfResetLockedMemory(); + const int kBufferSize = 123; + int result = 0; + int i; + pfResetPagedMemory(); + vm_address_t vm1 = pfAllocatePagedMemory(kBufferSize); + ASSERT_NE(0, vm1); + + uint8_t *pm1 = pfLockMemoryReadWrite(vm1, kBufferSize); + ASSERT_NE(pm1, NULL); + for (i = 0; i < kBufferSize; i++) { + pm1[i] = i; + } + result = pfUnlockMemory(vm1, pm1); + ASSERT_EQ(0, result); + + const uint8_t *pm2 = pfLockMemoryReadOnly(vm1, kBufferSize); + ASSERT_NE(pm2, NULL); + for (i = 0; i < kBufferSize; i++) { + ASSERT_EQ(pm2[i], i); + } + result = pfUnlockMemory(vm1 + 8, pm2); /* Pass bad virtual address! */ + ASSERT_GE(0, result); + result = pfUnlockMemory(vm1, pm2 + 8); /* Pass bad physical address! */ + ASSERT_GE(0, result); + result = pfUnlockMemory(vm1, pm2); /* GOOD */ + ASSERT_EQ(0, result); + result = pfUnlockMemory(vm1, pm2); /* Unlock twice! */ + ASSERT_GE(0, result); + + return 0; +error: + return 1; +} + int pfQaDemandPaging(void) { printf("pfQaDemandPaging\n"); int x = 4; @@ -76,6 +114,7 @@ int pfQaDemandPaging(void) { ASSERT_EQ(pfQaTestAllocate(), 0); ASSERT_EQ(pfQaTestReadWrite(), 0); + ASSERT_EQ(pfQaTestRegionLock(), 0); printf("pfQaDemandPaging ended\n"); diff --git a/csrc/pf_core.c b/csrc/pf_core.c index c0710fc..318d1e6 100644 --- a/csrc/pf_core.c +++ b/csrc/pf_core.c @@ -113,6 +113,7 @@ static void pfInit( void ) gVarTraceStack = 1; pfInitMemoryAllocator(); + pfResetLockedMemory(); ioInit(); } static void pfTerm( void ) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 386011f..1799be5 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -447,9 +447,10 @@ DBUG(("pfCatch: Token = 0x%x\n", Token )); case ID_ACCEPT_P: /* ( c-addr +n1 -- +n2 ) */ Temp = M_POP; - CharPtr = (char *) DP_LOCK_READ_WRITE((vm_address_t) Temp, TOS); + CharPtr = (char *) pfLockMemoryReadWrite((vm_address_t) Temp, TOS); TOS = ioAccept( CharPtr, TOS ); - DP_UNLOCK((vm_address_t) Temp); + printf("Call pfUnlockMemory from ID_ACCCEPT\n"); + pfUnlockMemory((vm_address_t) Temp, CharPtr); endcase; #ifndef PF_NO_SHELL @@ -595,11 +596,12 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); v2 = (vm_address_t) M_POP; len1 = M_POP; v1 = (vm_address_t) M_POP; - s2 = (const char *) DP_LOCK_READ_ONLY(v2, TOS); - s1 = (const char *) DP_LOCK_READ_ONLY(v1, len); + s2 = (const char *) pfLockMemoryReadOnly(v2, TOS); + s1 = (const char *) pfLockMemoryReadOnly(v1, len1); TOS = ffCompare( s1, len1, s2, TOS ); - DP_UNLOCK(v1); - DP_UNLOCK(v2); + printf("Call pfUnlockMemory from ID_COMPARE\n"); + pfUnlockMemory(v1, s1); + pfUnlockMemory(v2, s2); } endcase; @@ -905,9 +907,10 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_DUMP: Scratch = M_POP; - CharPtr = (char *) DP_LOCK_READ_ONLY((vm_address_t) Scratch, TOS); + CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) Scratch, TOS); DumpMemory( (char *) CharPtr, TOS ); - DP_UNLOCK((vm_address_t) Scratch); + printf("Call pfUnlockMemory from ID_DUMP\n"); + pfUnlockMemory((vm_address_t) Scratch, CharPtr); M_DROP; endcase; @@ -1192,20 +1195,36 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); #ifndef PF_NO_SHELL case ID_FIND: /* ( $addr -- $addr 0 | xt +-1 ) */ - Scratch = DP_FETCH_U8((vm_address_t) TOS) + 1; /* length including count */ - CharPtr = (char *) DP_LOCK_READ_ONLY((vm_address_t) TOS, Scratch); - TOS = ffFind( (char *) CharPtr, (ExecToken *) &Temp ); - DP_UNLOCK((vm_address_t) TOS); - M_PUSH( Temp ); + { + vm_address_t vaddr = (vm_address_t) TOS; + Scratch = DP_FETCH_U8(vaddr) + 1; /* length including count */ + CharPtr = (char *) pfLockMemoryReadOnly(vaddr, Scratch); + TOS = ffFind( (char *) CharPtr, (ExecToken *) &Temp ); + printf("Call pfUnlockMemory from ID_FIND\n"); + pfUnlockMemory(vaddr, CharPtr); + if (TOS != 0) { + M_PUSH( Temp ); /* xt */ + } else { + M_PUSH( vaddr ); /* $addr */ + } + } endcase; - case ID_FINDNFA: - Scratch = DP_FETCH_U8((vm_address_t) TOS) + 1; /* length including count */ - Temp = (cell_t) DP_LOCK_READ_ONLY((vm_address_t) TOS, Scratch); - TOS = ffFindNFA( (const ForthString *) Temp, (const ForthString **) &CellPtr ); - DP_UNLOCK((vm_address_t) TOS); - Temp = (cell_t) CellPtr; - M_PUSH( (cell_t) Temp ); + case ID_FINDNFA: /* ( $name -- $addr 0 | nfa -1 | nfa 1 , find NFA in dictionary ) */ + { + vm_address_t nfa = NULL; + vm_address_t name = (vm_address_t) TOS; + Scratch = DP_FETCH_U8(name) + 1; /* length including count */ + CharPtr = (char *) pfLockMemoryReadOnly(name, Scratch); + TOS = ffFindNFA( (const ForthString *) CharPtr, (const ForthString **) &nfa ); + printf("Call pfUnlockMemory from ID_FINDNFA\n"); + pfUnlockMemory(name, CharPtr); + if (TOS != 0) { + M_PUSH( nfa ); + } else { + M_PUSH( name ); /* $addr */ + } + } endcase; #endif /* !PF_NO_SHELL */ @@ -1249,9 +1268,10 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); ** Only supports single precision for bootstrap. */ Scratch = MASK_NAME_SIZE & DP_FETCH_U8((vm_address_t) TOS); /* Length of string. */ - CharPtr = (char *) DP_LOCK_READ_ONLY((vm_address_t) TOS, Scratch); + CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) TOS, Scratch); TOS = (cell_t) ffNumberQ( (char *) CharPtr, &Temp ); - DP_UNLOCK((vm_address_t) TOS); + printf("Call pfUnlockMemory from ID_NUMBERQ_P\n"); + pfUnlockMemory((vm_address_t) TOS, CharPtr); if( TOS == NUM_TYPE_SINGLE) { M_PUSH( Temp ); /* Push single number */ @@ -1700,12 +1720,12 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_SCAN: /* ( addr cnt char -- addr' cnt' ) */ { Scratch = M_POP; /* cnt */ - Temp = M_POP; /* addr */ - CharPtr = (char *) DP_LOCK_READ_ONLY((vm_address_t) Temp, Scratch); - TOS = ffScan( (char *) CharPtr, Scratch, (char) TOS, &CharPtr ); - vm_address_t vaddr = DP_LOCKED_ADDRESS_TO_VIRTUAL(CharPtr); - DP_UNLOCK((vm_address_t) Temp); - M_PUSH((cell_t) vaddr); + Temp = M_POP; /* virtual address */ + char *lockedMemory = (char *) pfLockMemoryReadOnly((vm_address_t) Temp, Scratch); + TOS = ffScan( lockedMemory, Scratch, (char) TOS, &CharPtr ); + printf("Call pfUnlockMemory from ID_SCAN\n"); + pfUnlockMemory((vm_address_t) Temp, lockedMemory); + M_PUSH((cell_t) (Temp + (Scratch - TOS))); /* offset address by (cnt - cnt') */ } endcase; @@ -1722,11 +1742,11 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); { Scratch = M_POP; /* cnt */ Temp = M_POP; /* addr */ - CharPtr = (char *) DP_LOCK_READ_ONLY((vm_address_t) Temp, Scratch); - TOS = ffSkip( (char *) CharPtr, Scratch, (char) TOS, &CharPtr ); - vm_address_t vaddr = DP_LOCKED_ADDRESS_TO_VIRTUAL(CharPtr); - DP_UNLOCK((vm_address_t) Temp); - M_PUSH((cell_t) vaddr); + char *lockedMemory = (char *) pfLockMemoryReadOnly((vm_address_t) Temp, Scratch); + TOS = ffSkip( lockedMemory, Scratch, (char) TOS, &CharPtr ); + printf("Call pfUnlockMemory from ID_SKIP\n"); + pfUnlockMemory((vm_address_t) Temp, lockedMemory); + M_PUSH((cell_t) (Temp + (Scratch - TOS))); /* offset address by (cnt - cnt') */ } endcase; @@ -1819,9 +1839,10 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_TYPE: Scratch = M_POP; /* addr */ - CharPtr = (char *) DP_LOCK_READ_ONLY((vm_address_t) Scratch, TOS); + CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) Scratch, TOS); ioType( (char *) CharPtr, TOS ); - DP_UNLOCK((vm_address_t) Scratch); + printf("Call pfUnlockMemory from ID_TYPE\n"); + pfUnlockMemory((vm_address_t) Scratch, CharPtr); M_DROP; endcase; diff --git a/platforms/unix/Makefile b/platforms/unix/Makefile index 43f59de..e133b0c 100644 --- a/platforms/unix/Makefile +++ b/platforms/unix/Makefile @@ -79,10 +79,11 @@ EMBCCOPTS = -DPF_STATIC_DIC #-DPF_NO_FILEIO PFINCLUDES = pf_all.h pf_cglue.h pf_clib.h pf_core.h pf_float.h \ pf_guts.h pf_host.h pf_inc1.h pf_io.h pf_mem.h pf_save.h \ pf_text.h pf_types.h pf_win32.h pf_words.h pfcompfp.h \ - pfcompil.h pfinnrfp.h pforth.h + pfcompil.h pfinnrfp.h pforth.h paging/dmpaging.h PFBASESOURCE = pf_cglue.c pf_clib.c pf_core.c pf_inner.c \ pf_io.c pf_io_none.c pf_main.c pf_mem.c pf_save.c \ - pf_text.c pf_words.c pfcompil.c pfcustom.c + pf_text.c pf_words.c pfcompil.c pfcustom.c \ + paging/pagedmem.c paging/lockpage.c paging/qadmpage.c PFSOURCE = $(PFBASESOURCE) $(IO_SOURCE) VPATH = .:$(CSRCDIR):$(CSRCDIR)/posix:$(CSRCDIR)/stdio:$(CSRCDIR)/win32_console:$(CSRCDIR)/win32 From 9860e9088c11880e30bdbe63ad2d551b2a2b52f5 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Fri, 1 May 2026 16:55:33 -0700 Subject: [PATCH 05/48] paging: munge paged addresses --- csrc/paging/pagedmem.c | 32 ++++++++++++++++++++++++++------ csrc/paging/qadmpage.c | 1 + csrc/paging/unittest.h | 2 +- csrc/pf_inner.c | 14 +++++++------- csrc/pforth.h | 11 ++++++++++- 5 files changed, 45 insertions(+), 15 deletions(-) diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index 94c18e9..f13779c 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -29,13 +29,23 @@ static uint8_t sFakeSerialRAM[PF_DP_AVAILABLE_SPACE]; static cell_t sDpNextAvailable = 0; #define DP_ALIGNMENT_MASK (DP_ALIGNMENT_SIZE - 1) +#if (PF_64BIT) +#define PF_DP_MUNGE_KEY (0x005A000000000000) +#elif (PF_32BIT) +#define PF_DP_MUNGE_KEY (0x5A000000) +#endif + +#define PF_DP_MUNGE(vaddr) ((vm_address_t)(((cell_t)vaddr) ^ PF_DP_MUNGE_KEY)) +#define PF_DP_UNMUNGE(vaddr) ((vm_address_t)(((cell_t)vaddr) ^ PF_DP_MUNGE_KEY)) void pfResetPagedMemory(void) { + printf("pfResetPagedMemory: cell = %d\n", (int)sizeof(cell_t)); sDpNextAvailable = 0; } int pfIsAddressInPagedMemory(void * p) { - cell_t offset = (uint8_t *)p - sFakeSerialRAM; + vm_address_t vaddr = PF_DP_UNMUNGE(p); + cell_t offset = (uint8_t *)vaddr - sFakeSerialRAM; return (offset >= 0) && (offset < PF_DP_AVAILABLE_SPACE); } @@ -48,7 +58,7 @@ vm_address_t pfAllocatePagedMemory(const cell_t numBytes) { } vm_address_t virtualAddress = (vm_address_t) &sFakeSerialRAM[sDpNextAvailable]; sDpNextAvailable = finalAvailable; - return virtualAddress; + return PF_DP_MUNGE(virtualAddress); } void pfFreePagedMemory(vm_address_t p) {} @@ -57,8 +67,13 @@ int pfReadPagedMemory(uint8_t *destination, vm_address_t source, size_t numBytes, int async) { - /* TODO check boundaries? */ - pfCopyMemory(destination, source, numBytes); + if (!pfIsAddressInPagedMemory(source)) { + printf("ERROR: not a paged address = %p\n", source); + return 0; + } + /* TODO check upper boundary */ + vm_address_t vaddr = PF_DP_UNMUNGE(source); + pfCopyMemory(destination, vaddr, numBytes); return numBytes; } @@ -70,7 +85,12 @@ int pfWritePagedMemory(vm_address_t destination, uint8_t *source, size_t numBytes, int async) { - /* TODO check boundaries? */ - pfCopyMemory(destination, source, numBytes); + if (!pfIsAddressInPagedMemory(destination)) { + printf("ERROR: not a paged address = %p\n", destination); + return 0; + } + /* TODO check upper boundary */ + vm_address_t vaddr = PF_DP_UNMUNGE(destination); + pfCopyMemory(vaddr, source, numBytes); return numBytes; } diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index b30cb16..92e2226 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -54,6 +54,7 @@ static int pfQaTestReadWrite(void) { pfResetPagedMemory(); vm_address_t vm1 = pfAllocatePagedMemory(kBufferSize); ASSERT_NE(vm1, 0); + printf("pfQaTestReadWrite: vm1 = %p\n", vm1); cell_t written = pfWritePagedMemory(vm1, buffer1, kBufferSize, 0); ASSERT_EQ(written, kBufferSize); cell_t numRead = pfReadPagedMemory(buffer2, vm1, kBufferSize, 0); diff --git a/csrc/paging/unittest.h b/csrc/paging/unittest.h index d158a7e..563362d 100644 --- a/csrc/paging/unittest.h +++ b/csrc/paging/unittest.h @@ -1,7 +1,7 @@ #ifndef _pf_unittest_h #define _pf_unittest_h /*************************************************************** -** Unit Tests support for pForth +** Unit Test support for pForth ** ** Author: Phil Burk ** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 1799be5..683b280 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -449,7 +449,7 @@ DBUG(("pfCatch: Token = 0x%x\n", Token )); Temp = M_POP; CharPtr = (char *) pfLockMemoryReadWrite((vm_address_t) Temp, TOS); TOS = ioAccept( CharPtr, TOS ); - printf("Call pfUnlockMemory from ID_ACCCEPT\n"); + // printf("Call pfUnlockMemory from ID_ACCCEPT\n"); pfUnlockMemory((vm_address_t) Temp, CharPtr); endcase; @@ -599,7 +599,7 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); s2 = (const char *) pfLockMemoryReadOnly(v2, TOS); s1 = (const char *) pfLockMemoryReadOnly(v1, len1); TOS = ffCompare( s1, len1, s2, TOS ); - printf("Call pfUnlockMemory from ID_COMPARE\n"); + // printf("Call pfUnlockMemory from ID_COMPARE\n"); pfUnlockMemory(v1, s1); pfUnlockMemory(v2, s2); } @@ -1200,7 +1200,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = DP_FETCH_U8(vaddr) + 1; /* length including count */ CharPtr = (char *) pfLockMemoryReadOnly(vaddr, Scratch); TOS = ffFind( (char *) CharPtr, (ExecToken *) &Temp ); - printf("Call pfUnlockMemory from ID_FIND\n"); + // printf("Call pfUnlockMemory from ID_FIND\n"); pfUnlockMemory(vaddr, CharPtr); if (TOS != 0) { M_PUSH( Temp ); /* xt */ @@ -1217,7 +1217,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = DP_FETCH_U8(name) + 1; /* length including count */ CharPtr = (char *) pfLockMemoryReadOnly(name, Scratch); TOS = ffFindNFA( (const ForthString *) CharPtr, (const ForthString **) &nfa ); - printf("Call pfUnlockMemory from ID_FINDNFA\n"); + // printf("Call pfUnlockMemory from ID_FINDNFA\n"); pfUnlockMemory(name, CharPtr); if (TOS != 0) { M_PUSH( nfa ); @@ -1270,7 +1270,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = MASK_NAME_SIZE & DP_FETCH_U8((vm_address_t) TOS); /* Length of string. */ CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) TOS, Scratch); TOS = (cell_t) ffNumberQ( (char *) CharPtr, &Temp ); - printf("Call pfUnlockMemory from ID_NUMBERQ_P\n"); + // printf("Call pfUnlockMemory from ID_NUMBERQ_P\n"); pfUnlockMemory((vm_address_t) TOS, CharPtr); if( TOS == NUM_TYPE_SINGLE) { @@ -1723,7 +1723,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Temp = M_POP; /* virtual address */ char *lockedMemory = (char *) pfLockMemoryReadOnly((vm_address_t) Temp, Scratch); TOS = ffScan( lockedMemory, Scratch, (char) TOS, &CharPtr ); - printf("Call pfUnlockMemory from ID_SCAN\n"); + // printf("Call pfUnlockMemory from ID_SCAN\n"); pfUnlockMemory((vm_address_t) Temp, lockedMemory); M_PUSH((cell_t) (Temp + (Scratch - TOS))); /* offset address by (cnt - cnt') */ } @@ -1841,7 +1841,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = M_POP; /* addr */ CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) Scratch, TOS); ioType( (char *) CharPtr, TOS ); - printf("Call pfUnlockMemory from ID_TYPE\n"); + // printf("Call pfUnlockMemory from ID_TYPE\n"); pfUnlockMemory((vm_address_t) Scratch, CharPtr); M_DROP; endcase; diff --git a/csrc/pforth.h b/csrc/pforth.h index 8dfdcc2..0a9c00c 100644 --- a/csrc/pforth.h +++ b/csrc/pforth.h @@ -30,9 +30,18 @@ typedef void *PForthTask; typedef void *PForthDictionary; #include +#if INTPTR_MAX == INT64_MAX + #define PF_64BIT 1 + #define PF_32BIT 0 +#elif INTPTR_MAX == INT32_MAX + #define PF_64BIT 0 + #define PF_32BIT 1 +#else + #error "Unsupported pointer size" +#endif + /* Integer types for Forth cells, signed and unsigned: */ typedef intptr_t cell_t; -#define PF_SIZEOF_CELL __SIZEOF_INTPTR__ typedef uintptr_t ucell_t; typedef ucell_t ExecToken; /* Execution Token */ From 1dc6c167c0d6742ba08b18372a22e59004fc91ca Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Sat, 2 May 2026 18:05:02 -0700 Subject: [PATCH 06/48] paging: load dictionary into serial RAM The basic outer interpreter works for static dictionaries. --- csrc/paging/dmpaging.h | 43 +++++++++++++++++++++----- csrc/paging/lockpage.c | 68 ++++++++++++++++++++++++++++++++++++++++-- csrc/paging/pagedmem.c | 2 +- csrc/paging/qadmpage.c | 34 +++++++++++++++++++++ csrc/pf_core.c | 19 +++++++++++- csrc/pf_guts.h | 16 +++++----- csrc/pf_inner.c | 13 ++++++-- csrc/pf_save.c | 4 +++ 8 files changed, 175 insertions(+), 24 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index 8e94764..ff6c9c3 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -32,13 +32,39 @@ extern "C" { typedef uint8_t *vm_address_t; /* Basic memory access macros. */ -#define DP_FETCH_CELL(address) (*((cell_t *)(address))) -#define DP_FETCH_U8(address) (*((uint8_t *)(address))) -#define DP_FETCH_U16(address) (*((uint16_t *)(address))) +#if (PF_DEMAND_PAGING == 0) +/* Straight memory access. */ +#define DP_FETCH_U8(address) (*((uint8_t *)(address))) +#define DP_FETCH_U16(address) (*((uint16_t *)(address))) +#define DP_FETCH_CELL(address) (*((cell_t *)(address))) +#define DP_FETCH_FLOAT(address) (*((PF_FLOAT *)(address))) + +#define DP_STORE_U8(address, value) *((uint8_t *)(address)) = (uint8_t)(value) +#define DP_STORE_U16(address, value) *((uint16_t *)(address)) = (uint16_t)(value) +#define DP_STORE_CELL(address, value) *((cell_t *)(address)) = (cell_t)(value) +#define DP_STORE_FLOAT(address, value) *((PF_FLOAT *)(address)) = (PF_FLOAT)(value) +#else +/* Use either physical or paged memory. */ +#define DP_FETCH_U8(address) pfFetchVirtualU8((uint8_t *)(address)) +#define DP_FETCH_U16(address) pfFetchVirtualU16((uint16_t *)(address)) +#define DP_FETCH_CELL(address) pfFetchVirtualCell((cell_t *)(address)) +#define DP_FETCH_FLOAT(address) pfFetchVirtualFloat((PF_FLOAT *)(address)) + +#define DP_STORE_U8(address, value) pfStoreVirtualU8(((uint8_t *)(address)), (uint8_t)(value)) +#define DP_STORE_U16(address, value) pfStoreVirtualU16(((uint16_t *)(address)), (uint16_t)(value)) +#define DP_STORE_CELL(address, value) pfStoreVirtualCell(((cell_t *)(address)), (cell_t)(value)) +#define DP_STORE_FLOAT(address, value) pfStoreVirtualFloat(((PF_FLOAT *)(address)), (PF_FLOAT)(value)) +#endif + +uint8_t pfFetchVirtualU8(uint8_t *address); +uint16_t pfFetchVirtualU16(uint16_t *address); +cell_t pfFetchVirtualCell(cell_t *address); +PF_FLOAT pfFetchVirtualFloat(PF_FLOAT *address); -#define DP_STORE_CELL(address, value) *((cell_t *)(address)) = (cell_t)(value) -#define DP_STORE_U8(address, value) *((uint8_t *)(address)) = (uint8_t)(value) -#define DP_STORE_U16(address, value) *((uint16_t *)(address)) = (uint16_t)(value) +void pfStoreVirtualU8(uint8_t *address, uint8_t value); +void pfStoreVirtualU16(uint16_t *address, uint16_t value); +void pfStoreVirtualCell(cell_t *address, cell_t value); +void pfStoreVirtualFloat(PF_FLOAT *address, PF_FLOAT value); /* Memory region locking and unlocking * A maximum of DP_MAX_REGIONS can be locked at one time. @@ -50,7 +76,8 @@ typedef uint8_t *vm_address_t; #define DP_MAX_REGIONS (4) /* maximum number of bytes per region */ #define DP_MAX_REGION_SIZE (256) - +/* typical timeout value for accessing serial memory */ +#define DP_TIMEOUT_MICROS 50000 void pfResetLockedMemory(void); @@ -103,7 +130,7 @@ void pfResetPagedMemory(void); /** Allocate demand paged memory from SPI or other storage. * Memory blocks will be aligned on DP_ALIGNMENT_SIZE byte boundaries. */ -vm_address_t pfAllocatePagedMemory(cell_t numBytes); +vm_address_t pfAllocatePagedMemory(ucell_t numBytes); /** Free demand paged memory. * This may simply be a NOOP. So just allocate diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index b113af5..d48a7ab 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -141,8 +141,72 @@ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { return 0; } -vm_address_t pfConvertPhysicalToVirtual(const uint8_t *p) { - return (vm_address_t) p; +uint8_t pfFetchVirtualU8(uint8_t *address) { + uint8_t value; + if (pfIsAddressInPagedMemory(address)) { + pfReadPagedMemory(&value, address, sizeof(uint8_t), DP_TIMEOUT_MICROS); + return value; + } else { + return (*((uint8_t *)(address))); + } + +} +uint16_t pfFetchVirtualU16(uint16_t *address) { + uint16_t value; + if (pfIsAddressInPagedMemory(address)) { + pfReadPagedMemory(&value, address, sizeof(uint16_t), DP_TIMEOUT_MICROS); + return value; + } else { + return (*((uint16_t *)(address))); + } +} +cell_t pfFetchVirtualCell(cell_t *address) { + cell_t value; + if (pfIsAddressInPagedMemory(address)) { + pfReadPagedMemory(&value, address, sizeof(cell_t), DP_TIMEOUT_MICROS); + return value; + } else { + return (*((cell_t *)(address))); + } +} +PF_FLOAT pfFetchVirtualFloat(PF_FLOAT *address) { + PF_FLOAT value; + if (pfIsAddressInPagedMemory(address)) { + pfReadPagedMemory(&value, address, sizeof(PF_FLOAT), DP_TIMEOUT_MICROS); + return value; + } else { + return (*((PF_FLOAT *)(address))); + } +} + +void pfStoreVirtualU8(uint8_t *address, uint8_t value) { + if (pfIsAddressInPagedMemory(address)) { + pfWritePagedMemory(address, &value, sizeof(uint8_t), DP_TIMEOUT_MICROS); + } else { + *address = value; + } +} + +void pfStoreVirtualU16(uint16_t *address, uint16_t value) { + if (pfIsAddressInPagedMemory(address)) { + pfWritePagedMemory(address, &value, sizeof(uint16_t), DP_TIMEOUT_MICROS); + } else { + *address = value; + } +} +void pfStoreVirtualCell(cell_t *address, cell_t value) { + if (pfIsAddressInPagedMemory(address)) { + pfWritePagedMemory(address, &value, sizeof(cell_t), DP_TIMEOUT_MICROS); + } else { + *address = value; + } +} +void pfStoreVirtualFloat(PF_FLOAT *address, PF_FLOAT value) { + if (pfIsAddressInPagedMemory(address)) { + pfWritePagedMemory(address, &value, sizeof(PF_FLOAT), DP_TIMEOUT_MICROS); + } else { + *address = value; + } } #endif diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index f13779c..e09f05f 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -49,7 +49,7 @@ int pfIsAddressInPagedMemory(void * p) { return (offset >= 0) && (offset < PF_DP_AVAILABLE_SPACE); } -vm_address_t pfAllocatePagedMemory(const cell_t numBytes) { +vm_address_t pfAllocatePagedMemory(const ucell_t numBytes) { cell_t alignedNumBytes = (numBytes + DP_ALIGNMENT_MASK) & (~DP_ALIGNMENT_MASK); cell_t finalAvailable = sDpNextAvailable + alignedNumBytes; if (finalAvailable > PF_DP_AVAILABLE_SPACE) { diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index 92e2226..e18766c 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -42,6 +42,39 @@ static int pfQaTestAllocate(void) { return 1; } +static int pfQaTestFetchStore(void) { + printf("pfQaDemandPaging : pfQaTestFetchStore\n"); + PF_FLOAT f1 = 3.14159; + PF_FLOAT f2; + cell_t c1 = 123456; + cell_t c2; + uint16_t w1 = 1234; + uint16_t w2; + uint8_t b1 = 91; + uint8_t b2; + + pfResetPagedMemory(); + vm_address_t vm1 = pfAllocatePagedMemory(1024); + ASSERT_NE(vm1, 0); + + DP_STORE_U8(vm1 + 16, b1); + DP_STORE_U16(vm1 + 32, w1); + DP_STORE_CELL(vm1 + 48, c1); + DP_STORE_FLOAT(vm1 + 64, f1); + + b2 = DP_FETCH_U8(vm1 + 16); + ASSERT_EQ(b1, b2); + w2 = DP_FETCH_U16(vm1 + 32); + ASSERT_EQ(w1, w2); + c2 = DP_FETCH_CELL(vm1 + 48); + ASSERT_EQ(c1, c2); + f2 = DP_FETCH_FLOAT(vm1 + 64); + ASSERT_EQ(f1, f2); + return 0; +error: + return 1; +} + static int pfQaTestReadWrite(void) { printf("pfQaDemandPaging : pfQaTestReadWrite\n"); uint8_t buffer1[73]; @@ -116,6 +149,7 @@ int pfQaDemandPaging(void) { ASSERT_EQ(pfQaTestAllocate(), 0); ASSERT_EQ(pfQaTestReadWrite(), 0); ASSERT_EQ(pfQaTestRegionLock(), 0); + ASSERT_EQ(pfQaTestFetchStore(), 0); printf("pfQaDemandPaging ended\n"); diff --git a/csrc/pf_core.c b/csrc/pf_core.c index 318d1e6..37b6f70 100644 --- a/csrc/pf_core.c +++ b/csrc/pf_core.c @@ -211,7 +211,14 @@ void pfDeleteDictionary( PForthDictionary dictionary ) if( dic->dic_Flags & PF_DICF_ALLOCATED_SEGMENTS ) { FREE_VAR( dic->dic_HeaderBaseUnaligned ); +#if PF_DEMAND_PAGING + if (dic->dic_CodeBaseUnaligned != 0) { + pfFreePagedMemory(dic->dic_CodeBaseUnaligned); + dic->dic_CodeBaseUnaligned = 0; + } +#else FREE_VAR( dic->dic_CodeBaseUnaligned ); +#endif } pfFreeMem( dic ); } @@ -244,7 +251,11 @@ PForthDictionary pfCreateDictionary( cell_t HeaderSize, cell_t CodeSize ) /* Allocate memory for header. */ if( HeaderSize > 0 ) { - dic->dic_HeaderBaseUnaligned = (ucell_t) pfAllocMem( (ucell_t) HeaderSize + DIC_ALIGNMENT_SIZE ); +//#if PF_DEMAND_PAGING +// dic->dic_HeaderBaseUnaligned = (ucell_t) pfAllocatePagedMemory( (ucell_t) HeaderSize + DIC_ALIGNMENT_SIZE); +//#else + dic->dic_HeaderBaseUnaligned = (ucell_t) pfAllocMem((ucell_t) HeaderSize + DIC_ALIGNMENT_SIZE ); +//#endif if( !dic->dic_HeaderBaseUnaligned ) goto nomem; /* Align header base. */ dic->dic_HeaderBase = DIC_ALIGN(dic->dic_HeaderBaseUnaligned); @@ -258,10 +269,16 @@ PForthDictionary pfCreateDictionary( cell_t HeaderSize, cell_t CodeSize ) } /* Allocate memory for code. */ +#if PF_DEMAND_PAGING + dic->dic_CodeBaseUnaligned = (ucell_t) pfAllocatePagedMemory( (ucell_t) CodeSize + DIC_ALIGNMENT_SIZE ); +#else dic->dic_CodeBaseUnaligned = (ucell_t) pfAllocMem( (ucell_t) CodeSize + DIC_ALIGNMENT_SIZE ); +#endif if( !dic->dic_CodeBaseUnaligned ) goto nomem; dic->dic_CodeBase = DIC_ALIGN(dic->dic_CodeBaseUnaligned); +#if (PF_DEMAND_PAGING == 0) pfSetMemory( (char *) dic->dic_CodeBase, 0x5A, (ucell_t) CodeSize); +#endif dic->dic_CodeLimit = dic->dic_CodeBase + CodeSize; dic->dic_CodePtr.Byte = ((uint8_t *) (dic->dic_CodeBase + QUADUP(NUM_PRIMITIVES))); diff --git a/csrc/pf_guts.h b/csrc/pf_guts.h index 94fd1cf..f43b1ea 100644 --- a/csrc/pf_guts.h +++ b/csrc/pf_guts.h @@ -94,7 +94,7 @@ #define PF_NAME_SIZE (0x20) #endif -/* these the same, but have different names for clarity */ +/* These are the same, but have different names for clarity. */ #define MASK_NAME_SIZE (PF_NAME_SIZE - 1) #define PF_NAME_SIZE_SAFE (PF_NAME_SIZE + 8) @@ -568,16 +568,14 @@ extern cell_t gIncludeIndex; #else -#define WRITE_FLOAT_DIC(addr,data) { *((PF_FLOAT *)(addr)) = (PF_FLOAT)(data); } -#define WRITE_CELL_DIC(addr,data) { *((cell_t *)(addr)) = (cell_t)(data); } -#define WRITE_SHORT_DIC(addr,data) { *((int16_t *)(addr)) = (int16_t)(data); } -#define READ_FLOAT_DIC(addr) ( *((PF_FLOAT *)(addr)) ) -#define READ_CELL_DIC(addr) ( *((const ucell_t *)(addr)) ) -#define READ_SHORT_DIC(addr) ( *((const uint16_t *)(addr)) ) - +#define WRITE_FLOAT_DIC(addr,data) DP_STORE_FLOAT(addr,data) +#define WRITE_CELL_DIC(addr,data) DP_STORE_CELL(addr,data) +#define WRITE_SHORT_DIC(addr,data) DP_STORE_U16(addr,data) +#define READ_FLOAT_DIC(addr) DP_FETCH_FLOAT(addr) +#define READ_CELL_DIC(addr) DP_FETCH_CELL(addr) +#define READ_SHORT_DIC(addr) DP_FETCH_U16(addr) #endif - #define HEADER_HERE (gCurrentDictionary->dic_HeaderPtr.Cell) #define CODE_HERE (gCurrentDictionary->dic_CodePtr.Cell) #define CODE_COMMA( N ) WRITE_CELL_DIC(CODE_HERE++,(N)) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 683b280..76f4a89 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -558,7 +558,10 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); CharPtr = (char *) M_POP; /* src */ for( Scratch=0; (ucell_t) Scratch < (ucell_t) TOS ; Scratch++ ) { - *DstPtr++ = *CharPtr++; + uint8_t value = DP_FETCH_U8(CharPtr); + CharPtr++; + DP_STORE_U8(DstPtr, value); + DstPtr++; } M_DROP; } @@ -570,7 +573,10 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); CharPtr = ((char *) M_POP) + TOS;; /* src */ for( Scratch=0; (ucell_t) Scratch < (ucell_t) TOS ; Scratch++ ) { - *(--DstPtr) = *(--CharPtr); + --CharPtr; + uint8_t value = DP_FETCH_U8(CharPtr); + --DstPtr; + DP_STORE_U8(DstPtr, value); } M_DROP; } @@ -1187,7 +1193,8 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); DstPtr = (char *) M_POP; /* dst */ for( Scratch=0; (ucell_t) Scratch < (ucell_t) Temp ; Scratch++ ) { - *DstPtr++ = (char) TOS; + DP_STORE_U8(DstPtr, TOS); + DstPtr++; } M_DROP; } diff --git a/csrc/pf_save.c b/csrc/pf_save.c index 6e3f331..27181ac 100644 --- a/csrc/pf_save.c +++ b/csrc/pf_save.c @@ -817,7 +817,11 @@ PForthDictionary pfLoadStaticDictionary( void ) if( !dic ) goto nomem_error; pfCopyMemory( (uint8_t *) dic->dic_HeaderBase, MinDicNames, sizeof(MinDicNames) ); +#if PF_DEMAND_PAGING + pfWritePagedMemory((uint8_t *) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode), DP_TIMEOUT_MICROS); +#else pfCopyMemory( (uint8_t *) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode) ); +#endif DBUG(("Static data copied to newly allocated dictionaries.\n")); dic->dic_CodePtr.Byte = (uint8_t *) CODEREL_TO_ABS(CODEPTR); From c225a18ce4a6c919670d65696e0645cc843ffacb Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Sat, 2 May 2026 18:13:57 -0700 Subject: [PATCH 07/48] paging: add folder for building paging code --- csrc/pf_core.c | 10 ++++++---- platforms/unix/paging/README.md | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 platforms/unix/paging/README.md diff --git a/csrc/pf_core.c b/csrc/pf_core.c index 37b6f70..b30f50e 100644 --- a/csrc/pf_core.c +++ b/csrc/pf_core.c @@ -251,11 +251,12 @@ PForthDictionary pfCreateDictionary( cell_t HeaderSize, cell_t CodeSize ) /* Allocate memory for header. */ if( HeaderSize > 0 ) { -//#if PF_DEMAND_PAGING -// dic->dic_HeaderBaseUnaligned = (ucell_t) pfAllocatePagedMemory( (ucell_t) HeaderSize + DIC_ALIGNMENT_SIZE); -//#else +/* +#if PF_DEMAND_PAGING + dic->dic_HeaderBaseUnaligned = (ucell_t) pfAllocatePagedMemory( (ucell_t) HeaderSize + DIC_ALIGNMENT_SIZE); +#else + */ dic->dic_HeaderBaseUnaligned = (ucell_t) pfAllocMem((ucell_t) HeaderSize + DIC_ALIGNMENT_SIZE ); -//#endif if( !dic->dic_HeaderBaseUnaligned ) goto nomem; /* Align header base. */ dic->dic_HeaderBase = DIC_ALIGN(dic->dic_HeaderBaseUnaligned); @@ -277,6 +278,7 @@ PForthDictionary pfCreateDictionary( cell_t HeaderSize, cell_t CodeSize ) if( !dic->dic_CodeBaseUnaligned ) goto nomem; dic->dic_CodeBase = DIC_ALIGN(dic->dic_CodeBaseUnaligned); #if (PF_DEMAND_PAGING == 0) + /* TODO also clear RAM for demand paging dic. */ pfSetMemory( (char *) dic->dic_CodeBase, 0x5A, (ucell_t) CodeSize); #endif diff --git a/platforms/unix/paging/README.md b/platforms/unix/paging/README.md new file mode 100644 index 0000000..642a374 --- /dev/null +++ b/platforms/unix/paging/README.md @@ -0,0 +1 @@ +This folder is needed for building pForth with demand paging on a Unix system. From 2dc2e593dc575938177a5abd46044bfd0fa4376d Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Sun, 3 May 2026 15:42:25 -0700 Subject: [PATCH 08/48] paging: forth builds and runs use demand paging in ffReadFile and ffWriteFile --- csrc/paging/pagedmem.c | 8 +++- csrc/paging/qadmpage.c | 96 ++++++++++++++++++++++++++++++++++++++++++ csrc/pf_core.c | 2 +- csrc/pf_inner.c | 38 +++++++++++------ csrc/pf_io.c | 1 - csrc/pf_main.c | 2 +- csrc/pf_save.c | 10 ++--- csrc/pf_words.c | 48 +++++++++++++++++++++ csrc/pf_words.h | 3 ++ fth/system.fth | 2 +- 10 files changed, 187 insertions(+), 23 deletions(-) diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index e09f05f..bb03b61 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -24,7 +24,10 @@ #include "../pf_all.h" #include "dmpaging.h" -#define PF_DP_AVAILABLE_SPACE (256*1024) +#ifndef PF_DP_AVAILABLE_SPACE +#define PF_DP_AVAILABLE_SPACE (512*1024) +#endif + static uint8_t sFakeSerialRAM[PF_DP_AVAILABLE_SPACE]; static cell_t sDpNextAvailable = 0; #define DP_ALIGNMENT_MASK (DP_ALIGNMENT_SIZE - 1) @@ -53,7 +56,8 @@ vm_address_t pfAllocatePagedMemory(const ucell_t numBytes) { cell_t alignedNumBytes = (numBytes + DP_ALIGNMENT_MASK) & (~DP_ALIGNMENT_MASK); cell_t finalAvailable = sDpNextAvailable + alignedNumBytes; if (finalAvailable > PF_DP_AVAILABLE_SPACE) { - printf("ERROR - Out of Demand Paged Memory!\n"); + printf("ERROR - Out of Demand Paged Memory! need %d, have %d\n", + (int)numBytes, (int)(PF_DP_AVAILABLE_SPACE - sDpNextAvailable)); return 0; } vm_address_t virtualAddress = (vm_address_t) &sFakeSerialRAM[sDpNextAvailable]; diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index e18766c..715d0bc 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -138,6 +138,100 @@ static int pfQaTestRegionLock(void) { return 1; } +#define PF_DP_TEST_PATHNAME "/tmp/pf_scratch_file" + + +static cell_t pfQaTestCreateFile(int numBytes) { + uint8_t buffer[100]; + int i; + FileStream *fid = sdOpenFile(PF_DP_TEST_PATHNAME, "wb"); + if (fid == NULL) { + printf("ERROR: Could not open file %s\n",PF_DP_TEST_PATHNAME); + return -1; + } + for (i = 0; i < sizeof(buffer); i++) { + buffer[i] = i; + } + while (numBytes > 0) { + int bytesToWrite = (numBytes < sizeof(buffer)) ? numBytes : sizeof(buffer); + int itemsWritten = sdWriteFile(buffer, 1, bytesToWrite, fid); + if (itemsWritten != bytesToWrite) { + printf("ERROR: writing file failed %d\n", itemsWritten); + return -1; + } + numBytes -= bytesToWrite; + } + sdCloseFile(fid); + return 0; +} + +static int pfQaTestReadFileStandard(int numBytes) { + uint8_t buffer[100]; + int i; + printf("pfQaDemandPaging : pfQaCheckReadFile\n"); + FileStream *fid = sdOpenFile(PF_DP_TEST_PATHNAME, "rb"); + ASSERT_NE(NULL, fid); + while (numBytes > 0) { + int bytesToRead = (numBytes < sizeof(buffer)) ? numBytes : sizeof(buffer); + cell_t result = sdReadFile(buffer, 1, (int32_t) bytesToRead, fid); /* use stdio */ + ASSERT_EQ(bytesToRead, result); + for (i = 0; i < bytesToRead; i++) { + ASSERT_EQ((i % 100), buffer[i]); + } + numBytes -= bytesToRead; + } + sdCloseFile(fid); + return 0; +error: + return 1; +} + +static int pfQaTestReadFilePaging(void) { + int i; + printf("pfQaDemandPaging : pfQaTestReadFile\n"); + pfResetLockedMemory(); + const int kBytesToRead = 1175; + cell_t result = pfQaTestCreateFile(kBytesToRead); + ASSERT_EQ(0, result); + vm_address_t vm1 = pfAllocatePagedMemory(kBytesToRead); + ASSERT_NE(NULL, vm1); + FileStream *fid = sdOpenFile(PF_DP_TEST_PATHNAME, "rb"); + ASSERT_NE(NULL, fid); + result = ffReadFile(vm1, 1, kBytesToRead, fid); /* use demand paging */ + ASSERT_EQ(kBytesToRead, result); + for (i = 0; i < kBytesToRead; i++) { + ASSERT_EQ((i % 100), DP_FETCH_U8(vm1 + i)); + } + sdCloseFile(fid); + return 0; +error: + return 1; +} + +static int pfQaTestWriteFilePaging(void) { + int i; + printf("pfQaDemandPaging : pfQaTestWriteFilePaging\n"); + pfResetLockedMemory(); + const int kBytesToWrite = 1175; + cell_t result = pfQaTestCreateFile(kBytesToWrite); + ASSERT_EQ(0, result); + vm_address_t vm1 = pfAllocatePagedMemory(kBytesToWrite); + ASSERT_NE(NULL, vm1); + for (i = 0; i < kBytesToWrite; i++) { + DP_STORE_U8((vm1 + i), (i % 100)); + } + FileStream *fid = sdOpenFile(PF_DP_TEST_PATHNAME, "wb"); + ASSERT_NE(NULL, fid); + result = ffWriteFile(vm1, 1, kBytesToWrite, fid); /* use demand paging */ + ASSERT_EQ(kBytesToWrite, result); + sdCloseFile(fid); + result = pfQaTestReadFileStandard(kBytesToWrite); + ASSERT_EQ(0, result); + return 0; +error: + return 1; +} + int pfQaDemandPaging(void) { printf("pfQaDemandPaging\n"); int x = 4; @@ -150,6 +244,8 @@ int pfQaDemandPaging(void) { ASSERT_EQ(pfQaTestReadWrite(), 0); ASSERT_EQ(pfQaTestRegionLock(), 0); ASSERT_EQ(pfQaTestFetchStore(), 0); + ASSERT_EQ(pfQaTestReadFilePaging(), 0); + ASSERT_EQ(pfQaTestWriteFilePaging(), 0); printf("pfQaDemandPaging ended\n"); diff --git a/csrc/pf_core.c b/csrc/pf_core.c index b30f50e..9bb2e3b 100644 --- a/csrc/pf_core.c +++ b/csrc/pf_core.c @@ -213,7 +213,7 @@ void pfDeleteDictionary( PForthDictionary dictionary ) FREE_VAR( dic->dic_HeaderBaseUnaligned ); #if PF_DEMAND_PAGING if (dic->dic_CodeBaseUnaligned != 0) { - pfFreePagedMemory(dic->dic_CodeBaseUnaligned); + pfFreePagedMemory((vm_address_t) dic->dic_CodeBaseUnaligned); dic->dic_CodeBaseUnaligned = 0; } #else diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 76f4a89..c8acb6c 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -589,8 +589,14 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); LOAD_REGISTERS; endcase; case ID_COLON_P: /* ( $name xt -- ) */ - CreateDicEntry( TOS, (char *) M_POP, 0 ); - M_DROP; + { + vm_address_t vp = (vm_address_t) M_POP; + Temp = DP_FETCH_U8(vp); /* length */ + CharPtr = (char *) pfLockMemoryReadOnly(vp, Temp + 1); + CreateDicEntry( TOS, CharPtr, 0 ); + pfUnlockMemory(vp, CharPtr); + M_DROP; + } endcase; #endif /* !PF_NO_SHELL */ @@ -986,13 +992,15 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); endcase; case ID_FILE_CREATE: /* ( c-addr u fam -- fid ior ) */ -/* Build NUL terminated name string. */ Scratch = M_POP; /* u */ - Temp = M_POP; /* caddr */ + CharPtr = (char *) M_POP; /* caddr */ if( Scratch < TIB_SIZE-2 ) { const char *famText = pfSelectFileModeCreate( TOS ); - pfCopyMemory( gScratch, (char *) Temp, (ucell_t) Scratch ); + /* Build NUL terminated name string. */ + const char *pName = (char *) pfLockMemoryReadOnly(CharPtr, Scratch); + pfCopyMemory( gScratch, pName, (ucell_t) Scratch ); + pfUnlockMemory(CharPtr, pName); gScratch[Scratch] = '\0'; DBUG(("Create file = %s with famTxt %s\n", gScratch, famText )); FileID = sdOpenFile( gScratch, famText ); @@ -1012,7 +1020,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Temp = M_POP; /* caddr */ if( TOS < TIB_SIZE-2 ) { - pfCopyMemory( gScratch, (char *) Temp, (ucell_t) TOS ); + pfCopyMemory( gScratch, (char *) Temp, (ucell_t) TOS ); /* FIXME vm */ gScratch[TOS] = '\0'; DBUG(("Delete file = %s\n", gScratch )); TOS = sdDeleteFile( gScratch ); @@ -1025,13 +1033,15 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); endcase; case ID_FILE_OPEN: /* ( c-addr u fam -- fid ior ) */ -/* Build NUL terminated name string. */ Scratch = M_POP; /* u */ - Temp = M_POP; /* caddr */ + CharPtr = (char *) M_POP; /* caddr */ if( Scratch < TIB_SIZE-2 ) { const char *famText = pfSelectFileModeOpen( TOS ); - pfCopyMemory( gScratch, (char *) Temp, (ucell_t) Scratch ); + /* Build NUL terminated name string. */ + const char *pName = (char *) pfLockMemoryReadOnly(CharPtr, Scratch); + pfCopyMemory( gScratch, pName, (ucell_t) Scratch ); + pfUnlockMemory(CharPtr, pName); gScratch[Scratch] = '\0'; DBUG(("Open file = %s\n", gScratch )); FileID = sdOpenFile( gScratch, famText ); @@ -1055,7 +1065,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); FileID = (FileStream *) TOS; Scratch = M_POP; CharPtr = (char *) M_POP; - Temp = sdReadFile( CharPtr, 1, Scratch, FileID ); + Temp = ffReadFile( CharPtr, 1, Scratch, FileID ); /* TODO check feof() or ferror() */ M_PUSH(Temp); TOS = 0; @@ -1095,7 +1105,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); FileID = (FileStream *) TOS; Scratch = M_POP; CharPtr = (char *) M_POP; - Temp = sdWriteFile( CharPtr, 1, Scratch, FileID ); + Temp = ffWriteFile( CharPtr, 1, Scratch, FileID ); TOS = (Temp != Scratch) ? -3 : 0; endcase; @@ -1688,8 +1698,12 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); CodeSize = TOS; NameSize = M_POP; EntryPoint = M_POP; - ForthStringToC( gScratch, (char *) M_POP, sizeof(gScratch) ); + vm_address_t vName = (vm_address_t) M_POP; + Temp = DP_FETCH_U8(vName); /* length */ + CharPtr = (char *) pfLockMemoryReadOnly(vName, Temp + 1); + ForthStringToC( gScratch, CharPtr, sizeof(gScratch) ); TOS = ffSaveForth( gScratch, EntryPoint, NameSize, CodeSize ); + pfUnlockMemory(vName, CharPtr); } endcase; #endif diff --git a/csrc/pf_io.c b/csrc/pf_io.c index d0c75d1..56aeeee 100644 --- a/csrc/pf_io.c +++ b/csrc/pf_io.c @@ -149,7 +149,6 @@ DBUGX(("ioAccept(0x%x, 0x%x)\n", buffer, len )); #define UNIMPLEMENTED(name) { MSG(name); MSG("is unimplemented!\n"); } - /***********************************************************************************/ /*********** File I/O **************************************************************/ /***********************************************************************************/ diff --git a/csrc/pf_main.c b/csrc/pf_main.c index b129859..eda9882 100644 --- a/csrc/pf_main.c +++ b/csrc/pf_main.c @@ -142,7 +142,7 @@ int main( int argc, char **argv ) } #endif - Result = pfQaDemandPaging(); +/* Result = pfQaDemandPaging(); FIXME */ Result = pfDoForth( DicName, SourceName, IfInit); diff --git a/csrc/pf_save.c b/csrc/pf_save.c index 27181ac..3472eda 100644 --- a/csrc/pf_save.c +++ b/csrc/pf_save.c @@ -366,7 +366,8 @@ static cell_t WriteChunkToFile( FileStream *fid, cell_t ID, char *Data, int32_t assert(EvenNumW <= UINT32_MAX); if( Write32ToFile( fid, (uint32_t)EvenNumW ) < 0 ) goto error; - numw = sdWriteFile( Data, 1, EvenNumW, fid ); + /* use demand paging just in case */ + numw = ffWriteFile( Data, 1, EvenNumW, fid ); if( numw != EvenNumW ) goto error; return 0; error: @@ -474,7 +475,6 @@ cell_t ffSaveForth( const char *FileName, ExecToken EntryPoint, cell_t NameSize, CodeSize = MAX( (ucell_t)CodeSize, (CodeChunkSize + 2048) ); SD.sd_CodeSize = CodeSize; - convertDictionaryInfoWrite (&SD); if( WriteChunkToFile( fid, ID_P4DI, (char *) &SD, sizeof(DictionaryInfoChunk) ) < 0 ) goto error; @@ -487,8 +487,7 @@ cell_t ffSaveForth( const char *FileName, ExecToken EntryPoint, cell_t NameSize, } /* Write Code Fields ---------------------------- */ - if( WriteChunkToFile( fid, ID_P4CD, (char *) CODE_BASE, - CodeChunkSize ) < 0 ) goto error; + if( WriteChunkToFile( fid, ID_P4CD, (char *) CODE_BASE, CodeChunkSize ) < 0 ) goto error; FormSize = (uint32_t) sdTellFile( fid ) - 8; sdSeekFile( fid, 4, PF_SEEK_SET ); @@ -710,7 +709,8 @@ DBUG(("pfLoadDictionary( %s )\n", FileName )); pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG); goto error; } - numr = sdReadFile( (uint8_t *) CODE_BASE, 1, ChunkSize, fid ); + /* read using demand paging if needed */ + numr = ffReadFile( (uint8_t *) CODE_BASE, 1, ChunkSize, fid ); if( numr != ChunkSize ) goto read_error; BytesLeft -= ChunkSize; break; diff --git a/csrc/pf_words.c b/csrc/pf_words.c index dc183c7..72fe55a 100644 --- a/csrc/pf_words.c +++ b/csrc/pf_words.c @@ -251,3 +251,51 @@ char * ffLWord( char c ) { return Word( c, FALSE ); } + +cell_t ffReadFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream ) +{ + if (pfIsAddressInPagedMemory(ptr)) { + /* Read file in blocks that will fit in locked regions. */ + vm_address_t vp = (vm_address_t)ptr; + cell_t numBytes = Size * nItems; + while (numBytes > 0) { + cell_t bytesToRead = (numBytes < DP_MAX_REGION_SIZE) ? numBytes : DP_MAX_REGION_SIZE; + uint8_t *buffer = pfLockMemoryReadWrite(vp, bytesToRead); + cell_t numRead = sdReadFile(buffer, 1, bytesToRead, Stream); + pfUnlockMemory(vp, buffer); /* writes to backing storage */ + if (numRead < bytesToRead) { + printf("ERROR: failed to read file: %d", (int)numRead); + return 0; + } + numBytes -= bytesToRead; + vp += bytesToRead; + } + return nItems; + } else { + return sdReadFile( ptr, Size, nItems, Stream); + } +} + +cell_t ffWriteFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream ) +{ + if (pfIsAddressInPagedMemory(ptr)) { + /* Write file in blocks that will fit in locked regions. */ + vm_address_t vp = (vm_address_t)ptr; + cell_t numBytes = Size * nItems; + while (numBytes > 0) { + cell_t bytesToWrite = (numBytes < DP_MAX_REGION_SIZE) ? numBytes : DP_MAX_REGION_SIZE; + const uint8_t *buffer = pfLockMemoryReadOnly(vp, bytesToWrite); + cell_t numWritten = sdWriteFile(buffer, 1, bytesToWrite, Stream); + pfUnlockMemory(vp, buffer); /* writes to backing storage */ + if (numWritten < bytesToWrite) { + printf("ERROR: failed to write file: %d", (int)numWritten); + return 0; + } + numBytes -= bytesToWrite; + vp += bytesToWrite; + } + return nItems; + } else { + return sdWriteFile( ptr, Size, nItems, Stream); + } +} diff --git a/csrc/pf_words.h b/csrc/pf_words.h index 33ec368..9d916e5 100644 --- a/csrc/pf_words.h +++ b/csrc/pf_words.h @@ -32,6 +32,9 @@ void ffDotS( void ); cell_t ffSkip( char *AddrIn, cell_t Cnt, char c, char **AddrOut ); cell_t ffScan( char *AddrIn, cell_t Cnt, char c, char **AddrOut ); +cell_t ffReadFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream ); +cell_t ffWriteFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream ); + #ifdef __cplusplus } #endif diff --git a/fth/system.fth b/fth/system.fth index 13f2ab8..6d35555 100644 --- a/fth/system.fth +++ b/fth/system.fth @@ -18,7 +18,7 @@ EOL word drop ; immediate -\ 1 echo ! \ Uncomment this line to echo Forth code while compiling. +1 echo ! \ Uncomment this line to echo Forth code while compiling. \ ********************************************************************* \ This is another style of comment that is common in Forth. From 5c3e034e349cb643f46494fe5c9bf5b11e7186fc Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Mon, 4 May 2026 17:57:59 -0700 Subject: [PATCH 09/48] paging: file words and EVALUATE Fix behavior of read and write when we hit the end of file. --- csrc/paging/dmpaging.h | 20 +++++++++++++++----- csrc/paging/lockpage.c | 11 +++++++++++ csrc/pf_guts.h | 24 ++++++++++++------------ csrc/pf_inner.c | 16 ++++++---------- csrc/pf_words.c | 33 ++++++++++++++++++++++----------- csrc/pfcompil.c | 5 ++++- csrc/pfinnrfp.h | 8 ++++---- fth/t_corex.fth | 1 + fth/t_file.fth | 5 +++-- 9 files changed, 78 insertions(+), 45 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index ff6c9c3..23dcd2d 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -29,7 +29,8 @@ extern "C" { #define PF_DEMAND_PAGING 1 #endif -typedef uint8_t *vm_address_t; +typedef uint8_t *vm_address_t; /** an address that may be in physical or paged memory */ +typedef uint8_t *paging_address_t; /** an address that may be in paged memory */ /* Basic memory access macros. */ #if (PF_DEMAND_PAGING == 0) @@ -110,13 +111,22 @@ uint8_t *pfLockMemoryReadWrite(vm_address_t vp, cell_t numBytes); */ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp); +/** Copy from virtual to physical memory synchronously. + * @param destination in physical memory + * @param source The data may be in physical or paged memory. + * @return destination + */ +void *pfCopyFromVirtualMemory(uint8_t *destination, + vm_address_t source, + size_t numBytes); + /* Serial Memory Access * A demand paging simulator is provided for testing the framework on a host. * The actual demand paging interface must be provided by the user. */ #define DP_ALIGNMENT_SIZE (16) -/** Is the given address associated in the paged memory? +/** Is the given address pointing to paged memory? * @return 1 if in paged memory, else 0 */ int pfIsAddressInPagedMemory(void *p); @@ -130,7 +140,7 @@ void pfResetPagedMemory(void); /** Allocate demand paged memory from SPI or other storage. * Memory blocks will be aligned on DP_ALIGNMENT_SIZE byte boundaries. */ -vm_address_t pfAllocatePagedMemory(ucell_t numBytes); +paging_address_t pfAllocatePagedMemory(ucell_t numBytes); /** Free demand paged memory. * This may simply be a NOOP. So just allocate @@ -144,7 +154,7 @@ void pfFreePagedMemory(vm_address_t p); * @return number of bytes read or 0 if timed out */ int pfReadPagedMemory(uint8_t *destination, - vm_address_t source, + paging_address_t source, size_t numBytes, int micros); @@ -159,7 +169,7 @@ int pfWaitAsyncPagedMemoryAccess(int micros); * @param micros if zero then issue an async transfer, else timeout in micros * @return number of bytes written or 0 if timed out */ -int pfWritePagedMemory(vm_address_t destination, +int pfWritePagedMemory(paging_address_t destination, uint8_t *source, size_t numBytes, int micros); diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index d48a7ab..ea7f5c6 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -209,5 +209,16 @@ void pfStoreVirtualFloat(PF_FLOAT *address, PF_FLOAT value) { } } +void *pfCopyFromVirtualMemory(uint8_t *destination, + vm_address_t source, + size_t numBytes) { + if (pfIsAddressInPagedMemory(source)) { + pfReadPagedMemory(destination, source, numBytes, DP_TIMEOUT_MICROS); /* TODO check result */ + return destination; + } else { + return pfCopyMemory(destination, source, numBytes); + } +} + #endif diff --git a/csrc/pf_guts.h b/csrc/pf_guts.h index f43b1ea..3b77472 100644 --- a/csrc/pf_guts.h +++ b/csrc/pf_guts.h @@ -432,15 +432,15 @@ typedef struct pfTaskData_s PF_FLOAT *td_FloatStackBase; PF_FLOAT *td_FloatStackLimit; #endif - cell_t *td_InsPtr; /* Instruction pointer, "PC" */ + cell_t *td_InsPtr; /* Instruction pointer, "PC" */ FileStream *td_InputStream; /* Terminal. */ - char td_TIB[TIB_SIZE]; /* Buffer for terminal input. */ - cell_t td_IN; /* Index into Source */ - cell_t td_SourceNum; /* #TIB after REFILL */ - char *td_SourcePtr; /* Pointer to TIB or other source. */ - cell_t td_LineNumber; /* Incremented on every refill. */ - cell_t td_OUT; /* Current output column. */ + char td_TIB[TIB_SIZE]; /* Buffer for terminal input. */ + cell_t td_IN; /* Index into Source */ + cell_t td_SourceNum; /* #TIB after REFILL */ + char *td_SourcePtr; /* Pointer to TIB or other source. */ + cell_t td_LineNumber; /* Incremented on every refill. */ + cell_t td_OUT; /* Current output column. */ } pfTaskData_t; typedef struct pfNode @@ -452,7 +452,7 @@ typedef struct pfNode /* Structure of header entry in dictionary. These will be stored in dictionary specific endian format*/ typedef struct cfNameLinks { - cell_t cfnl_PreviousName; /* name relative address of previous */ + cell_t cfnl_PreviousName; /* name relative address of previous */ ExecToken cfnl_ExecToken; /* Execution token for word. */ /* Followed by variable length name field. */ } cfNameLinks; @@ -461,7 +461,7 @@ typedef struct cfNameLinks typedef struct pfDictionary_s { pfNode dic_Node; - ucell_t dic_Flags; + ucell_t dic_Flags; /* Headers contain pointers to names and dictionary. */ ucell_t dic_HeaderBaseUnaligned; @@ -484,9 +484,9 @@ typedef struct pfDictionary_s typedef struct IncludeFrame { FileStream *inf_FileID; - cell_t inf_LineNumber; - cell_t inf_SourceNum; - cell_t inf_IN; + cell_t inf_LineNumber; + cell_t inf_SourceNum; + cell_t inf_IN; char inf_SaveTIB[TIB_SIZE]; } IncludeFrame; diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index c8acb6c..8bffbdc 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -998,9 +998,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); { const char *famText = pfSelectFileModeCreate( TOS ); /* Build NUL terminated name string. */ - const char *pName = (char *) pfLockMemoryReadOnly(CharPtr, Scratch); - pfCopyMemory( gScratch, pName, (ucell_t) Scratch ); - pfUnlockMemory(CharPtr, pName); + pfCopyFromVirtualMemory(gScratch, CharPtr, Scratch); gScratch[Scratch] = '\0'; DBUG(("Create file = %s with famTxt %s\n", gScratch, famText )); FileID = sdOpenFile( gScratch, famText ); @@ -1016,11 +1014,11 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); endcase; case ID_FILE_DELETE: /* ( c-addr u -- ior ) */ -/* Build NUL terminated name string. */ - Temp = M_POP; /* caddr */ + CharPtr = (char *)M_POP; /* caddr */ if( TOS < TIB_SIZE-2 ) { - pfCopyMemory( gScratch, (char *) Temp, (ucell_t) TOS ); /* FIXME vm */ + /* Build NUL terminated name string. */ + pfCopyFromVirtualMemory(gScratch, CharPtr, TOS); gScratch[TOS] = '\0'; DBUG(("Delete file = %s\n", gScratch )); TOS = sdDeleteFile( gScratch ); @@ -1039,9 +1037,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); { const char *famText = pfSelectFileModeOpen( TOS ); /* Build NUL terminated name string. */ - const char *pName = (char *) pfLockMemoryReadOnly(CharPtr, Scratch); - pfCopyMemory( gScratch, pName, (ucell_t) Scratch ); - pfUnlockMemory(CharPtr, pName); + pfCopyFromVirtualMemory(gScratch, CharPtr, Scratch); gScratch[Scratch] = '\0'; DBUG(("Open file = %s\n", gScratch )); FileID = sdOpenFile( gScratch, famText ); @@ -1073,7 +1069,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); /* TODO Why does this crash when passed an illegal FID? */ case ID_FILE_SIZE: /* ( fid -- ud ior ) */ -/* Determine file size by seeking to end and returning position. */ + /* Determine file size by seeking to the end and returning position. */ FileID = (FileStream *) TOS; { file_offset_t endposition = -1; diff --git a/csrc/pf_words.c b/csrc/pf_words.c index 72fe55a..a1bd44e 100644 --- a/csrc/pf_words.c +++ b/csrc/pf_words.c @@ -254,23 +254,28 @@ char * ffLWord( char c ) cell_t ffReadFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream ) { - if (pfIsAddressInPagedMemory(ptr)) { + cell_t numBytes = Size * nItems; + if (numBytes == 0) { + return 0; + } else if (pfIsAddressInPagedMemory(ptr)) { /* Read file in blocks that will fit in locked regions. */ vm_address_t vp = (vm_address_t)ptr; cell_t numBytes = Size * nItems; + cell_t bytesRead = 0; while (numBytes > 0) { cell_t bytesToRead = (numBytes < DP_MAX_REGION_SIZE) ? numBytes : DP_MAX_REGION_SIZE; uint8_t *buffer = pfLockMemoryReadWrite(vp, bytesToRead); cell_t numRead = sdReadFile(buffer, 1, bytesToRead, Stream); pfUnlockMemory(vp, buffer); /* writes to backing storage */ if (numRead < bytesToRead) { - printf("ERROR: failed to read file: %d", (int)numRead); - return 0; + numBytes = 0; // no more data left + } else { + numBytes -= bytesToRead; } - numBytes -= bytesToRead; - vp += bytesToRead; + bytesRead += numRead; + vp += numRead; } - return nItems; + return bytesRead / Size; } else { return sdReadFile( ptr, Size, nItems, Stream); } @@ -278,21 +283,27 @@ cell_t ffReadFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream cell_t ffWriteFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream ) { - if (pfIsAddressInPagedMemory(ptr)) { + cell_t numBytes = Size * nItems; + if (numBytes == 0) { + return 0; + } else if (pfIsAddressInPagedMemory(ptr)) { /* Write file in blocks that will fit in locked regions. */ vm_address_t vp = (vm_address_t)ptr; cell_t numBytes = Size * nItems; + cell_t bytesWritten = 0; while (numBytes > 0) { cell_t bytesToWrite = (numBytes < DP_MAX_REGION_SIZE) ? numBytes : DP_MAX_REGION_SIZE; const uint8_t *buffer = pfLockMemoryReadOnly(vp, bytesToWrite); cell_t numWritten = sdWriteFile(buffer, 1, bytesToWrite, Stream); pfUnlockMemory(vp, buffer); /* writes to backing storage */ + if (numWritten < bytesToWrite) { - printf("ERROR: failed to write file: %d", (int)numWritten); - return 0; + numBytes = 0; // no more data left + } else { + numBytes -= bytesToWrite; } - numBytes -= bytesToWrite; - vp += bytesToWrite; + bytesWritten += numWritten; + vp += numWritten; } return nItems; } else { diff --git a/csrc/pfcompil.c b/csrc/pfcompil.c index fd93fd6..f8fd64e 100644 --- a/csrc/pfcompil.c +++ b/csrc/pfcompil.c @@ -839,11 +839,13 @@ ThrowCode ffInterpret( void ) cell_t flag; char *theWord; ThrowCode exception = 0; + /* td_SourcePtr may be pointing to a string in the dictionary. */ + vm_address_t saveSource = (vm_address_t)gCurrentTask->td_SourcePtr; + gCurrentTask->td_SourcePtr = (char *)pfLockMemoryReadOnly(saveSource, gCurrentTask->td_SourceNum); /* Is there any text left in Source ? */ while( gCurrentTask->td_IN < (gCurrentTask->td_SourceNum) ) { - pfDebugMessage("ffInterpret: calling ffWord(()\n"); theWord = ffLWord( BLANK ); DBUG(("ffInterpret: theWord = 0x%x, Len = %d\n", theWord, *theWord )); @@ -869,6 +871,7 @@ ThrowCode ffInterpret( void ) gCurrentTask->td_SourceNum ) ); } error: + pfUnlockMemory(saveSource, gCurrentTask->td_SourcePtr); return exception; } diff --git a/csrc/pfinnrfp.h b/csrc/pfinnrfp.h index 3e35185..a0fd8f5 100644 --- a/csrc/pfinnrfp.h +++ b/csrc/pfinnrfp.h @@ -59,10 +59,10 @@ } else { - *((PF_FLOAT *) TOS) = FP_TOS; + DP_STORE_FLOAT(TOS, FP_TOS); } #else - *((PF_FLOAT *) TOS) = FP_TOS; + DP_STORE_FLOAT(TOS, FP_TOS); #endif M_FP_DROP; /* drop FP value */ M_DROP; /* drop addr */ @@ -147,10 +147,10 @@ } else { - FP_TOS = *((PF_FLOAT *) TOS); + FP_TOS = DP_FETCH_FLOAT(TOS); } #else - FP_TOS = *((PF_FLOAT *) TOS); + FP_TOS = DP_FETCH_FLOAT(TOS); #endif M_DROP; break; diff --git a/fth/t_corex.fth b/fth/t_corex.fth index a45114f..927f494 100644 --- a/fth/t_corex.fth +++ b/fth/t_corex.fth @@ -8,6 +8,7 @@ INCLUDE? }T{ t_tools.fth ANEW TASK-T_COREX.FTH DECIMAL +ECHO ON TEST{ diff --git a/fth/t_file.fth b/fth/t_file.fth index a947d82..1ab73e8 100644 --- a/fth/t_file.fth +++ b/fth/t_file.fth @@ -59,8 +59,8 @@ include? }T{ t_tools.fth true fp-require-e ! - -false value verbose +echo on +true value verbose : testing verbose IF @@ -180,6 +180,7 @@ T{ 0. FID2 @ REPOSITION-FILE -> 0 }T T{ CBUF BUF 29 FID2 @ READ-FILE -> 29 0 }T T{ PAD 29 BUF 29 S= -> TRUE }T T{ PAD 30 BUF 30 S= -> FALSE }T +TEST2 T{ CBUF BUF 29 FID2 @ READ-FILE -> 21 0 }T T{ PAD 29 + 21 BUF 21 S= -> TRUE }T T{ FID2 @ FILE-SIZE DROP FID2 @ FILE-POSITION DROP D= -> TRUE }T From 6bda4e31d2fd736cbd95effb80cba73cbc93d7af Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Mon, 4 May 2026 18:32:21 -0700 Subject: [PATCH 10/48] paging: fix rename-file --- csrc/pf_inner.c | 22 +++++++++++++++------- fth/t_corex.fth | 1 - fth/t_file.fth | 3 +-- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 8bffbdc..bb31309 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1173,13 +1173,21 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); } endcase; - case ID_FILE_RENAME: /* ( oldName newName -- ior ) */ - { - char *New = (char *) TOS; - char *Old = (char *) M_POP; - TOS = sdRenameFile( Old, New ); - } - endcase; + case ID_FILE_RENAME: /* ( oldName newName -- ior ) */ + { + /* oldName and newName are NUL terminated C strings */ + /* TODO: consider changing the API for (RENAME_FILE) to match ANS. + * Then we will have the name lengths. + */ + vm_address_t vNewName = (vm_address_t)TOS; + char *pNewName = pfLockMemoryReadOnly(vNewName, DP_MAX_REGION_SIZE); + vm_address_t vOldName = (vm_address_t)M_POP; + char *pOldName = pfLockMemoryReadOnly(vOldName, DP_MAX_REGION_SIZE); + TOS = sdRenameFile( pOldName, pNewName ); + pfUnlockMemory(vOldName, pOldName); + pfUnlockMemory(vNewName, pNewName); + } + endcase; case ID_FILE_RESIZE: /* ( ud fileid -- ior ) */ { diff --git a/fth/t_corex.fth b/fth/t_corex.fth index 927f494..a45114f 100644 --- a/fth/t_corex.fth +++ b/fth/t_corex.fth @@ -8,7 +8,6 @@ INCLUDE? }T{ t_tools.fth ANEW TASK-T_COREX.FTH DECIMAL -ECHO ON TEST{ diff --git a/fth/t_file.fth b/fth/t_file.fth index 1ab73e8..b550767 100644 --- a/fth/t_file.fth +++ b/fth/t_file.fth @@ -59,8 +59,7 @@ include? }T{ t_tools.fth true fp-require-e ! -echo on -true value verbose +false value verbose : testing verbose IF From 42a7136ce479e430c051fcb34e47cd03814f9517 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 5 May 2026 13:18:50 -0700 Subject: [PATCH 11/48] remove // comments --- csrc/pf_inner.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index bb31309..e570db0 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -449,7 +449,6 @@ DBUG(("pfCatch: Token = 0x%x\n", Token )); Temp = M_POP; CharPtr = (char *) pfLockMemoryReadWrite((vm_address_t) Temp, TOS); TOS = ioAccept( CharPtr, TOS ); - // printf("Call pfUnlockMemory from ID_ACCCEPT\n"); pfUnlockMemory((vm_address_t) Temp, CharPtr); endcase; @@ -611,7 +610,6 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); s2 = (const char *) pfLockMemoryReadOnly(v2, TOS); s1 = (const char *) pfLockMemoryReadOnly(v1, len1); TOS = ffCompare( s1, len1, s2, TOS ); - // printf("Call pfUnlockMemory from ID_COMPARE\n"); pfUnlockMemory(v1, s1); pfUnlockMemory(v2, s2); } @@ -1221,7 +1219,6 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = DP_FETCH_U8(vaddr) + 1; /* length including count */ CharPtr = (char *) pfLockMemoryReadOnly(vaddr, Scratch); TOS = ffFind( (char *) CharPtr, (ExecToken *) &Temp ); - // printf("Call pfUnlockMemory from ID_FIND\n"); pfUnlockMemory(vaddr, CharPtr); if (TOS != 0) { M_PUSH( Temp ); /* xt */ @@ -1238,7 +1235,6 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = DP_FETCH_U8(name) + 1; /* length including count */ CharPtr = (char *) pfLockMemoryReadOnly(name, Scratch); TOS = ffFindNFA( (const ForthString *) CharPtr, (const ForthString **) &nfa ); - // printf("Call pfUnlockMemory from ID_FINDNFA\n"); pfUnlockMemory(name, CharPtr); if (TOS != 0) { M_PUSH( nfa ); @@ -1291,7 +1287,6 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = MASK_NAME_SIZE & DP_FETCH_U8((vm_address_t) TOS); /* Length of string. */ CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) TOS, Scratch); TOS = (cell_t) ffNumberQ( (char *) CharPtr, &Temp ); - // printf("Call pfUnlockMemory from ID_NUMBERQ_P\n"); pfUnlockMemory((vm_address_t) TOS, CharPtr); if( TOS == NUM_TYPE_SINGLE) { @@ -1748,7 +1743,6 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Temp = M_POP; /* virtual address */ char *lockedMemory = (char *) pfLockMemoryReadOnly((vm_address_t) Temp, Scratch); TOS = ffScan( lockedMemory, Scratch, (char) TOS, &CharPtr ); - // printf("Call pfUnlockMemory from ID_SCAN\n"); pfUnlockMemory((vm_address_t) Temp, lockedMemory); M_PUSH((cell_t) (Temp + (Scratch - TOS))); /* offset address by (cnt - cnt') */ } @@ -1866,7 +1860,6 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = M_POP; /* addr */ CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) Scratch, TOS); ioType( (char *) CharPtr, TOS ); - // printf("Call pfUnlockMemory from ID_TYPE\n"); pfUnlockMemory((vm_address_t) Scratch, CharPtr); M_DROP; endcase; From c871988547d332826add36317b83c812ec2d63c6 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 5 May 2026 13:52:47 -0700 Subject: [PATCH 12/48] fix errors and warnings for CI --- csrc/paging/dmpaging.h | 10 +++++----- csrc/paging/lockpage.c | 26 +++++++++++++------------- csrc/paging/pagedmem.c | 12 ++++++------ csrc/paging/qadmpage.c | 15 ++++++++------- csrc/pf_inner.c | 18 +++++++++--------- csrc/pf_words.c | 2 +- csrc/posix/pf_io_posix.c | 2 +- 7 files changed, 43 insertions(+), 42 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index 23dcd2d..968e578 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -116,8 +116,8 @@ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp); * @param source The data may be in physical or paged memory. * @return destination */ -void *pfCopyFromVirtualMemory(uint8_t *destination, - vm_address_t source, +void *pfCopyFromVirtualMemory(void *destination, + vm_address_t source, size_t numBytes); /* Serial Memory Access @@ -153,7 +153,7 @@ void pfFreePagedMemory(vm_address_t p); * @param micros if zero then issue an async transfer, else timeout in micros * @return number of bytes read or 0 if timed out */ -int pfReadPagedMemory(uint8_t *destination, +size_t pfReadPagedMemory(void *destination, paging_address_t source, size_t numBytes, int micros); @@ -169,8 +169,8 @@ int pfWaitAsyncPagedMemoryAccess(int micros); * @param micros if zero then issue an async transfer, else timeout in micros * @return number of bytes written or 0 if timed out */ -int pfWritePagedMemory(paging_address_t destination, - uint8_t *source, +size_t pfWritePagedMemory(paging_address_t destination, + void *source, size_t numBytes, int micros); diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index ea7f5c6..b8d0550 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -102,7 +102,7 @@ const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, cell_t numBytes) { } uint8_t *pfLockMemoryReadWrite(vm_address_t vp, cell_t numBytes) { - return ((uint8_t *)(pfLockMemoryInternal(vp, numBytes, 1))); + return pfLockMemoryInternal(vp, numBytes, 1); } int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { @@ -144,7 +144,7 @@ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { uint8_t pfFetchVirtualU8(uint8_t *address) { uint8_t value; if (pfIsAddressInPagedMemory(address)) { - pfReadPagedMemory(&value, address, sizeof(uint8_t), DP_TIMEOUT_MICROS); + pfReadPagedMemory(&value, (paging_address_t) address, sizeof(uint8_t), DP_TIMEOUT_MICROS); return value; } else { return (*((uint8_t *)(address))); @@ -154,7 +154,7 @@ uint8_t pfFetchVirtualU8(uint8_t *address) { uint16_t pfFetchVirtualU16(uint16_t *address) { uint16_t value; if (pfIsAddressInPagedMemory(address)) { - pfReadPagedMemory(&value, address, sizeof(uint16_t), DP_TIMEOUT_MICROS); + pfReadPagedMemory(&value, (paging_address_t) address, sizeof(uint16_t), DP_TIMEOUT_MICROS); return value; } else { return (*((uint16_t *)(address))); @@ -163,7 +163,7 @@ uint16_t pfFetchVirtualU16(uint16_t *address) { cell_t pfFetchVirtualCell(cell_t *address) { cell_t value; if (pfIsAddressInPagedMemory(address)) { - pfReadPagedMemory(&value, address, sizeof(cell_t), DP_TIMEOUT_MICROS); + pfReadPagedMemory(&value, (paging_address_t) address, sizeof(cell_t), DP_TIMEOUT_MICROS); return value; } else { return (*((cell_t *)(address))); @@ -172,7 +172,7 @@ cell_t pfFetchVirtualCell(cell_t *address) { PF_FLOAT pfFetchVirtualFloat(PF_FLOAT *address) { PF_FLOAT value; if (pfIsAddressInPagedMemory(address)) { - pfReadPagedMemory(&value, address, sizeof(PF_FLOAT), DP_TIMEOUT_MICROS); + pfReadPagedMemory(&value, (paging_address_t) address, sizeof(PF_FLOAT), DP_TIMEOUT_MICROS); return value; } else { return (*((PF_FLOAT *)(address))); @@ -181,7 +181,7 @@ PF_FLOAT pfFetchVirtualFloat(PF_FLOAT *address) { void pfStoreVirtualU8(uint8_t *address, uint8_t value) { if (pfIsAddressInPagedMemory(address)) { - pfWritePagedMemory(address, &value, sizeof(uint8_t), DP_TIMEOUT_MICROS); + pfWritePagedMemory((paging_address_t) address, &value, sizeof(uint8_t), DP_TIMEOUT_MICROS); } else { *address = value; } @@ -189,31 +189,31 @@ void pfStoreVirtualU8(uint8_t *address, uint8_t value) { void pfStoreVirtualU16(uint16_t *address, uint16_t value) { if (pfIsAddressInPagedMemory(address)) { - pfWritePagedMemory(address, &value, sizeof(uint16_t), DP_TIMEOUT_MICROS); + pfWritePagedMemory((paging_address_t) address, &value, sizeof(uint16_t), DP_TIMEOUT_MICROS); } else { *address = value; } } void pfStoreVirtualCell(cell_t *address, cell_t value) { if (pfIsAddressInPagedMemory(address)) { - pfWritePagedMemory(address, &value, sizeof(cell_t), DP_TIMEOUT_MICROS); + pfWritePagedMemory((paging_address_t) address, &value, sizeof(cell_t), DP_TIMEOUT_MICROS); } else { *address = value; } } void pfStoreVirtualFloat(PF_FLOAT *address, PF_FLOAT value) { if (pfIsAddressInPagedMemory(address)) { - pfWritePagedMemory(address, &value, sizeof(PF_FLOAT), DP_TIMEOUT_MICROS); + pfWritePagedMemory((paging_address_t) address, &value, sizeof(PF_FLOAT), DP_TIMEOUT_MICROS); } else { *address = value; } } -void *pfCopyFromVirtualMemory(uint8_t *destination, - vm_address_t source, - size_t numBytes) { +void *pfCopyFromVirtualMemory(void *destination, + vm_address_t source, + size_t numBytes) { if (pfIsAddressInPagedMemory(source)) { - pfReadPagedMemory(destination, source, numBytes, DP_TIMEOUT_MICROS); /* TODO check result */ + pfReadPagedMemory(destination, (paging_address_t) source, numBytes, DP_TIMEOUT_MICROS); /* TODO check result */ return destination; } else { return pfCopyMemory(destination, source, numBytes); diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index bb03b61..74ddea9 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -67,7 +67,7 @@ vm_address_t pfAllocatePagedMemory(const ucell_t numBytes) { void pfFreePagedMemory(vm_address_t p) {} -int pfReadPagedMemory(uint8_t *destination, +size_t pfReadPagedMemory(void *destination, vm_address_t source, size_t numBytes, int async) { @@ -77,7 +77,7 @@ int pfReadPagedMemory(uint8_t *destination, } /* TODO check upper boundary */ vm_address_t vaddr = PF_DP_UNMUNGE(source); - pfCopyMemory(destination, vaddr, numBytes); + pfCopyMemory((uint8_t *)destination, vaddr, numBytes); return numBytes; } @@ -85,8 +85,8 @@ int pfWaitPendingVirtualRead(void) { return 0; } -int pfWritePagedMemory(vm_address_t destination, - uint8_t *source, +size_t pfWritePagedMemory(paging_address_t destination, + void *source, size_t numBytes, int async) { if (!pfIsAddressInPagedMemory(destination)) { @@ -94,7 +94,7 @@ int pfWritePagedMemory(vm_address_t destination, return 0; } /* TODO check upper boundary */ - vm_address_t vaddr = PF_DP_UNMUNGE(destination); - pfCopyMemory(vaddr, source, numBytes); + void *pAddr = PF_DP_UNMUNGE(destination); + pfCopyMemory(pAddr, source, numBytes); return numBytes; } diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index 715d0bc..7e76ed1 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -141,7 +141,7 @@ static int pfQaTestRegionLock(void) { #define PF_DP_TEST_PATHNAME "/tmp/pf_scratch_file" -static cell_t pfQaTestCreateFile(int numBytes) { +static cell_t pfQaTestCreateFile(size_t numBytes) { uint8_t buffer[100]; int i; FileStream *fid = sdOpenFile(PF_DP_TEST_PATHNAME, "wb"); @@ -153,10 +153,11 @@ static cell_t pfQaTestCreateFile(int numBytes) { buffer[i] = i; } while (numBytes > 0) { - int bytesToWrite = (numBytes < sizeof(buffer)) ? numBytes : sizeof(buffer); - int itemsWritten = sdWriteFile(buffer, 1, bytesToWrite, fid); + size_t bytesToWrite = (numBytes < sizeof(buffer)) + ? numBytes : sizeof(buffer); + size_t itemsWritten = sdWriteFile(buffer, 1, bytesToWrite, fid); if (itemsWritten != bytesToWrite) { - printf("ERROR: writing file failed %d\n", itemsWritten); + printf("ERROR: writing file failed %d\n", (int)itemsWritten); return -1; } numBytes -= bytesToWrite; @@ -165,15 +166,15 @@ static cell_t pfQaTestCreateFile(int numBytes) { return 0; } -static int pfQaTestReadFileStandard(int numBytes) { +static int pfQaTestReadFileStandard(size_t numBytes) { uint8_t buffer[100]; int i; printf("pfQaDemandPaging : pfQaCheckReadFile\n"); FileStream *fid = sdOpenFile(PF_DP_TEST_PATHNAME, "rb"); ASSERT_NE(NULL, fid); while (numBytes > 0) { - int bytesToRead = (numBytes < sizeof(buffer)) ? numBytes : sizeof(buffer); - cell_t result = sdReadFile(buffer, 1, (int32_t) bytesToRead, fid); /* use stdio */ + size_t bytesToRead = (numBytes < sizeof(buffer)) ? numBytes : sizeof(buffer); + size_t result = sdReadFile(buffer, 1, (int32_t) bytesToRead, fid); /* use stdio */ ASSERT_EQ(bytesToRead, result); for (i = 0; i < bytesToRead; i++) { ASSERT_EQ((i % 100), buffer[i]); diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index e570db0..c44b089 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -449,7 +449,7 @@ DBUG(("pfCatch: Token = 0x%x\n", Token )); Temp = M_POP; CharPtr = (char *) pfLockMemoryReadWrite((vm_address_t) Temp, TOS); TOS = ioAccept( CharPtr, TOS ); - pfUnlockMemory((vm_address_t) Temp, CharPtr); + pfUnlockMemory((vm_address_t) Temp, (const uint8_t *)CharPtr); endcase; #ifndef PF_NO_SHELL @@ -593,7 +593,7 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); Temp = DP_FETCH_U8(vp); /* length */ CharPtr = (char *) pfLockMemoryReadOnly(vp, Temp + 1); CreateDicEntry( TOS, CharPtr, 0 ); - pfUnlockMemory(vp, CharPtr); + pfUnlockMemory(vp, (const uint8_t *) CharPtr); M_DROP; } endcase; @@ -610,8 +610,8 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); s2 = (const char *) pfLockMemoryReadOnly(v2, TOS); s1 = (const char *) pfLockMemoryReadOnly(v1, len1); TOS = ffCompare( s1, len1, s2, TOS ); - pfUnlockMemory(v1, s1); - pfUnlockMemory(v2, s2); + pfUnlockMemory(v1, (const uint8_t *) s1); + pfUnlockMemory(v2, (const uint8_t *) s2); } endcase; @@ -919,8 +919,8 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = M_POP; CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) Scratch, TOS); DumpMemory( (char *) CharPtr, TOS ); - printf("Call pfUnlockMemory from ID_DUMP\n"); - pfUnlockMemory((vm_address_t) Scratch, CharPtr); + /* TODO handle dump of larger virtual areas. */ + pfUnlockMemory((vm_address_t) Scratch, (const uint8_t *) CharPtr); M_DROP; endcase; @@ -991,12 +991,12 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_FILE_CREATE: /* ( c-addr u fam -- fid ior ) */ Scratch = M_POP; /* u */ - CharPtr = (char *) M_POP; /* caddr */ if( Scratch < TIB_SIZE-2 ) { + vm_address_t vName = (vm_address_t) M_POP; /* caddr */ const char *famText = pfSelectFileModeCreate( TOS ); /* Build NUL terminated name string. */ - pfCopyFromVirtualMemory(gScratch, CharPtr, Scratch); + pfCopyFromVirtualMemory(gScratch, vName, Scratch); gScratch[Scratch] = '\0'; DBUG(("Create file = %s with famTxt %s\n", gScratch, famText )); FileID = sdOpenFile( gScratch, famText ); @@ -1006,6 +1006,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); else { ERR("Filename too large for name buffer.\n"); + M_POP; M_PUSH( 0 ); TOS = -2; } @@ -1763,7 +1764,6 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Temp = M_POP; /* addr */ char *lockedMemory = (char *) pfLockMemoryReadOnly((vm_address_t) Temp, Scratch); TOS = ffSkip( lockedMemory, Scratch, (char) TOS, &CharPtr ); - printf("Call pfUnlockMemory from ID_SKIP\n"); pfUnlockMemory((vm_address_t) Temp, lockedMemory); M_PUSH((cell_t) (Temp + (Scratch - TOS))); /* offset address by (cnt - cnt') */ } diff --git a/csrc/pf_words.c b/csrc/pf_words.c index a1bd44e..4843ca8 100644 --- a/csrc/pf_words.c +++ b/csrc/pf_words.c @@ -298,7 +298,7 @@ cell_t ffWriteFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream pfUnlockMemory(vp, buffer); /* writes to backing storage */ if (numWritten < bytesToWrite) { - numBytes = 0; // no more data left + numBytes = 0; /* no more data left */ } else { numBytes -= bytesToWrite; } diff --git a/csrc/posix/pf_io_posix.c b/csrc/posix/pf_io_posix.c index 526726f..b4c518d 100644 --- a/csrc/posix/pf_io_posix.c +++ b/csrc/posix/pf_io_posix.c @@ -157,7 +157,7 @@ cell_t sdSleepMillis(cell_t msec) while (micros > 0) { napTime = (micros > kMaxMicros) ? kMaxMicros : micros; - if (usleep(napTime)) + if (usleep((useconds_t)napTime)) { perror("sdSleepMillis: usleep failed"); return -1; From 877d75a8f596c774567d00fee7177ea815b195f6 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 5 May 2026 14:13:05 -0700 Subject: [PATCH 13/48] more type cleanup --- csrc/paging/dmpaging.h | 2 +- csrc/paging/lockpage.c | 16 ++++++++-------- csrc/paging/pagedmem.c | 2 +- csrc/paging/qadmpage.c | 4 ++-- csrc/pf_inner.c | 37 ++++++++++++++++++++----------------- csrc/pf_main.c | 2 +- csrc/pf_save.c | 2 +- csrc/pf_save.h | 3 ++- csrc/pf_words.c | 11 +++++------ csrc/pf_words.h | 4 ++-- 10 files changed, 43 insertions(+), 40 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index 968e578..bf22c2b 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -129,7 +129,7 @@ void *pfCopyFromVirtualMemory(void *destination, /** Is the given address pointing to paged memory? * @return 1 if in paged memory, else 0 */ -int pfIsAddressInPagedMemory(void *p); +int pfIsAddressInPagedMemory(vm_address_t p); /** * Reset the memory allocator. diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index b8d0550..9013d0b 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -143,7 +143,7 @@ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { uint8_t pfFetchVirtualU8(uint8_t *address) { uint8_t value; - if (pfIsAddressInPagedMemory(address)) { + if (pfIsAddressInPagedMemory((vm_address_t)address)) { pfReadPagedMemory(&value, (paging_address_t) address, sizeof(uint8_t), DP_TIMEOUT_MICROS); return value; } else { @@ -153,7 +153,7 @@ uint8_t pfFetchVirtualU8(uint8_t *address) { } uint16_t pfFetchVirtualU16(uint16_t *address) { uint16_t value; - if (pfIsAddressInPagedMemory(address)) { + if (pfIsAddressInPagedMemory((vm_address_t)address)) { pfReadPagedMemory(&value, (paging_address_t) address, sizeof(uint16_t), DP_TIMEOUT_MICROS); return value; } else { @@ -162,7 +162,7 @@ uint16_t pfFetchVirtualU16(uint16_t *address) { } cell_t pfFetchVirtualCell(cell_t *address) { cell_t value; - if (pfIsAddressInPagedMemory(address)) { + if (pfIsAddressInPagedMemory((vm_address_t)address)) { pfReadPagedMemory(&value, (paging_address_t) address, sizeof(cell_t), DP_TIMEOUT_MICROS); return value; } else { @@ -171,7 +171,7 @@ cell_t pfFetchVirtualCell(cell_t *address) { } PF_FLOAT pfFetchVirtualFloat(PF_FLOAT *address) { PF_FLOAT value; - if (pfIsAddressInPagedMemory(address)) { + if (pfIsAddressInPagedMemory((vm_address_t)address)) { pfReadPagedMemory(&value, (paging_address_t) address, sizeof(PF_FLOAT), DP_TIMEOUT_MICROS); return value; } else { @@ -180,7 +180,7 @@ PF_FLOAT pfFetchVirtualFloat(PF_FLOAT *address) { } void pfStoreVirtualU8(uint8_t *address, uint8_t value) { - if (pfIsAddressInPagedMemory(address)) { + if (pfIsAddressInPagedMemory((vm_address_t)address)) { pfWritePagedMemory((paging_address_t) address, &value, sizeof(uint8_t), DP_TIMEOUT_MICROS); } else { *address = value; @@ -188,21 +188,21 @@ void pfStoreVirtualU8(uint8_t *address, uint8_t value) { } void pfStoreVirtualU16(uint16_t *address, uint16_t value) { - if (pfIsAddressInPagedMemory(address)) { + if (pfIsAddressInPagedMemory((vm_address_t)address)) { pfWritePagedMemory((paging_address_t) address, &value, sizeof(uint16_t), DP_TIMEOUT_MICROS); } else { *address = value; } } void pfStoreVirtualCell(cell_t *address, cell_t value) { - if (pfIsAddressInPagedMemory(address)) { + if (pfIsAddressInPagedMemory((vm_address_t)address)) { pfWritePagedMemory((paging_address_t) address, &value, sizeof(cell_t), DP_TIMEOUT_MICROS); } else { *address = value; } } void pfStoreVirtualFloat(PF_FLOAT *address, PF_FLOAT value) { - if (pfIsAddressInPagedMemory(address)) { + if (pfIsAddressInPagedMemory((vm_address_t)address)) { pfWritePagedMemory((paging_address_t) address, &value, sizeof(PF_FLOAT), DP_TIMEOUT_MICROS); } else { *address = value; diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index 74ddea9..f96fff1 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -46,7 +46,7 @@ void pfResetPagedMemory(void) { sDpNextAvailable = 0; } -int pfIsAddressInPagedMemory(void * p) { +int pfIsAddressInPagedMemory(vm_address_t p) { vm_address_t vaddr = PF_DP_UNMUNGE(p); cell_t offset = (uint8_t *)vaddr - sFakeSerialRAM; return (offset >= 0) && (offset < PF_DP_AVAILABLE_SPACE); diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index 7e76ed1..61d55ca 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -35,8 +35,8 @@ static int pfQaTestAllocate(void) { ASSERT_EQ((vm2 - vm1), DP_ALIGNMENT_SIZE); int x = 0; - ASSERT_EQ(pfIsAddressInPagedMemory(&x), 0); - ASSERT_EQ(pfIsAddressInPagedMemory((void *)(vm2 + 5)), 1); + ASSERT_EQ(pfIsAddressInPagedMemory((vm_address_t)&x), 0); + ASSERT_EQ(pfIsAddressInPagedMemory((vm_address_t)(vm2 + 5)), 1); return 0; error: return 1; diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index c44b089..c03e523 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1013,11 +1013,11 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); endcase; case ID_FILE_DELETE: /* ( c-addr u -- ior ) */ - CharPtr = (char *)M_POP; /* caddr */ if( TOS < TIB_SIZE-2 ) { + vm_address_t vName = (vm_address_t) M_POP; /* caddr */ /* Build NUL terminated name string. */ - pfCopyFromVirtualMemory(gScratch, CharPtr, TOS); + pfCopyFromVirtualMemory(gScratch, vName, TOS); gScratch[TOS] = '\0'; DBUG(("Delete file = %s\n", gScratch )); TOS = sdDeleteFile( gScratch ); @@ -1025,18 +1025,19 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); else { ERR("Filename too large for name buffer.\n"); + M_POP; TOS = -2; } endcase; case ID_FILE_OPEN: /* ( c-addr u fam -- fid ior ) */ Scratch = M_POP; /* u */ - CharPtr = (char *) M_POP; /* caddr */ if( Scratch < TIB_SIZE-2 ) { const char *famText = pfSelectFileModeOpen( TOS ); + vm_address_t vName = (vm_address_t) M_POP; /* caddr */ /* Build NUL terminated name string. */ - pfCopyFromVirtualMemory(gScratch, CharPtr, Scratch); + pfCopyFromVirtualMemory(gScratch, vName, Scratch); gScratch[Scratch] = '\0'; DBUG(("Open file = %s\n", gScratch )); FileID = sdOpenFile( gScratch, famText ); @@ -1047,6 +1048,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); else { ERR("Filename too large for name buffer.\n"); + M_POP; M_PUSH( 0 ); TOS = -2; } @@ -1060,7 +1062,8 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); FileID = (FileStream *) TOS; Scratch = M_POP; CharPtr = (char *) M_POP; - Temp = ffReadFile( CharPtr, 1, Scratch, FileID ); + /* warning, only 32-bit nItems */ + Temp = ffReadFile( CharPtr, 1, (int32_t) Scratch, FileID ); /* TODO check feof() or ferror() */ M_PUSH(Temp); TOS = 0; @@ -1100,7 +1103,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); FileID = (FileStream *) TOS; Scratch = M_POP; CharPtr = (char *) M_POP; - Temp = ffWriteFile( CharPtr, 1, Scratch, FileID ); + Temp = ffWriteFile( CharPtr, 1, (int32_t)Scratch, FileID ); TOS = (Temp != Scratch) ? -3 : 0; endcase; @@ -1179,12 +1182,12 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); * Then we will have the name lengths. */ vm_address_t vNewName = (vm_address_t)TOS; - char *pNewName = pfLockMemoryReadOnly(vNewName, DP_MAX_REGION_SIZE); + char *pNewName = (char *)pfLockMemoryReadOnly(vNewName, DP_MAX_REGION_SIZE); vm_address_t vOldName = (vm_address_t)M_POP; - char *pOldName = pfLockMemoryReadOnly(vOldName, DP_MAX_REGION_SIZE); + char *pOldName = (char *)pfLockMemoryReadOnly(vOldName, DP_MAX_REGION_SIZE); TOS = sdRenameFile( pOldName, pNewName ); - pfUnlockMemory(vOldName, pOldName); - pfUnlockMemory(vNewName, pNewName); + pfUnlockMemory(vOldName, (const uint8_t *)pOldName); + pfUnlockMemory(vNewName, (const uint8_t *)pNewName); } endcase; @@ -1220,7 +1223,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = DP_FETCH_U8(vaddr) + 1; /* length including count */ CharPtr = (char *) pfLockMemoryReadOnly(vaddr, Scratch); TOS = ffFind( (char *) CharPtr, (ExecToken *) &Temp ); - pfUnlockMemory(vaddr, CharPtr); + pfUnlockMemory(vaddr, (const uint8_t *)CharPtr); if (TOS != 0) { M_PUSH( Temp ); /* xt */ } else { @@ -1236,7 +1239,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = DP_FETCH_U8(name) + 1; /* length including count */ CharPtr = (char *) pfLockMemoryReadOnly(name, Scratch); TOS = ffFindNFA( (const ForthString *) CharPtr, (const ForthString **) &nfa ); - pfUnlockMemory(name, CharPtr); + pfUnlockMemory(name, (const uint8_t *)CharPtr); if (TOS != 0) { M_PUSH( nfa ); } else { @@ -1288,7 +1291,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = MASK_NAME_SIZE & DP_FETCH_U8((vm_address_t) TOS); /* Length of string. */ CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) TOS, Scratch); TOS = (cell_t) ffNumberQ( (char *) CharPtr, &Temp ); - pfUnlockMemory((vm_address_t) TOS, CharPtr); + pfUnlockMemory((vm_address_t) TOS, (const uint8_t *) CharPtr); if( TOS == NUM_TYPE_SINGLE) { M_PUSH( Temp ); /* Push single number */ @@ -1703,7 +1706,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); CharPtr = (char *) pfLockMemoryReadOnly(vName, Temp + 1); ForthStringToC( gScratch, CharPtr, sizeof(gScratch) ); TOS = ffSaveForth( gScratch, EntryPoint, NameSize, CodeSize ); - pfUnlockMemory(vName, CharPtr); + pfUnlockMemory(vName, (const uint8_t *) CharPtr); } endcase; #endif @@ -1744,7 +1747,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Temp = M_POP; /* virtual address */ char *lockedMemory = (char *) pfLockMemoryReadOnly((vm_address_t) Temp, Scratch); TOS = ffScan( lockedMemory, Scratch, (char) TOS, &CharPtr ); - pfUnlockMemory((vm_address_t) Temp, lockedMemory); + pfUnlockMemory((vm_address_t) Temp, (const uint8_t *) lockedMemory); M_PUSH((cell_t) (Temp + (Scratch - TOS))); /* offset address by (cnt - cnt') */ } endcase; @@ -1764,7 +1767,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Temp = M_POP; /* addr */ char *lockedMemory = (char *) pfLockMemoryReadOnly((vm_address_t) Temp, Scratch); TOS = ffSkip( lockedMemory, Scratch, (char) TOS, &CharPtr ); - pfUnlockMemory((vm_address_t) Temp, lockedMemory); + pfUnlockMemory((vm_address_t) Temp, (const uint8_t *) lockedMemory); M_PUSH((cell_t) (Temp + (Scratch - TOS))); /* offset address by (cnt - cnt') */ } endcase; @@ -1860,7 +1863,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = M_POP; /* addr */ CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) Scratch, TOS); ioType( (char *) CharPtr, TOS ); - pfUnlockMemory((vm_address_t) Scratch, CharPtr); + pfUnlockMemory((vm_address_t) Scratch, (const uint8_t *) CharPtr); M_DROP; endcase; diff --git a/csrc/pf_main.c b/csrc/pf_main.c index eda9882..95c7724 100644 --- a/csrc/pf_main.c +++ b/csrc/pf_main.c @@ -58,7 +58,7 @@ int main( void ) } #else -int pfQaDemandPaging(); +int pfQaDemandPaging(void); int main( int argc, char **argv ) { diff --git a/csrc/pf_save.c b/csrc/pf_save.c index 3472eda..da9c6e5 100644 --- a/csrc/pf_save.c +++ b/csrc/pf_save.c @@ -367,7 +367,7 @@ static cell_t WriteChunkToFile( FileStream *fid, cell_t ID, char *Data, int32_t if( Write32ToFile( fid, (uint32_t)EvenNumW ) < 0 ) goto error; /* use demand paging just in case */ - numw = ffWriteFile( Data, 1, EvenNumW, fid ); + numw = ffWriteFile( Data, 1, (int32_t)EvenNumW, fid ); if( numw != EvenNumW ) goto error; return 0; error: diff --git a/csrc/pf_save.h b/csrc/pf_save.h index 098cd8e..05e4a18 100644 --- a/csrc/pf_save.h +++ b/csrc/pf_save.h @@ -27,7 +27,8 @@ typedef struct DictionaryInfoChunk { -/* All fields are stored in BIG ENDIAN format for consistency in data files. +/* Do NOT change this structure because it is stored in files. + * All fields are stored in BIG ENDIAN format for consistency in data files. * All fields must be the same size for easy endian conversion. * All fields must be 32 bit for file compatibility with older versions. */ diff --git a/csrc/pf_words.c b/csrc/pf_words.c index 4843ca8..ec5a493 100644 --- a/csrc/pf_words.c +++ b/csrc/pf_words.c @@ -252,9 +252,9 @@ char * ffLWord( char c ) return Word( c, FALSE ); } -cell_t ffReadFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream ) +size_t ffReadFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ) { - cell_t numBytes = Size * nItems; + size_t numBytes = Size * nItems; if (numBytes == 0) { return 0; } else if (pfIsAddressInPagedMemory(ptr)) { @@ -268,7 +268,7 @@ cell_t ffReadFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream cell_t numRead = sdReadFile(buffer, 1, bytesToRead, Stream); pfUnlockMemory(vp, buffer); /* writes to backing storage */ if (numRead < bytesToRead) { - numBytes = 0; // no more data left + numBytes = 0; /* no more data left */ } else { numBytes -= bytesToRead; } @@ -281,15 +281,14 @@ cell_t ffReadFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream } } -cell_t ffWriteFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream ) +size_t ffWriteFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ) { - cell_t numBytes = Size * nItems; + size_t numBytes = Size * nItems; if (numBytes == 0) { return 0; } else if (pfIsAddressInPagedMemory(ptr)) { /* Write file in blocks that will fit in locked regions. */ vm_address_t vp = (vm_address_t)ptr; - cell_t numBytes = Size * nItems; cell_t bytesWritten = 0; while (numBytes > 0) { cell_t bytesToWrite = (numBytes < DP_MAX_REGION_SIZE) ? numBytes : DP_MAX_REGION_SIZE; diff --git a/csrc/pf_words.h b/csrc/pf_words.h index 9d916e5..5d255f9 100644 --- a/csrc/pf_words.h +++ b/csrc/pf_words.h @@ -32,8 +32,8 @@ void ffDotS( void ); cell_t ffSkip( char *AddrIn, cell_t Cnt, char c, char **AddrOut ); cell_t ffScan( char *AddrIn, cell_t Cnt, char c, char **AddrOut ); -cell_t ffReadFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream ); -cell_t ffWriteFile( void *ptr, cell_t Size, int32_t nItems, FileStream * Stream ); +size_t ffReadFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ); +size_t ffWriteFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ); #ifdef __cplusplus } From ccb9e8abad98081f2a2cad637135c44fb211fd19 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 5 May 2026 15:04:39 -0700 Subject: [PATCH 14/48] fix for loop indices --- csrc/paging/lockpage.c | 6 ++++-- csrc/pf_inner.c | 11 ++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index 9013d0b..5ca2864 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -60,20 +60,22 @@ struct RegionControlBlock { struct RegionControlBlock sLockedRegions[DP_MAX_REGIONS]; void pfResetLockedMemory(void) { + int i; pfSetMemory(sLockedRegions, 0, sizeof(sLockedRegions)); - for (int i = 0; i < DP_MAX_REGIONS; i++) { + for (i = 0; i < DP_MAX_REGIONS; i++) { struct RegionControlBlock *region = &sLockedRegions[i]; region->magic = DP_MAGIC; } } uint8_t *pfLockMemoryInternal(vm_address_t vp, cell_t numBytes, int writable) { + int i; struct RegionControlBlock *region = NULL; if (pfIsAddressInPagedMemory(vp) == 0) { /* not in paged memory so locking not needed */ return (uint8_t *) vp; } /* Find an empty region. */ - for (int i = 0; i < DP_MAX_REGIONS; i++) { + for (i = 0; i < DP_MAX_REGIONS; i++) { if (sLockedRegions[i].locked == 0) { region = &sLockedRegions[i]; break; diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index c03e523..9f25799 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1859,13 +1859,14 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_TIMES: BINARY_OP( * ); endcase; - case ID_TYPE: + case ID_TYPE: { Scratch = M_POP; /* addr */ - CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) Scratch, TOS); - ioType( (char *) CharPtr, TOS ); - pfUnlockMemory((vm_address_t) Scratch, (const uint8_t *) CharPtr); + const char * pText = (const char *) pfLockMemoryReadOnly((vm_address_t) Scratch, TOS); + ioType(pText, TOS); + pfUnlockMemory((vm_address_t) Scratch, (const uint8_t *) pText); M_DROP; - endcase; + } + endcase; case ID_TO_R: M_R_PUSH( TOS ); From af844a0efbfb333e1dd8ade5c643b28f03b95efe Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 5 May 2026 15:29:23 -0700 Subject: [PATCH 15/48] use PD_DEMAND_PAGING to remove code --- csrc/paging/dmpaging.h | 9 ++++++--- csrc/paging/lockpage.c | 20 +++++++++++++------- csrc/paging/pagedmem.c | 4 ++++ csrc/paging/qadmpage.c | 4 ++++ csrc/pf_main.c | 5 ++++- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index bf22c2b..35a63e5 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -26,7 +26,7 @@ extern "C" { #endif #ifndef PF_DEMAND_PAGING -#define PF_DEMAND_PAGING 1 +#define PF_DEMAND_PAGING 0 #endif typedef uint8_t *vm_address_t; /** an address that may be in physical or paged memory */ @@ -124,13 +124,15 @@ void *pfCopyFromVirtualMemory(void *destination, * A demand paging simulator is provided for testing the framework on a host. * The actual demand paging interface must be provided by the user. */ -#define DP_ALIGNMENT_SIZE (16) /** Is the given address pointing to paged memory? * @return 1 if in paged memory, else 0 */ int pfIsAddressInPagedMemory(vm_address_t p); +#if PF_DEMAND_PAGING +#define DP_ALIGNMENT_SIZE (16) + /** * Reset the memory allocator. * This may or may not clear the memory. @@ -174,9 +176,10 @@ size_t pfWritePagedMemory(paging_address_t destination, size_t numBytes, int micros); +#endif /* PF_DEMAND_PAGING */ + #ifdef __cplusplus } #endif - #endif /* _pf_dmpaging_h */ diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index 5ca2864..0cad64a 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -21,7 +21,7 @@ #include "../pf_all.h" #include "dmpaging.h" -#ifndef PF_DEMAND_PAGING +#if PF_DEMAND_PAGING == 0 void pfResetLockedMemory(void) { } @@ -34,15 +34,21 @@ uint8_t *pfLockMemoryReadWrite(vm_address_t vp, cell_t numBytes) { return ((uint8_t *)(vp)); } -void pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { +int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { + return 0; +} + +void *pfCopyFromVirtualMemory(void *destination, + vm_address_t source, + size_t numBytes) { + return pfCopyMemory(destination, source, numBytes); } -vm_address_t pfConvertPhysicalToVirtual(const uint8_t *p) { - return (vm_address_t) p; +int pfIsAddressInPagedMemory(vm_address_t p) { + return FALSE; } -void pfUnlockMemory(vm_address_t vp, const uint8_t *pp); -#else +#else /* PF_DEMAND_PAGING */ #define DP_MAGIC (0x5A9E) @@ -222,5 +228,5 @@ void *pfCopyFromVirtualMemory(void *destination, } } -#endif +#endif /* PF_DEMAND_PAGING */ diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index f96fff1..01cf87b 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -24,6 +24,8 @@ #include "../pf_all.h" #include "dmpaging.h" +#if PF_DEMAND_PAGING + #ifndef PF_DP_AVAILABLE_SPACE #define PF_DP_AVAILABLE_SPACE (512*1024) #endif @@ -98,3 +100,5 @@ size_t pfWritePagedMemory(paging_address_t destination, pfCopyMemory(pAddr, source, numBytes); return numBytes; } + +#endif /* PF_DEMAND_PAGING */ diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index 61d55ca..75a11d3 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -22,6 +22,8 @@ #include "../pf_all.h" #include "unittest.h" +#if PF_DEMAND_PAGING + PFQA_INSTANTIATE_GLOBALS; static int pfQaTestAllocate(void) { @@ -254,3 +256,5 @@ int pfQaDemandPaging(void) { PFQA_PRINT_RESULT; return PFQA_EXIT_RESULT; } + +#endif /* PF_DEMAND_PAGING */ diff --git a/csrc/pf_main.c b/csrc/pf_main.c index 95c7724..46de136 100644 --- a/csrc/pf_main.c +++ b/csrc/pf_main.c @@ -142,7 +142,10 @@ int main( int argc, char **argv ) } #endif -/* Result = pfQaDemandPaging(); FIXME */ +#if PF_DEMAND_PAGING + Result = pfQaDemandPaging(); /* FIXME move to standalone qa test */ + if (Result != 0) goto on_error; +#endif Result = pfDoForth( DicName, SourceName, IfInit); From dab45b7a7149433fb1104197f4e73d505a7296ba Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 5 May 2026 15:35:59 -0700 Subject: [PATCH 16/48] try turning off the MUNGE mask --- csrc/paging/dmpaging.h | 2 +- csrc/paging/pagedmem.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index 35a63e5..fbaee56 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -26,7 +26,7 @@ extern "C" { #endif #ifndef PF_DEMAND_PAGING -#define PF_DEMAND_PAGING 0 +#define PF_DEMAND_PAGING 1 #endif typedef uint8_t *vm_address_t; /** an address that may be in physical or paged memory */ diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index 01cf87b..6d5d994 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -34,7 +34,9 @@ static uint8_t sFakeSerialRAM[PF_DP_AVAILABLE_SPACE]; static cell_t sDpNextAvailable = 0; #define DP_ALIGNMENT_MASK (DP_ALIGNMENT_SIZE - 1) -#if (PF_64BIT) +#if 1 +#define PF_DP_MUNGE_KEY (0) +#elif (PF_64BIT) #define PF_DP_MUNGE_KEY (0x005A000000000000) #elif (PF_32BIT) #define PF_DP_MUNGE_KEY (0x5A000000) From f7e00b093c680e0c1b79c7125bfff01eea6026de Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 5 May 2026 16:04:06 -0700 Subject: [PATCH 17/48] try to fix AddressSanitizer error --- csrc/pf_inner.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 9f25799..dc8a8ea 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -604,12 +604,13 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); const char *s1, *s2; vm_address_t v1, v2; cell_t len1; + cell_t len2 = TOS; v2 = (vm_address_t) M_POP; len1 = M_POP; v1 = (vm_address_t) M_POP; - s2 = (const char *) pfLockMemoryReadOnly(v2, TOS); + s2 = (const char *) pfLockMemoryReadOnly(v2, len2); s1 = (const char *) pfLockMemoryReadOnly(v1, len1); - TOS = ffCompare( s1, len1, s2, TOS ); + TOS = ffCompare( s1, len1, s2, len2 ); pfUnlockMemory(v1, (const uint8_t *) s1); pfUnlockMemory(v2, (const uint8_t *) s2); } @@ -1289,7 +1290,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); ** Only supports single precision for bootstrap. */ Scratch = MASK_NAME_SIZE & DP_FETCH_U8((vm_address_t) TOS); /* Length of string. */ - CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) TOS, Scratch); + CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) TOS, Scratch + 1); TOS = (cell_t) ffNumberQ( (char *) CharPtr, &Temp ); pfUnlockMemory((vm_address_t) TOS, (const uint8_t *) CharPtr); if( TOS == NUM_TYPE_SINGLE) From 902b4015e0815cc5305996e383c6e23908f5f0ed Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 5 May 2026 16:18:29 -0700 Subject: [PATCH 18/48] fix NUMBER? vm address --- csrc/pf_inner.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index dc8a8ea..16cc6aa 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1285,19 +1285,21 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); TOS = (cell_t)CODE_HERE; endcase; - case ID_NUMBERQ_P: /* ( addr -- 0 | n 1 ) */ -/* Convert using number converter in 'C'. -** Only supports single precision for bootstrap. -*/ - Scratch = MASK_NAME_SIZE & DP_FETCH_U8((vm_address_t) TOS); /* Length of string. */ - CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) TOS, Scratch + 1); - TOS = (cell_t) ffNumberQ( (char *) CharPtr, &Temp ); - pfUnlockMemory((vm_address_t) TOS, (const uint8_t *) CharPtr); + case ID_NUMBERQ_P: /* ( addr -- 0 | n 1 ) */ { + /* Convert using number converter in 'C'. + ** Only supports single precision for bootstrap. + */ + vm_address_t vAddr = (vm_address_t) TOS; + Scratch = MASK_NAME_SIZE & DP_FETCH_U8(vAddr); /* Length of string. */ + char *pAddr = (char *) pfLockMemoryReadOnly(vAddr, Scratch + 1); + TOS = (cell_t) ffNumberQ(pAddr, &Temp ); + pfUnlockMemory(vAddr, (const uint8_t *) pAddr); if( TOS == NUM_TYPE_SINGLE) { M_PUSH( Temp ); /* Push single number */ } - endcase; + } + endcase; case ID_I: /* ( -- i , DO LOOP index ) */ PUSH_TOS; @@ -1745,11 +1747,11 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_SCAN: /* ( addr cnt char -- addr' cnt' ) */ { Scratch = M_POP; /* cnt */ - Temp = M_POP; /* virtual address */ - char *lockedMemory = (char *) pfLockMemoryReadOnly((vm_address_t) Temp, Scratch); + vm_address_t vAddr = (vm_address_t)M_POP; + char *lockedMemory = (char *) pfLockMemoryReadOnly(vAddr, Scratch); TOS = ffScan( lockedMemory, Scratch, (char) TOS, &CharPtr ); - pfUnlockMemory((vm_address_t) Temp, (const uint8_t *) lockedMemory); - M_PUSH((cell_t) (Temp + (Scratch - TOS))); /* offset address by (cnt - cnt') */ + pfUnlockMemory(vAddr, (const uint8_t *) lockedMemory); + M_PUSH((cell_t) (vAddr + (Scratch - TOS))); /* offset address by (cnt - cnt') */ } endcase; From 7a9e70d3ce276a0e274c4b2f6e99b6dc94781543 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 5 May 2026 16:44:16 -0700 Subject: [PATCH 19/48] fix C90 warnings --- csrc/paging/dmpaging.h | 24 +++++++++++----------- csrc/paging/lockpage.c | 16 +++++++-------- csrc/paging/pagedmem.c | 4 ++-- csrc/pf_inner.c | 46 ++++++++++++++++++++---------------------- fth/system.fth | 2 +- 5 files changed, 45 insertions(+), 47 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index fbaee56..5c8970f 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -35,10 +35,10 @@ typedef uint8_t *paging_address_t; /** an address that may be in paged memory */ /* Basic memory access macros. */ #if (PF_DEMAND_PAGING == 0) /* Straight memory access. */ -#define DP_FETCH_U8(address) (*((uint8_t *)(address))) -#define DP_FETCH_U16(address) (*((uint16_t *)(address))) -#define DP_FETCH_CELL(address) (*((cell_t *)(address))) -#define DP_FETCH_FLOAT(address) (*((PF_FLOAT *)(address))) +#define DP_FETCH_U8(address) (*((const uint8_t *)(address))) +#define DP_FETCH_U16(address) (*((const uint16_t *)(address))) +#define DP_FETCH_CELL(address) (*((const cell_t *)(address))) +#define DP_FETCH_FLOAT(address) (*((const PF_FLOAT *)(address))) #define DP_STORE_U8(address, value) *((uint8_t *)(address)) = (uint8_t)(value) #define DP_STORE_U16(address, value) *((uint16_t *)(address)) = (uint16_t)(value) @@ -46,10 +46,10 @@ typedef uint8_t *paging_address_t; /** an address that may be in paged memory */ #define DP_STORE_FLOAT(address, value) *((PF_FLOAT *)(address)) = (PF_FLOAT)(value) #else /* Use either physical or paged memory. */ -#define DP_FETCH_U8(address) pfFetchVirtualU8((uint8_t *)(address)) -#define DP_FETCH_U16(address) pfFetchVirtualU16((uint16_t *)(address)) -#define DP_FETCH_CELL(address) pfFetchVirtualCell((cell_t *)(address)) -#define DP_FETCH_FLOAT(address) pfFetchVirtualFloat((PF_FLOAT *)(address)) +#define DP_FETCH_U8(address) pfFetchVirtualU8((const uint8_t *)(address)) +#define DP_FETCH_U16(address) pfFetchVirtualU16((const uint16_t *)(address)) +#define DP_FETCH_CELL(address) pfFetchVirtualCell((const cell_t *)(address)) +#define DP_FETCH_FLOAT(address) pfFetchVirtualFloat((const PF_FLOAT *)(address)) #define DP_STORE_U8(address, value) pfStoreVirtualU8(((uint8_t *)(address)), (uint8_t)(value)) #define DP_STORE_U16(address, value) pfStoreVirtualU16(((uint16_t *)(address)), (uint16_t)(value)) @@ -57,10 +57,10 @@ typedef uint8_t *paging_address_t; /** an address that may be in paged memory */ #define DP_STORE_FLOAT(address, value) pfStoreVirtualFloat(((PF_FLOAT *)(address)), (PF_FLOAT)(value)) #endif -uint8_t pfFetchVirtualU8(uint8_t *address); -uint16_t pfFetchVirtualU16(uint16_t *address); -cell_t pfFetchVirtualCell(cell_t *address); -PF_FLOAT pfFetchVirtualFloat(PF_FLOAT *address); +uint8_t pfFetchVirtualU8(const uint8_t *address); +uint16_t pfFetchVirtualU16(const uint16_t *address); +cell_t pfFetchVirtualCell(const cell_t *address); +PF_FLOAT pfFetchVirtualFloat(const PF_FLOAT *address); void pfStoreVirtualU8(uint8_t *address, uint8_t value); void pfStoreVirtualU16(uint16_t *address, uint16_t value); diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index 0cad64a..f43314e 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -149,41 +149,41 @@ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { return 0; } -uint8_t pfFetchVirtualU8(uint8_t *address) { +uint8_t pfFetchVirtualU8(const uint8_t *address) { uint8_t value; if (pfIsAddressInPagedMemory((vm_address_t)address)) { pfReadPagedMemory(&value, (paging_address_t) address, sizeof(uint8_t), DP_TIMEOUT_MICROS); return value; } else { - return (*((uint8_t *)(address))); + return *address; } } -uint16_t pfFetchVirtualU16(uint16_t *address) { +uint16_t pfFetchVirtualU16(const uint16_t *address) { uint16_t value; if (pfIsAddressInPagedMemory((vm_address_t)address)) { pfReadPagedMemory(&value, (paging_address_t) address, sizeof(uint16_t), DP_TIMEOUT_MICROS); return value; } else { - return (*((uint16_t *)(address))); + return *address; } } -cell_t pfFetchVirtualCell(cell_t *address) { +cell_t pfFetchVirtualCell(const cell_t *address) { cell_t value; if (pfIsAddressInPagedMemory((vm_address_t)address)) { pfReadPagedMemory(&value, (paging_address_t) address, sizeof(cell_t), DP_TIMEOUT_MICROS); return value; } else { - return (*((cell_t *)(address))); + return *address; } } -PF_FLOAT pfFetchVirtualFloat(PF_FLOAT *address) { +PF_FLOAT pfFetchVirtualFloat(const PF_FLOAT *address) { PF_FLOAT value; if (pfIsAddressInPagedMemory((vm_address_t)address)) { pfReadPagedMemory(&value, (paging_address_t) address, sizeof(PF_FLOAT), DP_TIMEOUT_MICROS); return value; } else { - return (*((PF_FLOAT *)(address))); + return *address; } } diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index 6d5d994..b92e1fd 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -34,12 +34,12 @@ static uint8_t sFakeSerialRAM[PF_DP_AVAILABLE_SPACE]; static cell_t sDpNextAvailable = 0; #define DP_ALIGNMENT_MASK (DP_ALIGNMENT_SIZE - 1) -#if 1 +#if 0 #define PF_DP_MUNGE_KEY (0) #elif (PF_64BIT) #define PF_DP_MUNGE_KEY (0x005A000000000000) #elif (PF_32BIT) -#define PF_DP_MUNGE_KEY (0x5A000000) +#define PF_DP_MUNGE_KEY (0x50000000) #endif #define PF_DP_MUNGE(vaddr) ((vm_address_t)(((cell_t)vaddr) ^ PF_DP_MUNGE_KEY)) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 16cc6aa..00a89c1 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -557,10 +557,8 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); CharPtr = (char *) M_POP; /* src */ for( Scratch=0; (ucell_t) Scratch < (ucell_t) TOS ; Scratch++ ) { - uint8_t value = DP_FETCH_U8(CharPtr); - CharPtr++; - DP_STORE_U8(DstPtr, value); - DstPtr++; + uint8_t value = DP_FETCH_U8(CharPtr++); + DP_STORE_U8(DstPtr++, value); } M_DROP; } @@ -569,13 +567,11 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); case ID_CMOVE_UP: /* ( src dst n -- ) */ { register char *DstPtr = ((char *) M_POP) + TOS; /* dst */ - CharPtr = ((char *) M_POP) + TOS;; /* src */ + CharPtr = ((char *) M_POP) + TOS; /* src */ for( Scratch=0; (ucell_t) Scratch < (ucell_t) TOS ; Scratch++ ) { - --CharPtr; - uint8_t value = DP_FETCH_U8(CharPtr); - --DstPtr; - DP_STORE_U8(DstPtr, value); + uint8_t value = DP_FETCH_U8(--CharPtr); + DP_STORE_U8(--DstPtr, value); } M_DROP; } @@ -1007,7 +1003,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); else { ERR("Filename too large for name buffer.\n"); - M_POP; + M_DROP; M_PUSH( 0 ); TOS = -2; } @@ -1026,7 +1022,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); else { ERR("Filename too large for name buffer.\n"); - M_POP; + M_DROP; TOS = -2; } endcase; @@ -1049,7 +1045,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); else { ERR("Filename too large for name buffer.\n"); - M_POP; + M_DROP; M_PUSH( 0 ); TOS = -2; } @@ -1183,9 +1179,9 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); * Then we will have the name lengths. */ vm_address_t vNewName = (vm_address_t)TOS; - char *pNewName = (char *)pfLockMemoryReadOnly(vNewName, DP_MAX_REGION_SIZE); + const char *pNewName = (char *)pfLockMemoryReadOnly(vNewName, DP_MAX_REGION_SIZE); vm_address_t vOldName = (vm_address_t)M_POP; - char *pOldName = (char *)pfLockMemoryReadOnly(vOldName, DP_MAX_REGION_SIZE); + const char *pOldName = (char *)pfLockMemoryReadOnly(vOldName, DP_MAX_REGION_SIZE); TOS = sdRenameFile( pOldName, pNewName ); pfUnlockMemory(vOldName, (const uint8_t *)pOldName); pfUnlockMemory(vNewName, (const uint8_t *)pNewName); @@ -1291,7 +1287,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); */ vm_address_t vAddr = (vm_address_t) TOS; Scratch = MASK_NAME_SIZE & DP_FETCH_U8(vAddr); /* Length of string. */ - char *pAddr = (char *) pfLockMemoryReadOnly(vAddr, Scratch + 1); + const char *pAddr = (const char *) pfLockMemoryReadOnly(vAddr, Scratch + 1); TOS = (cell_t) ffNumberQ(pAddr, &Temp ); pfUnlockMemory(vAddr, (const uint8_t *) pAddr); if( TOS == NUM_TYPE_SINGLE) @@ -1701,15 +1697,16 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_SAVE_FORTH_P: /* ( $name Entry NameSize CodeSize -- err ) */ { cell_t NameSize, CodeSize, EntryPoint; + vm_address_t vName; CodeSize = TOS; NameSize = M_POP; EntryPoint = M_POP; - vm_address_t vName = (vm_address_t) M_POP; + vName = (vm_address_t) M_POP; Temp = DP_FETCH_U8(vName); /* length */ - CharPtr = (char *) pfLockMemoryReadOnly(vName, Temp + 1); - ForthStringToC( gScratch, CharPtr, sizeof(gScratch) ); + const char *pFString = (const char *) pfLockMemoryReadOnly(vName, Temp + 1); + ForthStringToC( gScratch, pFString, sizeof(gScratch) ); TOS = ffSaveForth( gScratch, EntryPoint, NameSize, CodeSize ); - pfUnlockMemory(vName, (const uint8_t *) CharPtr); + pfUnlockMemory(vName, (const uint8_t *) pFString); } endcase; #endif @@ -1746,12 +1743,13 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_SCAN: /* ( addr cnt char -- addr' cnt' ) */ { - Scratch = M_POP; /* cnt */ - vm_address_t vAddr = (vm_address_t)M_POP; - char *lockedMemory = (char *) pfLockMemoryReadOnly(vAddr, Scratch); - TOS = ffScan( lockedMemory, Scratch, (char) TOS, &CharPtr ); + char charToFind = TOS; + cell_t cnt = M_POP; + vm_address_t vAddr = (vm_address_t) M_POP; + char *lockedMemory = (char *) pfLockMemoryReadOnly(vAddr, cnt); + TOS = ffScan( lockedMemory, cnt, charToFind, &CharPtr ); pfUnlockMemory(vAddr, (const uint8_t *) lockedMemory); - M_PUSH((cell_t) (vAddr + (Scratch - TOS))); /* offset address by (cnt - cnt') */ + M_PUSH((cell_t) (vAddr + (cnt - TOS))); /* offset address by (cnt - cnt') */ } endcase; diff --git a/fth/system.fth b/fth/system.fth index 6d35555..13f2ab8 100644 --- a/fth/system.fth +++ b/fth/system.fth @@ -18,7 +18,7 @@ EOL word drop ; immediate -1 echo ! \ Uncomment this line to echo Forth code while compiling. +\ 1 echo ! \ Uncomment this line to echo Forth code while compiling. \ ********************************************************************* \ This is another style of comment that is common in Forth. From 9b27825540b340f34b2a908d507e79061237cd2e Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 5 May 2026 17:14:01 -0700 Subject: [PATCH 20/48] modernize DUMP, fix warnings --- csrc/pf_inner.c | 19 +++++++++---------- csrc/pf_text.c | 31 +++++++++++++++++-------------- csrc/pf_text.h | 2 +- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 00a89c1..666c3f2 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -587,9 +587,9 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); { vm_address_t vp = (vm_address_t) M_POP; Temp = DP_FETCH_U8(vp); /* length */ - CharPtr = (char *) pfLockMemoryReadOnly(vp, Temp + 1); - CreateDicEntry( TOS, CharPtr, 0 ); - pfUnlockMemory(vp, (const uint8_t *) CharPtr); + const ForthStringPtr pName = (const ForthStringPtr) pfLockMemoryReadOnly(vp, Temp + 1); + CreateDicEntry( TOS, pName, 0 ); + pfUnlockMemory(vp, (const uint8_t *) pName); M_DROP; } endcase; @@ -912,14 +912,13 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_DROP: M_DROP; endcase; - case ID_DUMP: - Scratch = M_POP; - CharPtr = (char *) pfLockMemoryReadOnly((vm_address_t) Scratch, TOS); - DumpMemory( (char *) CharPtr, TOS ); - /* TODO handle dump of larger virtual areas. */ - pfUnlockMemory((vm_address_t) Scratch, (const uint8_t *) CharPtr); + case ID_DUMP: /* ( addr cnt -- ) */ { + cell_t cnt = TOS; + vm_address_t vAddr = (vm_address_t) M_POP; + DumpMemory(vAddr, cnt); M_DROP; - endcase; + } + endcase; case ID_DUP: M_DUP; endcase; diff --git a/csrc/pf_text.c b/csrc/pf_text.c index d491ecf..405f479 100644 --- a/csrc/pf_text.c +++ b/csrc/pf_text.c @@ -300,35 +300,38 @@ char *ConvertNumberToText( cell_t Num, cell_t Base, int32_t IfSigned, int32_t Mi /*************************************************************** ** Diagnostic routine that prints memory in table format. */ -void DumpMemory( void *addr, cell_t cnt) +void DumpMemory(vm_address_t vAddr, cell_t cnt) { - cell_t ln, cn, nlines; - unsigned char *ptr, *cptr, c; - - nlines = (cnt + 15) / 16; - - ptr = (unsigned char *) addr; + cell_t lineIndex, byteIndex; + cell_t numLines = (cnt + 15) / 16; + vm_address_t vPtr = vAddr; EMIT_CR; - for (ln=0; ln '}')) c = '.'; EMIT(c); } + + /* TODO handle dump of larger virtual areas. */ + pfUnlockMemory(vPtr, pAddr); + EMIT_CR; + vPtr += 16; } } diff --git a/csrc/pf_text.h b/csrc/pf_text.h index a816b06..f35e952 100644 --- a/csrc/pf_text.h +++ b/csrc/pf_text.h @@ -61,7 +61,7 @@ cell_t ffCompare( const char *s1, cell_t len1, const char *s2, cell_t len2 ); cell_t ffCompareText( const char *s1, const char *s2, cell_t len ); cell_t ffCompareTextCaseN( const char *s1, const char *s2, cell_t len ); -void DumpMemory( void *addr, cell_t cnt); +void DumpMemory(vm_address_t vAddr, cell_t cnt); char *ConvertNumberToText( cell_t Num, cell_t Base, int32_t IfSigned, int32_t MinChars ); void TypeName( const char *Name ); From 4f73632d3d90d68788feefd3e2742a710a879be5 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 5 May 2026 17:41:30 -0700 Subject: [PATCH 21/48] fix more warnings, SKIP, SCAN --- csrc/paging/dmpaging.h | 2 +- csrc/paging/pagedmem.c | 2 +- csrc/pf_inner.c | 46 ++++++++++++++++++++++-------------------- csrc/pf_save.c | 6 ++++-- csrc/pf_words.c | 10 ++++----- csrc/pf_words.h | 4 ++-- csrc/pfcompil.c | 4 ++-- csrc/pfcompil.h | 2 +- 8 files changed, 40 insertions(+), 36 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index 5c8970f..e344c12 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -172,7 +172,7 @@ int pfWaitAsyncPagedMemoryAccess(int micros); * @return number of bytes written or 0 if timed out */ size_t pfWritePagedMemory(paging_address_t destination, - void *source, + const void *source, size_t numBytes, int micros); diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index b92e1fd..f6348c4 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -90,7 +90,7 @@ int pfWaitPendingVirtualRead(void) { } size_t pfWritePagedMemory(paging_address_t destination, - void *source, + const void *source, size_t numBytes, int async) { if (!pfIsAddressInPagedMemory(destination)) { diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 666c3f2..be7a59c 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -586,8 +586,8 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); case ID_COLON_P: /* ( $name xt -- ) */ { vm_address_t vp = (vm_address_t) M_POP; - Temp = DP_FETCH_U8(vp); /* length */ - const ForthStringPtr pName = (const ForthStringPtr) pfLockMemoryReadOnly(vp, Temp + 1); + cell_t length = DP_FETCH_U8(vp); + const char *pName = (const char *) pfLockMemoryReadOnly(vp, length + 1); CreateDicEntry( TOS, pName, 0 ); pfUnlockMemory(vp, (const uint8_t *) pName); M_DROP; @@ -1178,9 +1178,9 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); * Then we will have the name lengths. */ vm_address_t vNewName = (vm_address_t)TOS; - const char *pNewName = (char *)pfLockMemoryReadOnly(vNewName, DP_MAX_REGION_SIZE); + const char *pNewName = (const char *)pfLockMemoryReadOnly(vNewName, DP_MAX_REGION_SIZE); vm_address_t vOldName = (vm_address_t)M_POP; - const char *pOldName = (char *)pfLockMemoryReadOnly(vOldName, DP_MAX_REGION_SIZE); + const char *pOldName = (const char *)pfLockMemoryReadOnly(vOldName, DP_MAX_REGION_SIZE); TOS = sdRenameFile( pOldName, pNewName ); pfUnlockMemory(vOldName, (const uint8_t *)pOldName); pfUnlockMemory(vNewName, (const uint8_t *)pNewName); @@ -1216,10 +1216,10 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_FIND: /* ( $addr -- $addr 0 | xt +-1 ) */ { vm_address_t vaddr = (vm_address_t) TOS; - Scratch = DP_FETCH_U8(vaddr) + 1; /* length including count */ - CharPtr = (char *) pfLockMemoryReadOnly(vaddr, Scratch); - TOS = ffFind( (char *) CharPtr, (ExecToken *) &Temp ); - pfUnlockMemory(vaddr, (const uint8_t *)CharPtr); + cell_t totalLength = DP_FETCH_U8(vaddr) + 1; /* length including count */ + const char *pAddr = (const char *) pfLockMemoryReadOnly(vaddr, totalLength); + TOS = ffFind(pAddr, (ExecToken *) &Temp ); + pfUnlockMemory(vaddr, (const uint8_t *)pAddr); if (TOS != 0) { M_PUSH( Temp ); /* xt */ } else { @@ -1231,15 +1231,15 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_FINDNFA: /* ( $name -- $addr 0 | nfa -1 | nfa 1 , find NFA in dictionary ) */ { vm_address_t nfa = NULL; - vm_address_t name = (vm_address_t) TOS; - Scratch = DP_FETCH_U8(name) + 1; /* length including count */ - CharPtr = (char *) pfLockMemoryReadOnly(name, Scratch); - TOS = ffFindNFA( (const ForthString *) CharPtr, (const ForthString **) &nfa ); - pfUnlockMemory(name, (const uint8_t *)CharPtr); + vm_address_t vName = (vm_address_t) TOS; + cell_t totalLength = DP_FETCH_U8(vName) + 1; /* length including count */ + const char *pAddr = (const char *) pfLockMemoryReadOnly(vName, totalLength); + TOS = ffFindNFA(pAddr, (const ForthString **) &nfa ); + pfUnlockMemory(vName, (const uint8_t *)CharPtr); if (TOS != 0) { M_PUSH( nfa ); } else { - M_PUSH( name ); /* $addr */ + M_PUSH( vName ); /* $addr */ } } endcase; @@ -1742,11 +1742,12 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_SCAN: /* ( addr cnt char -- addr' cnt' ) */ { + const char *dummy = 0; char charToFind = TOS; cell_t cnt = M_POP; vm_address_t vAddr = (vm_address_t) M_POP; - char *lockedMemory = (char *) pfLockMemoryReadOnly(vAddr, cnt); - TOS = ffScan( lockedMemory, cnt, charToFind, &CharPtr ); + const char *lockedMemory = (const char *) pfLockMemoryReadOnly(vAddr, cnt); + TOS = ffScan( lockedMemory, cnt, charToFind, &dummy ); pfUnlockMemory(vAddr, (const uint8_t *) lockedMemory); M_PUSH((cell_t) (vAddr + (cnt - TOS))); /* offset address by (cnt - cnt') */ } @@ -1763,12 +1764,13 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_SKIP: /* ( addr cnt char -- addr' cnt' ) */ { - Scratch = M_POP; /* cnt */ - Temp = M_POP; /* addr */ - char *lockedMemory = (char *) pfLockMemoryReadOnly((vm_address_t) Temp, Scratch); - TOS = ffSkip( lockedMemory, Scratch, (char) TOS, &CharPtr ); - pfUnlockMemory((vm_address_t) Temp, (const uint8_t *) lockedMemory); - M_PUSH((cell_t) (Temp + (Scratch - TOS))); /* offset address by (cnt - cnt') */ + const char *dummy; + cell_t cnt = M_POP; /* cnt */ + vm_address_t vAddr = (vm_address_t) M_POP; + char *lockedMemory = (char *) pfLockMemoryReadOnly(vAddr, cnt); + TOS = ffSkip( lockedMemory, cnt, (char) TOS, &dummy ); + pfUnlockMemory(vAddr, (const uint8_t *) lockedMemory); + M_PUSH((cell_t) (vAddr + (cnt - TOS))); /* offset address by (cnt - cnt') */ } endcase; diff --git a/csrc/pf_save.c b/csrc/pf_save.c index da9c6e5..82131a0 100644 --- a/csrc/pf_save.c +++ b/csrc/pf_save.c @@ -817,11 +817,13 @@ PForthDictionary pfLoadStaticDictionary( void ) if( !dic ) goto nomem_error; pfCopyMemory( (uint8_t *) dic->dic_HeaderBase, MinDicNames, sizeof(MinDicNames) ); + #if PF_DEMAND_PAGING - pfWritePagedMemory((uint8_t *) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode), DP_TIMEOUT_MICROS); + pfWritePagedMemory((paging_address_t) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode), DP_TIMEOUT_MICROS); #else - pfCopyMemory( (uint8_t *) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode) ); + pfCopyMemory((uint8_t *) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode)); #endif + DBUG(("Static data copied to newly allocated dictionaries.\n")); dic->dic_CodePtr.Byte = (uint8_t *) CODEREL_TO_ABS(CODEPTR); diff --git a/csrc/pf_words.c b/csrc/pf_words.c index ec5a493..1301e6d 100644 --- a/csrc/pf_words.c +++ b/csrc/pf_words.c @@ -75,9 +75,9 @@ void ffDotS( void ) } /* ( addr cnt char -- addr' cnt' , skip leading characters ) */ -cell_t ffSkip( char *AddrIn, cell_t Cnt, char c, char **AddrOut ) +cell_t ffSkip(const char *AddrIn, cell_t Cnt, char c, const char **AddrOut) { - char *s; + const char *s; s = AddrIn; @@ -105,9 +105,9 @@ DBUGX(("ffSkip: %c=0x%x, %d\n", *s, Cnt )); } /* ( addr cnt char -- addr' cnt' , scan for char ) */ -cell_t ffScan( char *AddrIn, cell_t Cnt, char c, char **AddrOut ) +cell_t ffScan(const char *AddrIn, cell_t Cnt, char c, const char **AddrOut) { - char *s; + const char *s; s = AddrIn; @@ -212,7 +212,7 @@ cell_t ffNumberQ( const char *FWord, cell_t *Num ) */ static char * Word ( char c, int Upcase ) { - char *s1,*s2,*s3; + const char *s1,*s2,*s3; cell_t n1, n2, n3; cell_t i, nc; diff --git a/csrc/pf_words.h b/csrc/pf_words.h index 5d255f9..ced0230 100644 --- a/csrc/pf_words.h +++ b/csrc/pf_words.h @@ -29,8 +29,8 @@ extern "C" { void ffDot( cell_t n ); void ffDotHex( cell_t n ); void ffDotS( void ); -cell_t ffSkip( char *AddrIn, cell_t Cnt, char c, char **AddrOut ); -cell_t ffScan( char *AddrIn, cell_t Cnt, char c, char **AddrOut ); +cell_t ffSkip(const char *AddrIn, cell_t Cnt, char c, const char **AddrOut); +cell_t ffScan(const char *AddrIn, cell_t Cnt, char c, const char **AddrOut); size_t ffReadFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ); size_t ffWriteFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ); diff --git a/csrc/pfcompil.c b/csrc/pfcompil.c index f8fd64e..103c310 100644 --- a/csrc/pfcompil.c +++ b/csrc/pfcompil.c @@ -57,7 +57,7 @@ cell_t NotCompiled( const char *FunctionName ) ** Create an entry in the Dictionary for the given ExecutionToken. ** FName is name in Forth format. */ -void CreateDicEntry( ExecToken XT, const ForthStringPtr FName, ucell_t Flags ) +void CreateDicEntry(ExecToken XT, const char *FName, ucell_t Flags) { cfNameLinks *cfnl; @@ -871,7 +871,7 @@ ThrowCode ffInterpret( void ) gCurrentTask->td_SourceNum ) ); } error: - pfUnlockMemory(saveSource, gCurrentTask->td_SourcePtr); + pfUnlockMemory(saveSource, (const uint8_t *) gCurrentTask->td_SourcePtr); return exception; } diff --git a/csrc/pfcompil.h b/csrc/pfcompil.h index f95ca43..cdafb53 100644 --- a/csrc/pfcompil.h +++ b/csrc/pfcompil.h @@ -46,7 +46,7 @@ const ForthString *NameToPrevious( const ForthString *NFA ); cell_t FindSpecialCFAs( void ); cell_t FindSpecialXTs( void ); cell_t NotCompiled( const char *FunctionName ); -void CreateDicEntry( ExecToken XT, const ForthStringPtr FName, ucell_t Flags ); +void CreateDicEntry(ExecToken XT, const char *FName, ucell_t Flags); void CreateDicEntryC( ExecToken XT, const char *CName, ucell_t Flags ); void ff2Literal( cell_t dHi, cell_t dLo ); void ffALiteral( cell_t Num ); From aad87215c4bfa541a929e1d0c5e0d83998f4d478 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 5 May 2026 17:43:03 -0700 Subject: [PATCH 22/48] fix SKIP warning --- csrc/pf_inner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index be7a59c..eb040ca 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1767,7 +1767,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); const char *dummy; cell_t cnt = M_POP; /* cnt */ vm_address_t vAddr = (vm_address_t) M_POP; - char *lockedMemory = (char *) pfLockMemoryReadOnly(vAddr, cnt); + const char *lockedMemory = (const char *) pfLockMemoryReadOnly(vAddr, cnt); TOS = ffSkip( lockedMemory, cnt, (char) TOS, &dummy ); pfUnlockMemory(vAddr, (const uint8_t *) lockedMemory); M_PUSH((cell_t) (vAddr + (cnt - TOS))); /* offset address by (cnt - cnt') */ From bac29535773b2c72b65c2ff259606081e8dc973a Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 5 May 2026 17:55:43 -0700 Subject: [PATCH 23/48] fix FINDNFA --- csrc/pf_inner.c | 2 +- csrc/pfcompil.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index eb040ca..bf23f2c 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1235,7 +1235,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); cell_t totalLength = DP_FETCH_U8(vName) + 1; /* length including count */ const char *pAddr = (const char *) pfLockMemoryReadOnly(vName, totalLength); TOS = ffFindNFA(pAddr, (const ForthString **) &nfa ); - pfUnlockMemory(vName, (const uint8_t *)CharPtr); + pfUnlockMemory(vName, (const uint8_t *)pAddr); if (TOS != 0) { M_PUSH( nfa ); } else { diff --git a/csrc/pfcompil.c b/csrc/pfcompil.c index 103c310..fb69b2e 100644 --- a/csrc/pfcompil.c +++ b/csrc/pfcompil.c @@ -841,6 +841,7 @@ ThrowCode ffInterpret( void ) ThrowCode exception = 0; /* td_SourcePtr may be pointing to a string in the dictionary. */ vm_address_t saveSource = (vm_address_t)gCurrentTask->td_SourcePtr; + /* It may be difficult to make td_SourcePtr const because of refill(). */ gCurrentTask->td_SourcePtr = (char *)pfLockMemoryReadOnly(saveSource, gCurrentTask->td_SourceNum); /* Is there any text left in Source ? */ From 024ca1e5fb90c2fc78f8cf29b674ea31d0748c1a Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Wed, 6 May 2026 17:01:09 -0700 Subject: [PATCH 24/48] use uint32_t for paging transfers Add PF_ASSERT() macro. Add pagedmem.h to highlight the serial memory API. --- csrc/paging/dmpaging.h | 76 ++++--------------------------------- csrc/paging/lockpage.c | 33 ++++++++-------- csrc/paging/pagedmem.c | 25 ++++++------- csrc/paging/pagedmem.h | 85 ++++++++++++++++++++++++++++++++++++++++++ csrc/paging/qadmpage.c | 4 +- csrc/pf_all.h | 1 + csrc/pf_core.c | 9 ++++- csrc/pf_main.c | 7 ---- csrc/pf_save.c | 2 +- csrc/pforth.h | 17 +++++++++ 10 files changed, 151 insertions(+), 108 deletions(-) create mode 100644 csrc/paging/pagedmem.h diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index e344c12..192b834 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -25,10 +25,6 @@ extern "C" { #endif -#ifndef PF_DEMAND_PAGING -#define PF_DEMAND_PAGING 1 -#endif - typedef uint8_t *vm_address_t; /** an address that may be in physical or paged memory */ typedef uint8_t *paging_address_t; /** an address that may be in paged memory */ @@ -77,8 +73,6 @@ void pfStoreVirtualFloat(PF_FLOAT *address, PF_FLOAT value); #define DP_MAX_REGIONS (4) /* maximum number of bytes per region */ #define DP_MAX_REGION_SIZE (256) -/* typical timeout value for accessing serial memory */ -#define DP_TIMEOUT_MICROS 50000 void pfResetLockedMemory(void); @@ -88,17 +82,19 @@ void pfResetLockedMemory(void); * A region should only be locked temporarily, for example within * a single primitive. * If the virtual memory address is not in paged memory then it will be passed through. + * You cannot lock more than DP_MAX_REGION_SIZE bytes. * @return physical address that can be used by normal C code as “const” memory. */ -const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, cell_t numBytes); +const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, uint32_t numBytes); /** * Lock a read-write region of demand paging in physical memory. * Load the data from demand paging if not already loaded. * If the virtual memory address is not in paged memory then it will be passed through. - * @return physical address that can be used by normal C code as “const” memory. + * You cannot lock more than DP_MAX_REGION_SIZE bytes. + * @return physical address that can be read or written by normal C code. */ -uint8_t *pfLockMemoryReadWrite(vm_address_t vp, cell_t numBytes); +uint8_t *pfLockMemoryReadWrite(vm_address_t vp, uint32_t numBytes); /** * Release a previously locked region of memory. @@ -111,72 +107,14 @@ uint8_t *pfLockMemoryReadWrite(vm_address_t vp, cell_t numBytes); */ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp); -/** Copy from virtual to physical memory synchronously. +/** Copy from virtual to physical memory. * @param destination in physical memory * @param source The data may be in physical or paged memory. * @return destination */ void *pfCopyFromVirtualMemory(void *destination, vm_address_t source, - size_t numBytes); - -/* Serial Memory Access - * A demand paging simulator is provided for testing the framework on a host. - * The actual demand paging interface must be provided by the user. - */ - -/** Is the given address pointing to paged memory? - * @return 1 if in paged memory, else 0 - */ -int pfIsAddressInPagedMemory(vm_address_t p); - -#if PF_DEMAND_PAGING -#define DP_ALIGNMENT_SIZE (16) - -/** - * Reset the memory allocator. - * This may or may not clear the memory. - */ -void pfResetPagedMemory(void); - -/** Allocate demand paged memory from SPI or other storage. - * Memory blocks will be aligned on DP_ALIGNMENT_SIZE byte boundaries. - */ -paging_address_t pfAllocatePagedMemory(ucell_t numBytes); - -/** Free demand paged memory. - * This may simply be a NOOP. So just allocate - * what you need at the beginning and don't rely on being able to free it. - */ -void pfFreePagedMemory(vm_address_t p); - -/** Read from virtual to physical memory. - * Only one async read or write can be pending at a time. - * @param micros if zero then issue an async transfer, else timeout in micros - * @return number of bytes read or 0 if timed out - */ -size_t pfReadPagedMemory(void *destination, - paging_address_t source, - size_t numBytes, - int micros); - -/* Wait for asynchronous paged memory read or write to complete. - * This is useful for read-ahead buffering. - * return 0 if finished in under the specified microseconds - */ -int pfWaitAsyncPagedMemoryAccess(int micros); - -/** Read from virtual to physical memory. - * Only one async read or write can be pending at a time. - * @param micros if zero then issue an async transfer, else timeout in micros - * @return number of bytes written or 0 if timed out - */ -size_t pfWritePagedMemory(paging_address_t destination, - const void *source, - size_t numBytes, - int micros); - -#endif /* PF_DEMAND_PAGING */ + uint32_t numBytes); #ifdef __cplusplus } diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index f43314e..c55e73d 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -74,12 +74,14 @@ void pfResetLockedMemory(void) { } } -uint8_t *pfLockMemoryInternal(vm_address_t vp, cell_t numBytes, int writable) { +uint8_t *pfLockMemoryInternal(vm_address_t vp, uint32_t numBytes, int writable) { int i; struct RegionControlBlock *region = NULL; if (pfIsAddressInPagedMemory(vp) == 0) { /* not in paged memory so locking not needed */ return (uint8_t *) vp; } + PF_ASSERT(numBytes <= DP_MAX_REGION_SIZE); + /* Find an empty region. */ for (i = 0; i < DP_MAX_REGIONS; i++) { if (sLockedRegions[i].locked == 0) { @@ -91,8 +93,9 @@ uint8_t *pfLockMemoryInternal(vm_address_t vp, cell_t numBytes, int writable) { printf("ERROR: no available region!"); return NULL; } + /* Read serial data into the buffer. */ - cell_t numRead = pfReadPagedMemory(®ion->physical[0], vp, numBytes, 0); + cell_t numRead = pfReadPagedMemory(®ion->physical[0], vp, numBytes); if (numRead != numBytes) { printf("ERROR: could not read data for region!"); return NULL; @@ -105,11 +108,11 @@ uint8_t *pfLockMemoryInternal(vm_address_t vp, cell_t numBytes, int writable) { return ®ion->physical[0]; } -const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, cell_t numBytes) { +const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, uint32_t numBytes) { return ((const uint8_t *)(pfLockMemoryInternal(vp, numBytes, 0))); } -uint8_t *pfLockMemoryReadWrite(vm_address_t vp, cell_t numBytes) { +uint8_t *pfLockMemoryReadWrite(vm_address_t vp, uint32_t numBytes) { return pfLockMemoryInternal(vp, numBytes, 1); } @@ -134,7 +137,7 @@ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { } if (region->writable != 0) { /* write back to serial memory */ - cell_t numWritten = pfWritePagedMemory(vp, ®ion->physical[0], region->length, 0); + cell_t numWritten = pfWritePagedMemory(vp, ®ion->physical[0], region->length); if (numWritten != region->length) { printf("ERROR: virtual could not be written back, only wrote %d bytes\n", @@ -152,7 +155,7 @@ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { uint8_t pfFetchVirtualU8(const uint8_t *address) { uint8_t value; if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfReadPagedMemory(&value, (paging_address_t) address, sizeof(uint8_t), DP_TIMEOUT_MICROS); + pfReadPagedMemory(&value, (paging_address_t) address, sizeof(uint8_t)); return value; } else { return *address; @@ -162,7 +165,7 @@ uint8_t pfFetchVirtualU8(const uint8_t *address) { uint16_t pfFetchVirtualU16(const uint16_t *address) { uint16_t value; if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfReadPagedMemory(&value, (paging_address_t) address, sizeof(uint16_t), DP_TIMEOUT_MICROS); + pfReadPagedMemory(&value, (paging_address_t) address, sizeof(uint16_t)); return value; } else { return *address; @@ -171,7 +174,7 @@ uint16_t pfFetchVirtualU16(const uint16_t *address) { cell_t pfFetchVirtualCell(const cell_t *address) { cell_t value; if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfReadPagedMemory(&value, (paging_address_t) address, sizeof(cell_t), DP_TIMEOUT_MICROS); + pfReadPagedMemory(&value, (paging_address_t) address, sizeof(cell_t)); return value; } else { return *address; @@ -180,7 +183,7 @@ cell_t pfFetchVirtualCell(const cell_t *address) { PF_FLOAT pfFetchVirtualFloat(const PF_FLOAT *address) { PF_FLOAT value; if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfReadPagedMemory(&value, (paging_address_t) address, sizeof(PF_FLOAT), DP_TIMEOUT_MICROS); + pfReadPagedMemory(&value, (paging_address_t) address, sizeof(PF_FLOAT)); return value; } else { return *address; @@ -189,7 +192,7 @@ PF_FLOAT pfFetchVirtualFloat(const PF_FLOAT *address) { void pfStoreVirtualU8(uint8_t *address, uint8_t value) { if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfWritePagedMemory((paging_address_t) address, &value, sizeof(uint8_t), DP_TIMEOUT_MICROS); + pfWritePagedMemory((paging_address_t) address, &value, sizeof(uint8_t)); } else { *address = value; } @@ -197,21 +200,21 @@ void pfStoreVirtualU8(uint8_t *address, uint8_t value) { void pfStoreVirtualU16(uint16_t *address, uint16_t value) { if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfWritePagedMemory((paging_address_t) address, &value, sizeof(uint16_t), DP_TIMEOUT_MICROS); + pfWritePagedMemory((paging_address_t) address, &value, sizeof(uint16_t)); } else { *address = value; } } void pfStoreVirtualCell(cell_t *address, cell_t value) { if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfWritePagedMemory((paging_address_t) address, &value, sizeof(cell_t), DP_TIMEOUT_MICROS); + pfWritePagedMemory((paging_address_t) address, &value, sizeof(cell_t)); } else { *address = value; } } void pfStoreVirtualFloat(PF_FLOAT *address, PF_FLOAT value) { if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfWritePagedMemory((paging_address_t) address, &value, sizeof(PF_FLOAT), DP_TIMEOUT_MICROS); + pfWritePagedMemory((paging_address_t) address, &value, sizeof(PF_FLOAT)); } else { *address = value; } @@ -219,9 +222,9 @@ void pfStoreVirtualFloat(PF_FLOAT *address, PF_FLOAT value) { void *pfCopyFromVirtualMemory(void *destination, vm_address_t source, - size_t numBytes) { + uint32_t numBytes) { if (pfIsAddressInPagedMemory(source)) { - pfReadPagedMemory(destination, (paging_address_t) source, numBytes, DP_TIMEOUT_MICROS); /* TODO check result */ + pfReadPagedMemory(destination, (paging_address_t) source, numBytes); /* TODO check result */ return destination; } else { return pfCopyMemory(destination, source, numBytes); diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index f6348c4..7f7ded4 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -1,5 +1,6 @@ /*************************************************************** ** Demand Paged Memory Simulator +** ** This should be replaced by a hardware specific implementation ** when doing actual demand paging. The real code may, for example, ** access SPI RAM. @@ -34,7 +35,11 @@ static uint8_t sFakeSerialRAM[PF_DP_AVAILABLE_SPACE]; static cell_t sDpNextAvailable = 0; #define DP_ALIGNMENT_MASK (DP_ALIGNMENT_SIZE - 1) -#if 0 +/* By munging the virtual address, we can cause memory errors if it is not converted. + * This will help us catch areas where we need to use functions like pfLockMemoryReadWrite(). + * You may need to use a different mask on your system depending on the memory layout. + */ +#if 1 #define PF_DP_MUNGE_KEY (0) #elif (PF_64BIT) #define PF_DP_MUNGE_KEY (0x005A000000000000) @@ -72,27 +77,21 @@ vm_address_t pfAllocatePagedMemory(const ucell_t numBytes) { void pfFreePagedMemory(vm_address_t p) {} size_t pfReadPagedMemory(void *destination, - vm_address_t source, - size_t numBytes, - int async) { + vm_address_t source, + uint32_t numBytes) { if (!pfIsAddressInPagedMemory(source)) { printf("ERROR: not a paged address = %p\n", source); return 0; } /* TODO check upper boundary */ - vm_address_t vaddr = PF_DP_UNMUNGE(source); - pfCopyMemory((uint8_t *)destination, vaddr, numBytes); + void *pAddr = PF_DP_UNMUNGE(source); + pfCopyMemory(destination, pAddr, numBytes); return numBytes; } -int pfWaitPendingVirtualRead(void) { - return 0; -} - size_t pfWritePagedMemory(paging_address_t destination, - const void *source, - size_t numBytes, - int async) { + const void *source, + uint32_t numBytes) { if (!pfIsAddressInPagedMemory(destination)) { printf("ERROR: not a paged address = %p\n", destination); return 0; diff --git a/csrc/paging/pagedmem.h b/csrc/paging/pagedmem.h new file mode 100644 index 0000000..d326884 --- /dev/null +++ b/csrc/paging/pagedmem.h @@ -0,0 +1,85 @@ +#ifndef _pf_pagedmem_h +#define _pf_pagedmem_h + +/*************************************************************** +** Include file for PForth Paged Memory +** +** If you want to use demand paging then you will need to replace +** the paged memory simulator in pagedmem.c with your own function. +** +** Author: Phil Burk +** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom +** +** Permission to use, copy, modify, and/or distribute this +** software for any purpose with or without fee is hereby granted. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +** THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +** FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +** +***************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Serial Memory Access + * A demand paging simulator is provided for testing the framework on a host. + * The actual demand paging interface must be provided by the user. + */ + +/** Is the given address pointing to paged memory? + * @return 1 if in paged memory, else 0 + */ +int pfIsAddressInPagedMemory(vm_address_t p); + +#if PF_DEMAND_PAGING +#define DP_ALIGNMENT_SIZE (16) + +/** + * Reset the memory allocator. + * This may or may not clear the memory. + */ +void pfResetPagedMemory(void); + +/** Allocate demand paged memory from SPI or other storage. + * Memory blocks will be aligned on DP_ALIGNMENT_SIZE byte boundaries. + */ +paging_address_t pfAllocatePagedMemory(ucell_t numBytes); + +/** Free demand paged memory. + * This may simply be a NOOP. So just allocate + * what you need at the beginning and don't rely on being able to free it. + */ +void pfFreePagedMemory(vm_address_t p); + +/** Read from virtual to physical memory. + * Only one async read or write can be pending at a time. + * @param micros if zero then issue an async transfer, else timeout in micros + * @return number of bytes read or 0 if timed out + */ +size_t pfReadPagedMemory(void *destination, + paging_address_t source, + uint32_t numBytes); + +/** Read from virtual to physical memory. + * Only one async read or write can be pending at a time. + * @param micros if zero then issue an async transfer, else timeout in micros + * @return number of bytes written or 0 if timed out + */ +size_t pfWritePagedMemory(paging_address_t destination, + const void *source, + uint32_t numBytes); + +#endif /* PF_DEMAND_PAGING */ + +#ifdef __cplusplus +} +#endif + +#endif /* _pf_pagedmem_h */ diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index 75a11d3..03b1f62 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -90,9 +90,9 @@ static int pfQaTestReadWrite(void) { vm_address_t vm1 = pfAllocatePagedMemory(kBufferSize); ASSERT_NE(vm1, 0); printf("pfQaTestReadWrite: vm1 = %p\n", vm1); - cell_t written = pfWritePagedMemory(vm1, buffer1, kBufferSize, 0); + cell_t written = pfWritePagedMemory(vm1, buffer1, kBufferSize); ASSERT_EQ(written, kBufferSize); - cell_t numRead = pfReadPagedMemory(buffer2, vm1, kBufferSize, 0); + cell_t numRead = pfReadPagedMemory(buffer2, vm1, kBufferSize); ASSERT_EQ(numRead, kBufferSize); for (i = 0; i < kBufferSize; i++) { ASSERT_EQ(buffer2[i], buffer1[i]); diff --git a/csrc/pf_all.h b/csrc/pf_all.h index 4be0694..8dae68b 100644 --- a/csrc/pf_all.h +++ b/csrc/pf_all.h @@ -51,6 +51,7 @@ #include "pforth.h" #include "pf_types.h" #include "paging/dmpaging.h" +#include "paging/pagedmem.h" #include "pf_io.h" #include "pf_guts.h" #include "pf_text.h" diff --git a/csrc/pf_core.c b/csrc/pf_core.c index 9bb2e3b..bc8bdb4 100644 --- a/csrc/pf_core.c +++ b/csrc/pf_core.c @@ -51,6 +51,7 @@ ExecToken gLocalCompiler_XT; /* custom compiler for local variables */ ExecToken gNumberQ_XT; /* XT of NUMBER? */ ExecToken gQuitP_XT; /* XT of (QUIT) */ ExecToken gAcceptP_XT; /* XT of ACCEPT */ +cell_t gPfAssertEnabled = 0; /* Depth of data stack when colon called. */ cell_t gDepthAtColon; @@ -88,6 +89,8 @@ static void pfTerm( void ); #define PF_DEFAULT_CODE_SIZE (300000) #endif +int pfQaDemandPaging(void); + /* Initialize globals in a function to simplify loading on * embedded systems which may not support initialization of data section. */ @@ -115,6 +118,11 @@ static void pfInit( void ) pfInitMemoryAllocator(); pfResetLockedMemory(); ioInit(); + +#if PF_DEMAND_PAGING + pfQaDemandPaging(); /* FIXME move to standalone qa test */ +#endif + } static void pfTerm( void ) { @@ -447,7 +455,6 @@ void pfDebugPrintDecimalNumber( int n ) pfDebugMessage( ConvertNumberToText( n, 10, TRUE, 1 ) ); } - /*************************************************************** ** Output 'C' string message. ** This is provided to help avoid the use of printf() and other I/O diff --git a/csrc/pf_main.c b/csrc/pf_main.c index 46de136..1d9fa08 100644 --- a/csrc/pf_main.c +++ b/csrc/pf_main.c @@ -58,8 +58,6 @@ int main( void ) } #else -int pfQaDemandPaging(void); - int main( int argc, char **argv ) { #ifdef PF_STATIC_DIC @@ -142,11 +140,6 @@ int main( int argc, char **argv ) } #endif -#if PF_DEMAND_PAGING - Result = pfQaDemandPaging(); /* FIXME move to standalone qa test */ - if (Result != 0) goto on_error; -#endif - Result = pfDoForth( DicName, SourceName, IfInit); on_error: diff --git a/csrc/pf_save.c b/csrc/pf_save.c index 82131a0..23c1beb 100644 --- a/csrc/pf_save.c +++ b/csrc/pf_save.c @@ -819,7 +819,7 @@ PForthDictionary pfLoadStaticDictionary( void ) pfCopyMemory( (uint8_t *) dic->dic_HeaderBase, MinDicNames, sizeof(MinDicNames) ); #if PF_DEMAND_PAGING - pfWritePagedMemory((paging_address_t) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode), DP_TIMEOUT_MICROS); + pfWritePagedMemory((paging_address_t) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode)); #else pfCopyMemory((uint8_t *) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode)); #endif diff --git a/csrc/pforth.h b/csrc/pforth.h index 0a9c00c..f7824db 100644 --- a/csrc/pforth.h +++ b/csrc/pforth.h @@ -47,6 +47,10 @@ typedef uintptr_t ucell_t; typedef ucell_t ExecToken; /* Execution Token */ typedef cell_t ThrowCode; +#ifndef PF_DEMAND_PAGING +#define PF_DEMAND_PAGING 1 +#endif + #ifdef __cplusplus extern "C" { #endif @@ -99,8 +103,21 @@ ThrowCode pfIncludeFile( const char *FileName ); /* Execute a Forth word by name. */ ThrowCode pfExecIfDefined( const char *CString ); + +/* Assertion macro for pForth. */ +extern cell_t gPfAssertEnabled; +#define PF_ASSERT(_expr) do { \ + if (!(_expr)) { \ + if (gPfAssertEnabled) { \ + pfMessage("PF_ASSERT failed: " #_expr "\n"); \ + (void)(*(volatile int *)0); \ + } \ + } \ +} while(0) + #ifdef __cplusplus } #endif #endif /* _pforth_h */ + From fa227d3ae3eef60408cc2c9301da04b02f40c565 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Thu, 7 May 2026 11:20:40 -0700 Subject: [PATCH 25/48] put header name space in paged memory --- csrc/paging/dmpaging.h | 24 ++++++++++++++++++++++++ csrc/paging/lockpage.c | 38 ++++++++++++++++++++++++++++++++++++++ csrc/paging/pagedmem.c | 2 +- csrc/paging/qadmpage.c | 30 ++++++++++++++++++++++++++++++ csrc/pf_core.c | 19 +++++-------------- csrc/pf_guts.h | 2 +- csrc/pf_mem.c | 2 +- csrc/pf_save.c | 7 ++++++- csrc/pfcompil.c | 38 ++++++++++++++++++++++---------------- 9 files changed, 128 insertions(+), 34 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index 192b834..e319908 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -116,6 +116,30 @@ void *pfCopyFromVirtualMemory(void *destination, vm_address_t source, uint32_t numBytes); +/** Copy from physical to virtual memory. + * @param destination The target may be in physical or paged memory. + * @param source in physical memory + * @return destination + */ +void *pfCopyToVirtualMemory(vm_address_t destination, + void * source, + uint32_t numBytes); + +/** Free virtual memory. + * @param address may be in physical or paged memory + */ +void pfFreeVirtualMemory(vm_address_t address); + +/** Set a region of virtual memory to a value. + * @param destination in physical or paged memory + * @param value fill memory with this value + * @param numBytes how many bytes to set + * @return destination + */ +void *pfSetVirtualMemory(vm_address_t destination, + uint8_t value, + uint32_t numBytes); + #ifdef __cplusplus } #endif diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index c55e73d..cd7cf14 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -231,5 +231,43 @@ void *pfCopyFromVirtualMemory(void *destination, } } +void *pfCopyToVirtualMemory(vm_address_t destination, + void * source, + uint32_t numBytes) { + if (pfIsAddressInPagedMemory(destination)) { + pfWritePagedMemory((paging_address_t) destination, source, numBytes); /* TODO check result */ + return destination; + } else { + return pfCopyMemory(destination, source, numBytes); + } +} + +void pfFreeVirtualMemory(vm_address_t address) { + if (pfIsAddressInPagedMemory(address)) { + pfFreePagedMemory((paging_address_t) address); + } else { + pfFreeMem(address); + } +} + +void *pfSetVirtualMemory(vm_address_t destination, + uint8_t value, + uint32_t numBytes) { + if (pfIsAddressInPagedMemory(destination)) { + /* Set memory in blocks that will fit in locked regions. */ + vm_address_t vp = destination; + uint8_t buffer[16]; + pfSetMemory(buffer, value, sizeof(buffer)); + while (numBytes > 0) { + uint32_t bytesToWrite = (numBytes < sizeof(buffer)) ? numBytes : sizeof(buffer); + pfWritePagedMemory(vp, buffer, bytesToWrite); + numBytes -= bytesToWrite; + vp += bytesToWrite; + } + return destination; + } else { + return pfSetMemory(destination, value, numBytes); + } +} #endif /* PF_DEMAND_PAGING */ diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index 7f7ded4..de8d16b 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -39,7 +39,7 @@ static cell_t sDpNextAvailable = 0; * This will help us catch areas where we need to use functions like pfLockMemoryReadWrite(). * You may need to use a different mask on your system depending on the memory layout. */ -#if 1 +#if 0 #define PF_DP_MUNGE_KEY (0) #elif (PF_64BIT) #define PF_DP_MUNGE_KEY (0x005A000000000000) diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index 03b1f62..ecc9d09 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -235,6 +235,35 @@ static int pfQaTestWriteFilePaging(void) { return 1; } +static int pfQaTestSetVirtualMemory(void) { + int i; + printf("pfQaDemandPaging : pfQaTestSetVirtualMemory\n"); + pfResetLockedMemory(); + vm_address_t dest; + /* Paint a large region then paint a small region in the middle. */ + const int largeSize = 1175; + const int smallSize = 234; + const int smallOffset = 571; + vm_address_t vm1 = pfAllocatePagedMemory(largeSize); + ASSERT_NE(NULL, vm1); + dest = pfSetVirtualMemory(vm1, 0x5A, largeSize); + ASSERT_EQ(dest, vm1); + dest = pfSetVirtualMemory(vm1 + smallOffset, 0x3C, smallSize); + ASSERT_EQ(dest, vm1); + i = 0; + for (; i < smallOffset; i++) { + ASSERT_EQ(0x3C, DP_FETCH_U8(vm1 + i)); + } + for (; i < smallOffset + smallSize; i++) { + ASSERT_EQ(0x5A, DP_FETCH_U8(vm1 + i)); + } + for (; i < largeSize; i++) { + ASSERT_EQ(0x3C, DP_FETCH_U8(vm1 + i)); + } + return 0; +error: + return 1; +} int pfQaDemandPaging(void) { printf("pfQaDemandPaging\n"); int x = 4; @@ -249,6 +278,7 @@ int pfQaDemandPaging(void) { ASSERT_EQ(pfQaTestFetchStore(), 0); ASSERT_EQ(pfQaTestReadFilePaging(), 0); ASSERT_EQ(pfQaTestWriteFilePaging(), 0); + ASSERT_EQ(pfQaTestSetVirtualMemory(), 0); printf("pfQaDemandPaging ended\n"); diff --git a/csrc/pf_core.c b/csrc/pf_core.c index bc8bdb4..9f95a67 100644 --- a/csrc/pf_core.c +++ b/csrc/pf_core.c @@ -219,14 +219,7 @@ void pfDeleteDictionary( PForthDictionary dictionary ) if( dic->dic_Flags & PF_DICF_ALLOCATED_SEGMENTS ) { FREE_VAR( dic->dic_HeaderBaseUnaligned ); -#if PF_DEMAND_PAGING - if (dic->dic_CodeBaseUnaligned != 0) { - pfFreePagedMemory((vm_address_t) dic->dic_CodeBaseUnaligned); - dic->dic_CodeBaseUnaligned = 0; - } -#else FREE_VAR( dic->dic_CodeBaseUnaligned ); -#endif } pfFreeMem( dic ); } @@ -259,16 +252,17 @@ PForthDictionary pfCreateDictionary( cell_t HeaderSize, cell_t CodeSize ) /* Allocate memory for header. */ if( HeaderSize > 0 ) { -/* + #if PF_DEMAND_PAGING dic->dic_HeaderBaseUnaligned = (ucell_t) pfAllocatePagedMemory( (ucell_t) HeaderSize + DIC_ALIGNMENT_SIZE); #else - */ + dic->dic_HeaderBaseUnaligned = (ucell_t) pfAllocMem((ucell_t) HeaderSize + DIC_ALIGNMENT_SIZE ); +#endif if( !dic->dic_HeaderBaseUnaligned ) goto nomem; /* Align header base. */ dic->dic_HeaderBase = DIC_ALIGN(dic->dic_HeaderBaseUnaligned); - pfSetMemory( (char *) dic->dic_HeaderBase, 0xA5, (ucell_t) HeaderSize); + pfSetVirtualMemory((vm_address_t) dic->dic_HeaderBase, 0xA5, (uint32_t) HeaderSize); dic->dic_HeaderLimit = dic->dic_HeaderBase + HeaderSize; dic->dic_HeaderPtr = dic->dic_HeaderBase; } @@ -285,10 +279,7 @@ PForthDictionary pfCreateDictionary( cell_t HeaderSize, cell_t CodeSize ) #endif if( !dic->dic_CodeBaseUnaligned ) goto nomem; dic->dic_CodeBase = DIC_ALIGN(dic->dic_CodeBaseUnaligned); -#if (PF_DEMAND_PAGING == 0) - /* TODO also clear RAM for demand paging dic. */ - pfSetMemory( (char *) dic->dic_CodeBase, 0x5A, (ucell_t) CodeSize); -#endif + pfSetVirtualMemory((vm_address_t) dic->dic_CodeBase, 0x5A, (uint32_t) CodeSize); dic->dic_CodeLimit = dic->dic_CodeBase + CodeSize; dic->dic_CodePtr.Byte = ((uint8_t *) (dic->dic_CodeBase + QUADUP(NUM_PRIMITIVES))); diff --git a/csrc/pf_guts.h b/csrc/pf_guts.h index 3b77472..d0f298d 100644 --- a/csrc/pf_guts.h +++ b/csrc/pf_guts.h @@ -598,7 +598,7 @@ extern cell_t gIncludeIndex; /* The check for >0 is only needed for CLONE testing. !!! */ #define IsTokenPrimitive(xt) ((xt=0)) -#define FREE_VAR(v) { if (v) { pfFreeMem((void *)(v)); v = 0; } } +#define FREE_VAR(v) { pfFreeVirtualMemory((void *)(v)); v = 0; } #define DATA_STACK_DEPTH (gCurrentTask->td_StackBase - gCurrentTask->td_StackPtr) #define DROP_DATA_STACK (gCurrentTask->td_StackPtr++) diff --git a/csrc/pf_mem.c b/csrc/pf_mem.c index fed36eb..f412022 100644 --- a/csrc/pf_mem.c +++ b/csrc/pf_mem.c @@ -1,5 +1,5 @@ /*************************************************************** -** Memory allocator for systems that don't have real one. +** Memory allocator for systems that don't have malloc(). ** This might be useful when bringing up a new computer with no OS. ** ** For PForth based on 'C' diff --git a/csrc/pf_save.c b/csrc/pf_save.c index 23c1beb..bbd36e0 100644 --- a/csrc/pf_save.c +++ b/csrc/pf_save.c @@ -692,7 +692,8 @@ DBUG(("pfLoadDictionary( %s )\n", FileName )); pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG); goto error; } - numr = sdReadFile( (char *) NAME_BASE, 1, ChunkSize, fid ); + /* read using demand paging if needed */ + numr = ffReadFile( (char *) NAME_BASE, 1, ChunkSize, fid ); if( numr != ChunkSize ) goto read_error; BytesLeft -= ChunkSize; #endif /* PF_NO_SHELL */ @@ -816,7 +817,11 @@ PForthDictionary pfLoadStaticDictionary( void ) gCurrentDictionary = dic = pfCreateDictionary( NewNameSize, NewCodeSize ); if( !dic ) goto nomem_error; +#if PF_DEMAND_PAGING + pfWritePagedMemory((paging_address_t) dic->dic_HeaderBase, MinDicNames, sizeof(MinDicNames)); +#else pfCopyMemory( (uint8_t *) dic->dic_HeaderBase, MinDicNames, sizeof(MinDicNames) ); +#endif #if PF_DEMAND_PAGING pfWritePagedMemory((paging_address_t) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode)); diff --git a/csrc/pfcompil.c b/csrc/pfcompil.c index fb69b2e..b8aff4c 100644 --- a/csrc/pfcompil.c +++ b/csrc/pfcompil.c @@ -66,11 +66,11 @@ void CreateDicEntry(ExecToken XT, const char *FName, ucell_t Flags) /* Set link to previous header, if any. */ if( gVarContext ) { - WRITE_CELL_DIC( &cfnl->cfnl_PreviousName, ABS_TO_NAMEREL( gVarContext ) ); + WRITE_CELL_DIC(&cfnl->cfnl_PreviousName, ABS_TO_NAMEREL( gVarContext )); } else { - cfnl->cfnl_PreviousName = 0; + WRITE_CELL_DIC(&cfnl->cfnl_PreviousName, 0); } /* Put Execution token in header. */ @@ -81,16 +81,16 @@ void CreateDicEntry(ExecToken XT, const char *FName, ucell_t Flags) /* Laydown name. */ gVarContext = gCurrentDictionary->dic_HeaderPtr; - pfCopyMemory( (uint8_t *) gCurrentDictionary->dic_HeaderPtr, FName, (*FName)+1 ); + pfCopyToVirtualMemory((uint8_t *) gCurrentDictionary->dic_HeaderPtr, FName, (*FName)+1); gCurrentDictionary->dic_HeaderPtr += (*FName)+1; /* Set flags. */ - *(char*)gVarContext |= (char) Flags; + DP_STORE_U8(gVarContext, DP_FETCH_U8(gVarContext) | (uint8_t)Flags); /* Align to quad byte boundaries with zeroes. */ while( gCurrentDictionary->dic_HeaderPtr & UINT32_MASK ) { - *(char*)(gCurrentDictionary->dic_HeaderPtr++) = 0; + DP_STORE_U8(gCurrentDictionary->dic_HeaderPtr++, 0); } } @@ -458,40 +458,46 @@ cell_t ffFindNFA( const ForthString *WordName, const ForthString **NFAPtr ) { const ForthString *WordChar; uint8_t WordLen; - const char *NameField, *NameChar; + vm_address_t vNameField, vNextNameField; int8_t NameLen; cell_t Searching = TRUE; cell_t Result = 0; + const char *pNameField; + const char *pNameChar; WordLen = (uint8_t) ((ucell_t)*WordName & MASK_NAME_SIZE); WordChar = WordName+1; - NameField = (ForthString *) gVarContext; + vNameField = (vm_address_t) gVarContext; DBUG(("\nffFindNFA: WordLen = %d, WordName = %*s\n", WordLen, WordLen, WordChar )); DBUG(("\nffFindNFA: gVarContext = 0x%x\n", gVarContext)); do { - NameLen = (uint8_t) ((ucell_t)(*NameField) & MASK_NAME_SIZE); - NameChar = NameField+1; + uint8_t countAndFlags = DP_FETCH_U8(vNameField); + NameLen = (uint8_t) (countAndFlags & MASK_NAME_SIZE); /* DBUG((" %c\n", (*NameField & FLAG_SMUDGE) ? 'S' : 'V' )); */ - if( ((*NameField & FLAG_SMUDGE) == 0) && + pNameField = (const char *) pfLockMemoryReadOnly(vNameField, NameLen + 1); + pNameChar = pNameField + 1; + if( ((countAndFlags & FLAG_SMUDGE) == 0) && (NameLen == WordLen) && - ffCompareTextCaseN( NameChar, WordChar, WordLen ) ) /* FIXME - slow */ + ffCompareTextCaseN( pNameChar, WordChar, WordLen ) ) /* FIXME - slow */ { DBUG(("ffFindNFA: found it at NFA = 0x%x\n", NameField)); - *NFAPtr = NameField ; - Result = ((*NameField) & FLAG_IMMEDIATE) ? 1 : -1; + *NFAPtr = (const ForthString *) vNameField ; + Result = (countAndFlags & FLAG_IMMEDIATE) ? 1 : -1; Searching = FALSE; } else { - NameField = NameToPrevious( NameField ); - if( NameField == NULL ) + vNextNameField = NameToPrevious( vNameField ); + if( vNextNameField == NULL ) { *NFAPtr = WordName; Searching = FALSE; } } + pfUnlockMemory(vNameField, (const uint8_t *) pNameField); + vNameField = vNextNameField; } while ( Searching); DBUG(("ffFindNFA: returns 0x%x\n", Result)); return Result; @@ -677,7 +683,7 @@ void ffDefer( void ) /* Unsmudge the word to make it visible. */ static void ffUnSmudge( void ) { - *(char*)gVarContext &= ~FLAG_SMUDGE; + DP_STORE_U8(gVarContext, DP_FETCH_U8(gVarContext) & (uint8_t)(~FLAG_SMUDGE)); } /* Implement ; */ From dad41a1f7c22f94a642fad1f4f54144506fe9d5e Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Thu, 7 May 2026 11:28:12 -0700 Subject: [PATCH 26/48] condition virtual Float support on PF_SUPPORT_FP --- csrc/paging/dmpaging.h | 5 ++++- csrc/paging/lockpage.c | 6 ++++++ csrc/paging/qadmpage.c | 23 ++++++++++++++++++++--- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index e319908..307d013 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -56,12 +56,15 @@ typedef uint8_t *paging_address_t; /** an address that may be in paged memory */ uint8_t pfFetchVirtualU8(const uint8_t *address); uint16_t pfFetchVirtualU16(const uint16_t *address); cell_t pfFetchVirtualCell(const cell_t *address); -PF_FLOAT pfFetchVirtualFloat(const PF_FLOAT *address); void pfStoreVirtualU8(uint8_t *address, uint8_t value); void pfStoreVirtualU16(uint16_t *address, uint16_t value); void pfStoreVirtualCell(cell_t *address, cell_t value); + +#ifdef PF_SUPPORT_FP +PF_FLOAT pfFetchVirtualFloat(const PF_FLOAT *address); void pfStoreVirtualFloat(PF_FLOAT *address, PF_FLOAT value); +#endif /* PF_SUPPORT_FP */ /* Memory region locking and unlocking * A maximum of DP_MAX_REGIONS can be locked at one time. diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index cd7cf14..5af2e24 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -180,6 +180,8 @@ cell_t pfFetchVirtualCell(const cell_t *address) { return *address; } } + +#ifdef PF_SUPPORT_FP PF_FLOAT pfFetchVirtualFloat(const PF_FLOAT *address) { PF_FLOAT value; if (pfIsAddressInPagedMemory((vm_address_t)address)) { @@ -189,6 +191,7 @@ PF_FLOAT pfFetchVirtualFloat(const PF_FLOAT *address) { return *address; } } +#endif /* PF_SUPPORT_FP */ void pfStoreVirtualU8(uint8_t *address, uint8_t value) { if (pfIsAddressInPagedMemory((vm_address_t)address)) { @@ -212,6 +215,8 @@ void pfStoreVirtualCell(cell_t *address, cell_t value) { *address = value; } } + +#ifdef PF_SUPPORT_FP void pfStoreVirtualFloat(PF_FLOAT *address, PF_FLOAT value) { if (pfIsAddressInPagedMemory((vm_address_t)address)) { pfWritePagedMemory((paging_address_t) address, &value, sizeof(PF_FLOAT)); @@ -219,6 +224,7 @@ void pfStoreVirtualFloat(PF_FLOAT *address, PF_FLOAT value) { *address = value; } } +#endif /* PF_SUPPORT_FP */ void *pfCopyFromVirtualMemory(void *destination, vm_address_t source, diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index ecc9d09..c25b3db 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -46,8 +46,6 @@ static int pfQaTestAllocate(void) { static int pfQaTestFetchStore(void) { printf("pfQaDemandPaging : pfQaTestFetchStore\n"); - PF_FLOAT f1 = 3.14159; - PF_FLOAT f2; cell_t c1 = 123456; cell_t c2; uint16_t w1 = 1234; @@ -62,7 +60,6 @@ static int pfQaTestFetchStore(void) { DP_STORE_U8(vm1 + 16, b1); DP_STORE_U16(vm1 + 32, w1); DP_STORE_CELL(vm1 + 48, c1); - DP_STORE_FLOAT(vm1 + 64, f1); b2 = DP_FETCH_U8(vm1 + 16); ASSERT_EQ(b1, b2); @@ -70,12 +67,29 @@ static int pfQaTestFetchStore(void) { ASSERT_EQ(w1, w2); c2 = DP_FETCH_CELL(vm1 + 48); ASSERT_EQ(c1, c2); + return 0; +error: + return 1; +} + +#ifdef PF_SUPPORT_FP +static int pfQaTestFetchStoreFloat(void) { + printf("pfQaDemandPaging : pfQaTestFetchStoreFloat\n"); + PF_FLOAT f1 = 3.14159; + PF_FLOAT f2; + + pfResetPagedMemory(); + vm_address_t vm1 = pfAllocatePagedMemory(1024); + ASSERT_NE(vm1, 0); + + DP_STORE_FLOAT(vm1 + 64, f1); f2 = DP_FETCH_FLOAT(vm1 + 64); ASSERT_EQ(f1, f2); return 0; error: return 1; } +#endif /* PF_SUPPORT_FP */ static int pfQaTestReadWrite(void) { printf("pfQaDemandPaging : pfQaTestReadWrite\n"); @@ -274,6 +288,9 @@ int pfQaDemandPaging(void) { ASSERT_EQ(pfQaTestAllocate(), 0); ASSERT_EQ(pfQaTestReadWrite(), 0); +#ifdef PF_SUPPORT_FP + ASSERT_EQ(pfQaTestReadWriteFloat(), 0); +#endif /* PF_SUPPORT_FP */ ASSERT_EQ(pfQaTestRegionLock(), 0); ASSERT_EQ(pfQaTestFetchStore(), 0); ASSERT_EQ(pfQaTestReadFilePaging(), 0); From 0fbbde6abb0c347e2451e604b47ae7f0723047d5 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Thu, 7 May 2026 11:39:47 -0700 Subject: [PATCH 27/48] add missing stubs for when PF_DEMAND_PAGING is zero --- csrc/paging/lockpage.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index 5af2e24..adbb558 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -26,11 +26,11 @@ void pfResetLockedMemory(void) { } -const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, cell_t numBytes) { +const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, uint32_t numBytes) { return ((const uint8_t *)(vp)); } -uint8_t *pfLockMemoryReadWrite(vm_address_t vp, cell_t numBytes) { +uint8_t *pfLockMemoryReadWrite(vm_address_t vp, uint32_t numBytes) { return ((uint8_t *)(vp)); } @@ -38,14 +38,30 @@ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { return 0; } +int pfIsAddressInPagedMemory(vm_address_t p) { + return FALSE; +} + void *pfCopyFromVirtualMemory(void *destination, vm_address_t source, - size_t numBytes) { + uint32_t numBytes) { return pfCopyMemory(destination, source, numBytes); } -int pfIsAddressInPagedMemory(vm_address_t p) { - return FALSE; +void *pfCopyToVirtualMemory(vm_address_t destination, + void * source, + uint32_t numBytes) { + return pfCopyMemory(destination, source, numBytes); +} + +void pfFreeVirtualMemory(vm_address_t address) { + pfFreeMem(address); +} + +void *pfSetVirtualMemory(vm_address_t destination, + uint8_t value, + uint32_t numBytes) { + return pfSetMemory(destination, value, numBytes); } #else /* PF_DEMAND_PAGING */ @@ -275,5 +291,5 @@ void *pfSetVirtualMemory(vm_address_t destination, return pfSetMemory(destination, value, numBytes); } } -#endif /* PF_DEMAND_PAGING */ +#endif /* PF_DEMAND_PAGING */ From 22105594389103e53c65767b6dec7b8874037089 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Thu, 7 May 2026 11:46:58 -0700 Subject: [PATCH 28/48] fix bad name in paging QA --- csrc/paging/qadmpage.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index c25b3db..0a6f4fa 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -278,6 +278,7 @@ static int pfQaTestSetVirtualMemory(void) { error: return 1; } + int pfQaDemandPaging(void) { printf("pfQaDemandPaging\n"); int x = 4; @@ -288,11 +289,11 @@ int pfQaDemandPaging(void) { ASSERT_EQ(pfQaTestAllocate(), 0); ASSERT_EQ(pfQaTestReadWrite(), 0); -#ifdef PF_SUPPORT_FP - ASSERT_EQ(pfQaTestReadWriteFloat(), 0); -#endif /* PF_SUPPORT_FP */ ASSERT_EQ(pfQaTestRegionLock(), 0); ASSERT_EQ(pfQaTestFetchStore(), 0); +#ifdef PF_SUPPORT_FP + ASSERT_EQ(pfQaTestFetchStoreFloat(), 0); +#endif /* PF_SUPPORT_FP */ ASSERT_EQ(pfQaTestReadFilePaging(), 0); ASSERT_EQ(pfQaTestWriteFilePaging(), 0); ASSERT_EQ(pfQaTestSetVirtualMemory(), 0); From 09a17f52d86c04f2226ed925790b78abee1dc782 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Thu, 7 May 2026 11:57:46 -0700 Subject: [PATCH 29/48] add matrix to CI for FLOAT and DEMAND_PAGING --- .github/workflows/make.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/make.yml b/.github/workflows/make.yml index 015d564..61933a3 100644 --- a/.github/workflows/make.yml +++ b/.github/workflows/make.yml @@ -16,9 +16,14 @@ jobs: # This uses a Unix Makefile and should run on Linux and Mac runs-on: ubuntu-latest + strategy: + matrix: + demand_paging: [0, 1] + support_fp: [0, 1] + steps: - uses: actions/checkout@v2 - name: Build and Test working-directory: ${{github.workspace}}/platforms/unix - run: make test ASAN=1 + run: make test ASAN=1 XCPPFLAGS="-DPF_SUPPORT_FP=${{ matrix.support_fp }} -DPF_DEMAND_PAGING=${{ matrix.demand_paging }} -D_DEFAULT_SOURCE -D_GNU_SOURCE" From 17208291b90ed98ae020b3b13e1f6296aa6a2142 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Thu, 7 May 2026 13:06:46 -0700 Subject: [PATCH 30/48] CI: should build options in name --- .github/workflows/make.yml | 1 + .github/workflows/make32.yml | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/make.yml b/.github/workflows/make.yml index 61933a3..326c95a 100644 --- a/.github/workflows/make.yml +++ b/.github/workflows/make.yml @@ -13,6 +13,7 @@ env: jobs: build: + name: Build (PAGING=${{ matrix.demand_paging }}, FLOAT=${{ matrix.support_fp }}) # This uses a Unix Makefile and should run on Linux and Mac runs-on: ubuntu-latest diff --git a/.github/workflows/make32.yml b/.github/workflows/make32.yml index 862407b..e43e81a 100644 --- a/.github/workflows/make32.yml +++ b/.github/workflows/make32.yml @@ -13,9 +13,15 @@ env: jobs: build: + name: Build 32-bit (PAGING=${{ matrix.demand_paging }}, FLOAT=${{ matrix.support_fp }}) # This uses a Unix Makefile and should run on Linux and Mac runs-on: ubuntu-latest + strategy: + matrix: + demand_paging: [0, 1] + support_fp: [0, 1] + steps: - uses: actions/checkout@v2 @@ -24,5 +30,5 @@ jobs: - name: Build and Test working-directory: ${{github.workspace}}/platforms/unix - run: make test WIDTHOPT=-m32 ASAN=1 + run: make test WIDTHOPT=-m32 ASAN=1 XCPPFLAGS="-DPF_SUPPORT_FP=${{ matrix.support_fp }} -DPF_DEMAND_PAGING=${{ matrix.demand_paging }} -D_DEFAULT_SOURCE -D_GNU_SOURCE" From b7a8f43bdaaf6a0eaee11bf6067684164c4beed5 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Thu, 7 May 2026 13:39:11 -0700 Subject: [PATCH 31/48] fix demand paging unit tests --- csrc/paging/dmpaging.h | 4 ++-- csrc/paging/qadmpage.c | 11 ++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index 307d013..868db94 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -106,7 +106,7 @@ uint8_t *pfLockMemoryReadWrite(vm_address_t vp, uint32_t numBytes); * to improve performance. * @param vp virtual memory address * @param pp physical memory address - * @return negative code if an error occured + * @return negative code if an error occured else zero */ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp); @@ -133,7 +133,7 @@ void *pfCopyToVirtualMemory(vm_address_t destination, */ void pfFreeVirtualMemory(vm_address_t address); -/** Set a region of virtual memory to a value. +/** Set a region of virtual memory to a byte value. * @param destination in physical or paged memory * @param value fill memory with this value * @param numBytes how many bytes to set diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index 0a6f4fa..07785f0 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -263,16 +263,16 @@ static int pfQaTestSetVirtualMemory(void) { dest = pfSetVirtualMemory(vm1, 0x5A, largeSize); ASSERT_EQ(dest, vm1); dest = pfSetVirtualMemory(vm1 + smallOffset, 0x3C, smallSize); - ASSERT_EQ(dest, vm1); + ASSERT_EQ(dest, vm1 + smallOffset); i = 0; for (; i < smallOffset; i++) { - ASSERT_EQ(0x3C, DP_FETCH_U8(vm1 + i)); + ASSERT_EQ(0x5A, DP_FETCH_U8(vm1 + i)); } for (; i < smallOffset + smallSize; i++) { - ASSERT_EQ(0x5A, DP_FETCH_U8(vm1 + i)); + ASSERT_EQ(0x3C, DP_FETCH_U8(vm1 + i)); } for (; i < largeSize; i++) { - ASSERT_EQ(0x3C, DP_FETCH_U8(vm1 + i)); + ASSERT_EQ(0x5A, DP_FETCH_U8(vm1 + i)); } return 0; error: @@ -281,9 +281,6 @@ static int pfQaTestSetVirtualMemory(void) { int pfQaDemandPaging(void) { printf("pfQaDemandPaging\n"); - int x = 4; - int y = 4; - ASSERT_EQ(x,y); ASSERT_EQ(sizeof(vm_address_t), sizeof(cell_t)); From 46a45970005e7b8f007f9e657a13d6044e11ab86 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Thu, 7 May 2026 13:39:39 -0700 Subject: [PATCH 32/48] reduce use of int data type --- csrc/pf_core.c | 14 ++++++++------ csrc/pf_core.h | 2 +- csrc/pf_inner.c | 2 +- csrc/pf_io.c | 2 +- csrc/pfcompil.c | 4 ++-- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/csrc/pf_core.c b/csrc/pf_core.c index 9f95a67..97c300a 100644 --- a/csrc/pf_core.c +++ b/csrc/pf_core.c @@ -119,10 +119,6 @@ static void pfInit( void ) pfResetLockedMemory(); ioInit(); -#if PF_DEMAND_PAGING - pfQaDemandPaging(); /* FIXME move to standalone qa test */ -#endif - } static void pfTerm( void ) { @@ -136,6 +132,7 @@ static void pfTerm( void ) void pfDeleteTask( PForthTask task ) { pfTaskData_t *cftd = (pfTaskData_t *)task; + if (cftd == NULL) return; #ifdef PF_SUPPORT_FP FREE_VAR( cftd->td_FloatStackLimit ); #endif @@ -441,7 +438,7 @@ void pfDebugMessage( const char *CString ) /*************************************************************** ** Print a decimal number to debug output. */ -void pfDebugPrintDecimalNumber( int n ) +void pfDebugPrintDecimalNumber( cell_t n ) { pfDebugMessage( ConvertNumberToText( n, 10, TRUE, 1 ) ); } @@ -462,7 +459,7 @@ void pfMessage( const char *CString ) */ ThrowCode pfDoForth( const char *DicFileName, const char *SourceName, cell_t IfInit ) { - pfTaskData_t *cftd; + pfTaskData_t *cftd = NULL; pfDictionary_t *dic = NULL; ThrowCode Result = 0; ExecToken EntryPoint = 0; @@ -474,6 +471,11 @@ ThrowCode pfDoForth( const char *DicFileName, const char *SourceName, cell_t IfI pfInit(); +#if PF_DEMAND_PAGING + Result = pfQaDemandPaging(); /* FIXME move to standalone qa test */ + if (Result != 0) goto error2; +#endif + /* Allocate Task structure. */ pfDebugMessage("pfDoForth: call pfCreateTask()\n"); cftd = pfCreateTask( DEFAULT_USER_DEPTH, DEFAULT_RETURN_DEPTH ); diff --git a/csrc/pf_core.h b/csrc/pf_core.h index 46b5753..d593791 100644 --- a/csrc/pf_core.h +++ b/csrc/pf_core.h @@ -29,7 +29,7 @@ extern "C" { void pfInitGlobals( void ); void pfDebugMessage( const char *CString ); -void pfDebugPrintDecimalNumber( int n ); +void pfDebugPrintDecimalNumber( cell_t n ); cell_t pfUnitTestText( void ); diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index bf23f2c..9ebc283 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1983,7 +1983,7 @@ DBUGX(("After 0Branch: IP = 0x%x\n", InsPtr )); if( _CrtCheckMemory() == 0 ) { ERR("_CrtCheckMemory abort: InsPtr = 0x"); - ffDotHex((int)InsPtr); + ffDotHex((cell_t)InsPtr); ERR("\n"); } #endif diff --git a/csrc/pf_io.c b/csrc/pf_io.c index 56aeeee..c4cd62f 100644 --- a/csrc/pf_io.c +++ b/csrc/pf_io.c @@ -96,7 +96,7 @@ cell_t ioKey( void ) cell_t ioAccept( char *buffer, cell_t maxChars ) { int c; - int len; + cell_t len; char *p; DBUGX(("ioAccept(0x%x, 0x%x)\n", buffer, len )); diff --git a/csrc/pfcompil.c b/csrc/pfcompil.c index b8aff4c..2f42419 100644 --- a/csrc/pfcompil.c +++ b/csrc/pfcompil.c @@ -966,7 +966,7 @@ ThrowCode ffIncludeFile( FileStream *InputFile ) exception = ffOuterInterpreterLoop(); if( exception ) { - int i; + cell_t i; /* Report line number and nesting level. */ MSG("INCLUDE error on line #"); ffDot(gCurrentTask->td_LineNumber); MSG(", level = "); ffDot(gIncludeIndex ); @@ -1116,7 +1116,7 @@ FileStream * ffConvertSourceIDToStream( cell_t id ) static cell_t readLineFromStream( char *buffer, cell_t maxChars, FileStream *stream ) { int c; - int len; + cell_t len; char *p; static int lastChar = 0; int done = 0; From fef42f547bf54eb7825018c95244e42b2a80208d Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Thu, 7 May 2026 13:53:53 -0700 Subject: [PATCH 33/48] turn off demand paging by default --- csrc/paging/dmpaging.h | 26 +++++++++++++++++++------- csrc/pforth.h | 8 ++++---- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index 868db94..bab3fbc 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -25,8 +25,12 @@ extern "C" { #endif +/** + * To use demand paged memory, enable the code by passing -DPF_DEMAND_PAGING=1 + * to the C compiler. + */ typedef uint8_t *vm_address_t; /** an address that may be in physical or paged memory */ -typedef uint8_t *paging_address_t; /** an address that may be in paged memory */ +typedef uint8_t *paging_address_t; /** an address in paged memory */ /* Basic memory access macros. */ #if (PF_DEMAND_PAGING == 0) @@ -40,7 +44,9 @@ typedef uint8_t *paging_address_t; /** an address that may be in paged memory */ #define DP_STORE_U16(address, value) *((uint16_t *)(address)) = (uint16_t)(value) #define DP_STORE_CELL(address, value) *((cell_t *)(address)) = (cell_t)(value) #define DP_STORE_FLOAT(address, value) *((PF_FLOAT *)(address)) = (PF_FLOAT)(value) -#else + +#else /* PF_DEMAND_PAGING */ + /* Use either physical or paged memory. */ #define DP_FETCH_U8(address) pfFetchVirtualU8((const uint8_t *)(address)) #define DP_FETCH_U16(address) pfFetchVirtualU16((const uint16_t *)(address)) @@ -51,7 +57,7 @@ typedef uint8_t *paging_address_t; /** an address that may be in paged memory */ #define DP_STORE_U16(address, value) pfStoreVirtualU16(((uint16_t *)(address)), (uint16_t)(value)) #define DP_STORE_CELL(address, value) pfStoreVirtualCell(((cell_t *)(address)), (cell_t)(value)) #define DP_STORE_FLOAT(address, value) pfStoreVirtualFloat(((PF_FLOAT *)(address)), (PF_FLOAT)(value)) -#endif +#endif /* PF_DEMAND_PAGING */ uint8_t pfFetchVirtualU8(const uint8_t *address); uint16_t pfFetchVirtualU16(const uint16_t *address); @@ -86,6 +92,9 @@ void pfResetLockedMemory(void); * a single primitive. * If the virtual memory address is not in paged memory then it will be passed through. * You cannot lock more than DP_MAX_REGION_SIZE bytes. + * + * @param vp virtual address in physical or paged memory + * @param numBytes number of byte in region * @return physical address that can be used by normal C code as “const” memory. */ const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, uint32_t numBytes); @@ -95,6 +104,9 @@ const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, uint32_t numBytes); * Load the data from demand paging if not already loaded. * If the virtual memory address is not in paged memory then it will be passed through. * You cannot lock more than DP_MAX_REGION_SIZE bytes. + * + * @param vp virtual address in physical or paged memory + * @param numBytes number of byte in region * @return physical address that can be read or written by normal C code. */ uint8_t *pfLockMemoryReadWrite(vm_address_t vp, uint32_t numBytes); @@ -104,15 +116,15 @@ uint8_t *pfLockMemoryReadWrite(vm_address_t vp, uint32_t numBytes); * Writable regions will be written back to serial memory. * Regions may be kept in physical memory on an LRU basis * to improve performance. - * @param vp virtual memory address + * @param vp virtual address in physical or paged memory * @param pp physical memory address * @return negative code if an error occured else zero */ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp); /** Copy from virtual to physical memory. - * @param destination in physical memory - * @param source The data may be in physical or paged memory. + * @param destination target address in physical memory + * @param source data address in physical or paged memory * @return destination */ void *pfCopyFromVirtualMemory(void *destination, @@ -120,7 +132,7 @@ void *pfCopyFromVirtualMemory(void *destination, uint32_t numBytes); /** Copy from physical to virtual memory. - * @param destination The target may be in physical or paged memory. + * @param destination target address in physical or paged memory * @param source in physical memory * @return destination */ diff --git a/csrc/pforth.h b/csrc/pforth.h index f7824db..64b04b1 100644 --- a/csrc/pforth.h +++ b/csrc/pforth.h @@ -25,11 +25,12 @@ ** ***************************************************************/ -/* Define stubs for data types so we can pass pointers but not touch inside. */ +/* Opaque pointer types used to hide internal structures. */ typedef void *PForthTask; typedef void *PForthDictionary; #include + #if INTPTR_MAX == INT64_MAX #define PF_64BIT 1 #define PF_32BIT 0 @@ -41,14 +42,14 @@ typedef void *PForthDictionary; #endif /* Integer types for Forth cells, signed and unsigned: */ -typedef intptr_t cell_t; +typedef intptr_t cell_t; /* primary data type for the stack and dictionary */ typedef uintptr_t ucell_t; typedef ucell_t ExecToken; /* Execution Token */ typedef cell_t ThrowCode; #ifndef PF_DEMAND_PAGING -#define PF_DEMAND_PAGING 1 +#define PF_DEMAND_PAGING 0 #endif #ifdef __cplusplus @@ -103,7 +104,6 @@ ThrowCode pfIncludeFile( const char *FileName ); /* Execute a Forth word by name. */ ThrowCode pfExecIfDefined( const char *CString ); - /* Assertion macro for pForth. */ extern cell_t gPfAssertEnabled; #define PF_ASSERT(_expr) do { \ From d6900cd2f4f78b6c9b04c43c8b212f0a94ef1963 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Fri, 8 May 2026 18:29:19 -0700 Subject: [PATCH 34/48] Support different sized ptr and cell DRAFT - need to try on RPi in 32-bit mode --- csrc/paging/dmpaging.h | 9 ++-- csrc/paging/lockpage.c | 28 +++++----- csrc/paging/pagedmem.c | 4 +- csrc/pf_cglue.c | 2 +- csrc/pf_core.c | 2 +- csrc/pf_guts.h | 34 +++++++------ csrc/pf_inner.c | 8 +-- csrc/pf_io.h | 6 +-- csrc/pf_save.c | 6 +-- csrc/pf_words.c | 16 +++--- csrc/pfcompil.c | 113 +++++++++++++++++++---------------------- csrc/pfcompil.h | 8 +-- csrc/pforth.h | 48 +++++++++++++---- 13 files changed, 151 insertions(+), 133 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index bab3fbc..3a978b2 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -29,8 +29,7 @@ extern "C" { * To use demand paged memory, enable the code by passing -DPF_DEMAND_PAGING=1 * to the C compiler. */ -typedef uint8_t *vm_address_t; /** an address that may be in physical or paged memory */ -typedef uint8_t *paging_address_t; /** an address in paged memory */ +typedef ucell_t paging_address_t; /** an address in paged memory */ /* Basic memory access macros. */ #if (PF_DEMAND_PAGING == 0) @@ -136,8 +135,8 @@ void *pfCopyFromVirtualMemory(void *destination, * @param source in physical memory * @return destination */ -void *pfCopyToVirtualMemory(vm_address_t destination, - void * source, +vm_address_t pfCopyToVirtualMemory(vm_address_t destination, + const void *source, uint32_t numBytes); /** Free virtual memory. @@ -151,7 +150,7 @@ void pfFreeVirtualMemory(vm_address_t address); * @param numBytes how many bytes to set * @return destination */ -void *pfSetVirtualMemory(vm_address_t destination, +vm_address_t pfSetVirtualMemory(vm_address_t destination, uint8_t value, uint32_t numBytes); diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index adbb558..b89d933 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -45,23 +45,23 @@ int pfIsAddressInPagedMemory(vm_address_t p) { void *pfCopyFromVirtualMemory(void *destination, vm_address_t source, uint32_t numBytes) { - return pfCopyMemory(destination, source, numBytes); + return pfCopyMemory(destination, (const void *)source, numBytes); } -void *pfCopyToVirtualMemory(vm_address_t destination, - void * source, +vm_address_t pfCopyToVirtualMemory(vm_address_t destination, + const void *source, uint32_t numBytes) { - return pfCopyMemory(destination, source, numBytes); + return (vm_address_t) pfCopyMemory((void *)destination, source, numBytes); } void pfFreeVirtualMemory(vm_address_t address) { - pfFreeMem(address); + pfFreeMem((void *)address); } -void *pfSetVirtualMemory(vm_address_t destination, +vm_address_t pfSetVirtualMemory(vm_address_t destination, uint8_t value, uint32_t numBytes) { - return pfSetMemory(destination, value, numBytes); + return (vm_address_t) pfSetMemory((void *)destination, value, numBytes); } #else /* PF_DEMAND_PAGING */ @@ -247,20 +247,20 @@ void *pfCopyFromVirtualMemory(void *destination, uint32_t numBytes) { if (pfIsAddressInPagedMemory(source)) { pfReadPagedMemory(destination, (paging_address_t) source, numBytes); /* TODO check result */ - return destination; + return (void *) destination; } else { - return pfCopyMemory(destination, source, numBytes); + return pfCopyMemory(destination, (void *) source, numBytes); } } -void *pfCopyToVirtualMemory(vm_address_t destination, - void * source, +vm_address_t pfCopyToVirtualMemory(vm_address_t destination, + const void *source, uint32_t numBytes) { if (pfIsAddressInPagedMemory(destination)) { pfWritePagedMemory((paging_address_t) destination, source, numBytes); /* TODO check result */ return destination; } else { - return pfCopyMemory(destination, source, numBytes); + return (vm_address_t) pfCopyMemory((void *) destination, source, numBytes); } } @@ -268,11 +268,11 @@ void pfFreeVirtualMemory(vm_address_t address) { if (pfIsAddressInPagedMemory(address)) { pfFreePagedMemory((paging_address_t) address); } else { - pfFreeMem(address); + pfFreeMem((void *) address); } } -void *pfSetVirtualMemory(vm_address_t destination, +vm_address_t pfSetVirtualMemory(vm_address_t destination, uint8_t value, uint32_t numBytes) { if (pfIsAddressInPagedMemory(destination)) { diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index de8d16b..c2c62e7 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -41,9 +41,9 @@ static cell_t sDpNextAvailable = 0; */ #if 0 #define PF_DP_MUNGE_KEY (0) -#elif (PF_64BIT) +#elif (PF_CELL_SIZE == 8) #define PF_DP_MUNGE_KEY (0x005A000000000000) -#elif (PF_32BIT) +#elif (PF_CELL_SIZE == 4) #define PF_DP_MUNGE_KEY (0x50000000) #endif diff --git a/csrc/pf_cglue.c b/csrc/pf_cglue.c index 6c6ab0b..2106190 100644 --- a/csrc/pf_cglue.c +++ b/csrc/pf_cglue.c @@ -94,7 +94,7 @@ Err CreateGlueToC( const char *CName, ucell_t Index, cell_t ReturnMode, int32_t DBUG(("Packed = 0x%8x\n", Packed)); ffCreateSecondaryHeader( FName ); - CODE_COMMA( ID_CALL_C ); + CODE_COMMA(ID_CALL_C); CODE_COMMA(Packed); ffFinishSecondary(); diff --git a/csrc/pf_core.c b/csrc/pf_core.c index 97c300a..d22225b 100644 --- a/csrc/pf_core.c +++ b/csrc/pf_core.c @@ -279,7 +279,7 @@ PForthDictionary pfCreateDictionary( cell_t HeaderSize, cell_t CodeSize ) pfSetVirtualMemory((vm_address_t) dic->dic_CodeBase, 0x5A, (uint32_t) CodeSize); dic->dic_CodeLimit = dic->dic_CodeBase + CodeSize; - dic->dic_CodePtr.Byte = ((uint8_t *) (dic->dic_CodeBase + QUADUP(NUM_PRIMITIVES))); + dic->dic_CodePtr = (vm_address_t) (dic->dic_CodeBase + (QUADUP(NUM_PRIMITIVES) * PF_CELL_SIZE)); return (PForthDictionary) dic; nomem: diff --git a/csrc/pf_guts.h b/csrc/pf_guts.h index d0f298d..a3e683b 100644 --- a/csrc/pf_guts.h +++ b/csrc/pf_guts.h @@ -449,6 +449,12 @@ typedef struct pfNode struct pfNode *n_Prev; } pfNode; +/* Define offsets to fields in an header entry. */ +#define PF_HEADER_OFFSET_PREVIOUS_NAME (0) +#define PF_HEADER_OFFSET_EXEC_TOKEN (PF_CELL_SIZE) +#define PF_HEADER_OFFSET_NFA (PF_HEADER_OFFSET_EXEC_TOKEN + PF_CELL_SIZE) + +#if 0 /* Structure of header entry in dictionary. These will be stored in dictionary specific endian format*/ typedef struct cfNameLinks { @@ -456,6 +462,7 @@ typedef struct cfNameLinks ExecToken cfnl_ExecToken; /* Execution token for word. */ /* Followed by variable length name field. */ } cfNameLinks; +#endif #define PF_DICF_ALLOCATED_SEGMENTS ( 0x0001) typedef struct pfDictionary_s @@ -463,21 +470,16 @@ typedef struct pfDictionary_s pfNode dic_Node; ucell_t dic_Flags; /* Headers contain pointers to names and dictionary. */ + vm_address_t dic_HeaderBaseUnaligned; - ucell_t dic_HeaderBaseUnaligned; - - ucell_t dic_HeaderBase; - ucell_t dic_HeaderPtr; - ucell_t dic_HeaderLimit; + vm_address_t dic_HeaderBase; + vm_address_t dic_HeaderPtr; + vm_address_t dic_HeaderLimit; /* Code segment contains tokenized code and data. */ - ucell_t dic_CodeBaseUnaligned; - ucell_t dic_CodeBase; - union - { - cell_t *Cell; - uint8_t *Byte; - } dic_CodePtr; - ucell_t dic_CodeLimit; + vm_address_t dic_CodeBaseUnaligned; + vm_address_t dic_CodeBase; + vm_address_t dic_CodePtr; + vm_address_t dic_CodeLimit; } pfDictionary_t; /* Save state of include when nesting files. */ @@ -577,8 +579,8 @@ extern cell_t gIncludeIndex; #endif #define HEADER_HERE (gCurrentDictionary->dic_HeaderPtr.Cell) -#define CODE_HERE (gCurrentDictionary->dic_CodePtr.Cell) -#define CODE_COMMA( N ) WRITE_CELL_DIC(CODE_HERE++,(N)) +#define CODE_HERE (gCurrentDictionary->dic_CodePtr) +#define CODE_COMMA(N) { WRITE_CELL_DIC(CODE_HERE,(N)); CODE_HERE += PF_CELL_SIZE; } #define NAME_BASE (gCurrentDictionary->dic_HeaderBase) #define CODE_BASE (gCurrentDictionary->dic_CodeBase) #define NAME_SIZE (gCurrentDictionary->dic_HeaderLimit - gCurrentDictionary->dic_HeaderBase) @@ -598,7 +600,7 @@ extern cell_t gIncludeIndex; /* The check for >0 is only needed for CLONE testing. !!! */ #define IsTokenPrimitive(xt) ((xt=0)) -#define FREE_VAR(v) { pfFreeVirtualMemory((void *)(v)); v = 0; } +#define FREE_VAR(v) { pfFreeVirtualMemory((vm_address_t)(v)); v = 0; } #define DATA_STACK_DEPTH (gCurrentTask->td_StackBase - gCurrentTask->td_StackPtr) #define DROP_DATA_STACK (gCurrentTask->td_StackPtr++) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 9ebc283..b381834 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1230,7 +1230,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_FINDNFA: /* ( $name -- $addr 0 | nfa -1 | nfa 1 , find NFA in dictionary ) */ { - vm_address_t nfa = NULL; + vm_address_t nfa = (vm_address_t) NULL; vm_address_t vName = (vm_address_t) TOS; cell_t totalLength = DP_FETCH_U8(vName) + 1; /* length including count */ const char *pAddr = (const char *) pfLockMemoryReadOnly(vName, totalLength); @@ -1484,11 +1484,11 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); #ifndef PF_NO_SHELL case ID_NAME_TO_TOKEN: - TOS = (cell_t) NameToToken((ForthString *)TOS); + TOS = (cell_t) NameToToken(TOS); endcase; case ID_NAME_TO_PREVIOUS: - TOS = (cell_t) NameToPrevious((ForthString *)TOS); + TOS = (cell_t) NameToPrevious(TOS); endcase; #endif @@ -1880,7 +1880,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_VAR_CODE_BASE: DO_VAR(gCurrentDictionary->dic_CodeBase); endcase; case ID_VAR_CODE_LIMIT: DO_VAR(gCurrentDictionary->dic_CodeLimit); endcase; case ID_VAR_CONTEXT: DO_VAR(gVarContext); endcase; - case ID_VAR_DP: DO_VAR(gCurrentDictionary->dic_CodePtr.Cell); endcase; + case ID_VAR_DP: DO_VAR(gCurrentDictionary->dic_CodePtr); endcase; case ID_VAR_ECHO: DO_VAR(gVarEcho); endcase; case ID_VAR_HEADERS_BASE: DO_VAR(gCurrentDictionary->dic_HeaderBase); endcase; case ID_VAR_HEADERS_LIMIT: DO_VAR(gCurrentDictionary->dic_HeaderLimit); endcase; diff --git a/csrc/pf_io.h b/csrc/pf_io.h index 4db8faf..667f5f2 100644 --- a/csrc/pf_io.h +++ b/csrc/pf_io.h @@ -119,9 +119,9 @@ void ioTerm( void ); #else #ifdef PF_USER_FILEIO -/* Get user prototypes or macros from include file. -** API must match that defined above for the stubs. -*/ + /* Get user prototypes or macros from include file. + ** API must match that defined above for the stubs. + */ #include PF_USER_FILEIO #else diff --git a/csrc/pf_save.c b/csrc/pf_save.c index bbd36e0..f502939 100644 --- a/csrc/pf_save.c +++ b/csrc/pf_save.c @@ -407,7 +407,7 @@ cell_t ffSaveForth( const char *FileName, ExecToken EntryPoint, cell_t NameSize, /* Write P4DI Dictionary Info ------------------ */ SD.sd_Version = PF_FILE_VERSION; - relativeCodePtr = ABS_TO_CODEREL(gCurrentDictionary->dic_CodePtr.Byte); /* 940225 */ + relativeCodePtr = (uint32_t) ABS_TO_CODEREL(gCurrentDictionary->dic_CodePtr); /* 940225 */ SD.sd_RelCodePtr = relativeCodePtr; SD.sd_UserStackSize = sizeof(cell_t) * (gCurrentTask->td_StackBase - gCurrentTask->td_StackLimit); SD.sd_ReturnStackSize = sizeof(cell_t) * (gCurrentTask->td_ReturnBase - gCurrentTask->td_ReturnLimit); @@ -665,7 +665,7 @@ DBUG(("pfLoadDictionary( %s )\n", FileName )); gVarContext = 0; gCurrentDictionary->dic_HeaderPtr = (ucell_t)NULL; } - gCurrentDictionary->dic_CodePtr.Byte = (uint8_t *) CODEREL_TO_ABS(sd->sd_RelCodePtr); + gCurrentDictionary->dic_CodePtr = (vm_address_t) CODEREL_TO_ABS(sd->sd_RelCodePtr); gNumPrimitives = sd->sd_NumPrimitives; /* Must match compiled dictionary. */ /* Pass EntryPoint back to caller. */ if( EntryPointPtr != NULL ) *EntryPointPtr = sd->sd_EntryPoint; @@ -831,7 +831,7 @@ PForthDictionary pfLoadStaticDictionary( void ) DBUG(("Static data copied to newly allocated dictionaries.\n")); - dic->dic_CodePtr.Byte = (uint8_t *) CODEREL_TO_ABS(CODEPTR); + dic->dic_CodePtr = CODEREL_TO_ABS(CODEPTR); gNumPrimitives = NUM_PRIMITIVES; if( NAME_BASE != 0) diff --git a/csrc/pf_words.c b/csrc/pf_words.c index 1301e6d..2539268 100644 --- a/csrc/pf_words.c +++ b/csrc/pf_words.c @@ -254,16 +254,16 @@ char * ffLWord( char c ) size_t ffReadFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ) { - size_t numBytes = Size * nItems; + vm_address_t vp = (vm_address_t)ptr; + uint32_t numBytes = (uint32_t)(Size * nItems); if (numBytes == 0) { return 0; - } else if (pfIsAddressInPagedMemory(ptr)) { + } else if (pfIsAddressInPagedMemory(vp)) { /* Read file in blocks that will fit in locked regions. */ - vm_address_t vp = (vm_address_t)ptr; cell_t numBytes = Size * nItems; cell_t bytesRead = 0; while (numBytes > 0) { - cell_t bytesToRead = (numBytes < DP_MAX_REGION_SIZE) ? numBytes : DP_MAX_REGION_SIZE; + uint32_t bytesToRead = (numBytes < DP_MAX_REGION_SIZE) ? numBytes : DP_MAX_REGION_SIZE; uint8_t *buffer = pfLockMemoryReadWrite(vp, bytesToRead); cell_t numRead = sdReadFile(buffer, 1, bytesToRead, Stream); pfUnlockMemory(vp, buffer); /* writes to backing storage */ @@ -283,15 +283,15 @@ size_t ffReadFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ) size_t ffWriteFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ) { - size_t numBytes = Size * nItems; + vm_address_t vp = (vm_address_t)ptr; + uint32_t numBytes = (uint32_t)(Size * nItems); if (numBytes == 0) { return 0; - } else if (pfIsAddressInPagedMemory(ptr)) { + } else if (pfIsAddressInPagedMemory(vp)) { /* Write file in blocks that will fit in locked regions. */ - vm_address_t vp = (vm_address_t)ptr; cell_t bytesWritten = 0; while (numBytes > 0) { - cell_t bytesToWrite = (numBytes < DP_MAX_REGION_SIZE) ? numBytes : DP_MAX_REGION_SIZE; + uint32_t bytesToWrite = (numBytes < DP_MAX_REGION_SIZE) ? numBytes : DP_MAX_REGION_SIZE; const uint8_t *buffer = pfLockMemoryReadOnly(vp, bytesToWrite); cell_t numWritten = sdWriteFile(buffer, 1, bytesToWrite, Stream); pfUnlockMemory(vp, buffer); /* writes to backing storage */ diff --git a/csrc/pfcompil.c b/csrc/pfcompil.c index 2f42419..c299437 100644 --- a/csrc/pfcompil.c +++ b/csrc/pfcompil.c @@ -28,7 +28,7 @@ #include "pfcompil.h" #define ABORT_RETURN_CODE (10) -#define UINT32_MASK ((sizeof(ucell_t)-1)) +#define CELL_MASK ((sizeof(ucell_t)-1)) /***************************************************************/ /************** Static Prototypes ******************************/ @@ -59,36 +59,37 @@ cell_t NotCompiled( const char *FunctionName ) */ void CreateDicEntry(ExecToken XT, const char *FName, ucell_t Flags) { - cfNameLinks *cfnl; - - cfnl = (cfNameLinks *) gCurrentDictionary->dic_HeaderPtr; + vm_address_t headerPtr = gCurrentDictionary->dic_HeaderPtr; + vm_address_t previousNamePtr = headerPtr + PF_HEADER_OFFSET_PREVIOUS_NAME; + vm_address_t execTokenPtr = headerPtr + PF_HEADER_OFFSET_EXEC_TOKEN; + vm_address_t nfaPtr = headerPtr + PF_HEADER_OFFSET_NFA; /* Set link to previous header, if any. */ if( gVarContext ) { - WRITE_CELL_DIC(&cfnl->cfnl_PreviousName, ABS_TO_NAMEREL( gVarContext )); + WRITE_CELL_DIC(previousNamePtr, ABS_TO_NAMEREL( gVarContext )); } else { - WRITE_CELL_DIC(&cfnl->cfnl_PreviousName, 0); + WRITE_CELL_DIC(previousNamePtr, 0); } /* Put Execution token in header. */ - WRITE_CELL_DIC( &cfnl->cfnl_ExecToken, XT ); + WRITE_CELL_DIC(execTokenPtr, XT); -/* Advance Header Dictionary Pointer */ - gCurrentDictionary->dic_HeaderPtr += sizeof(cfNameLinks); +/* Advance Header Dictionary Pointer to the NFA. */ + gCurrentDictionary->dic_HeaderPtr = nfaPtr; /* Laydown name. */ gVarContext = gCurrentDictionary->dic_HeaderPtr; - pfCopyToVirtualMemory((uint8_t *) gCurrentDictionary->dic_HeaderPtr, FName, (*FName)+1); + pfCopyToVirtualMemory(gCurrentDictionary->dic_HeaderPtr, FName, (*FName)+1); gCurrentDictionary->dic_HeaderPtr += (*FName)+1; /* Set flags. */ DP_STORE_U8(gVarContext, DP_FETCH_U8(gVarContext) | (uint8_t)Flags); -/* Align to quad byte boundaries with zeroes. */ - while( gCurrentDictionary->dic_HeaderPtr & UINT32_MASK ) +/* Align to cell byte boundaries with zeroes. */ + while( gCurrentDictionary->dic_HeaderPtr & CELL_MASK ) { DP_STORE_U8(gCurrentDictionary->dic_HeaderPtr++, 0); } @@ -104,40 +105,33 @@ void CreateDicEntryC( ExecToken XT, const char *CName, ucell_t Flags ) CreateDicEntry( XT, FName, Flags ); } +/* Define offsets to fields in an header entry. */ +#define PF_HEADER_OFFSET_PREVIOUS_NAME (0) +#define PF_HEADER_OFFSET_EXEC_TOKEN (PF_CELL_SIZE) +#define PF_HEADER_OFFSET_NFA (PF_HEADER_OFFSET_EXEC_TOKEN + PF_CELL_SIZE) + /*************************************************************** ** Convert absolute namefield address to previous absolute name ** field address or NULL. */ -const ForthString *NameToPrevious( const ForthString *NFA ) +vm_address_t NameToPrevious(vm_address_t NFA) { - cell_t RelNamePtr; - const cfNameLinks *cfnl; - -/* DBUG(("\nNameToPrevious: NFA = 0x%x\n", (cell_t) NFA)); */ - cfnl = (const cfNameLinks *) ( ((const char *) NFA) - sizeof(cfNameLinks) ); - - RelNamePtr = READ_CELL_DIC((const cell_t *) (&cfnl->cfnl_PreviousName)); -/* DBUG(("\nNameToPrevious: RelNamePtr = 0x%x\n", (cell_t) RelNamePtr )); */ - if( RelNamePtr ) - { - return ( (ForthString *) NAMEREL_TO_ABS( RelNamePtr ) ); - } - else - { - return NULL; + vm_address_t previousNamePtr = NFA - PF_HEADER_OFFSET_NFA + PF_HEADER_OFFSET_PREVIOUS_NAME; + cell_t relativeNamePtr = READ_CELL_DIC(previousNamePtr); + if (relativeNamePtr) { + return NAMEREL_TO_ABS( relativeNamePtr ); + } else { + return (vm_address_t) NULL; } } + /*************************************************************** ** Convert NFA to ExecToken. */ -ExecToken NameToToken( const ForthString *NFA ) +ExecToken NameToToken(vm_address_t NFA) { - const cfNameLinks *cfnl; - -/* Convert absolute namefield address to absolute link field address. */ - cfnl = (const cfNameLinks *) ( ((const char *) NFA) - sizeof(cfNameLinks) ); - - return READ_CELL_DIC((const cell_t *) (&cfnl->cfnl_ExecToken)); + vm_address_t tokenPtr = NFA - PF_HEADER_OFFSET_NFA + PF_HEADER_OFFSET_EXEC_TOKEN; + return READ_CELL_DIC(tokenPtr); } /*************************************************************** @@ -415,14 +409,14 @@ PForthDictionary pfBuildDictionary( cell_t HeaderSize, cell_t CodeSize ) ** ( xt -- nfa 1 , x 0 , find NFA in dictionary from XT ) ** 1 for IMMEDIATE values */ -cell_t ffTokenToName( ExecToken XT, const ForthString **NFAPtr ) +cell_t ffTokenToName( ExecToken XT, vm_address_t *NFAPtr ) { - const ForthString *NameField; + vm_address_t NameField; cell_t Searching = TRUE; cell_t Result = 0; ExecToken TempXT; - NameField = (ForthString *) gVarContext; + NameField = gVarContext; DBUGX(("\ffCodeToName: gVarContext = 0x%x\n", gVarContext)); do @@ -439,7 +433,7 @@ DBUGX(("ffCodeToName: NFA = 0x%x\n", NameField)); else { NameField = NameToPrevious( NameField ); - if( NameField == NULL ) + if( NameField == PF_VM_NULL ) { *NFAPtr = 0; Searching = FALSE; @@ -454,7 +448,7 @@ DBUGX(("ffCodeToName: NFA = 0x%x\n", NameField)); ** ( $name -- $addr 0 | nfa -1 | nfa 1 , find NFA in dictionary ) ** 1 for IMMEDIATE values */ -cell_t ffFindNFA( const ForthString *WordName, const ForthString **NFAPtr ) +cell_t ffFindNFA( const ForthString *WordName, vm_address_t *NFAPtr ) { const ForthString *WordChar; uint8_t WordLen; @@ -483,16 +477,16 @@ DBUG(("\nffFindNFA: gVarContext = 0x%x\n", gVarContext)); ffCompareTextCaseN( pNameChar, WordChar, WordLen ) ) /* FIXME - slow */ { DBUG(("ffFindNFA: found it at NFA = 0x%x\n", NameField)); - *NFAPtr = (const ForthString *) vNameField ; + *NFAPtr = vNameField ; Result = (countAndFlags & FLAG_IMMEDIATE) ? 1 : -1; Searching = FALSE; } else { vNextNameField = NameToPrevious( vNameField ); - if( vNextNameField == NULL ) + if( vNextNameField == PF_VM_NULL ) { - *NFAPtr = WordName; + *NFAPtr = (vm_address_t) WordName; Searching = FALSE; } } @@ -510,7 +504,7 @@ DBUG(("ffFindNFA: returns 0x%x\n", Result)); */ cell_t ffFind( const ForthString *WordName, ExecToken *pXT ) { - const ForthString *NFA; + vm_address_t NFA; cell_t Result; Result = ffFindNFA( WordName, &NFA ); @@ -549,16 +543,16 @@ DBUG(("ffFindC: %s\n", WordName )); static cell_t ffCheckDicRoom( void ) { cell_t RoomLeft; - RoomLeft = (char *)gCurrentDictionary->dic_HeaderLimit - - (char *)gCurrentDictionary->dic_HeaderPtr; + RoomLeft = gCurrentDictionary->dic_HeaderLimit - + gCurrentDictionary->dic_HeaderPtr; if( RoomLeft < DIC_SAFETY_MARGIN ) { pfReportError("ffCheckDicRoom", PF_ERR_HEADER_ROOM); return PF_ERR_HEADER_ROOM; } - RoomLeft = (char *)gCurrentDictionary->dic_CodeLimit - - (char *)gCurrentDictionary->dic_CodePtr.Byte; + RoomLeft = gCurrentDictionary->dic_CodeLimit - + gCurrentDictionary->dic_CodePtr; if( RoomLeft < DIC_SAFETY_MARGIN ) { pfReportError("ffCheckDicRoom", PF_ERR_CODE_ROOM); @@ -573,13 +567,13 @@ static cell_t ffCheckDicRoom( void ) void ffCreateSecondaryHeader( const ForthStringPtr FName) { pfDebugMessage("ffCreateSecondaryHeader()\n"); -/* Check for dictionary overflow. */ + /* Check for dictionary overflow. */ if( ffCheckDicRoom() ) return; pfDebugMessage("ffCreateSecondaryHeader: CheckRedefinition()\n"); CheckRedefinition( FName ); -/* Align CODE_HERE */ - CODE_HERE = (cell_t *)( (((ucell_t)CODE_HERE) + UINT32_MASK) & ~UINT32_MASK); + /* Align CODE_HERE */ + CODE_HERE = (vm_address_t)( (((ucell_t)CODE_HERE) + CELL_MASK) & ~CELL_MASK); CreateDicEntry( (ExecToken) ABS_TO_CODEREL(CODE_HERE), FName, FLAG_SMUDGE ); } @@ -734,25 +728,20 @@ void ffLiteral( cell_t Num ) #ifdef PF_SUPPORT_FP void ffFPLiteral( PF_FLOAT fnum ) { - /* Hack for Metrowerks compiler which won't compile the - * original expression. - */ - PF_FLOAT *temp; - cell_t *dicPtr; + vm_address_t dicPtr; /* Make sure that literal float data is float aligned. */ - dicPtr = CODE_HERE + 1; - while( (((ucell_t) dicPtr++) & (sizeof(PF_FLOAT) - 1)) != 0) + dicPtr = CODE_HERE + PF_CELL_SIZE; + while( (((ucell_t) dicPtr) & (sizeof(PF_FLOAT) - 1)) != 0) { + dicPtr += PF_CELL_SIZE; DBUG((" comma NOOP to align FPLiteral\n")); CODE_COMMA( ID_NOOP ); } CODE_COMMA( ID_FP_FLITERAL_P ); - temp = (PF_FLOAT *)CODE_HERE; - WRITE_FLOAT_DIC(temp,fnum); /* Write to dictionary. */ - temp++; - CODE_HERE = (cell_t *) temp; + WRITE_FLOAT_DIC(CODE_HERE, fnum); /* Write to dictionary. */ + CODE_HERE += sizeof(PF_FLOAT); } #endif /* PF_SUPPORT_FP */ diff --git a/csrc/pfcompil.h b/csrc/pfcompil.h index cdafb53..a94522e 100644 --- a/csrc/pfcompil.h +++ b/csrc/pfcompil.h @@ -28,21 +28,21 @@ extern "C" { #endif Err ffPushInputStream( FileStream *InputFile ); -ExecToken NameToToken( const ForthString *NFA ); +ExecToken NameToToken(vm_address_t NFA); FileStream * ffConvertSourceIDToStream( cell_t id ); FileStream *ffPopInputStream( void ); cell_t ffConvertStreamToSourceID( FileStream *Stream ); cell_t ffFind( const ForthString *WordName, ExecToken *pXT ); cell_t ffFindC( const char *WordName, ExecToken *pXT ); -cell_t ffFindNFA( const ForthString *WordName, const ForthString **NFAPtr ); +cell_t ffFindNFA( const ForthString *WordName, vm_address_t *NFAPtr ); cell_t ffNumberQ( const char *FWord, cell_t *Num ); cell_t ffRefill( void ); -cell_t ffTokenToName( ExecToken XT, const ForthString **NFAPtr ); +cell_t ffTokenToName( ExecToken XT, vm_address_t *NFAPtr ); cell_t *NameToCode( ForthString *NFA ); PForthDictionary pfBuildDictionary( cell_t HeaderSize, cell_t CodeSize ); char *ffWord( char c ); char *ffLWord( char c ); -const ForthString *NameToPrevious( const ForthString *NFA ); +vm_address_t NameToPrevious(vm_address_t NFA); cell_t FindSpecialCFAs( void ); cell_t FindSpecialXTs( void ); cell_t NotCompiled( const char *FunctionName ); diff --git a/csrc/pforth.h b/csrc/pforth.h index 64b04b1..0f8ae52 100644 --- a/csrc/pforth.h +++ b/csrc/pforth.h @@ -32,25 +32,53 @@ typedef void *PForthDictionary; #include #if INTPTR_MAX == INT64_MAX - #define PF_64BIT 1 - #define PF_32BIT 0 + #define PF_POINTER_SIZE 8 #elif INTPTR_MAX == INT32_MAX - #define PF_64BIT 0 - #define PF_32BIT 1 + #define PF_POINTER_SIZE 4 +#elif INTPTR_MAX == INT16_MAX + #define PF_POINTER_SIZE 2 #else - #error "Unsupported pointer size" + #error "Unsupported pointer size" +#endif + +/* Set CELL size to match pointer size if not defined. */ +#ifndef PF_CELL_SIZE + #if PF_POINTER_SIZE >= 4 + #define PF_CELL_SIZE PF_POINTER_SIZE + #else + #define PF_CELL_SIZE 4 + #endif +#endif /* PF_CELL_SIZE */ + +#if (PF_CELL_SIZE < PF_POINTER_SIZE) + #error "PF_CELL_SIZE must be at least as big as a pointer." #endif /* Integer types for Forth cells, signed and unsigned: */ -typedef intptr_t cell_t; /* primary data type for the stack and dictionary */ -typedef uintptr_t ucell_t; +#if (PF_CELL_SIZE == 8) + typedef int64_t cell_t; + typedef uint64_t ucell_t; +#elif (PF_CELL_SIZE == 4) + typedef int32_t cell_t; + typedef uint32_t ucell_t; +#else + #error "Unsupported PF_CELL_SIZE" +#endif -typedef ucell_t ExecToken; /* Execution Token */ +typedef cell_t ExecToken; /* Execution Token */ typedef cell_t ThrowCode; #ifndef PF_DEMAND_PAGING -#define PF_DEMAND_PAGING 0 -#endif + #if INTPTR_MAX == INT16_MAX + /* The only way to address enough RAM for the dictionary is through demand paging. */ + #define PF_DEMAND_PAGING 1 + #else /* INTPTR_MAX */ + #define PF_DEMAND_PAGING 0 + #endif /* INTPTR_MAX */ +#endif /* PF_DEMAND_PAGING */ + +typedef ucell_t vm_address_t; /** an address that may be in physical or paged memory */ +#define PF_VM_NULL ((vm_address_t) 0) #ifdef __cplusplus extern "C" { From 2ab0741e4e85efeca8cc90ad29dbad81418465d5 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Sat, 9 May 2026 16:39:49 -0700 Subject: [PATCH 35/48] add U.HEX and use it in MAP --- fth/misc2.fth | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/fth/misc2.fth b/fth/misc2.fth index b1ae8ea..4f6ecb2 100644 --- a/fth/misc2.fth +++ b/fth/misc2.fth @@ -210,20 +210,26 @@ VARIABLE SPAN CODELIMIT HERE - ; +: U.HEX ( n -- , print a as hex unsigned ) + base @ + swap u. + base ! +; + : MAP ( -- , dump interesting dictionary info ) ." Code Segment" cr - ." CODEBASE = " codebase .hex cr - ." HERE = " here .hex cr - ." CODELIMIT = " codelimit .hex cr + ." CODEBASE = 0x" codebase u.hex cr + ." HERE = 0x" here u.hex cr + ." CODELIMIT = 0x" codelimit u.hex cr ." Compiled Code Size = " here codebase - . cr ." CODE-SIZE = " code-size @ . cr ." Code Room UNUSED = " UNUSED . cr ." Name Segment" cr - ." NAMEBASE = " namebase .hex cr - ." HEADERS-PTR @ = " headers-ptr @ .hex cr - ." NAMELIMIT = " namelimit .hex cr - ." CONTEXT @ = " context @ .hex cr - ." LATEST = " latest .hex ." = " latest id. cr + ." NAMEBASE = 0x" namebase u.hex cr + ." HEADERS-PTR @ = 0x" headers-ptr @ u.hex cr + ." NAMELIMIT = 0x" namelimit u.hex cr + ." CONTEXT @ = 0x" context @ u.hex cr + ." LATEST = 0x" latest u.hex ." = " latest id. cr ." Compiled Name size = " headers-ptr @ namebase - . cr ." HEADERS-SIZE = " headers-size @ . cr ." Name Room Left = " namelimit headers-ptr @ - . cr From 025bda8081d05ac3196055adda0a1f6e38437297 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Sat, 9 May 2026 16:40:03 -0700 Subject: [PATCH 36/48] clean up code related to ptr size != cell For demand paging on a system with 16-bit pointers, we need to support 16-bit pointers in the kernel, and 32-bit CELL and VM addresses on the stack. This commit fixes some problem related to casting pointers to cell_t. We were getting sign expension. This was fixed by by using (uintptr_t). I also fixed some unnecessary narrowing when aligning dictionary addresses. --- csrc/paging/dmpaging.h | 18 +++++++++--------- csrc/pf_core.c | 10 +++++----- csrc/pf_guts.h | 2 +- csrc/pf_save.c | 5 ++--- csrc/pfcompil.c | 26 +++++++++++++------------- csrc/pforth.h | 7 ++++++- 6 files changed, 36 insertions(+), 32 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index 3a978b2..a372287 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -34,15 +34,15 @@ typedef ucell_t paging_address_t; /** an address in paged memory */ /* Basic memory access macros. */ #if (PF_DEMAND_PAGING == 0) /* Straight memory access. */ -#define DP_FETCH_U8(address) (*((const uint8_t *)(address))) -#define DP_FETCH_U16(address) (*((const uint16_t *)(address))) -#define DP_FETCH_CELL(address) (*((const cell_t *)(address))) -#define DP_FETCH_FLOAT(address) (*((const PF_FLOAT *)(address))) - -#define DP_STORE_U8(address, value) *((uint8_t *)(address)) = (uint8_t)(value) -#define DP_STORE_U16(address, value) *((uint16_t *)(address)) = (uint16_t)(value) -#define DP_STORE_CELL(address, value) *((cell_t *)(address)) = (cell_t)(value) -#define DP_STORE_FLOAT(address, value) *((PF_FLOAT *)(address)) = (PF_FLOAT)(value) +#define DP_FETCH_U8(address) (*((const uint8_t *)(uintptr_t)(address))) +#define DP_FETCH_U16(address) (*((const uint16_t *)(uintptr_t)(address))) +#define DP_FETCH_CELL(address) (*((const cell_t *)(uintptr_t)(address))) +#define DP_FETCH_FLOAT(address) (*((const PF_FLOAT *)(uintptr_t)(address))) + +#define DP_STORE_U8(address, value) *((uint8_t *)(uintptr_t)(address)) = (uint8_t)(value) +#define DP_STORE_U16(address, value) *((uint16_t *)(uintptr_t)(address)) = (uint16_t)(value) +#define DP_STORE_CELL(address, value) *((cell_t *)(uintptr_t)(address)) = (cell_t)(value) +#define DP_STORE_FLOAT(address, value) *((PF_FLOAT *)(uintptr_t)(address)) = (PF_FLOAT)(value) #else /* PF_DEMAND_PAGING */ diff --git a/csrc/pf_core.c b/csrc/pf_core.c index d22225b..3a1ca05 100644 --- a/csrc/pf_core.c +++ b/csrc/pf_core.c @@ -51,7 +51,7 @@ ExecToken gLocalCompiler_XT; /* custom compiler for local variables */ ExecToken gNumberQ_XT; /* XT of NUMBER? */ ExecToken gQuitP_XT; /* XT of (QUIT) */ ExecToken gAcceptP_XT; /* XT of ACCEPT */ -cell_t gPfAssertEnabled = 0; +cell_t gPfAssertEnabled = PF_ASSERT_ENABLED; /* Depth of data stack when colon called. */ cell_t gDepthAtColon; @@ -251,10 +251,10 @@ PForthDictionary pfCreateDictionary( cell_t HeaderSize, cell_t CodeSize ) { #if PF_DEMAND_PAGING - dic->dic_HeaderBaseUnaligned = (ucell_t) pfAllocatePagedMemory( (ucell_t) HeaderSize + DIC_ALIGNMENT_SIZE); + dic->dic_HeaderBaseUnaligned = pfAllocatePagedMemory( (ucell_t) HeaderSize + DIC_ALIGNMENT_SIZE); #else - dic->dic_HeaderBaseUnaligned = (ucell_t) pfAllocMem((ucell_t) HeaderSize + DIC_ALIGNMENT_SIZE ); + dic->dic_HeaderBaseUnaligned = PTR_TO_VMA(pfAllocMem((ucell_t) HeaderSize + DIC_ALIGNMENT_SIZE )); #endif if( !dic->dic_HeaderBaseUnaligned ) goto nomem; /* Align header base. */ @@ -270,9 +270,9 @@ PForthDictionary pfCreateDictionary( cell_t HeaderSize, cell_t CodeSize ) /* Allocate memory for code. */ #if PF_DEMAND_PAGING - dic->dic_CodeBaseUnaligned = (ucell_t) pfAllocatePagedMemory( (ucell_t) CodeSize + DIC_ALIGNMENT_SIZE ); + dic->dic_CodeBaseUnaligned = pfAllocatePagedMemory( (ucell_t) CodeSize + DIC_ALIGNMENT_SIZE ); #else - dic->dic_CodeBaseUnaligned = (ucell_t) pfAllocMem( (ucell_t) CodeSize + DIC_ALIGNMENT_SIZE ); + dic->dic_CodeBaseUnaligned = PTR_TO_VMA(pfAllocMem( (ucell_t) CodeSize + DIC_ALIGNMENT_SIZE )); #endif if( !dic->dic_CodeBaseUnaligned ) goto nomem; dic->dic_CodeBase = DIC_ALIGN(dic->dic_CodeBaseUnaligned); diff --git a/csrc/pf_guts.h b/csrc/pf_guts.h index a3e683b..8faf2bf 100644 --- a/csrc/pf_guts.h +++ b/csrc/pf_guts.h @@ -578,7 +578,6 @@ extern cell_t gIncludeIndex; #define READ_SHORT_DIC(addr) DP_FETCH_U16(addr) #endif -#define HEADER_HERE (gCurrentDictionary->dic_HeaderPtr.Cell) #define CODE_HERE (gCurrentDictionary->dic_CodePtr) #define CODE_COMMA(N) { WRITE_CELL_DIC(CODE_HERE,(N)); CODE_HERE += PF_CELL_SIZE; } #define NAME_BASE (gCurrentDictionary->dic_HeaderBase) @@ -606,6 +605,7 @@ extern cell_t gIncludeIndex; #define DROP_DATA_STACK (gCurrentTask->td_StackPtr++) #define POP_DATA_STACK (*gCurrentTask->td_StackPtr++) #define PUSH_DATA_STACK(x) {*(--(gCurrentTask->td_StackPtr)) = (cell_t) x; } +#define PUSH_PTR_DATA_STACK(x) {*(--(gCurrentTask->td_StackPtr)) = PTR_TO_VMA(x); } /* Force Quad alignment. */ #define QUADUP(x) (((x)+3)&~3) diff --git a/csrc/pf_save.c b/csrc/pf_save.c index f502939..e779868 100644 --- a/csrc/pf_save.c +++ b/csrc/pf_save.c @@ -657,8 +657,7 @@ DBUG(("pfLoadDictionary( %s )\n", FileName )); if( sd->sd_NameSize > 0 ) { gVarContext = NAMEREL_TO_ABS(sd->sd_RelContext); /* Restore context. */ - gCurrentDictionary->dic_HeaderPtr = (ucell_t)(uint8_t *) - NAMEREL_TO_ABS(sd->sd_RelHeaderPtr); + gCurrentDictionary->dic_HeaderPtr = NAMEREL_TO_ABS(sd->sd_RelHeaderPtr); } else { @@ -837,7 +836,7 @@ PForthDictionary pfLoadStaticDictionary( void ) if( NAME_BASE != 0) { /* Setup name space. */ - dic->dic_HeaderPtr = (ucell_t)(uint8_t *) NAMEREL_TO_ABS(HEADERPTR); + dic->dic_HeaderPtr = (vm_address_t) NAMEREL_TO_ABS(HEADERPTR); gVarContext = NAMEREL_TO_ABS(RELCONTEXT); /* Restore context. */ /* Find special words in dictionary for global XTs. */ diff --git a/csrc/pfcompil.c b/csrc/pfcompil.c index c299437..ef7b268 100644 --- a/csrc/pfcompil.c +++ b/csrc/pfcompil.c @@ -23,12 +23,12 @@ ** 941004 PLB Extracted IO calls from pforth_main.c ** 950320 RDG Added underflow checking for FP stack ***************************************************************/ - +#include #include "pf_all.h" #include "pfcompil.h" #define ABORT_RETURN_CODE (10) -#define CELL_MASK ((sizeof(ucell_t)-1)) +#define UCELL_MASK (((ucell_t)PF_CELL_SIZE) - 1) /***************************************************************/ /************** Static Prototypes ******************************/ @@ -89,7 +89,7 @@ void CreateDicEntry(ExecToken XT, const char *FName, ucell_t Flags) DP_STORE_U8(gVarContext, DP_FETCH_U8(gVarContext) | (uint8_t)Flags); /* Align to cell byte boundaries with zeroes. */ - while( gCurrentDictionary->dic_HeaderPtr & CELL_MASK ) + while( gCurrentDictionary->dic_HeaderPtr & UCELL_MASK ) { DP_STORE_U8(gCurrentDictionary->dic_HeaderPtr++, 0); } @@ -121,7 +121,7 @@ vm_address_t NameToPrevious(vm_address_t NFA) if (relativeNamePtr) { return NAMEREL_TO_ABS( relativeNamePtr ); } else { - return (vm_address_t) NULL; + return PF_VM_NULL; } } @@ -462,7 +462,7 @@ cell_t ffFindNFA( const ForthString *WordName, vm_address_t *NFAPtr ) WordLen = (uint8_t) ((ucell_t)*WordName & MASK_NAME_SIZE); WordChar = WordName+1; - vNameField = (vm_address_t) gVarContext; + vNameField = gVarContext; DBUG(("\nffFindNFA: WordLen = %d, WordName = %*s\n", WordLen, WordLen, WordChar )); DBUG(("\nffFindNFA: gVarContext = 0x%x\n", gVarContext)); do @@ -486,7 +486,7 @@ DBUG(("ffFindNFA: found it at NFA = 0x%x\n", NameField)); vNextNameField = NameToPrevious( vNameField ); if( vNextNameField == PF_VM_NULL ) { - *NFAPtr = (vm_address_t) WordName; + *NFAPtr = PTR_TO_VMA(WordName); Searching = FALSE; } } @@ -515,7 +515,7 @@ DBUG(("ffFind: %8s at 0x%x\n", WordName+1, NFA)); /* WARNING, not NUL terminated } else { - *pXT = (ExecToken) WordName; + *pXT = (ExecToken)PTR_TO_VMA(WordName); } return Result; @@ -573,7 +573,7 @@ void ffCreateSecondaryHeader( const ForthStringPtr FName) pfDebugMessage("ffCreateSecondaryHeader: CheckRedefinition()\n"); CheckRedefinition( FName ); /* Align CODE_HERE */ - CODE_HERE = (vm_address_t)( (((ucell_t)CODE_HERE) + CELL_MASK) & ~CELL_MASK); + CODE_HERE = (CODE_HERE + UCELL_MASK) & ~UCELL_MASK; CreateDicEntry( (ExecToken) ABS_TO_CODEREL(CODE_HERE), FName, FLAG_SMUDGE ); } @@ -779,7 +779,7 @@ DBUG(("FindAndCompile: IMMEDIATE, theWord = 0x%x\n", theWord )); cell_t NumResult; DBUG(("FindAndCompile: not found, try number?\n" )); - PUSH_DATA_STACK( theWord ); /* Push text of number */ + PUSH_PTR_DATA_STACK( theWord ); /* Push text of number */ exception = pfCatch( gNumberQ_XT ); if( exception ) goto error; @@ -835,7 +835,7 @@ ThrowCode ffInterpret( void ) char *theWord; ThrowCode exception = 0; /* td_SourcePtr may be pointing to a string in the dictionary. */ - vm_address_t saveSource = (vm_address_t)gCurrentTask->td_SourcePtr; + vm_address_t saveSource = PTR_TO_VMA(gCurrentTask->td_SourcePtr); /* It may be difficult to make td_SourcePtr const because of refill(). */ gCurrentTask->td_SourcePtr = (char *)pfLockMemoryReadOnly(saveSource, gCurrentTask->td_SourceNum); @@ -851,7 +851,7 @@ ThrowCode ffInterpret( void ) flag = 0; if( gLocalCompiler_XT ) { - PUSH_DATA_STACK( theWord ); /* Push word. */ + PUSH_PTR_DATA_STACK( theWord ); /* Push word. */ exception = pfCatch( gLocalCompiler_XT ); if( exception ) goto error; flag = POP_DATA_STACK; /* Compiled local? */ @@ -1070,7 +1070,7 @@ cell_t ffConvertStreamToSourceID( FileStream *Stream ) } else { - Result = (cell_t) Stream; + Result = PTR_TO_VMA(Stream); } return Result; } @@ -1165,7 +1165,7 @@ cell_t ffRefill( void ) { /* ACCEPT is deferred so we call it through the dictionary. */ ThrowCode throwCode; - PUSH_DATA_STACK( gCurrentTask->td_SourcePtr ); + PUSH_PTR_DATA_STACK( gCurrentTask->td_SourcePtr ); PUSH_DATA_STACK( TIB_SIZE ); throwCode = pfCatch( gAcceptP_XT ); if (throwCode) { diff --git a/csrc/pforth.h b/csrc/pforth.h index 0f8ae52..4d56269 100644 --- a/csrc/pforth.h +++ b/csrc/pforth.h @@ -78,7 +78,12 @@ typedef cell_t ThrowCode; #endif /* PF_DEMAND_PAGING */ typedef ucell_t vm_address_t; /** an address that may be in physical or paged memory */ -#define PF_VM_NULL ((vm_address_t) 0) +#define PTR_TO_VMA(p) ((vm_address_t)(uintptr_t)(p)) +#define PF_VM_NULL PTR_TO_VMA(0) + +#ifndef PF_ASSERT_ENABLED +#define PF_ASSERT_ENABLED 0 +#endif /* PF_ASSERT_ENABLED */ #ifdef __cplusplus extern "C" { From 2b0bedaa4c033b9de42d32d56155e80495caff60 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Sat, 9 May 2026 18:29:18 -0700 Subject: [PATCH 37/48] build using --std=c99 --- csrc/paging/qadmpage.h | 0 platforms/unix/Makefile | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 csrc/paging/qadmpage.h diff --git a/csrc/paging/qadmpage.h b/csrc/paging/qadmpage.h new file mode 100644 index 0000000..e69de29 diff --git a/platforms/unix/Makefile b/platforms/unix/Makefile index e133b0c..54f32ed 100644 --- a/platforms/unix/Makefile +++ b/platforms/unix/Makefile @@ -47,7 +47,7 @@ PFDICDAT = pfdicdat.h PFORTHAPP = pforth_standalone FULL_WARNINGS = \ - --std=c89 \ + --std=c99 \ -fsigned-char \ -fno-builtin \ -fno-unroll-loops \ From 206c502ab06c323fa65e27729c8bc9ac4a35119d Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Sat, 9 May 2026 18:29:33 -0700 Subject: [PATCH 38/48] Cleanup some additional pointer conversions Change td_sourcePtr to virtual_address_t. Fix lots of warnings. Portable formats for printing cell in unittest.h Some assistance from Gemini Pro. --- csrc/paging/lockpage.c | 16 +++++++-------- csrc/paging/pagedmem.c | 24 +++++++++-------------- csrc/paging/qadmpage.c | 2 +- csrc/paging/qadmpage.h | 37 +++++++++++++++++++++++++++++++++++ csrc/paging/unittest.h | 10 +++++++--- csrc/pf_core.c | 5 ++--- csrc/pf_guts.h | 2 +- csrc/pf_inner.c | 44 +++++++++++++++++++++++------------------- csrc/pf_save.c | 12 ++++++------ csrc/pf_words.c | 14 ++++++-------- csrc/pf_words.h | 4 ++-- csrc/pfcompil.c | 14 +++++++------- 12 files changed, 110 insertions(+), 74 deletions(-) diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index b89d933..7586309 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -90,7 +90,7 @@ void pfResetLockedMemory(void) { } } -uint8_t *pfLockMemoryInternal(vm_address_t vp, uint32_t numBytes, int writable) { +static uint8_t *pfLockMemoryInternal(vm_address_t vp, uint32_t numBytes, int writable) { int i; struct RegionControlBlock *region = NULL; if (pfIsAddressInPagedMemory(vp) == 0) { /* not in paged memory so locking not needed */ @@ -133,11 +133,12 @@ uint8_t *pfLockMemoryReadWrite(vm_address_t vp, uint32_t numBytes) { } int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { - if (vp == pp ) { + if (vp == PTR_TO_VMA(pp) ) { return 0; /* not paged memory */ } - const size_t kPhysicalOffset = (((void *)&sLockedRegions[0].physical[0]) - ((void *)&sLockedRegions[0])); - struct RegionControlBlock *region = (struct RegionControlBlock *)(pp - kPhysicalOffset); + const size_t kPhysicalOffset = (((uint8_t *)&sLockedRegions[0].physical[0]) + - ((uint8_t *)&sLockedRegions[0])); + struct RegionControlBlock *region = (struct RegionControlBlock *)(uintptr_t)(pp - kPhysicalOffset); if (region->magic != DP_MAGIC) { printf("ERROR: physical address was not in a region!\n"); return -1; @@ -147,8 +148,7 @@ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { return -1; } if (region->virtual != vp) { - printf("ERROR: virtual address did not match region, %p != %p!\n", - region->virtual, vp); + printf("ERROR: virtual address did not match region\n"); return -1; } if (region->writable != 0) { @@ -161,7 +161,7 @@ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { return -1; } } - region->virtual = NULL; + region->virtual = PF_VM_NULL; region->length = 0; region->locked = 0; region->writable = 0; @@ -288,7 +288,7 @@ vm_address_t pfSetVirtualMemory(vm_address_t destination, } return destination; } else { - return pfSetMemory(destination, value, numBytes); + return PTR_TO_VMA(pfSetMemory((void *)destination, value, numBytes)); } } diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index c2c62e7..fd74839 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -47,8 +47,8 @@ static cell_t sDpNextAvailable = 0; #define PF_DP_MUNGE_KEY (0x50000000) #endif -#define PF_DP_MUNGE(vaddr) ((vm_address_t)(((cell_t)vaddr) ^ PF_DP_MUNGE_KEY)) -#define PF_DP_UNMUNGE(vaddr) ((vm_address_t)(((cell_t)vaddr) ^ PF_DP_MUNGE_KEY)) +#define PF_DP_MUNGE(addr) ((vm_address_t)((PTR_TO_VMA(addr)) ^ PF_DP_MUNGE_KEY)) +#define PF_DP_UNMUNGE(paging_addr) ((uintptr_t)((paging_addr) ^ PF_DP_MUNGE_KEY)) void pfResetPagedMemory(void) { printf("pfResetPagedMemory: cell = %d\n", (int)sizeof(cell_t)); @@ -56,8 +56,8 @@ void pfResetPagedMemory(void) { } int pfIsAddressInPagedMemory(vm_address_t p) { - vm_address_t vaddr = PF_DP_UNMUNGE(p); - cell_t offset = (uint8_t *)vaddr - sFakeSerialRAM; + uintptr_t addr = PF_DP_UNMUNGE(p); + cell_t offset = (uint8_t *)addr - sFakeSerialRAM; return (offset >= 0) && (offset < PF_DP_AVAILABLE_SPACE); } @@ -77,14 +77,11 @@ vm_address_t pfAllocatePagedMemory(const ucell_t numBytes) { void pfFreePagedMemory(vm_address_t p) {} size_t pfReadPagedMemory(void *destination, - vm_address_t source, + paging_address_t source, uint32_t numBytes) { - if (!pfIsAddressInPagedMemory(source)) { - printf("ERROR: not a paged address = %p\n", source); - return 0; - } + PF_ASSERT(pfIsAddressInPagedMemory(source)); /* TODO check upper boundary */ - void *pAddr = PF_DP_UNMUNGE(source); + void *pAddr = (void *)(uintptr_t) PF_DP_UNMUNGE(source); pfCopyMemory(destination, pAddr, numBytes); return numBytes; } @@ -92,12 +89,9 @@ size_t pfReadPagedMemory(void *destination, size_t pfWritePagedMemory(paging_address_t destination, const void *source, uint32_t numBytes) { - if (!pfIsAddressInPagedMemory(destination)) { - printf("ERROR: not a paged address = %p\n", destination); - return 0; - } + PF_ASSERT(pfIsAddressInPagedMemory(destination)); /* TODO check upper boundary */ - void *pAddr = PF_DP_UNMUNGE(destination); + void *pAddr = (void *)(uintptr_t) PF_DP_UNMUNGE(destination); pfCopyMemory(pAddr, source, numBytes); return numBytes; } diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index 07785f0..44c312f 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -21,6 +21,7 @@ #include "../pf_all.h" #include "unittest.h" +#include "qadmpage.h" #if PF_DEMAND_PAGING @@ -103,7 +104,6 @@ static int pfQaTestReadWrite(void) { pfResetPagedMemory(); vm_address_t vm1 = pfAllocatePagedMemory(kBufferSize); ASSERT_NE(vm1, 0); - printf("pfQaTestReadWrite: vm1 = %p\n", vm1); cell_t written = pfWritePagedMemory(vm1, buffer1, kBufferSize); ASSERT_EQ(written, kBufferSize); cell_t numRead = pfReadPagedMemory(buffer2, vm1, kBufferSize); diff --git a/csrc/paging/qadmpage.h b/csrc/paging/qadmpage.h index e69de29..7c20b1e 100644 --- a/csrc/paging/qadmpage.h +++ b/csrc/paging/qadmpage.h @@ -0,0 +1,37 @@ +#ifndef _pf_qadmpage_h +#define _pf_qadmpage_h + +/*************************************************************** +** Include file for PForth Paged Memory Unit Tests +** +** Author: Phil Burk +** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom +** +** Permission to use, copy, modify, and/or distribute this +** software for any purpose with or without fee is hereby granted. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +** THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +** FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +** +***************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if PF_DEMAND_PAGING +/* Run C unit tests for demand paging. */ +int pfQaDemandPaging(void); +#endif /* PF_DEMAND_PAGING */ + +#ifdef __cplusplus +} +#endif + +#endif /* _pf_qadmpage_h */ diff --git a/csrc/paging/unittest.h b/csrc/paging/unittest.h index 563362d..29c9ab7 100644 --- a/csrc/paging/unittest.h +++ b/csrc/paging/unittest.h @@ -26,9 +26,13 @@ extern int pfQaNumFailed; /* You must use this macro exactly once in each test program. */ #define PFQA_INSTANTIATE_GLOBALS\ int pfQaNumPassed = 0;\ - int pfQaNumFailed = 0; + int pfQaNumFailed = 0 -#define CELL_FORMAT "%l" +#if PF_CELL_SIZE == 4 +#define CELL_FORMAT "%ld" +#elif PF_CELL_SIZE == 8 +#define CELL_FORMAT "%lld" +#endif /*------------------- Macros ------------------------------*/ /* Print ERROR if it fails. Tally success or failure. Odd */ /* do-while wrapper seems to be needed for some compilers. */ @@ -58,7 +62,7 @@ extern int pfQaNumFailed; pfQaNumPassed++; \ } \ else { \ - printf("ERROR at %s:%d, (%s) %s (%s), %ld %s %ld\n", \ + printf("ERROR at %s:%d, (%s) %s (%s), " CELL_FORMAT " %s " CELL_FORMAT "\n", \ __FILE__, __LINE__, #_a, #_opn, #_b, mA, #_opn, mB ); \ pfQaNumFailed++; \ _on_error; \ diff --git a/csrc/pf_core.c b/csrc/pf_core.c index 3a1ca05..2efeb2a 100644 --- a/csrc/pf_core.c +++ b/csrc/pf_core.c @@ -37,6 +37,7 @@ ***************************************************************/ #include "pf_all.h" +#include "paging/qadmpage.h" /*************************************************************** ** Global Data @@ -89,8 +90,6 @@ static void pfTerm( void ); #define PF_DEFAULT_CODE_SIZE (300000) #endif -int pfQaDemandPaging(void); - /* Initialize globals in a function to simplify loading on * embedded systems which may not support initialization of data section. */ @@ -176,7 +175,7 @@ PForthTask pfCreateTask( cell_t UserStackDepth, cell_t ReturnStackDepth ) cftd->td_InputStream = PF_STDIN; - cftd->td_SourcePtr = &cftd->td_TIB[0]; + cftd->td_SourcePtr = PTR_TO_VMA(&cftd->td_TIB[0]); cftd->td_SourceNum = 0; return (PForthTask) cftd; diff --git a/csrc/pf_guts.h b/csrc/pf_guts.h index 8faf2bf..fdb2758 100644 --- a/csrc/pf_guts.h +++ b/csrc/pf_guts.h @@ -438,7 +438,7 @@ typedef struct pfTaskData_s char td_TIB[TIB_SIZE]; /* Buffer for terminal input. */ cell_t td_IN; /* Index into Source */ cell_t td_SourceNum; /* #TIB after REFILL */ - char *td_SourcePtr; /* Pointer to TIB or other source. */ + vm_address_t td_SourcePtr; /* Pointer to TIB or other source. */ cell_t td_LineNumber; /* Incremented on every refill. */ cell_t td_OUT; /* Current output column. */ } pfTaskData_t; diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index b381834..271a0c7 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -553,12 +553,12 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); case ID_CMOVE: /* ( src dst n -- ) */ { - register char *DstPtr = (char *) M_POP; /* dst */ - CharPtr = (char *) M_POP; /* src */ + vm_address_t dstVAddr = (vm_address_t) M_POP; /* dst */ + vm_address_t srcVAddr = (vm_address_t) M_POP; /* src */ for( Scratch=0; (ucell_t) Scratch < (ucell_t) TOS ; Scratch++ ) { - uint8_t value = DP_FETCH_U8(CharPtr++); - DP_STORE_U8(DstPtr++, value); + uint8_t value = DP_FETCH_U8(srcVAddr++); + DP_STORE_U8(dstVAddr++, value); } M_DROP; } @@ -566,12 +566,12 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); case ID_CMOVE_UP: /* ( src dst n -- ) */ { - register char *DstPtr = ((char *) M_POP) + TOS; /* dst */ - CharPtr = ((char *) M_POP) + TOS; /* src */ + vm_address_t dstVAddr = ((vm_address_t) M_POP) + TOS; /* dst */ + vm_address_t srcVAddr = ((vm_address_t) M_POP) + TOS; /* src */ for( Scratch=0; (ucell_t) Scratch < (ucell_t) TOS ; Scratch++ ) { - uint8_t value = DP_FETCH_U8(--CharPtr); - DP_STORE_U8(--DstPtr, value); + uint8_t value = DP_FETCH_U8(--srcVAddr); + DP_STORE_U8(--dstVAddr, value); } M_DROP; } @@ -1057,9 +1057,11 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_FILE_READ: /* ( addr len fid -- u2 ior ) */ FileID = (FileStream *) TOS; Scratch = M_POP; - CharPtr = (char *) M_POP; - /* warning, only 32-bit nItems */ - Temp = ffReadFile( CharPtr, 1, (int32_t) Scratch, FileID ); + { + vm_address_t vAddr = (vm_address_t) M_POP; + /* warning, only 32-bit nItems */ + Temp = ffReadFile( vAddr, 1, (int32_t) Scratch, FileID ); + } /* TODO check feof() or ferror() */ M_PUSH(Temp); TOS = 0; @@ -1098,9 +1100,11 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_FILE_WRITE: /* ( addr len fid -- ior ) */ FileID = (FileStream *) TOS; Scratch = M_POP; - CharPtr = (char *) M_POP; - Temp = ffWriteFile( CharPtr, 1, (int32_t)Scratch, FileID ); - TOS = (Temp != Scratch) ? -3 : 0; + { + vm_address_t vAddr = (vm_address_t) M_POP; + Temp = ffWriteFile( vAddr, 1, (int32_t)Scratch, FileID ); + TOS = (Temp != Scratch) ? -3 : 0; + } endcase; case ID_FILE_REPOSITION: /* ( ud fid -- ior ) */ @@ -1200,13 +1204,13 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_FILL: /* ( caddr num charval -- ) */ { - register char *DstPtr; + vm_address_t dstVAddr; Temp = M_POP; /* num */ - DstPtr = (char *) M_POP; /* dst */ + dstVAddr = (vm_address_t) M_POP; /* dst */ for( Scratch=0; (ucell_t) Scratch < (ucell_t) Temp ; Scratch++ ) { - DP_STORE_U8(DstPtr, TOS); - DstPtr++; + DP_STORE_U8(dstVAddr, TOS); + dstVAddr++; } M_DROP; } @@ -1234,7 +1238,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); vm_address_t vName = (vm_address_t) TOS; cell_t totalLength = DP_FETCH_U8(vName) + 1; /* length including count */ const char *pAddr = (const char *) pfLockMemoryReadOnly(vName, totalLength); - TOS = ffFindNFA(pAddr, (const ForthString **) &nfa ); + TOS = ffFindNFA((const ForthString *)pAddr, &nfa ); pfUnlockMemory(vName, (const uint8_t *)pAddr); if (TOS != 0) { M_PUSH( nfa ); @@ -1781,7 +1785,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); endcase; case ID_SOURCE_SET: /* ( c-addr num -- ) */ - gCurrentTask->td_SourcePtr = (char *) M_POP; + gCurrentTask->td_SourcePtr = (vm_address_t) M_POP; gCurrentTask->td_SourceNum = TOS; M_DROP; endcase; diff --git a/csrc/pf_save.c b/csrc/pf_save.c index e779868..e35dcd5 100644 --- a/csrc/pf_save.c +++ b/csrc/pf_save.c @@ -354,7 +354,7 @@ static int Write32ToFile( FileStream *fid, uint32_t Val ) } /***************************************************************/ -static cell_t WriteChunkToFile( FileStream *fid, cell_t ID, char *Data, int32_t NumBytes ) +static cell_t WriteChunkToFile( FileStream *fid, cell_t ID, vm_address_t Data, int32_t NumBytes ) { cell_t numw; cell_t EvenNumW; @@ -477,17 +477,17 @@ cell_t ffSaveForth( const char *FileName, ExecToken EntryPoint, cell_t NameSize, convertDictionaryInfoWrite (&SD); - if( WriteChunkToFile( fid, ID_P4DI, (char *) &SD, sizeof(DictionaryInfoChunk) ) < 0 ) goto error; + if( WriteChunkToFile( fid, ID_P4DI, PTR_TO_VMA(&SD), sizeof(DictionaryInfoChunk) ) < 0 ) goto error; /* Write Name Fields if NameSize non-zero ------- */ if( NameSize > 0 ) { - if( WriteChunkToFile( fid, ID_P4NM, (char *) NAME_BASE, + if( WriteChunkToFile( fid, ID_P4NM, (vm_address_t) NAME_BASE, NameChunkSize ) < 0 ) goto error; } /* Write Code Fields ---------------------------- */ - if( WriteChunkToFile( fid, ID_P4CD, (char *) CODE_BASE, CodeChunkSize ) < 0 ) goto error; + if( WriteChunkToFile( fid, ID_P4CD, (vm_address_t) CODE_BASE, CodeChunkSize ) < 0 ) goto error; FormSize = (uint32_t) sdTellFile( fid ) - 8; sdSeekFile( fid, 4, PF_SEEK_SET ); @@ -692,7 +692,7 @@ DBUG(("pfLoadDictionary( %s )\n", FileName )); goto error; } /* read using demand paging if needed */ - numr = ffReadFile( (char *) NAME_BASE, 1, ChunkSize, fid ); + numr = ffReadFile( (vm_address_t) NAME_BASE, 1, ChunkSize, fid ); if( numr != ChunkSize ) goto read_error; BytesLeft -= ChunkSize; #endif /* PF_NO_SHELL */ @@ -710,7 +710,7 @@ DBUG(("pfLoadDictionary( %s )\n", FileName )); goto error; } /* read using demand paging if needed */ - numr = ffReadFile( (uint8_t *) CODE_BASE, 1, ChunkSize, fid ); + numr = ffReadFile( (vm_address_t) CODE_BASE, 1, ChunkSize, fid ); if( numr != ChunkSize ) goto read_error; BytesLeft -= ChunkSize; break; diff --git a/csrc/pf_words.c b/csrc/pf_words.c index 2539268..6910cc5 100644 --- a/csrc/pf_words.c +++ b/csrc/pf_words.c @@ -216,7 +216,7 @@ static char * Word ( char c, int Upcase ) cell_t n1, n2, n3; cell_t i, nc; - s1 = gCurrentTask->td_SourcePtr + gCurrentTask->td_IN; + s1 = (const char *)(uintptr_t)gCurrentTask->td_SourcePtr + gCurrentTask->td_IN; n1 = gCurrentTask->td_SourceNum - gCurrentTask->td_IN; n2 = ffSkip( s1, n1, c, &s2 ); DBUGX(("Word: s2=%c, %d\n", *s2, n2 )); @@ -252,9 +252,8 @@ char * ffLWord( char c ) return Word( c, FALSE ); } -size_t ffReadFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ) +size_t ffReadFile( vm_address_t vp, size_t Size, size_t nItems, FileStream * Stream ) { - vm_address_t vp = (vm_address_t)ptr; uint32_t numBytes = (uint32_t)(Size * nItems); if (numBytes == 0) { return 0; @@ -277,13 +276,12 @@ size_t ffReadFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ) } return bytesRead / Size; } else { - return sdReadFile( ptr, Size, nItems, Stream); + return sdReadFile( (void *)(uintptr_t) vp, Size, nItems, Stream); } } -size_t ffWriteFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ) +size_t ffWriteFile( vm_address_t vp, size_t Size, size_t nItems, FileStream * Stream ) { - vm_address_t vp = (vm_address_t)ptr; uint32_t numBytes = (uint32_t)(Size * nItems); if (numBytes == 0) { return 0; @@ -304,8 +302,8 @@ size_t ffWriteFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream bytesWritten += numWritten; vp += numWritten; } - return nItems; + return bytesWritten / Size; } else { - return sdWriteFile( ptr, Size, nItems, Stream); + return sdWriteFile( (void *)(uintptr_t) vp, Size, nItems, Stream); } } diff --git a/csrc/pf_words.h b/csrc/pf_words.h index ced0230..3bf3e30 100644 --- a/csrc/pf_words.h +++ b/csrc/pf_words.h @@ -32,8 +32,8 @@ void ffDotS( void ); cell_t ffSkip(const char *AddrIn, cell_t Cnt, char c, const char **AddrOut); cell_t ffScan(const char *AddrIn, cell_t Cnt, char c, const char **AddrOut); -size_t ffReadFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ); -size_t ffWriteFile( void *ptr, size_t Size, size_t nItems, FileStream * Stream ); +size_t ffReadFile( vm_address_t vp, size_t Size, size_t nItems, FileStream * Stream ); +size_t ffWriteFile( vm_address_t vp, size_t Size, size_t nItems, FileStream * Stream ); #ifdef __cplusplus } diff --git a/csrc/pfcompil.c b/csrc/pfcompil.c index ef7b268..d140925 100644 --- a/csrc/pfcompil.c +++ b/csrc/pfcompil.c @@ -835,9 +835,9 @@ ThrowCode ffInterpret( void ) char *theWord; ThrowCode exception = 0; /* td_SourcePtr may be pointing to a string in the dictionary. */ - vm_address_t saveSource = PTR_TO_VMA(gCurrentTask->td_SourcePtr); + vm_address_t saveSource = gCurrentTask->td_SourcePtr; /* It may be difficult to make td_SourcePtr const because of refill(). */ - gCurrentTask->td_SourcePtr = (char *)pfLockMemoryReadOnly(saveSource, gCurrentTask->td_SourceNum); + gCurrentTask->td_SourcePtr = PTR_TO_VMA(pfLockMemoryReadOnly(saveSource, gCurrentTask->td_SourceNum)); /* Is there any text left in Source ? */ while( gCurrentTask->td_IN < (gCurrentTask->td_SourceNum) ) @@ -867,7 +867,7 @@ ThrowCode ffInterpret( void ) gCurrentTask->td_SourceNum ) ); } error: - pfUnlockMemory(saveSource, (const uint8_t *) gCurrentTask->td_SourcePtr); + pfUnlockMemory(saveSource, (const uint8_t *)(uintptr_t) gCurrentTask->td_SourcePtr); return exception; } @@ -964,7 +964,7 @@ ThrowCode ffIncludeFile( FileStream *InputFile ) /* Dump line of error and show offset in line for >IN */ for( i=0; itd_SourceNum; i++ ) { - char c = gCurrentTask->td_SourcePtr[i]; + char c = ((char *)(uintptr_t)gCurrentTask->td_SourcePtr)[i]; if( c == '\t' ) c = ' '; EMIT(c); } @@ -1165,7 +1165,7 @@ cell_t ffRefill( void ) { /* ACCEPT is deferred so we call it through the dictionary. */ ThrowCode throwCode; - PUSH_PTR_DATA_STACK( gCurrentTask->td_SourcePtr ); + PUSH_DATA_STACK( gCurrentTask->td_SourcePtr ); PUSH_DATA_STACK( TIB_SIZE ); throwCode = pfCatch( gAcceptP_XT ); if (throwCode) { @@ -1181,7 +1181,7 @@ cell_t ffRefill( void ) } else { - Num = readLineFromStream( gCurrentTask->td_SourcePtr, TIB_SIZE, + Num = readLineFromStream( (char *)(uintptr_t)gCurrentTask->td_SourcePtr, TIB_SIZE, gCurrentTask->td_InputStream ); if( Num == EOF ) { @@ -1196,7 +1196,7 @@ cell_t ffRefill( void ) /* echo input if requested */ if( gVarEcho && ( Num > 0)) { - ioType( gCurrentTask->td_SourcePtr, gCurrentTask->td_SourceNum ); + ioType( (const char *)(uintptr_t)gCurrentTask->td_SourcePtr, gCurrentTask->td_SourceNum ); EMIT_CR; } From d47680b8838f36f28243d5d665d16927edcdd407 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Sun, 10 May 2026 12:26:20 -0700 Subject: [PATCH 39/48] eliminate many warnings in paged mem support --- csrc/paging/dmpaging.h | 34 ++++++++--------- csrc/paging/lockpage.c | 87 +++++++++++++++++++++--------------------- csrc/paging/pagedmem.c | 2 +- csrc/paging/qadmpage.c | 21 +++++----- csrc/pf_inner.c | 24 ++++++------ csrc/pf_save.c | 2 +- csrc/pfcompil.c | 2 +- 7 files changed, 87 insertions(+), 85 deletions(-) diff --git a/csrc/paging/dmpaging.h b/csrc/paging/dmpaging.h index a372287..34a464d 100644 --- a/csrc/paging/dmpaging.h +++ b/csrc/paging/dmpaging.h @@ -47,28 +47,28 @@ typedef ucell_t paging_address_t; /** an address in paged memory */ #else /* PF_DEMAND_PAGING */ /* Use either physical or paged memory. */ -#define DP_FETCH_U8(address) pfFetchVirtualU8((const uint8_t *)(address)) -#define DP_FETCH_U16(address) pfFetchVirtualU16((const uint16_t *)(address)) -#define DP_FETCH_CELL(address) pfFetchVirtualCell((const cell_t *)(address)) -#define DP_FETCH_FLOAT(address) pfFetchVirtualFloat((const PF_FLOAT *)(address)) - -#define DP_STORE_U8(address, value) pfStoreVirtualU8(((uint8_t *)(address)), (uint8_t)(value)) -#define DP_STORE_U16(address, value) pfStoreVirtualU16(((uint16_t *)(address)), (uint16_t)(value)) -#define DP_STORE_CELL(address, value) pfStoreVirtualCell(((cell_t *)(address)), (cell_t)(value)) -#define DP_STORE_FLOAT(address, value) pfStoreVirtualFloat(((PF_FLOAT *)(address)), (PF_FLOAT)(value)) +#define DP_FETCH_U8(address) pfFetchVirtualU8(PTR_TO_VMA(address)) +#define DP_FETCH_U16(address) pfFetchVirtualU16(PTR_TO_VMA(address)) +#define DP_FETCH_CELL(address) pfFetchVirtualCell(PTR_TO_VMA(address)) +#define DP_FETCH_FLOAT(address) pfFetchVirtualFloat(PTR_TO_VMA(address)) + +#define DP_STORE_U8(address, value) pfStoreVirtualU8(PTR_TO_VMA(address), (uint8_t)(value)) +#define DP_STORE_U16(address, value) pfStoreVirtualU16(PTR_TO_VMA(address), (uint16_t)(value)) +#define DP_STORE_CELL(address, value) pfStoreVirtualCell(PTR_TO_VMA(address), (cell_t)(value)) +#define DP_STORE_FLOAT(address, value) pfStoreVirtualFloat(PTR_TO_VMA(address), (PF_FLOAT)(value)) #endif /* PF_DEMAND_PAGING */ -uint8_t pfFetchVirtualU8(const uint8_t *address); -uint16_t pfFetchVirtualU16(const uint16_t *address); -cell_t pfFetchVirtualCell(const cell_t *address); +uint8_t pfFetchVirtualU8(vm_address_t address); +uint16_t pfFetchVirtualU16(vm_address_t address); +cell_t pfFetchVirtualCell(vm_address_t address); -void pfStoreVirtualU8(uint8_t *address, uint8_t value); -void pfStoreVirtualU16(uint16_t *address, uint16_t value); -void pfStoreVirtualCell(cell_t *address, cell_t value); +void pfStoreVirtualU8(vm_address_t address, uint8_t value); +void pfStoreVirtualU16(vm_address_t address, uint16_t value); +void pfStoreVirtualCell(vm_address_t address, cell_t value); #ifdef PF_SUPPORT_FP -PF_FLOAT pfFetchVirtualFloat(const PF_FLOAT *address); -void pfStoreVirtualFloat(PF_FLOAT *address, PF_FLOAT value); +PF_FLOAT pfFetchVirtualFloat(vm_address_t address); +void pfStoreVirtualFloat(vm_address_t address, PF_FLOAT value); #endif /* PF_SUPPORT_FP */ /* Memory region locking and unlocking diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index 7586309..bcff226 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -55,7 +55,7 @@ vm_address_t pfCopyToVirtualMemory(vm_address_t destination, } void pfFreeVirtualMemory(vm_address_t address) { - pfFreeMem((void *)address); + pfFreeMem((void *) address); } vm_address_t pfSetVirtualMemory(vm_address_t destination, @@ -94,7 +94,7 @@ static uint8_t *pfLockMemoryInternal(vm_address_t vp, uint32_t numBytes, int wri int i; struct RegionControlBlock *region = NULL; if (pfIsAddressInPagedMemory(vp) == 0) { /* not in paged memory so locking not needed */ - return (uint8_t *) vp; + return (uint8_t *) (uintptr_t) vp; } PF_ASSERT(numBytes <= DP_MAX_REGION_SIZE); @@ -168,76 +168,77 @@ int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { return 0; } -uint8_t pfFetchVirtualU8(const uint8_t *address) { - uint8_t value; - if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfReadPagedMemory(&value, (paging_address_t) address, sizeof(uint8_t)); +uint8_t pfFetchVirtualU8(vm_address_t address) { + if (pfIsAddressInPagedMemory(address)) { + uint8_t value; + pfReadPagedMemory(&value, (paging_address_t) address, sizeof(value)); return value; } else { - return *address; + return *((uint8_t *) (uintptr_t) address); } - } -uint16_t pfFetchVirtualU16(const uint16_t *address) { - uint16_t value; - if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfReadPagedMemory(&value, (paging_address_t) address, sizeof(uint16_t)); + +uint16_t pfFetchVirtualU16(vm_address_t address) { + if (pfIsAddressInPagedMemory(address)) { + uint16_t value; + pfReadPagedMemory(&value, (paging_address_t) address, sizeof(value)); return value; } else { - return *address; + return *((uint16_t *) (uintptr_t) address); } } -cell_t pfFetchVirtualCell(const cell_t *address) { - cell_t value; - if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfReadPagedMemory(&value, (paging_address_t) address, sizeof(cell_t)); + +cell_t pfFetchVirtualCell(vm_address_t address) { + if (pfIsAddressInPagedMemory(address)) { + cell_t value; + pfReadPagedMemory(&value, (paging_address_t) address, sizeof(value)); return value; } else { - return *address; + return *((cell_t *) (uintptr_t) address); } } #ifdef PF_SUPPORT_FP -PF_FLOAT pfFetchVirtualFloat(const PF_FLOAT *address) { - PF_FLOAT value; - if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfReadPagedMemory(&value, (paging_address_t) address, sizeof(PF_FLOAT)); +PF_FLOAT pfFetchVirtualFloat(vm_address_t address) { + if (pfIsAddressInPagedMemory(address)) { + PF_FLOAT value; + pfReadPagedMemory(&value, (paging_address_t) address, sizeof(value)); return value; } else { - return *address; + return *((PF_FLOAT *) (uintptr_t) address); } } #endif /* PF_SUPPORT_FP */ -void pfStoreVirtualU8(uint8_t *address, uint8_t value) { - if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfWritePagedMemory((paging_address_t) address, &value, sizeof(uint8_t)); +void pfStoreVirtualU8(vm_address_t address, uint8_t value) { + if (pfIsAddressInPagedMemory(address)) { + pfWritePagedMemory((paging_address_t) address, &value, sizeof(value)); } else { - *address = value; + *((uint8_t *) (uintptr_t) address) = value; } } -void pfStoreVirtualU16(uint16_t *address, uint16_t value) { - if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfWritePagedMemory((paging_address_t) address, &value, sizeof(uint16_t)); +void pfStoreVirtualU16(vm_address_t address, uint16_t value) { + if (pfIsAddressInPagedMemory(address)) { + pfWritePagedMemory((paging_address_t) address, &value, sizeof(value)); } else { - *address = value; + *((uint16_t *) (uintptr_t) address) = value; } } -void pfStoreVirtualCell(cell_t *address, cell_t value) { - if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfWritePagedMemory((paging_address_t) address, &value, sizeof(cell_t)); +void pfStoreVirtualCell(vm_address_t address, cell_t value) { + if (pfIsAddressInPagedMemory(address)) { + pfWritePagedMemory((paging_address_t) address, &value, sizeof(value)); } else { - *address = value; + *((cell_t *) (uintptr_t) address) = value; } } #ifdef PF_SUPPORT_FP -void pfStoreVirtualFloat(PF_FLOAT *address, PF_FLOAT value) { - if (pfIsAddressInPagedMemory((vm_address_t)address)) { - pfWritePagedMemory((paging_address_t) address, &value, sizeof(PF_FLOAT)); +void pfStoreVirtualFloat(vm_address_t address, PF_FLOAT value) { + if (pfIsAddressInPagedMemory(address)) { + pfWritePagedMemory((paging_address_t) address, &value, sizeof(value)); } else { - *address = value; + *((PF_FLOAT *) (uintptr_t) address) = value; } } #endif /* PF_SUPPORT_FP */ @@ -249,7 +250,7 @@ void *pfCopyFromVirtualMemory(void *destination, pfReadPagedMemory(destination, (paging_address_t) source, numBytes); /* TODO check result */ return (void *) destination; } else { - return pfCopyMemory(destination, (void *) source, numBytes); + return pfCopyMemory(destination, (void *) (uintptr_t) source, numBytes); } } @@ -260,7 +261,7 @@ vm_address_t pfCopyToVirtualMemory(vm_address_t destination, pfWritePagedMemory((paging_address_t) destination, source, numBytes); /* TODO check result */ return destination; } else { - return (vm_address_t) pfCopyMemory((void *) destination, source, numBytes); + return PTR_TO_VMA(pfCopyMemory((void *) (uintptr_t) destination, source, numBytes)); } } @@ -268,7 +269,7 @@ void pfFreeVirtualMemory(vm_address_t address) { if (pfIsAddressInPagedMemory(address)) { pfFreePagedMemory((paging_address_t) address); } else { - pfFreeMem((void *) address); + pfFreeMem((void *) (uintptr_t) address); } } @@ -288,7 +289,7 @@ vm_address_t pfSetVirtualMemory(vm_address_t destination, } return destination; } else { - return PTR_TO_VMA(pfSetMemory((void *)destination, value, numBytes)); + return PTR_TO_VMA(pfSetMemory((void *) (uintptr_t) destination, value, numBytes)); } } diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index fd74839..55c2f07 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -69,7 +69,7 @@ vm_address_t pfAllocatePagedMemory(const ucell_t numBytes) { (int)numBytes, (int)(PF_DP_AVAILABLE_SPACE - sDpNextAvailable)); return 0; } - vm_address_t virtualAddress = (vm_address_t) &sFakeSerialRAM[sDpNextAvailable]; + vm_address_t virtualAddress = PTR_TO_VMA(&sFakeSerialRAM[sDpNextAvailable]); sDpNextAvailable = finalAvailable; return PF_DP_MUNGE(virtualAddress); } diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index 44c312f..d314282 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -27,6 +27,7 @@ PFQA_INSTANTIATE_GLOBALS; + static int pfQaTestAllocate(void) { printf("pfQaDemandPaging : pfQaTestAllocate\n"); pfResetPagedMemory(); @@ -38,8 +39,8 @@ static int pfQaTestAllocate(void) { ASSERT_EQ((vm2 - vm1), DP_ALIGNMENT_SIZE); int x = 0; - ASSERT_EQ(pfIsAddressInPagedMemory((vm_address_t)&x), 0); - ASSERT_EQ(pfIsAddressInPagedMemory((vm_address_t)(vm2 + 5)), 1); + ASSERT_EQ(pfIsAddressInPagedMemory(PTR_TO_VMA(&x)), 0); + ASSERT_EQ(pfIsAddressInPagedMemory((vm2 + 5)), 1); return 0; error: return 1; @@ -128,7 +129,7 @@ static int pfQaTestRegionLock(void) { ASSERT_NE(0, vm1); uint8_t *pm1 = pfLockMemoryReadWrite(vm1, kBufferSize); - ASSERT_NE(pm1, NULL); + ASSERT_NE(PTR_TO_VMA(pm1), PF_VM_NULL); for (i = 0; i < kBufferSize; i++) { pm1[i] = i; } @@ -136,7 +137,7 @@ static int pfQaTestRegionLock(void) { ASSERT_EQ(0, result); const uint8_t *pm2 = pfLockMemoryReadOnly(vm1, kBufferSize); - ASSERT_NE(pm2, NULL); + ASSERT_NE(PTR_TO_VMA(pm2), PF_VM_NULL); for (i = 0; i < kBufferSize; i++) { ASSERT_EQ(pm2[i], i); } @@ -187,7 +188,7 @@ static int pfQaTestReadFileStandard(size_t numBytes) { int i; printf("pfQaDemandPaging : pfQaCheckReadFile\n"); FileStream *fid = sdOpenFile(PF_DP_TEST_PATHNAME, "rb"); - ASSERT_NE(NULL, fid); + ASSERT_NE(PF_VM_NULL, PTR_TO_VMA(fid)); while (numBytes > 0) { size_t bytesToRead = (numBytes < sizeof(buffer)) ? numBytes : sizeof(buffer); size_t result = sdReadFile(buffer, 1, (int32_t) bytesToRead, fid); /* use stdio */ @@ -211,9 +212,9 @@ static int pfQaTestReadFilePaging(void) { cell_t result = pfQaTestCreateFile(kBytesToRead); ASSERT_EQ(0, result); vm_address_t vm1 = pfAllocatePagedMemory(kBytesToRead); - ASSERT_NE(NULL, vm1); + ASSERT_NE(PF_VM_NULL, vm1); FileStream *fid = sdOpenFile(PF_DP_TEST_PATHNAME, "rb"); - ASSERT_NE(NULL, fid); + ASSERT_NE(PF_VM_NULL, PTR_TO_VMA(fid)); result = ffReadFile(vm1, 1, kBytesToRead, fid); /* use demand paging */ ASSERT_EQ(kBytesToRead, result); for (i = 0; i < kBytesToRead; i++) { @@ -233,12 +234,12 @@ static int pfQaTestWriteFilePaging(void) { cell_t result = pfQaTestCreateFile(kBytesToWrite); ASSERT_EQ(0, result); vm_address_t vm1 = pfAllocatePagedMemory(kBytesToWrite); - ASSERT_NE(NULL, vm1); + ASSERT_NE(PF_VM_NULL, vm1); for (i = 0; i < kBytesToWrite; i++) { DP_STORE_U8((vm1 + i), (i % 100)); } FileStream *fid = sdOpenFile(PF_DP_TEST_PATHNAME, "wb"); - ASSERT_NE(NULL, fid); + ASSERT_NE(PF_VM_NULL, PTR_TO_VMA(fid)); result = ffWriteFile(vm1, 1, kBytesToWrite, fid); /* use demand paging */ ASSERT_EQ(kBytesToWrite, result); sdCloseFile(fid); @@ -259,7 +260,7 @@ static int pfQaTestSetVirtualMemory(void) { const int smallSize = 234; const int smallOffset = 571; vm_address_t vm1 = pfAllocatePagedMemory(largeSize); - ASSERT_NE(NULL, vm1); + ASSERT_NE(PF_VM_NULL, vm1); dest = pfSetVirtualMemory(vm1, 0x5A, largeSize); ASSERT_EQ(dest, vm1); dest = pfSetVirtualMemory(vm1 + smallOffset, 0x3C, smallSize); diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 271a0c7..d1309b1 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -128,7 +128,7 @@ ffDotS( ); \ LOAD_REGISTERS; -#define DO_VAR(varname) { PUSH_TOS; TOS = (cell_t) &varname; } +#define DO_VAR(varname) { PUSH_TOS; TOS = PTR_TO_VMA(&varname); } #ifdef PF_SUPPORT_FP #define M_THROW(err) \ @@ -482,14 +482,14 @@ DBUG(("pfCatch: Token = 0x%x\n", Token )); { /* This was broken into two steps because different compilers incremented ** CellPtr before or after the XOR step. */ - Temp = (cell_t)CellPtr ^ PF_MEMORY_VALIDATOR; + Temp = (cell_t) (uintptr_t) CellPtr ^ PF_MEMORY_VALIDATOR; *CellPtr++ = Temp; - M_PUSH( (cell_t) CellPtr ); + M_PUSH(PTR_TO_VMA(CellPtr)); TOS = 0; } else { - M_PUSH( 0 ); + M_PUSH(0); TOS = -1; /* FIXME Fix error code. */ } endcase; @@ -1631,10 +1631,10 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); { /* Copy memory including validation. */ pfCopyMemory( (char *) CellPtr, (char *) FreePtr, TOS + sizeof(cell_t) ); - *CellPtr = (cell_t)(((ucell_t)CellPtr) ^ (ucell_t)PF_MEMORY_VALIDATOR); + *CellPtr = (cell_t)(((uintptr_t)CellPtr) ^ (ucell_t)PF_MEMORY_VALIDATOR); /* 090218 - Fixed bug that was incrementing the address twice. Thanks Reinhold Straub. */ /* Increment past validator to user address. */ - M_PUSH( (cell_t) (CellPtr + 1) ); + M_PUSH(PTR_TO_VMA(CellPtr + 1)); TOS = 0; /* Result code. */ /* Mark old cell as dead so we can't free it twice. */ FreePtr[0] = 0xDeadBeef; @@ -1643,7 +1643,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); else { /* 090218 - Fixed bug, was returning zero. */ - M_PUSH( Addr1 ); + M_PUSH(PTR_TO_VMA(Addr1)); TOS = -4; /* FIXME Fix error code. */ } } @@ -1656,11 +1656,11 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); */ case ID_RP_FETCH: /* ( -- rp , address of top of return stack ) */ PUSH_TOS; - TOS = (cell_t)TORPTR; /* value before calling RP@ */ + TOS = PTR_TO_VMA(TORPTR); /* value before calling RP@ */ endcase; case ID_RP_STORE: /* ( rp -- , address of top of return stack ) */ - TORPTR = (cell_t *) TOS; + TORPTR = (cell_t *) (uintptr_t) TOS; M_DROP; endcase; @@ -1720,11 +1720,11 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_SP_FETCH: /* ( -- sp , address of top of stack, sorta ) */ PUSH_TOS; - TOS = (cell_t)STKPTR; + TOS = PTR_TO_VMA(STKPTR); endcase; case ID_SP_STORE: /* ( sp -- , address of top of stack, sorta ) */ - STKPTR = (cell_t *) TOS; + STKPTR = (cell_t *) (uintptr_t) TOS; M_DROP; endcase; @@ -1971,7 +1971,7 @@ DBUGX(("After 0Branch: IP = 0x%x\n", InsPtr )); ERR("pfCatch: Unrecognised token = 0x"); ffDotHex(Token); ERR(" at 0x"); - ffDotHex((cell_t) InsPtr); + ffDotHex(PTR_TO_VMA(InsPtr)); EMIT_CR; InsPtr = 0; endcase; diff --git a/csrc/pf_save.c b/csrc/pf_save.c index e35dcd5..7739bd8 100644 --- a/csrc/pf_save.c +++ b/csrc/pf_save.c @@ -662,7 +662,7 @@ DBUG(("pfLoadDictionary( %s )\n", FileName )); else { gVarContext = 0; - gCurrentDictionary->dic_HeaderPtr = (ucell_t)NULL; + gCurrentDictionary->dic_HeaderPtr = PF_VM_NULL; } gCurrentDictionary->dic_CodePtr = (vm_address_t) CODEREL_TO_ABS(sd->sd_RelCodePtr); gNumPrimitives = sd->sd_NumPrimitives; /* Must match compiled dictionary. */ diff --git a/csrc/pfcompil.c b/csrc/pfcompil.c index d140925..9849c9a 100644 --- a/csrc/pfcompil.c +++ b/csrc/pfcompil.c @@ -1092,7 +1092,7 @@ FileStream * ffConvertSourceIDToStream( cell_t id ) } else { - stream = (FileStream *) id; + stream = (FileStream *) (uintptr_t) id; } return stream; } From ec0d77b772d2ee3cd53a946727b5dab6df78767e Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Sun, 10 May 2026 14:06:47 -0700 Subject: [PATCH 40/48] link with ldatomic for address sanitization --- platforms/unix/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platforms/unix/Makefile b/platforms/unix/Makefile index 54f32ed..0c8b299 100644 --- a/platforms/unix/Makefile +++ b/platforms/unix/Makefile @@ -69,6 +69,9 @@ ASAN ?= 0 # Set ASANOPTS based on ASAN value ifeq ($(ASAN),1) ASANOPTS = -fsanitize=address + ifneq ($(UNAME),Darwin) + LDADD += -latomic + endif else ASANOPTS = endif From b2719ab242498d3d4ad8e03019d9cc006e5fa05a Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Sun, 10 May 2026 14:52:56 -0700 Subject: [PATCH 41/48] make InsPtr in pf_inner.c a virtual address Add test for FLOAT compiled in a word Fix FLOAT LITERAL --- csrc/paging/pagedmem.c | 4 +- csrc/pf_inner.c | 81 ++++++++++++++++++++++------------------- csrc/pfinnrfp.h | 11 +----- fth/misc2.fth | 2 +- fth/t_floats.fth | 4 ++ platforms/unix/Makefile | 1 + 6 files changed, 53 insertions(+), 50 deletions(-) diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index 55c2f07..55a30e4 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -41,9 +41,9 @@ static cell_t sDpNextAvailable = 0; */ #if 0 #define PF_DP_MUNGE_KEY (0) -#elif (PF_CELL_SIZE == 8) +#elif (PF_POINTER_SIZE == 8) #define PF_DP_MUNGE_KEY (0x005A000000000000) -#elif (PF_CELL_SIZE == 4) +#elif (PF_POINTER_SIZE == 4) #define PF_DP_MUNGE_KEY (0x50000000) #endif diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index d1309b1..9a5fbf1 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -84,7 +84,7 @@ ** Misc Forth macros ***************************************************************/ -#define M_BRANCH { InsPtr = (cell_t *) (((uint8_t *) InsPtr) + READ_CELL_DIC(InsPtr)); } +#define M_BRANCH { InsPtr = InsPtr + READ_CELL_DIC(InsPtr); } /* Cache top of data stack like in JForth. */ #ifdef PF_SUPPORT_FP @@ -195,7 +195,7 @@ static void TraceNames( ExecToken Token, cell_t Level ) #endif /* PF_NO_SHELL */ /* Use local copy of CODE_BASE for speed. */ -#define LOCAL_CODEREL_TO_ABS( a ) ((cell_t *) (((cell_t) a) + CodeBase)) +#define LOCAL_CODEREL_TO_ABS( a ) (PTR_TO_VMA(a) + CodeBase) /* Truncate the unsigned double cell integer LO/HI to an uint64_t. */ static uint64_t UdToUint64( ucell_t Lo, ucell_t Hi ) @@ -281,7 +281,7 @@ ThrowCode pfCatch( ExecToken XT ) register cell_t TopOfStack; /* Cache for faster execution. */ register cell_t *DataStackPtr; register cell_t *ReturnStackPtr; - register cell_t *InsPtr = NULL; + register vm_address_t InsPtr = PF_VM_NULL; register cell_t Token; cell_t Scratch; @@ -303,7 +303,7 @@ ThrowCode pfCatch( ExecToken XT ) char *CharPtr; cell_t *CellPtr; FileStream *FileID; - uint8_t *CodeBase = (uint8_t *) CODE_BASE; + vm_address_t CodeBase = CODE_BASE; ThrowCode ExceptionReturnCode = 0; /* FIXME @@ -352,10 +352,11 @@ DBUG(("pfCatch: Token = 0x%x\n", Token )); M_R_PUSH( InsPtr ); /* Convert execution token to absolute address. */ - InsPtr = (cell_t *) ( LOCAL_CODEREL_TO_ABS(Token) ); + InsPtr = LOCAL_CODEREL_TO_ABS(Token); /* Fetch token at IP. */ - Token = READ_CELL_DIC(InsPtr++); + Token = READ_CELL_DIC(InsPtr); + InsPtr += PF_CELL_SIZE; #ifdef PF_SUPPORT_TRACE /* Bump level for trace display */ @@ -376,7 +377,7 @@ DBUG(("pfCatch: Token = 0x%x\n", Token )); ** Used to implement semicolon. ** Put first in switch because ID_EXIT==0 */ case ID_EXIT: - InsPtr = ( cell_t *) M_R_POP; + InsPtr = M_R_POP; #ifdef PF_SUPPORT_TRACE Level--; #endif @@ -396,8 +397,10 @@ DBUG(("pfCatch: Token = 0x%x\n", Token )); case ID_2LITERAL_P: /* hi part stored first, put on top of stack */ PUSH_TOS; - TOS = READ_CELL_DIC(InsPtr++); - M_PUSH(READ_CELL_DIC(InsPtr++)); + TOS = READ_CELL_DIC(InsPtr); + InsPtr += PF_CELL_SIZE; + M_PUSH(READ_CELL_DIC(InsPtr)); + InsPtr += PF_CELL_SIZE; endcase; case ID_2MINUS: TOS -= 2; endcase; @@ -461,7 +464,8 @@ DBUG(("pfCatch: Token = 0x%x\n", Token )); case ID_ALITERAL_P: PUSH_TOS; - TOS = (cell_t) LOCAL_CODEREL_TO_ABS( READ_CELL_DIC(InsPtr++) ); + TOS = (cell_t) LOCAL_CODEREL_TO_ABS( READ_CELL_DIC(InsPtr) ); + InsPtr += PF_CELL_SIZE; endcase; /* Allocate some extra and put validation identifier at base */ @@ -532,7 +536,8 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); case ID_CALL_C: SAVE_REGISTERS; - Scratch = READ_CELL_DIC(InsPtr++); + Scratch = READ_CELL_DIC(InsPtr); + InsPtr += PF_CELL_SIZE; CallUserFunction( Scratch & 0xFFFF, (Scratch >> 31) & 1, (Scratch >> 24) & 0x7F ); @@ -659,7 +664,7 @@ DBUGX(("After Branch: IP = 0x%x\n", InsPtr )); case ID_CREATE_P: PUSH_TOS; /* Put address of body on stack. Insptr points after code start. */ - TOS = (cell_t) ((char *)InsPtr - sizeof(cell_t) + CREATE_BODY_OFFSET ); + TOS = (cell_t) (InsPtr - sizeof(cell_t) + CREATE_BODY_OFFSET); endcase; case ID_CSTORE: /* ( c caddr -- ) */ @@ -953,19 +958,19 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_EXECUTE: /* Save IP on return stack like a JSR. */ - M_R_PUSH( InsPtr ); + M_R_PUSH(InsPtr); #ifdef PF_SUPPORT_TRACE /* Bump level for trace. */ Level++; #endif if( IsTokenPrimitive( TOS ) ) { - WRITE_CELL_DIC( (cell_t *) &FakeSecondary[0], TOS); /* Build a fake secondary and execute it. */ - InsPtr = &FakeSecondary[0]; + InsPtr = PTR_TO_VMA(&FakeSecondary[0]); + WRITE_CELL_DIC(InsPtr, TOS); /* Build a fake secondary and execute it. */ } else { - InsPtr = (cell_t *) LOCAL_CODEREL_TO_ABS(TOS); + InsPtr = LOCAL_CODEREL_TO_ABS(TOS); } M_DROP; endcase; @@ -997,7 +1002,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); DBUG(("Create file = %s with famTxt %s\n", gScratch, famText )); FileID = sdOpenFile( gScratch, famText ); TOS = ( FileID == NULL ) ? -1 : 0 ; - M_PUSH( (cell_t) FileID ); + M_PUSH(PTR_TO_VMA(FileID)); } else { @@ -1039,7 +1044,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); FileID = sdOpenFile( gScratch, famText ); TOS = ( FileID == NULL ) ? -1 : 0 ; - M_PUSH( (cell_t) FileID ); + M_PUSH(PTR_TO_VMA(FileID)); } else { @@ -1346,9 +1351,9 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); #endif /* !PF_NO_SHELL */ case ID_LITERAL_P: - DBUG(("ID_LITERAL_P: InsPtr = 0x%x, *InsPtr = 0x%x\n", InsPtr, *InsPtr )); PUSH_TOS; - TOS = READ_CELL_DIC(InsPtr++); + TOS = READ_CELL_DIC(InsPtr); + InsPtr += PF_CELL_SIZE; endcase; #ifndef PF_NO_SHELL @@ -1408,7 +1413,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); /* End of locals. Create stack frame */ DBUG(("LocalEntry: before RP@ = 0x%x, LP = 0x%x\n", TORPTR, LocalsPtr)); - M_R_PUSH(LocalsPtr); + M_R_PUSH(PTR_TO_VMA(LocalsPtr)); LocalsPtr = TORPTR; TORPTR -= TOS; DBUG(("LocalEntry: after RP@ = 0x%x, LP = 0x%x\n", @@ -1426,7 +1431,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); DBUG(("LocalExit: before RP@ = 0x%x, LP = 0x%x\n", TORPTR, LocalsPtr)); TORPTR = LocalsPtr; - LocalsPtr = (cell_t *) M_R_POP; + LocalsPtr = (cell_t *) (uintptr_t) M_R_POP; DBUG(("LocalExit: after RP@ = 0x%x, LP = 0x%x\n", TORPTR, LocalsPtr)); endcase; @@ -1460,7 +1465,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = M_R_POP + 1; /* index */ if( Scratch == Temp ) { - InsPtr++; /* skip branch offset, exit loop */ + InsPtr += PF_CELL_SIZE; /* skip branch offset, exit loop */ } else { @@ -1546,12 +1551,9 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); (x^y)<0 is equivalent to (x<0) != (y<0) */ if( ((OldDiff ^ (OldDiff + Delta)) /* is the limit crossed? */ & (OldDiff ^ Delta)) /* is it a wrap-around? */ - < 0 ) - { - InsPtr++; /* skip branch offset, exit loop */ - } - else - { + < 0 ) { + InsPtr += PF_CELL_SIZE; /* skip branch offset, exit loop */ + } else { /* Push index and limit back to R */ M_R_PUSH( NewIndex ); M_R_PUSH( Limit ); @@ -1573,7 +1575,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); { M_R_PUSH( TOS ); M_R_PUSH( Scratch ); - InsPtr++; /* skip branch offset, enter loop */ + InsPtr += PF_CELL_SIZE; /* skip branch offset, enter loop */ } M_DROP; endcase; @@ -1614,13 +1616,13 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); /* Resize memory allocated by ALLOCATE. */ case ID_RESIZE: /* ( addr1 u -- addr2 result ) */ { - cell_t *Addr1 = (cell_t *) M_POP; + cell_t *Addr1 = (cell_t *) (uintptr_t) M_POP; /* Point to validator below users address. */ cell_t *FreePtr = Addr1 - 1; - if( ((ucell_t)*FreePtr) != ((ucell_t)FreePtr ^ PF_MEMORY_VALIDATOR)) + if( ((ucell_t)*FreePtr) != (((ucell_t) (uintptr_t) FreePtr) ^ PF_MEMORY_VALIDATOR)) { /* 090218 - Fixed bug, was returning zero. */ - M_PUSH( Addr1 ); + M_PUSH(PTR_TO_VMA(Addr1)); TOS = -3; } else @@ -1951,7 +1953,7 @@ DBUGX(("Before 0Branch: IP = 0x%x\n", InsPtr )); } else { - InsPtr++; /* skip over offset */ + InsPtr += PF_CELL_SIZE; /* skip over offset */ } M_DROP; DBUGX(("After 0Branch: IP = 0x%x\n", InsPtr )); @@ -1971,13 +1973,16 @@ DBUGX(("After 0Branch: IP = 0x%x\n", InsPtr )); ERR("pfCatch: Unrecognised token = 0x"); ffDotHex(Token); ERR(" at 0x"); - ffDotHex(PTR_TO_VMA(InsPtr)); + ffDotHex(InsPtr); EMIT_CR; - InsPtr = 0; + InsPtr = PF_VM_NULL; endcase; } - if(InsPtr) Token = READ_CELL_DIC(InsPtr++); /* Traverse to next token in secondary. */ + if(InsPtr) { + Token = READ_CELL_DIC(InsPtr); /* Traverse to next token in secondary. */ + InsPtr += PF_CELL_SIZE; + } #ifdef PF_DEBUG M_DOTS; @@ -1987,7 +1992,7 @@ DBUGX(("After 0Branch: IP = 0x%x\n", InsPtr )); if( _CrtCheckMemory() == 0 ) { ERR("_CrtCheckMemory abort: InsPtr = 0x"); - ffDotHex((cell_t)InsPtr); + ffDotHex(InsPtr); ERR("\n"); } #endif diff --git a/csrc/pfinnrfp.h b/csrc/pfinnrfp.h index a0fd8f5..85c4154 100644 --- a/csrc/pfinnrfp.h +++ b/csrc/pfinnrfp.h @@ -283,17 +283,10 @@ case ID_FP_FLITERAL_P: PUSH_FP_TOS; -#if 0 -/* Some wimpy compilers can't handle this! */ - FP_TOS = *(((PF_FLOAT *)InsPtr)++); -#else { - PF_FLOAT *fptr; - fptr = (PF_FLOAT *)InsPtr; - FP_TOS = READ_FLOAT_DIC( fptr++ ); - InsPtr = (cell_t *) fptr; + FP_TOS = READ_FLOAT_DIC(InsPtr); + InsPtr += sizeof(PF_FLOAT); } -#endif endcase; case ID_FP_FLN: /* ( -- ) ( F: r1 -- r2 ) */ diff --git a/fth/misc2.fth b/fth/misc2.fth index 4f6ecb2..b4285f3 100644 --- a/fth/misc2.fth +++ b/fth/misc2.fth @@ -212,7 +212,7 @@ VARIABLE SPAN : U.HEX ( n -- , print a as hex unsigned ) base @ - swap u. + swap hex u. base ! ; diff --git a/fth/t_floats.fth b/fth/t_floats.fth index 2d95f7a..66c49c8 100644 --- a/fth/t_floats.fth +++ b/fth/t_floats.fth @@ -163,5 +163,9 @@ T{ my-abcs abc.f1 f@ 23.45 0.0 F~ }T{ true }T T{ my-abcs abc.w2 @ }T{ 98765 }T \ ----------------------------------------------------- \ +\ Compile FLOAT into the dictionary. +: TF.123 123.456 ; +T{ TF.123 123.456 0.0 F~ }T{ true }T + }TEST diff --git a/platforms/unix/Makefile b/platforms/unix/Makefile index 0c8b299..600b471 100644 --- a/platforms/unix/Makefile +++ b/platforms/unix/Makefile @@ -70,6 +70,7 @@ ASAN ?= 0 ifeq ($(ASAN),1) ASANOPTS = -fsanitize=address ifneq ($(UNAME),Darwin) + ASANOPTS += -static-libasan LDADD += -latomic endif else From 449c0df5de49786d94865ecb4aada25df21f8fad Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Mon, 11 May 2026 11:27:44 -0700 Subject: [PATCH 42/48] Fix all warning on Unix except SourcePtr related Used (uintptr_t) casting to address warnings related to converting form a 32-bit cell_t to a pointer. --- csrc/paging/lockpage.c | 12 ++++++------ csrc/pf_core.c | 8 ++++---- csrc/pf_guts.h | 4 +++- csrc/pf_inner.c | 27 ++++++++++++++------------- csrc/pf_save.c | 4 ++-- 5 files changed, 29 insertions(+), 26 deletions(-) diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index bcff226..635dab0 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -27,11 +27,11 @@ void pfResetLockedMemory(void) { } const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, uint32_t numBytes) { - return ((const uint8_t *)(vp)); + return ((const uint8_t *) (uintptr_t) (vp)); } uint8_t *pfLockMemoryReadWrite(vm_address_t vp, uint32_t numBytes) { - return ((uint8_t *)(vp)); + return ((uint8_t *) (uintptr_t) (vp)); } int pfUnlockMemory(vm_address_t vp, const uint8_t *pp) { @@ -45,23 +45,23 @@ int pfIsAddressInPagedMemory(vm_address_t p) { void *pfCopyFromVirtualMemory(void *destination, vm_address_t source, uint32_t numBytes) { - return pfCopyMemory(destination, (const void *)source, numBytes); + return pfCopyMemory(destination, (const void *) (uintptr_t) source, numBytes); } vm_address_t pfCopyToVirtualMemory(vm_address_t destination, const void *source, uint32_t numBytes) { - return (vm_address_t) pfCopyMemory((void *)destination, source, numBytes); + return PTR_TO_VMA(pfCopyMemory((void *) (uintptr_t) destination, source, numBytes)); } void pfFreeVirtualMemory(vm_address_t address) { - pfFreeMem((void *) address); + pfFreeMem((void *) (uintptr_t) address); } vm_address_t pfSetVirtualMemory(vm_address_t destination, uint8_t value, uint32_t numBytes) { - return (vm_address_t) pfSetMemory((void *)destination, value, numBytes); + return PTR_TO_VMA(pfSetMemory((void *) (uintptr_t) destination, value, numBytes)); } #else /* PF_DEMAND_PAGING */ diff --git a/csrc/pf_core.c b/csrc/pf_core.c index 2efeb2a..41cd6a8 100644 --- a/csrc/pf_core.c +++ b/csrc/pf_core.c @@ -100,7 +100,7 @@ static void pfInit( void ) gCurrentDictionary = NULL; gNumPrimitives = 0; gLocalCompiler_XT = 0; - gVarContext = (cell_t)NULL; /* Points to last name field. */ + gVarContext = PF_VM_NULL; /* Points to last name field. */ gVarState = 0; /* 1 if compiling. */ gVarByeCode = 0; /* BYE-CODE */ gVarEcho = 0; /* Echo input. */ @@ -193,7 +193,7 @@ PForthTask pfCreateTask( cell_t UserStackDepth, cell_t ReturnStackDepth ) ThrowCode pfExecIfDefined( const char *CString ) { ThrowCode result = 0; - if( NAME_BASE != (cell_t)NULL) + if( NAME_BASE != PF_VM_NULL) { ExecToken XT; if( ffFindC( CString, &XT ) ) @@ -214,8 +214,8 @@ void pfDeleteDictionary( PForthDictionary dictionary ) if( dic->dic_Flags & PF_DICF_ALLOCATED_SEGMENTS ) { - FREE_VAR( dic->dic_HeaderBaseUnaligned ); - FREE_VAR( dic->dic_CodeBaseUnaligned ); + FREE_VM_VAR( dic->dic_HeaderBaseUnaligned ); + FREE_VM_VAR( dic->dic_CodeBaseUnaligned ); } pfFreeMem( dic ); } diff --git a/csrc/pf_guts.h b/csrc/pf_guts.h index fdb2758..6ad5a6e 100644 --- a/csrc/pf_guts.h +++ b/csrc/pf_guts.h @@ -599,7 +599,9 @@ extern cell_t gIncludeIndex; /* The check for >0 is only needed for CLONE testing. !!! */ #define IsTokenPrimitive(xt) ((xt=0)) -#define FREE_VAR(v) { pfFreeVirtualMemory((vm_address_t)(v)); v = 0; } +#define FREE_VAR(pm_var) { pfFreeMem(pm_var); pm_var = 0; } +/* For virtual memory addresses we have to avoid narrowing of the address. */ +#define FREE_VM_VAR(vm_var) { pfFreeVirtualMemory(vm_var); vm_var = 0; } #define DATA_STACK_DEPTH (gCurrentTask->td_StackBase - gCurrentTask->td_StackPtr) #define DROP_DATA_STACK (gCurrentTask->td_StackPtr++) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 9a5fbf1..2dd3242 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1056,11 +1056,11 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); endcase; case ID_FILE_CLOSE: /* ( fid -- ior ) */ - TOS = sdCloseFile( (FileStream *) TOS ); + TOS = sdCloseFile( (FileStream *) (uintptr_t) TOS ); endcase; case ID_FILE_READ: /* ( addr len fid -- u2 ior ) */ - FileID = (FileStream *) TOS; + FileID = (FileStream *) (uintptr_t) TOS; Scratch = M_POP; { vm_address_t vAddr = (vm_address_t) M_POP; @@ -1075,7 +1075,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); /* TODO Why does this crash when passed an illegal FID? */ case ID_FILE_SIZE: /* ( fid -- ud ior ) */ /* Determine file size by seeking to the end and returning position. */ - FileID = (FileStream *) TOS; + FileID = (FileStream *) (uintptr_t) TOS; { file_offset_t endposition = -1; file_offset_t original = sdTellFile( FileID ); @@ -1103,7 +1103,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); endcase; case ID_FILE_WRITE: /* ( addr len fid -- ior ) */ - FileID = (FileStream *) TOS; + FileID = (FileStream *) (uintptr_t) TOS; Scratch = M_POP; { vm_address_t vAddr = (vm_address_t) M_POP; @@ -1117,7 +1117,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); file_offset_t offset; cell_t offsetHigh; cell_t offsetLow; - FileID = (FileStream *) TOS; + FileID = (FileStream *) (uintptr_t) TOS; offsetHigh = M_POP; offsetLow = M_POP; /* We do not support double precision file offsets in pForth. @@ -1136,7 +1136,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_FILE_POSITION: /* ( fid -- ud ior ) */ { file_offset_t position; - FileID = (FileStream *) TOS; + FileID = (FileStream *) (uintptr_t) TOS; position = sdTellFile( FileID ); if (position < 0) { @@ -1175,7 +1175,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_FILE_FLUSH: /* ( fileid -- ior ) */ { - FileStream *Stream = (FileStream *) TOS; + FileStream *Stream = (FileStream *) (uintptr_t) TOS; TOS = (sdFlushFile( Stream ) == 0) ? 0 : THROW_FLUSH_FILE; } endcase; @@ -1198,7 +1198,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_FILE_RESIZE: /* ( ud fileid -- ior ) */ { - FileStream *File = (FileStream *) TOS; + FileStream *File = (FileStream *) (uintptr_t) TOS; ucell_t SizeHi = (ucell_t) M_POP; ucell_t SizeLo = (ucell_t) M_POP; TOS = ( UdIsUint64( SizeHi ) @@ -1239,7 +1239,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_FINDNFA: /* ( $name -- $addr 0 | nfa -1 | nfa 1 , find NFA in dictionary ) */ { - vm_address_t nfa = (vm_address_t) NULL; + vm_address_t nfa = PF_VM_NULL; vm_address_t vName = (vm_address_t) TOS; cell_t totalLength = DP_FETCH_U8(vName) + 1; /* length including count */ const char *pAddr = (const char *) pfLockMemoryReadOnly(vName, totalLength); @@ -1267,9 +1267,10 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); } else { - CellPtr = (cell_t *) TOS; + CellPtr = (cell_t *) (uintptr_t) TOS; CellPtr--; - if( ((ucell_t)*CellPtr) != ((ucell_t)CellPtr ^ PF_MEMORY_VALIDATOR)) + if( ((ucell_t)*CellPtr) != + (((ucell_t) (uintptr_t) CellPtr) ^ PF_MEMORY_VALIDATOR)) { TOS = -2; /* FIXME error code */ } @@ -1312,7 +1313,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); #ifndef PF_NO_SHELL case ID_INCLUDE_FILE: - FileID = (FileStream *) TOS; + FileID = (FileStream *) (uintptr_t) TOS; M_DROP; /* Drop now so that INCLUDE has a clean stack. */ SAVE_REGISTERS; Scratch = ffIncludeFile( FileID ); @@ -1668,7 +1669,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); case ID_R_ZERO: /* ( -- rbase , base of return stack ) */ PUSH_TOS; - TOS = (cell_t)gCurrentTask->td_ReturnBase; + TOS = PTR_TO_VMA(gCurrentTask->td_ReturnBase); endcase; case ID_ROLL: /* ( xu xu-1 xu-1 ... x0 u -- xu-1 xu-1 ... x0 xu ) */ diff --git a/csrc/pf_save.c b/csrc/pf_save.c index 7739bd8..1e1c079 100644 --- a/csrc/pf_save.c +++ b/csrc/pf_save.c @@ -819,13 +819,13 @@ PForthDictionary pfLoadStaticDictionary( void ) #if PF_DEMAND_PAGING pfWritePagedMemory((paging_address_t) dic->dic_HeaderBase, MinDicNames, sizeof(MinDicNames)); #else - pfCopyMemory( (uint8_t *) dic->dic_HeaderBase, MinDicNames, sizeof(MinDicNames) ); + pfCopyMemory((uint8_t *) (uintptr_t) dic->dic_HeaderBase, MinDicNames, sizeof(MinDicNames)); #endif #if PF_DEMAND_PAGING pfWritePagedMemory((paging_address_t) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode)); #else - pfCopyMemory((uint8_t *) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode)); + pfCopyMemory((uint8_t *) (uintptr_t) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode)); #endif DBUG(("Static data copied to newly allocated dictionaries.\n")); From 51785bf549226d46b0a3fd5d42509e7112c9d5b7 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Mon, 11 May 2026 14:48:35 -0700 Subject: [PATCH 43/48] add new paging files to CMake build --- CMakeLists.txt | 4 ++-- csrc/sources.cmake | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e91b8d..0a42c4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,7 +70,7 @@ add_custom_command(OUTPUT ${PFORTH_DIC} COMMAND ./${PFORTH_EXE} -i ${PFORTH_FTH_DIR}/system.fth WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS pforth - COMMENT Building pforth.dic + COMMENT "Building pforth.dic" VERBATIM ) add_custom_target(pforth_dic DEPENDS ${PFORTH_DIC}) @@ -83,7 +83,7 @@ add_custom_command(OUTPUT ${PFORTH_DIC_HEADER} COMMAND ${CMAKE_COMMAND} -E rename pfdicdat.h ../csrc/pfdicdat.h WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS pforth_dic - COMMENT Building pfdicdat.h + COMMENT "Building pfdicdat.h" VERBATIM ) add_custom_target(pforth_dic_header DEPENDS ${PFORTH_DIC_HEADER}) diff --git a/csrc/sources.cmake b/csrc/sources.cmake index c4dcf43..0aa2100 100644 --- a/csrc/sources.cmake +++ b/csrc/sources.cmake @@ -18,6 +18,7 @@ pfcompfp.h pfcompil.h pfinnrfp.h pforth.h +paging/dmpaging.h pf_cglue.c pf_clib.c pf_core.c @@ -30,4 +31,7 @@ pf_text.c pf_words.c pfcompil.c pfcustom.c +paging/pagedmem.c +paging/lockpage.c +paging/qadmpage.c From 216f0abb9895394d8a94615d0121ff214f579b7d Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Mon, 11 May 2026 15:22:05 -0700 Subject: [PATCH 44/48] CI for cell size 4 and 8 on 32-bit builds --- .github/workflows/make32.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/make32.yml b/.github/workflows/make32.yml index e43e81a..853dc34 100644 --- a/.github/workflows/make32.yml +++ b/.github/workflows/make32.yml @@ -13,7 +13,7 @@ env: jobs: build: - name: Build 32-bit (PAGING=${{ matrix.demand_paging }}, FLOAT=${{ matrix.support_fp }}) + name: Build 32-bit (PAGING=${{ matrix.demand_paging }}, FLOAT=${{ matrix.support_fp }}, CELL=${{ matrix.cell_size }}) # This uses a Unix Makefile and should run on Linux and Mac runs-on: ubuntu-latest @@ -21,6 +21,7 @@ jobs: matrix: demand_paging: [0, 1] support_fp: [0, 1] + cell_size: [4, 8] steps: - uses: actions/checkout@v2 @@ -30,5 +31,5 @@ jobs: - name: Build and Test working-directory: ${{github.workspace}}/platforms/unix - run: make test WIDTHOPT=-m32 ASAN=1 XCPPFLAGS="-DPF_SUPPORT_FP=${{ matrix.support_fp }} -DPF_DEMAND_PAGING=${{ matrix.demand_paging }} -D_DEFAULT_SOURCE -D_GNU_SOURCE" + run: make test WIDTHOPT=-m32 ASAN=1 XCPPFLAGS="-DPF_SUPPORT_FP=${{ matrix.support_fp }} -DPF_DEMAND_PAGING=${{ matrix.demand_paging }} -DPF_CELL_SIZE=${{ matrix.cell_size }} -D_DEFAULT_SOURCE -D_GNU_SOURCE" From 5f4002c088d46575c0b801e4a9d6ccab9cd6a499 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Mon, 11 May 2026 17:36:30 -0700 Subject: [PATCH 45/48] Reset paged memory after running the QA tests. Leave paged memory in known state. Also add another technique for munging virtual addresses in the simulator. --- csrc/paging/pagedmem.c | 53 ++++++++++++++++++++++++++++++++++-------- csrc/paging/pagedmem.h | 8 +++++++ csrc/paging/qadmpage.c | 7 ++---- csrc/pf_core.c | 4 ++++ csrc/pf_inner.c | 3 ++- 5 files changed, 59 insertions(+), 16 deletions(-) diff --git a/csrc/paging/pagedmem.c b/csrc/paging/pagedmem.c index 55a30e4..87763ce 100644 --- a/csrc/paging/pagedmem.c +++ b/csrc/paging/pagedmem.c @@ -31,7 +31,6 @@ #define PF_DP_AVAILABLE_SPACE (512*1024) #endif -static uint8_t sFakeSerialRAM[PF_DP_AVAILABLE_SPACE]; static cell_t sDpNextAvailable = 0; #define DP_ALIGNMENT_MASK (DP_ALIGNMENT_SIZE - 1) @@ -39,22 +38,56 @@ static cell_t sDpNextAvailable = 0; * This will help us catch areas where we need to use functions like pfLockMemoryReadWrite(). * You may need to use a different mask on your system depending on the memory layout. */ -#if 0 -#define PF_DP_MUNGE_KEY (0) -#elif (PF_POINTER_SIZE == 8) -#define PF_DP_MUNGE_KEY (0x005A000000000000) -#elif (PF_POINTER_SIZE == 4) -#define PF_DP_MUNGE_KEY (0x50000000) -#endif +#define MUNGE_BY_OFFSET 0 +#if (MUNGE_BY_OFFSET) + /* Allocate twice the needed space. Munged addresses point to the high half. */ + static uint8_t sFakeSerialRAM[2 * PF_DP_AVAILABLE_SPACE]; + /* Munge by offsetting the address. This might be helpful if high address bits are ignored, + * causing the XOR bits to be ignored. */ + #define PF_DP_MUNGE(addr) ((vm_address_t)((PTR_TO_VMA(addr)) + PF_DP_AVAILABLE_SPACE)) + #define PF_DP_UNMUNGE(paging_addr) ((uintptr_t)((paging_addr) - PF_DP_AVAILABLE_SPACE)) + #define DEAD_MARKER ((uint8_t)0x00) +#else + static uint8_t sFakeSerialRAM[PF_DP_AVAILABLE_SPACE]; + #if (PF_POINTER_SIZE == 8) + #define PF_DP_MUNGE_KEY (0x005A000000000000) + #elif (PF_POINTER_SIZE == 4) + #define PF_DP_MUNGE_KEY (0x50000000) + #endif -#define PF_DP_MUNGE(addr) ((vm_address_t)((PTR_TO_VMA(addr)) ^ PF_DP_MUNGE_KEY)) -#define PF_DP_UNMUNGE(paging_addr) ((uintptr_t)((paging_addr) ^ PF_DP_MUNGE_KEY)) + #define PF_DP_MUNGE(addr) ((vm_address_t)((PTR_TO_VMA(addr)) ^ PF_DP_MUNGE_KEY)) + #define PF_DP_UNMUNGE(paging_addr) ((uintptr_t)((paging_addr) ^ PF_DP_MUNGE_KEY)) +#endif void pfResetPagedMemory(void) { printf("pfResetPagedMemory: cell = %d\n", (int)sizeof(cell_t)); sDpNextAvailable = 0; + +#if (MUNGE_BY_OFFSET) + /* Fill memory that should not be touched with a marker. */ + memset(&sFakeSerialRAM[PF_DP_AVAILABLE_SPACE], DEAD_MARKER, PF_DP_AVAILABLE_SPACE); +#endif } +int pfCheckPagedMemory(void) { + /* Check to see if anything wrote to the high memory. */ +#if (MUNGE_BY_OFFSET) + uint32_t i; + int numErrors = 0; + uint8_t *ram = &sFakeSerialRAM[PF_DP_AVAILABLE_SPACE]; /* point to high unused half */ + for (i = 0; i < PF_DP_AVAILABLE_SPACE; i++) { + uint8_t value = *ram++; + if (value != DEAD_MARKER) { + printf("pfCheckPagedMemory: bad byte 0x%02X at offset %u\n", value, i); + numErrors++; + } + } + printf("pfCheckPagedMemory: found %d errors\n", numErrors); + return numErrors; +#else + return 0; +#endif +} int pfIsAddressInPagedMemory(vm_address_t p) { uintptr_t addr = PF_DP_UNMUNGE(p); cell_t offset = (uint8_t *)addr - sFakeSerialRAM; diff --git a/csrc/paging/pagedmem.h b/csrc/paging/pagedmem.h index d326884..7f33f35 100644 --- a/csrc/paging/pagedmem.h +++ b/csrc/paging/pagedmem.h @@ -47,6 +47,14 @@ int pfIsAddressInPagedMemory(vm_address_t p); */ void pfResetPagedMemory(void); +/** + * Check the paged memory for corruption. + * This is only implemented for the memory simulator. + * This can be a NOOP in a real implementation. + * @return zero if memory untouched else number of bad bytes + */ +int pfCheckPagedMemory(void); + /** Allocate demand paged memory from SPI or other storage. * Memory blocks will be aligned on DP_ALIGNMENT_SIZE byte boundaries. */ diff --git a/csrc/paging/qadmpage.c b/csrc/paging/qadmpage.c index d314282..25b0e84 100644 --- a/csrc/paging/qadmpage.c +++ b/csrc/paging/qadmpage.c @@ -157,7 +157,6 @@ static int pfQaTestRegionLock(void) { #define PF_DP_TEST_PATHNAME "/tmp/pf_scratch_file" - static cell_t pfQaTestCreateFile(size_t numBytes) { uint8_t buffer[100]; int i; @@ -281,10 +280,8 @@ static int pfQaTestSetVirtualMemory(void) { } int pfQaDemandPaging(void) { - printf("pfQaDemandPaging\n"); - + printf("pfQaDemandPaging called\n"); ASSERT_EQ(sizeof(vm_address_t), sizeof(cell_t)); - ASSERT_EQ(pfQaTestAllocate(), 0); ASSERT_EQ(pfQaTestReadWrite(), 0); ASSERT_EQ(pfQaTestRegionLock(), 0); @@ -295,10 +292,10 @@ int pfQaDemandPaging(void) { ASSERT_EQ(pfQaTestReadFilePaging(), 0); ASSERT_EQ(pfQaTestWriteFilePaging(), 0); ASSERT_EQ(pfQaTestSetVirtualMemory(), 0); - printf("pfQaDemandPaging ended\n"); error: + pfResetPagedMemory(); PFQA_PRINT_RESULT; return PFQA_EXIT_RESULT; } diff --git a/csrc/pf_core.c b/csrc/pf_core.c index 41cd6a8..1b633d5 100644 --- a/csrc/pf_core.c +++ b/csrc/pf_core.c @@ -592,6 +592,10 @@ ThrowCode pfDoForth( const char *DicFileName, const char *SourceName, cell_t IfI pfTerm(); +#if PF_DEMAND_PAGING + pfCheckPagedMemory(); +#endif + #ifdef PF_USER_TERM PF_USER_TERM; #endif diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 2dd3242..ffc4473 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1318,7 +1318,8 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); SAVE_REGISTERS; Scratch = ffIncludeFile( FileID ); LOAD_REGISTERS; - if( Scratch ) M_THROW(Scratch) + if( Scratch ) M_THROW(Scratch); + pfCheckPagedMemory(); endcase; #endif /* !PF_NO_SHELL */ From 26b1f572438d43a704677f44e96b290049ea6400 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Mon, 11 May 2026 17:45:41 -0700 Subject: [PATCH 46/48] fix reference to pfCheckPagedMemory() --- csrc/pf_inner.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index ffc4473..083634c 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1319,7 +1319,9 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); Scratch = ffIncludeFile( FileID ); LOAD_REGISTERS; if( Scratch ) M_THROW(Scratch); +#if PF_DEMAND_PAGING pfCheckPagedMemory(); +#endif endcase; #endif /* !PF_NO_SHELL */ From a566ecad4989d263433551d51df34a6341a15967 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Thu, 14 May 2026 09:15:27 -0700 Subject: [PATCH 47/48] Fix overindexing of memory lock in DUMP --- Testing/Temporary/CTestCostData.txt | 1 + Testing/Temporary/LastTest.log | 3 +++ csrc/pf_core.h | 9 ++++----- csrc/pf_text.c | 11 ++++++----- csrc/pforth.h | 2 +- 5 files changed, 15 insertions(+), 11 deletions(-) create mode 100644 Testing/Temporary/CTestCostData.txt create mode 100644 Testing/Temporary/LastTest.log diff --git a/Testing/Temporary/CTestCostData.txt b/Testing/Temporary/CTestCostData.txt new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/Testing/Temporary/CTestCostData.txt @@ -0,0 +1 @@ +--- diff --git a/Testing/Temporary/LastTest.log b/Testing/Temporary/LastTest.log new file mode 100644 index 0000000..ce0c647 --- /dev/null +++ b/Testing/Temporary/LastTest.log @@ -0,0 +1,3 @@ +Start testing: May 14 09:13 PDT +---------------------------------------------------------- +End testing: May 14 09:13 PDT diff --git a/csrc/pf_core.h b/csrc/pf_core.h index d593791..3c8cdfa 100644 --- a/csrc/pf_core.h +++ b/csrc/pf_core.h @@ -26,16 +26,15 @@ extern "C" { #endif -void pfInitGlobals( void ); +void pfInitGlobals(void); -void pfDebugMessage( const char *CString ); -void pfDebugPrintDecimalNumber( cell_t n ); +void pfDebugMessage(const char *CString); +void pfDebugPrintDecimalNumber(cell_t n); -cell_t pfUnitTestText( void ); +cell_t pfUnitTestText(void); #ifdef __cplusplus } #endif - #endif /* _pf_core_h */ diff --git a/csrc/pf_text.c b/csrc/pf_text.c index 405f479..15e78c2 100644 --- a/csrc/pf_text.c +++ b/csrc/pf_text.c @@ -302,25 +302,26 @@ char *ConvertNumberToText( cell_t Num, cell_t Base, int32_t IfSigned, int32_t Mi */ void DumpMemory(vm_address_t vAddr, cell_t cnt) { + const cell_t kLineSize = 16; cell_t lineIndex, byteIndex; - cell_t numLines = (cnt + 15) / 16; + cell_t numLines = (cnt + (kLineSize - 1)) / kLineSize; /* print whole last line */ vm_address_t vPtr = vAddr; EMIT_CR; for (lineIndex=0; lineIndex '}')) c = '.'; @@ -331,7 +332,7 @@ void DumpMemory(vm_address_t vAddr, cell_t cnt) pfUnlockMemory(vPtr, pAddr); EMIT_CR; - vPtr += 16; + vPtr += kLineSize; } } diff --git a/csrc/pforth.h b/csrc/pforth.h index 4d56269..b8e5f3d 100644 --- a/csrc/pforth.h +++ b/csrc/pforth.h @@ -82,7 +82,7 @@ typedef ucell_t vm_address_t; /** an address that may be in physical or paged me #define PF_VM_NULL PTR_TO_VMA(0) #ifndef PF_ASSERT_ENABLED -#define PF_ASSERT_ENABLED 0 +#define PF_ASSERT_ENABLED 1 #endif /* PF_ASSERT_ENABLED */ #ifdef __cplusplus From 523fd753389ebc2be237abffa2dbabc3e3d7e428 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Thu, 14 May 2026 09:26:29 -0700 Subject: [PATCH 48/48] Use pfSetVirtualMemory() for FILL --- csrc/paging/lockpage.c | 2 +- csrc/pf_inner.c | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/csrc/paging/lockpage.c b/csrc/paging/lockpage.c index 635dab0..ca40a62 100644 --- a/csrc/paging/lockpage.c +++ b/csrc/paging/lockpage.c @@ -277,7 +277,7 @@ vm_address_t pfSetVirtualMemory(vm_address_t destination, uint8_t value, uint32_t numBytes) { if (pfIsAddressInPagedMemory(destination)) { - /* Set memory in blocks that will fit in locked regions. */ + /* Set memory in blocks for faster writes. */ vm_address_t vp = destination; uint8_t buffer[16]; pfSetMemory(buffer, value, sizeof(buffer)); diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index 083634c..e9979f0 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1212,11 +1212,7 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); vm_address_t dstVAddr; Temp = M_POP; /* num */ dstVAddr = (vm_address_t) M_POP; /* dst */ - for( Scratch=0; (ucell_t) Scratch < (ucell_t) Temp ; Scratch++ ) - { - DP_STORE_U8(dstVAddr, TOS); - dstVAddr++; - } + pfSetVirtualMemory(dstVAddr, TOS, (uint32_t) Temp); M_DROP; } endcase;