Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Forth Implementations advantages and disadvantages.

935 views
Skip to first unread message

Cecil Bayona

unread,
May 26, 2017, 3:49:41 PM5/26/17
to
I'm working on a Forth system with the following properties in order of
importance;

1. Easy to migrate to other CPUs.
2. Good and simple to understand.
3. Small
4. Fast

You can't have all four items to the max as they are somewhat
contradictory but I'm hoping to get a decent mix of those qualities.

So far my plan has been to write the primitives in C or Go, making it a
Direct Threaded Token based Forth. It would use Direct Threading but
instead of using native assembler code for the primitives it would use C
or Go code to implement the primitives. That makes it easier to port but
it is not lightning fast, but maybe fast enough.

The tokens would be byte size allowing for up to 256 primitives if
desired, more with extension codes, an array of addresses would be used
to speed it up some instead of a bunch of IF statements or CASE statements.

This scheme would allow the easy porting of the Forth to any CPU that
has a C compiler and for custom FPGA CPUs things are a little more
complicated, as an assembler and the primitives would be written using
the assembler or the primitives would be the actual CPU instructions. In
either case it's a little more messy.

Items one through three are well supported with the above scheme but
item four is not so well. If a particular version will be used a lot and
the extra speed is needed then the use of assembler primitives instead
of tokens would create a good speed increase, but this would not be done
for most CPUs.

Currently I use Dr. Tings eForth to Meta-compile a Forth for FPGA CPUs
and it does a good job but I would like to have my own software. Maybe
I'm wrong here and continuing this approach is not a bad option.

Any suggestions, opinions, or general comments would be appreciated.


--
Cecil - k5nwa

minf...@arcor.de

unread,
May 26, 2017, 4:17:03 PM5/26/17
to
You asked for a general comment: stay as close to _real_ applications as possible, don't spend time on tool cosmetics ( unless it is good fun ;-)
or building your own tools ( unless you can afford the time to neglect
the real applications while building the tools which might at the end
of the days be inferior to what you expected )

Solutions for real world problems are always the best and most satisfying.

Cecil Bayona

unread,
May 26, 2017, 6:53:55 PM5/26/17
to
Building a compiler is fun in itself but there are other reasons why a
custom Forth is needed.

Well a problem I see specially with custom FPGA CPUs is that there are
not any tools available for the unique device. So I have two choices
available to have my own super easy to port Forth software or modify an
existing tool to meta-compile a Forth system to a CPU that has none
available, this is more complex than having my own easily ported Forth.
In either case I will have to build my own tools since they will not be
available.

Another advantage to my own compiler is that when I work on various CPUs
the software is identical. One of the things noted while doing research
is that there are Forth available for many CPUs but they all have their
differences which could be changed so they are closely matched but that
is a lot more work than having an easily ported Forth that are identical
to each other.

With the second option which is to modify an existing tool there are
several choices also.

eForth can be easily used to create an Assembler and Meta-Compiler I
already have all the software, it's just a question of modifying
existing software to the CPU of the day.

I also have two commercial Forth systems that optimize machine code and
have a lot of features, VFX Forth by MPE and SwiftForth by Forth Inc
either could be used to generate the Assembler and Meta-Compiler needed
to create my own Forth tools.

Originally I wanted to use Go to create a Forth Virtual Machine at the
core of a eForth tools but I'm finding some issues that make it harder
for me to create what I want. This project does not need to be done in
Go or C instead using Forth might be a better option.

There is no simple solution, the more I look at it the more options that
come up.

--
Cecil - k5nwa

rickman

unread,
May 27, 2017, 1:09:48 AM5/27/17
to
"I would like to have my own software". Why is this important? I don't
get it. If you have software you can use as you wish, why does it
matter who wrote it?

--

Rick C

Raimond Dragomir

unread,
May 27, 2017, 1:32:00 AM5/27/17
to
> Well a problem I see specially with custom FPGA CPUs is that there are
> not any tools available for the unique device. So I have two choices
> available to have my own super easy to port Forth software or modify an
> existing tool to meta-compile a Forth system to a CPU that has none
> available, this is more complex than having my own easily ported Forth.
> In either case I will have to build my own tools since they will not be
> available.

When I hear "FPGA CPU" I think it can be any kind of an animal... And I saw
really really weird architectures. It's hard to say what kind of threading
technique is best for such a CPU before seeing it. The problem is that
for one CPU a tokenizing forth can be ok, but for another one it can be
awfully slow... There is a well-known example, of the very well-known 8051
CPU. It has such a poor support for memory addressing that the only decent
forth threading for it is just STC. Everything else (even DTC) is so slow
that's embarassing.

Cecil Bayona

unread,
May 27, 2017, 1:57:12 AM5/27/17
to
That is why I'm having a hard time deciding what to do, the
possibilities are too large and varied so no one solution works great.

So far the best solution is Direct Token Threaded with the proviso that
if used often and its not fast enough the it could be modified to use
assembler primitives instead of C that would not be a big change.

--
Cecil - k5nwa

Cecil Bayona

unread,
May 27, 2017, 1:59:28 AM5/27/17
to
Having total control so it can be the way I want it can be important. I
really don't know of any Forth whose main goal is easy porting which is
the most important feature I desire. Most Forth are either all
assembler, or a mix of assembler and Forth, either one is hard to port,
there are a few written in C but they fail at being simple to understand
and change.

eForth is the closest to those goals that doesn't break the bank and
there are a multitude of architectures available, Indirect Threaded,
Direct Threaded, Subroutine Threaded, and even Token Threaded versions
of eForth so in the end that might not be a bad way to go but no matter
what when a new FPGA CPU or an existing one is modified one needs to
port the software to the new device.

Before I put a lot of effort into creating something from scratch it
might be worth the effort to attempt to port an existing eForth version
to a different CPU and see how practical that is. port ep16 eForth to
become ep32 eForth that would be a nice test as I have working ep32
software to compare it to. If it works OK then no need to write anything
from scratch just port a new version as needed. ep16 CPU eForth to J1
CPU eForth might also be a nice test since the CPUs are quite different.

--
Cecil - k5nwa

rickman

unread,
May 27, 2017, 2:09:18 AM5/27/17
to
If the Forth is not written in assembler, how would it be ported to
custom CPU designs? Actually I have no idea where you are going with
this. You talk about writing a "super easy to port" Forth, but I
haven't read how you might go about this.

--

Rick C

Fred J. Scipione

unread,
May 27, 2017, 2:12:18 AM5/27/17
to
[This followup was posted to comp.lang.forth and a copy was sent to the cited author.]
In article <oga0m5$56d$1...@dont-email.me>, you say...
>
> I'm working on a Forth system with the following properties in order of
> importance;
>
> 1. Easy to migrate to other CPUs.
> 2. Good and simple to understand.
> 3. Small
> 4. Fast
>
> You can't have all four items to the max as they are somewhat
> contradictory but I'm hoping to get a decent mix of those qualities.
>
> So far my plan has been to write the primitives in C or Go, making it a
> Direct Threaded Token based Forth. It would use Direct Threading but
> instead of using native assembler code for the primitives it would use C
> or Go code to implement the primitives. That makes it easier to port but
> it is not lightning fast, but maybe fast enough.
>
... snip ...
> Currently I use Dr. Tings eForth to Meta-compile a Forth for FPGA CPUs
> and it does a good job but I would like to have my own software. Maybe
> I'm wrong here and continuing this approach is not a bad option.
>
> Any suggestions, opinions, or general comments would be appreciated.

If you want to follow this path, might I suggest SmallC 2.2 and SmallA?
The SmallA assembler is table driven (similar to the SmallMac package),
so adaption to other processors (especially FPGA custom CPU's) is made
somewhat easier. The compiler is table driven for optimization and
assembler output, again easing adaptation.

I have a version (2.2.1) that is a work-in-progress. I have separated
the host and target constants to support making cross-tools. That
helped me to develop a 32-bit target version w/ right-to-left function
argument stacking, necessary OS interface, run-time, and standard
function libraries, etc. With an OMF librarian and linker one has a
complete tool chain.

SmallA uses a utility called 'cmit' to create '.obj' tables that cannot
be programmed directly within SmallC's limitations. I have extended it
to emit the tables as either 'c' code or assembler as well. Some of the
compiler's tables can be expressed in '#asm ... #endasm' blocks. You
might use these techniques, or find a way to add 'dispatch tables' to
the Small C syntax.

Perhaps you might want to just study these table-driven approaches, and
then implement them in Forth.

Fred



Andrew Haley

unread,
May 27, 2017, 2:23:17 AM5/27/17
to
Cecil Bayona <cba...@cbayona.com> wrote:
> I'm working on a Forth system with the following properties in order of
> importance;
>
> 1. Easy to migrate to other CPUs.
> 2. Good and simple to understand.
> 3. Small
> 4. Fast

I'm not sure that it's possible to have 1 and 2. Mind you, that
depends on how you define "easy": if it includes rewriting a bunch of
primitives for each CPU, then it's possible to have both.

Andrew.

Cecil Bayona

unread,
May 27, 2017, 10:29:38 AM5/27/17
to
On 5/27/2017 1:23 AM, Andrew Haley wrote:
> Cecil Bayona <cba...@cbayona.com> wrote:
>> I'm working on a Forth system with the following properties in order of
>> importance;
>>
>> 1. Easy to migrate to other CPUs.

If the primitives are written in C then it's easy to port it to another
CPU that has a C compiler, just re-compile. If it's a FPGA CPU with no C
compiler then one would need to write an assembler for the device,
specially with a stack CPU that would be a very simple assembler, the
primitives would be either in assembler or the instructions are the
primitives.

>> 2. Good and simple to understand.

That depends on the Forth implemented, since this is for embedded CPUs,
keeping the Forth simple entails being selective about what is in it, no
2400 word Forth but keeping it under 300 words.

>> 3. Small

A token Forth would be very small since most Forth words would take one
byte. Keep the number of words down to the necessities will help keep it
small.

>> 4. Fast

Here is the big issue, items 1-3 make it hard for it to be fast except
in the case of a FPGA CPU, if the CPU will be used a lot and it needs to
be faster, then a re-write of the primitives to use assembler will speed
it up, this is to be done only when the speed is vital.
>
> I'm not sure that it's possible to have 1 and 2. Mind you, that
> depends on how you define "easy": if it includes rewriting a bunch of
> primitives for each CPU, then it's possible to have both.
>
> Andrew.
>

The alternative to writing a Forth from scratch is to use an existing
compiler and modify the assembler and Meta-compiler for each CPU, which
is not that bad.

--
Cecil - k5nwa

Cecil Bayona

unread,
May 27, 2017, 10:35:10 AM5/27/17
to
If the primitives are written in C then a recompile with a C for a
different CPU would generate a Forth for that CPU. Some minor work on
the I/O words might be needed but that is relatively simple.

A custom FPGA CPU would not have a C compiler but in any case is would
still be not that difficult to write an assembler to be used in creating
the primitives, in some cases the CPU instructions are the primitives so
that is easy to implement.

--
Cecil - k5nwa

Cecil Bayona

unread,
May 27, 2017, 10:50:36 AM5/27/17
to
Small C brings back a lot of good memories, back in 1980 Small C came
out, after a while I extended it to include structures, unions, and
floating point using an AMD math co-processor and created the code
generation modules for several CPUs with peephole optimizations. In the
late 70's I was working on my own C compiler but it was more like Tiny
C, originally written in PL/M.

I'm not sure if having to modify a C compiler in addition to the Forth
compiler would simplify things, still having a C compiler for the FPGA
CPUs would be nice.

--
Cecil - k5nwa

rickman

unread,
May 27, 2017, 12:22:22 PM5/27/17
to
Do you see the problem with these two statements? According to your
concept you would be keeping N versions of your Forth, one in C and many
in assembly.

I would also point out that in addition to needing a C compiler for each
target, you will still need to change the source code to account for
differences in hardware.

Try looking at existing implementations, Mecrisp would be a good
example. It has been ported to many different CPUs with two mainstream
processor ISAs as well as some FPGA designs. It is always done in
assembly, but that's not really an important factor. The issue is each
version has to be different to account for differences in the hardware.

--

Rick C

Cecil Bayona

unread,
May 27, 2017, 12:53:29 PM5/27/17
to
An assembler version would be a rare thing, it's just an option that is
available if the extra work is merited but for most I would not need it.
One starts with the C version for most CPUs that is good enough.
>
> I would also point out that in addition to needing a C compiler for each
> target, you will still need to change the source code to account for
> differences in hardware.

C is available for just about every CPU in existence except custom FPGA
and that is handled by a simple assembler and Meta-compiler.

>
> Try looking at existing implementations, Mecrisp would be a good
> example. It has been ported to many different CPUs with two mainstream
> processor ISAs as well as some FPGA designs. It is always done in
> assembly, but that's not really an important factor. The issue is each
> version has to be different to account for differences in the hardware.
>

Actually Mecrisp is not a great example, assembler is the least portable
method there is, if it were in C one would use the built in libraries to
setup the clock, and do I/O, part of that is telling the C compiler what
device you are compiling it for and the C compiler will take care of the
differences assembler does not do that for you.

I currently use C and Pascal with embedded CPUs, switching chips used is
not a major problem, part of the project settings is identifying the CPU
used and the compiler takes care of the details. So this is a minor
issue, that is one reason for using C one can re-compile software for
different CPUs with at most minor software changes, the big minus is
that it's not as fast as assembler, with a lot of CPUs it's still fast
enough so not big deal.

--
Cecil - k5nwa

rickman

unread,
May 27, 2017, 1:13:47 PM5/27/17
to
Cecil Bayona wrote on 5/27/2017 12:53 PM:
> On 5/27/2017 11:22 AM, rickman wrote:
>> Cecil Bayona wrote on 5/27/2017 10:35 AM:
>>>
>>> If the primitives are written in C then a recompile with a C for a
>>> different CPU would generate a Forth for that CPU. Some minor work on
>>> the I/O words might be needed but that is relatively simple.
>>>
>>> A custom FPGA CPU would not have a C compiler but in any case is would
>>> still be not that difficult to write an assembler to be used in creating
>>> the primitives, in some cases the CPU instructions are the primitives so
>>> that is easy to implement.
>>
>> Do you see the problem with these two statements? According to your
>> concept you would be keeping N versions of your Forth, one in C and many
>> in assembly.
>
> An assembler version would be a rare thing, it's just an option that is
> available if the extra work is merited but for most I would not need it. One
> starts with the C version for most CPUs that is good enough.

I'm not following you. Every custom CPU design will require either a C
compiler be written or the coding will have to be in assembler. Are you
saying you expect custom FPGA CPUs to only be supported rarely? I thought
you had this as one of your requirements.


>> I would also point out that in addition to needing a C compiler for each
>> target, you will still need to change the source code to account for
>> differences in hardware.
>
> C is available for just about every CPU in existence except custom FPGA and
> that is handled by a simple assembler and Meta-compiler.

Yes, assembly will be required. That's what I'm saying. You seem to be
brushing this off somehow. So you will need a C version along with a number
of assembly language versions. That is a real PITA to try to keep in sync
as you add features.


>> Try looking at existing implementations, Mecrisp would be a good example.
>> It has been ported to many different CPUs with two mainstream processor
>> ISAs as well as some FPGA designs. It is always done in assembly, but
>> that's not really an important factor. The issue is each version has to
>> be different to account for differences in the hardware.
>>
>
> Actually Mecrisp is not a great example, assembler is the least portable
> method there is, if it were in C one would use the built in libraries to
> setup the clock, and do I/O, part of that is telling the C compiler what
> device you are compiling it for and the C compiler will take care of the
> differences assembler does not do that for you.

Dismissing Mecrisp as a vehicle to learn about porting Forth across CPUs is
disingenuous. The issue is how it has to change. It exists for multiple
CPUs and and multiple manufacturers. Go study it and learn from it. You
will also find that a C compiler is not needed to take advantage of the
manufacturer's experience. They provide a setup file in assembly, not C.

Libraries are not always compatible. There may be library routines, but
they aren't called the same way or do the same functions across different
CPUs. I've had this discussion before relating to the importance of staying
with one CPU line. It has been pointed out the main difference in coding
for a CPU is the variation between manufacturers rather than CPU ISAs. The
important point here is using C and libraries doesn't solve the porting
problem for you.


> I currently use C and Pascal with embedded CPUs, switching chips used is not
> a major problem, part of the project settings is identifying the CPU used
> and the compiler takes care of the details. So this is a minor issue, that
> is one reason for using C one can re-compile software for different CPUs
> with at most minor software changes, the big minus is that it's not as fast
> as assembler, with a lot of CPUs it's still fast enough so not big deal.

That depends on what you are doing in the programs you write. Have you done
much embedded work that writes to the Flash? Works in low power modes?

--

Rick C

David Schultz

unread,
May 27, 2017, 1:25:06 PM5/27/17
to
On 05/27/2017 11:53 AM, Cecil Bayona wrote:
> Actually Mecrisp is not a great example, assembler is the least portable
> method there is, if it were in C one would use the built in libraries to
> setup the clock, and do I/O, part of that is telling the C compiler what
> device you are compiling it for and the C compiler will take care of the
> differences assembler does not do that for you.
>
> I currently use C and Pascal with embedded CPUs, switching chips used is
> not a major problem, part of the project settings is identifying the CPU
> used and the compiler takes care of the details. So this is a minor
> issue, that is one reason for using C one can re-compile software for
> different CPUs with at most minor software changes, the big minus is
> that it's not as fast as assembler, with a lot of CPUs it's still fast
> enough so not big deal.
>

This makes no sense to me at all.

The C compiler knows nothing about the hardware, all it knows is how to
generate code for the CPU. The care and feeding of things like UARTS is
up to the user.


You might get lucky and find that someone else has already written code
to make a UART dance the way you want it to but that isn't likely.

Worse, the CPUs have supporting hardware (clock generation, etc.) that
can vary between devices. The compiler has no clue.

My C code startup looks a lot like my assembly code startup for the
MSP430. Turn off the watch dog, configure the clocks, start a timer,
etc. They are both equally portable between devices, ie. not very.

--
David W. Schultz
http://home.earthlink.net/~david.schultz
"Life without stock is barely worth living..." - Anthony Bourdain

Cecil Bayona

unread,
May 27, 2017, 2:13:18 PM5/27/17
to
Libraries are part of the C development environment. I have no clue what
C compilers others are using but with my C compilers I do not need to
use assembler at all, libraries are provided to initialize and use the
hardware, all I have to change is the CPU in use and the software will
work on different CPU devices. Some changes might be needed in some
cases but it's minor.

I get the impression that just about everyone with a few exceptions is
against a custom compiler, so pray tell where does one get compilers for
custom or oddball CPUs?

The negativity is off the chart but then this is c.l.f so I should have
expected it.

--
Cecil - k5nwa

hughag...@gmail.com

unread,
May 27, 2017, 2:20:03 PM5/27/17
to
I think that both #1 and #2 are possible. Write an assembler for the MSP430 and write your Forth in this assembly-language and have your Forth use this assembly-language to generate code. Use a subset of the MSP430, rather than the entire instruction set (think: "MSP430; the Good Parts").

To port your Forth to another processor, you rewrite the assembler so it generates code for the new processor rather than for the MSP430. You do NOT rewrite your Forth system.

The PIC24 should be easy because most of the MSP430 instructions will correspond one-to-one with PIC24 instructions. The PIC24 has more registers than the MSP430 and more addressing modes, but you won't use any of these extra features, so you won't be using the full power of the PIC24.

The 6812 will be more difficult because you don't have as many registers as the MSP430. Some of the MSP430 registers will have to be implemented as pseudo-registers (memory variables). Some of the MSP430 instructions will generate multiple 6812 instructions rather than correspond one-to-one.

I picked the MSP430 as the target to write your original system for, because it is a popular processor and is pretty useful. The MSP430 is in the middle of the field --- some processors, such as the PIC24, are more powerful --- some processors, such as the 6812, are less powerful.

I think that your idea of using C or Go is totally wrong --- you are introducing huge complications for yourself, and your end result will be inefficient --- use the technique that I described and you will have an uncomplicated system, easy portability, and good efficiency (especially on the MSP430).

On Saturday, May 27, 2017 at 11:13:18 AM UTC-7, Cecil - k5nwa wrote:
> I get the impression that just about everyone with a few exceptions is
> against a custom compiler, so pray tell where does one get compilers for
> custom or oddball CPUs?
>
> The negativity is off the chart but then this is c.l.f so I should have
> expected it.

I'm in favor of a custom compiler!
Don't listen to the nattering nabobs of negativity --- listen to me --- Mr. Positive!

David Schultz

unread,
May 27, 2017, 2:33:53 PM5/27/17
to
On 05/27/2017 01:13 PM, Cecil Bayona wrote:
> Libraries are part of the C development environment.

The libraries of which you are speaking are specific to a particular
vendors system. gcc includes some library code but it is for generic
things that work across all devices (sprintf for example) and not for
specific hardware like UARTs or timers.

> I have no clue what
> C compilers others are using but with my C compilers I do not need to
> use assembler at all,

I don't use assembler with C either but the initialization code is the
same either way. One is in C and the other is in assembler. Customized
for the particular device.

Paul Rubin

unread,
May 27, 2017, 2:36:21 PM5/27/17
to
Cecil Bayona <cba...@cbayona.com> writes:
> A token Forth would be very small since most Forth words would take
> one byte. Keep the number of words down to the necessities will help
> keep it small.

But then you need the VM that can understand what to do about the byte
codes, and there's its overhead, etc.

rickman

unread,
May 27, 2017, 2:53:58 PM5/27/17
to
I don't know why you feel this is negativity. This is a discussion. You
have described something that appears to have some flaws. We are pointing
out the flaws. What would you prefer, that we be a cheering section without
even reading what you are writing?

I am not clear on what you expect libraries to do for you. As you say, the
parts of Forth that will change between CPUs will be limited, but not zero.
You will need to tailor the communications and the memory map along with
various details about how you access memory such as writing to the on chip
flash or the on board external memories such as serial Flash or RAM.

I'm not "against" writing a C compiler for a custom CPU. But I think it is
no small job. Most custom CPUs Forth would be ported to will be stack
processors of one type or another. I would believe it is a much bigger job
than porting the Forth code itself by writing a C compiler than to just
write the Forth in assembly for such a CPU. This provides a relatively easy
way to fully optimize the code for such processors which typically have some
feature(s) to facilitate Forth code in some way.

I do know of one custom stack CPU with a C compiler, the ZPU. But then it
was designed explicitly to run C code with no thought to running Forth. It
has even been used commercially although not very widely.

All I'm saying is that using C to facilitate porting between CPUs will not
be as straightforward as you make it out to be. Most of the Mecrisp ports
are ARM CPUs and there is still a fair amount of work involved in doing a
port between CPUs with the same ISA. That's why I suggested you look at
Mecrisp to learn about the issues involved.

I'm not trying to tell you not to do it. I'm trying to help by pointing you
to some useful information.

--

Rick C

rickman

unread,
May 27, 2017, 3:20:08 PM5/27/17
to
Let's compare the three methods of trying to port a single Forth to a
variety of targets. Those targets will only include embedded processors
which makes the job a bit less global. It will include typical small CPUs
like the ARM CM3 and CM4 as well as other processors like the MSP430 and
AVR, PIC, et cetera. Let's also include various stack processors like the
J1, B16, F18A, et cetera. I won't list any particularly, but rather the
issues involved in porting to them.

The methods I'll list include C coding, assembly coding, Forth with a
metacompiler and finally a "special" language tailored to this application
(essentially a custom language along with a custom back end for each
processor). I'll add an X to a column if that issue requires changes to
source or tool for that method in all or nearly all cases. I'll use a lower
case 'c' when it is required only for custom processors.


Issues C coding Assembly Forth Special
--------------------- --------- -------- ------ -------
Processor c X X X
Flash memory X X X X
Comms c X c X
Memory map X X X X
Peripherals X X X X
Board level functions X X X X
Speed optimizations X X X X
Memory use optimizations X X X X

What other issues will require special handling? I wasn't expecting this to
show all methods to require special handling in almost all cases, but I
guess that's the way it is.

--

Rick C

Cecil Bayona

unread,
May 27, 2017, 3:20:48 PM5/27/17
to
On 5/27/2017 1:20 PM, hughag...@gmail.com wrote:
> On Friday, May 26, 2017 at 11:23:17 PM UTC-7, Andrew Haley wrote:
>> Cecil Bayona <cba...@cbayona.com> wrote:
>>> I'm working on a Forth system with the following properties in order of
>>> importance;
>>>
>>> 1. Easy to migrate to other CPUs.
>>> 2. Good and simple to understand.
>>> 3. Small
>>> 4. Fast
>>
>> I'm not sure that it's possible to have 1 and 2. Mind you, that
>> depends on how you define "easy": if it includes rewriting a bunch of
>> primitives for each CPU, then it's possible to have both.
>>
>> Andrew.
>
> I think that both #1 and #2 are possible. Write an assembler for the MSP430 and write your Forth in this assembly-language and have your Forth use this assembly-language to generate code. Use a subset of the MSP430, rather than the entire instruction set (think: "MSP430; the Good Parts").

I already have source code for eForth for the MSP430 in Direct Threaded,
and Subroutine Threaded versions written in MSP430 Assembler.

>
> To port your Forth to another processor, you rewrite the assembler so it generates code for the new processor rather than for the MSP430. You do NOT rewrite your Forth system.
>
> The PIC24 should be easy because most of the MSP430 instructions will correspond one-to-one with PIC24 instructions. The PIC24 has more registers than the MSP430 and more addressing modes, but you won't use any of these extra features, so you won't be using the full power of the PIC24.
>
> The 6812 will be more difficult because you don't have as many registers as the MSP430. Some of the MSP430 registers will have to be implemented as pseudo-registers (memory variables). Some of the MSP430 instructions will generate multiple 6812 instructions rather than correspond one-to-one.
>
> I picked the MSP430 as the target to write your original system for, because it is a popular processor and is pretty useful. The MSP430 is in the middle of the field --- some processors, such as the PIC24, are more powerful --- some processors, such as the 6812, are less powerful.
>
> I think that your idea of using C or Go is totally wrong --- you are introducing huge complications for yourself, and your end result will be inefficient --- use the technique that I described and you will have an uncomplicated system, easy portability, and good efficiency (especially on the MSP430).
>

Interesting idea, I've read about it before but it was not in my
thoughts. There have been proposals for a Portable Assembler code many
times, and Go supports assembler mixed with high level code which is not
unusual but it uses it's own Portable Assembler Code so for various CPUs
the assembler code is not changed but the compiler generates code
according to the CPU one is compiling for. It uses a generic register
and instruction set that is basic to many CPUs, so you end up with
software using assembler that supports several CPUs without any changes.

> On Saturday, May 27, 2017 at 11:13:18 AM UTC-7, Cecil - k5nwa wrote:
>> I get the impression that just about everyone with a few exceptions is
>> against a custom compiler, so pray tell where does one get compilers for
>> custom or oddball CPUs?
>>
>> The negativity is off the chart but then this is c.l.f so I should have
>> expected it.
>
> I'm in favor of a custom compiler!
> Don't listen to the nattering nabobs of negativity --- listen to me --- Mr. Positive!
>

Interesting proposal and I can see it being faster than using C or Go
while still being easy to port.

I'm not sure that using a limited MSP430 instruction set is the way to
go, it has a very nice instruction set but maybe a Portable Instruction
Set that has some added primitive like instructions might be a better
choice or a combination of the two. One way to find out is to test some
examples by using a decent Macro Assembler to generate the code and see
what is useful and what is not needed.

I have some pretty decent Macro Processor software that is extremely
capable of manipulating text and do all sorts of translation, maybe it's
time to dig it out and see how good is a Portable Assembler and how
efficient it is at generating efficient code for multiple CPUs.


LOL.....Mr Positive, allrighty then.

Thanks, something to consider as it might get high scores in all four
categories.

--
Cecil - k5nwa

Cecil Bayona

unread,
May 27, 2017, 3:25:03 PM5/27/17
to
Not much overhead if one has an array of the addresses of the primitive,
use the token as the index and go to the routine point at.

This might become moot in any case as Hugh Aguilar has pointed to a
possible solution that requires no High Level Language at all while
being easy to port. I will do some testing to see if it works out OK.

--
Cecil - k5nwa

Cecil Bayona

unread,
May 27, 2017, 3:44:34 PM5/27/17
to
Criticism is OK but it need to be accompanied with at least hints to a
possible solution otherwise it doesn't help much, and it seems people
are looking for a perfect solution, there usually isn't one, all
approaches may have some problems just what is one that the problems are
not as severe.

> I am not clear on what you expect libraries to do for you. As you say,
> the parts of Forth that will change between CPUs will be limited, but
> not zero. You will need to tailor the communications and the memory map
> along with various details about how you access memory such as writing
> to the on chip flash or the on board external memories such as serial
> Flash or RAM.

It doesn't need to be zero just minimal issues if possible, I've already
mention that communication and other issues might need adjustment, not
perfect but not the end.

>
> I'm not "against" writing a C compiler for a custom CPU. But I think it
> is no small job. Most custom CPUs Forth would be ported to will be
> stack processors of one type or another. I would believe it is a much
> bigger job than porting the Forth code itself by writing a C compiler
> than to just write the Forth in assembly for such a CPU. This provides
> a relatively easy way to fully optimize the code for such processors
> which typically have some feature(s) to facilitate Forth code in some way.
>
> I do know of one custom stack CPU with a C compiler, the ZPU. But then
> it was designed explicitly to run C code with no thought to running
> Forth. It has even been used commercially although not very widely.
>

I already mentioned the same, FPGAs do not have a C compiler so a
different approach is necessary, a customized assembler and
meta-compiler is needed, I already have that software so a customization
would be needed. An FPGA requires more work but then the alternative is
to assemble code with a pencil and paper.

Also I mentioned that I do not intend to write a C compiler, that is not
needed for FPGAs the answer does not lie with C. That being said, I have
written my own C compiler in the past, and enhanced SmallC by quite a
bit so it's not an impossible task for me.

> All I'm saying is that using C to facilitate porting between CPUs will
> not be as straightforward as you make it out to be. Most of the Mecrisp
> ports are ARM CPUs and there is still a fair amount of work involved in
> doing a port between CPUs with the same ISA. That's why I suggested you
> look at Mecrisp to learn about the issues involved.
>

Mecrisp uses assembler the most un-portable way to write software, a C
compiler handles those issues a lot better than assembler.

> I'm not trying to tell you not to do it. I'm trying to help by pointing
> you to some useful information.
>

Thanks

--
Cecil - k5nwa

rickman

unread,
May 27, 2017, 6:34:00 PM5/27/17
to
I'm not sure what advantage "portable" assembly language would have over a
metacompiled Forth. Both approaches require writing a back end for the
tool. A metacompiled Forth has one HUGE advantage for developing a Forth
system... it's in Forth.

--

Rick C

Cecil Bayona

unread,
May 27, 2017, 7:50:36 PM5/27/17
to
It would be part of the Forth System and written in Forth, instead of
having a specific assembler to each CPU with it's own set on mnemonics
it would use a Portable Instruction Set, the same mnemonics for all the
CPUs, to change it to a different CPU one would change the generated
code which is fairly easy to do. Primitives would use the Portable
Instructions Set so there would be no need to change them when switching
to a different CPU as the assembler would generate the machine code for
the CPU currently in use.

--
Cecil - k5nwa

rickman

unread,
May 27, 2017, 8:13:38 PM5/27/17
to
As I have said, I think that is not appreciable different from writing a few
core Forth words in generic assembler and coding the rest of the Forth tool
in Forth. I guess the terms used in discussing this are far too broad to be
able to actually make any comparisons.

For your basic assembler instruction set I can refer you to a reference that
has some suggestions.

https://users.ece.cmu.edu/~koopman/stack_computers/stack_computers_book.pdf

--

Rick C

Rod Pemberton

unread,
May 27, 2017, 9:57:17 PM5/27/17
to
On Sat, 27 May 2017 09:29:34 -0500
Cecil Bayona <cba...@cbayona.com> wrote:

> If the primitives are written in C then it's easy to port it to
> another CPU that has a C compiler, just re-compile.

For the most part, I think that's true, as my ITC Forth interpreter has
it's primitives in C and the rest in Forth.

However, IIRC, the loop constructs in Forth use the processor overflow
flag. This is not available in C. You'll have to work around this.

Another issue I had was with the line buffering that's used by default
with C. Each compiler has different implementations of non-buffered
input, and sometimes different functions to change the settings.

> >> 2. Good and simple to understand.
>
> That depends on the Forth implemented, since this is for embedded
> CPUs, keeping the Forth simple entails being selective about what is
> in it, no 2400 word Forth but keeping it under 300 words.

Are you wanting the Forth code or C code to be "good and simple to
understand"? If most of the code is in Forth and only the primitives
are in C, then it'll be understandable to a Forth programmer, for the
most part.

> >> 3. Small
>
> A token Forth would be very small since most Forth words would take
> one byte. Keep the number of words down to the necessities will help
> keep it small.

If your Forth is based on primitives, like eForth, then the size is
primarily dependent on how many high-level Forth words you create.

> >> 4. Fast
>
> Here is the big issue, items 1-3 make it hard for it to be fast
> except in the case of a FPGA CPU, if the CPU will be used a lot and
> it needs to be faster, then a re-write of the primitives to use
> assembler will speed it up, this is to be done only when the speed is
> vital.

You'll need 30 to 60 or so primitives to prevent it from being
exceptionally slow. These should mostly fit cleanly onto the
instruction set of the processor you use. You can speed it up somewhat
by using efficient definitions for stack operations and Forth words
that execute frequently.


Rod Pemberton
--

hughag...@gmail.com

unread,
May 27, 2017, 11:00:39 PM5/27/17
to
On Saturday, May 27, 2017 at 12:20:48 PM UTC-7, Cecil - k5nwa wrote:
> I'm not sure that using a limited MSP430 instruction set is the way to
> go, it has a very nice instruction set but maybe a Portable Instruction
> Set that has some added primitive like instructions might be a better
> choice or a combination of the two. One way to find out is to test some
> examples by using a decent Macro Assembler to generate the code and see
> what is useful and what is not needed.
>
> I have some pretty decent Macro Processor software that is extremely
> capable of manipulating text and do all sorts of translation, maybe it's
> time to dig it out and see how good is a Portable Assembler and how
> efficient it is at generating efficient code for multiple CPUs.

Well, it should be a 16-bit processor. In the 32-bit world, ARM assembly-language already is the "portable assembly language" because 99% of the boards use an ARM processor.

I just said the MSP430 because it is a common 16-bit processor. What application program do you have in mind? Is there some reason why the MSP430 wouldn't be a good choice for building a board?

The PDP11 would be another possibility. It has these points in favor of it:

1.) the PDP11 has 8 registers rather than 16, which makes it a good choice for an FPGA (the number of registers is the primary factor in how much chip resources are needed, and how expensive the FPGA is).

2.) There are public-domain implementations of the PDP11 available in Verilog, which is not true of the MSP430.

3.) The PDP11 has a very orthogonal and straight-forward instruction set, which is not true of the 8086, although it is true of the MSP430.

Cecil Bayona

unread,
May 27, 2017, 11:30:04 PM5/27/17
to
16 bit is fine, the MSP430 is a very nice processor to program in
assembler. I was just thinking out loud, it might not hurt to have some
extra words that are Forth generic.

The PDP11 is very nice for it's day but compared to modern CPUs it is
register starved, I'm mostly interested in Forth CPUs and there are a
few available, some are very simple such as the J1 CPU but with minor
changes it can be improved but then I would need software that works
with it hence the reason why this software is needed.

I'll send you an email tomorrow or a modification to the assembler and
get feedback on it.

Big thunderstorm rolling through so I will need to turn the PC of for a
while.

--
Cecil - k5nwa

jim.bra...@ieee.org

unread,
May 28, 2017, 12:05:01 AM5/28/17
to
]>There are public-domain implementations of the PDP11 available in Verilog,
]> which is not true of the MSP430.

http://opencores.org/project,neo430 (VHDL)
http://opencores.org/project,openmsp430 (Verilog)

hughag...@gmail.com

unread,
May 28, 2017, 12:56:50 AM5/28/17
to
Cool!

I suspect that the MSP430 requires a bigger and more expensive FPGA than the PDP11 --- I doubt that Cecil cares about saving a few dollars however, as he is only planning on making one board for his own use --- price only matters to people who are producing boards in a high volume.

I'm just speculating as to requirements and prices --- I don't really know anything about FPGAs, so I can't really answer the question.

hughag...@gmail.com

unread,
May 28, 2017, 1:10:20 AM5/28/17
to
On Saturday, May 27, 2017 at 8:30:04 PM UTC-7, Cecil - k5nwa wrote:
> The PDP11 is very nice for it's day but compared to modern CPUs it is
> register starved, I'm mostly interested in Forth CPUs and there are a
> few available, some are very simple such as the J1 CPU but with minor
> changes it can be improved but then I would need software that works
> with it hence the reason why this software is needed.

I don't think the J1 supports local variables --- you are going to get Forth code that looks like it was written in the 1970s --- Forth code that passes data between functions in global variables is terrible; you would be better off to forget about Forth and use C instead.

I just came up with this for a PDP11 STC off the top of my head, but it seems like it might work:

R0 general-purpose
R1 general-purpose
R2 top-of-stack
R3 local-frame pointer
R4 data-stack pointer
R5 double-stack pointer
R6 return-stack pointer
R7 program counter

An optimizing compiler could take advantage of 16 registers, such as available on the MSP430 --- but are you planning on writing an optimizing compiler? --- that does take a lot of effort, and if you don't believe me, then ask Stephen Pelc.

The JSR in the PDP11 would work very well for DTC. If you are going with STC however, you can simplify JSR so that it would be simple like on the MSP430 etc..

rickman

unread,
May 28, 2017, 2:17:13 AM5/28/17
to
hughag...@gmail.com wrote on 5/27/2017 11:00 PM:
> On Saturday, May 27, 2017 at 12:20:48 PM UTC-7, Cecil - k5nwa wrote:
>> I'm not sure that using a limited MSP430 instruction set is the way to
>> go, it has a very nice instruction set but maybe a Portable Instruction
>> Set that has some added primitive like instructions might be a better
>> choice or a combination of the two. One way to find out is to test some
>> examples by using a decent Macro Assembler to generate the code and see
>> what is useful and what is not needed.
>>
>> I have some pretty decent Macro Processor software that is extremely
>> capable of manipulating text and do all sorts of translation, maybe it's
>> time to dig it out and see how good is a Portable Assembler and how
>> efficient it is at generating efficient code for multiple CPUs.
>
> Well, it should be a 16-bit processor. In the 32-bit world, ARM assembly-language already is the "portable assembly language" because 99% of the boards use an ARM processor.
>
> I just said the MSP430 because it is a common 16-bit processor. What application program do you have in mind? Is there some reason why the MSP430 wouldn't be a good choice for building a board?
>
> The PDP11 would be another possibility. It has these points in favor of it:
>
> 1.) the PDP11 has 8 registers rather than 16, which makes it a good choice for an FPGA (the number of registers is the primary factor in how much chip resources are needed, and how expensive the FPGA is).

Not trying to get on your case, but you are talking outside your realm of
familiarity. Many FPGAs provide small RAMs for exactly this sort of thing.
In Xilinx derived parts the look up tables used to create logic can be used
as register files. Each one is a 16x1 RAM (or in newer parts 64x1). So
restricting the register count to 8 is of little value in conserving
resources. There are many other things that impact resources in a much
greater way.


> 2.) There are public-domain implementations of the PDP11 available in Verilog, which is not true of the MSP430.
>
> 3.) The PDP11 has a very orthogonal and straight-forward instruction set, which is not true of the 8086, although it is true of the MSP430.

I don't think the issue would be how nice the "virtual" instruction set is.
The issue is how well it will map to the plurality of targets. Most FPGA
targets will be stack machines which don't even have register files. Most
likely programming a stack machine using an assembly language for a register
based processor would be difficult to make efficient.

Actually, it isn't even just targeting multiple processors with the
programming language. The issue is writing a Forth in assembly for a
register based machine and then translating that into an efficient Forth for
a stack based machine. Maybe this can be done. But I don't see it as being
a better solution than just taking the easy route and programming the Forth
in assembly for the given target.

--

Rick C

Albert van der Horst

unread,
May 28, 2017, 4:09:04 AM5/28/17
to
In article <ogcfde$9qi$1...@dont-email.me>,
Cecil Bayona <cba...@cbayona.com> wrote:
<SNIP>
>Libraries are part of the C development environment. I have no clue what
>C compilers others are using but with my C compilers I do not need to
>use assembler at all, libraries are provided to initialize and use the
>hardware, all I have to change is the CPU in use and the software will
>work on different CPU devices. Some changes might be needed in some
>cases but it's minor.

Yes libraries are in the C development environment of about
every microprocessor.
Now give me one example of an AD conversion or switching to low
power mode that is portable between two different micro processors using
the portable C. 1]
Then give me one example of a usefull uP application that
doesn't use one of those.

I'm sick of the "it is C, so it is portable" dogma.

>
>--
>Cecil - k5nwa

1] A manufacturer may strive for compatibility between her uP's
and sometimes succeed.
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

jim.bra...@ieee.org

unread,
May 28, 2017, 4:10:45 AM5/28/17
to
]>I suspect that the MSP430 requires a bigger and more expensive FPGA than the PDP11

Ugh, just the opposite
neo430 ~1000 LUTs
openmsp430 ~1400 LUTs
pdp11-34verilog 2500-3400 LUTs
pdp2011 huge
w11 3400+ LUTs

PDP11 web links:
http://www.heeltoe.com/download/pdp11/README.html
http://pdp2011.sytse.net/wordpress/pdp-11/
http://opencores.org/project,w11

Modern low cost FPGAs run about 1K LUTs to the dollar.
And even "small" FPGAs have 10K LUTs plus multipliers and dual port RAM

Albert van der Horst

unread,
May 28, 2017, 4:23:14 AM5/28/17
to
In article <ogcum7$r9t$2...@dont-email.me>, rickman <gnu...@gmail.com> wrote:
>Cecil Bayona wrote on 5/27/2017 3:20 PM:
<SNIP>
>
>I'm not sure what advantage "portable" assembly language would have over a
>metacompiled Forth. Both approaches require writing a back end for the
>tool. A metacompiled Forth has one HUGE advantage for developing a Forth
>system... it's in Forth.

Truely "portable" or "high level" assembly is a pipe dream.
Using macro's to make assembly more portable surely is feasible.
ciforth may be a good example of that, using m4 a lot.

I can turn my indirect threaded Forth ciforth into a direct threaded Forth
rather easily, while Forth in c is probably subroutine threaded.
(At first sight I would think it infeasible to make an indirect threaded
Forth in c but apparently gforth has a threaded version.)

>
>--
>
>Rick C

Groetjes Albert

Cecil Bayona

unread,
May 28, 2017, 12:22:57 PM5/28/17
to
On 5/28/2017 12:10 AM, hughag...@gmail.com wrote:
> On Saturday, May 27, 2017 at 8:30:04 PM UTC-7, Cecil - k5nwa wrote:
>> The PDP11 is very nice for it's day but compared to modern CPUs it is
>> register starved, I'm mostly interested in Forth CPUs and there are a
>> few available, some are very simple such as the J1 CPU but with minor
>> changes it can be improved but then I would need software that works
>> with it hence the reason why this software is needed.
>
> I don't think the J1 supports local variables --- you are going to get Forth code that looks like it was written in the 1970s --- Forth code that passes data between functions in global variables is terrible; you would be better off to forget about Forth and use C instead.

The J1 is a stack CPU so why would one pass data in global variables?
One would use the Data Stack with Forth.

>
> I just came up with this for a PDP11 STC off the top of my head, but it seems like it might work:
>
> R0 general-purpose
> R1 general-purpose
> R2 top-of-stack
> R3 local-frame pointer
> R4 data-stack pointer
> R5 double-stack pointer
> R6 return-stack pointer
> R7 program counter
>
> An optimizing compiler could take advantage of 16 registers, such as available on the MSP430 --- but are you planning on writing an optimizing compiler? --- that does take a lot of effort, and if you don't believe me, then ask Stephen Pelc.
>

The MSP430 is very similar to a PDP11 in it's architecture and faster
for a couple of dollars, very nice.

Having a Doubles Stack is very odd so it would create a lot of software
compatibility issues but then Forthers are not famous for sharing
software. What is the justification for such an odd item, does it really
improve Forth?

I would think if one is going to be odd and add an extra stack it might
be more useful as a DO LOOP stack so the Data Stack and the Return Stack
has no extra garbage making the code simpler.

I have used in the past a very primitive but effective optimizing scheme
that is easy to use and can generate very good code but it's a kludge at
best. Using an external program to the compiler to do the optimizing, I
mentioned the text macro processor before, it would be fed the code from
each word and it would optimize it and generate assembler code that
would be assembled in turn by the Forth compiler.

Even the macro processor is a kludge itself, it was originally in
FORTRAN then I used it to translate itself into C code but done without
a whole lot of optimizing so the generated code was a mess but it worked
and I never bothered to go back and clean it up. I once converted it to
Forth but it was not efficient so I don't even have a copy anymore. Code
from the early 70s used to translate code into efficient code in 2017,
what a joke, but it would work.

I dug it up last night one of the few old software projects that I still
have a copy, it's for DOS currently. Over the next couple of days I will
familiarize myself with it and see what I can do with it as a quick test
environment, in with Portable Assembler Code and out with native CPU
instructions for various CPUs to determine what instructions should be
in the Portable Assembler Code. This would be to judge how efficient
could be done and what instructions are necessary to do a good job.

I also have a copy of a Forth based Macro Processor, its newer and
totally different and it seems not as powerful but that would be a
mistake in assuming so, it can incorporate Forth code that is executed
during it's translation so one could do just about anything with it.
Either one of these old software programs could do very good
optimization but and it's a big but that there is little to no
documentation on how to use them so I will have to rely on my memory to
figure them out. Later in my life I started writing good documentation
with my software to avoid such problems.

> The JSR in the PDP11 would work very well for DTC. If you are going with STC however, you can simplify JSR so that it would be simple like on the MSP430 etc..
>

Thanks for reminding me about PAC (Portable Assembler Code), it changes
the whole trajectory of the project, if PAC can generate efficient code
then it would be an ideal setup for this and other projects. In any case
it is bound to be faster than using C.

Mind you the whole purpose of this software is to Meta-Compile an
efficient as reasonably possible Forth compiler for a variety of CPUs so
it would not be used on a daily basis, it's a tool to create tools.

This is getting very interesting and looks like a fun project.

--
Cecil - k5nwa

Cecil Bayona

unread,
May 28, 2017, 12:50:16 PM5/28/17
to
On 5/28/2017 1:17 AM, rickman wrote:
> hughag...@gmail.com wrote on 5/27/2017 11:00 PM:

>> The PDP11 would be another possibility. It has these points in favor
>> of it:
>>
>> 1.) the PDP11 has 8 registers rather than 16, which makes it a good
>> choice for an FPGA (the number of registers is the primary factor in
>> how much chip resources are needed, and how expensive the FPGA is).
>
> Not trying to get on your case, but you are talking outside your realm
> of familiarity. Many FPGAs provide small RAMs for exactly this sort of
> thing. In Xilinx derived parts the look up tables used to create logic
> can be used as register files. Each one is a 16x1 RAM (or in newer
> parts 64x1). So restricting the register count to 8 is of little value
> in conserving resources. There are many other things that impact
> resources in a much greater way.
>
>

All kinds of useful information is coming out of this topic, I been
using Lattice FPGAs so far because its a decent tool for low $, but I
did buy one Xilinx board for more serious work and it's an Artix 7
board, with a lot of LUTS and Memory for use in larger CPUs. That is
nice to know in case I want to create a more conventional Register based
CPU.


>> 2.) There are public-domain implementations of the PDP11 available in
>> Verilog, which is not true of the MSP430.
>>
>> 3.) The PDP11 has a very orthogonal and straight-forward instruction
>> set, which is not true of the 8086, although it is true of the MSP430.
>
> I don't think the issue would be how nice the "virtual" instruction set
> is. The issue is how well it will map to the plurality of targets. Most
> FPGA targets will be stack machines which don't even have register
> files. Most likely programming a stack machine using an assembly
> language for a register based processor would be difficult to make
> efficient.

Stack machines is my current line of interest so far the richest machine
I've used uses the following registers;

TOS top of Data Stack
TRS top of Return Stack
W a temporary register
IX an Index register to use with memory access specially in accessing
arrays of data.
IP Instruction Pointer

Add to that a Data and Return Stack but those are not registers but
their pointers use a small register not directly accessible.

Not a whole lot of registers specially when compared to a MSP430 CPU
with 16 general registers, or an ARM CPU with 32 general registers.

>
> Actually, it isn't even just targeting multiple processors with the
> programming language. The issue is writing a Forth in assembly for a
> register based machine and then translating that into an efficient Forth
> for a stack based machine. Maybe this can be done. But I don't see it
> as being a better solution than just taking the easy route and
> programming the Forth in assembly for the given target.
>

Using PAC (Portable Assembler Code) mnemonics when moving the code to
another CPU the primitives and other assembler code does not need to be
changed, only the assembler needs to be changed and that would need
changes no matter what scheme one uses, so it is simpler to port using a
PAC assembler. It's not the traditional way where you have to re-write
all the assembly code but times are changing we are not in the 70s anymore.

I tend to think that this is a superior way to write a Forth that is
efficient and easy to port qualities that with traditional assemble code
are at odds with each other. Mind you no matter what one uses there are
some CPU specific items that need to be update such clock management and
I/O but those need changing with a new CPU no matter what way one uses
so it something to be dealt with.


--
Cecil - k5nwa

rickman

unread,
May 28, 2017, 12:57:47 PM5/28/17
to
Albert van der Horst wrote on 5/28/2017 4:09 AM:
> In article <ogcfde$9qi$1...@dont-email.me>,
> Cecil Bayona <cba...@cbayona.com> wrote:
> <SNIP>
>> Libraries are part of the C development environment. I have no clue what
>> C compilers others are using but with my C compilers I do not need to
>> use assembler at all, libraries are provided to initialize and use the
>> hardware, all I have to change is the CPU in use and the software will
>> work on different CPU devices. Some changes might be needed in some
>> cases but it's minor.
>
> Yes libraries are in the C development environment of about
> every microprocessor.
> Now give me one example of an AD conversion or switching to low
> power mode that is portable between two different micro processors using
> the portable C. 1]
> Then give me one example of a usefull uP application that
> doesn't use one of those.
>
> I'm sick of the "it is C, so it is portable" dogma.
>
>>
>> --
>> Cecil - k5nwa
>
> 1] A manufacturer may strive for compatibility between her uP's
> and sometimes succeed.

I recall having a conversation some 10 years ago (or more) about how ARM
would be taking over the world. Mostly this was based on how it is to the
designer's advantage to stick with one CPU type and not need to port between
ISAs in order to switch manufacturers with the ebb and flow of technology
and economics. A strong argument against this was the fact that it is much
more work to port the peripheral code than the code directly supporting CPU
features.

In the end ARM has taken over despite our conversation. But that does not
invalidate the complexity of porting an app of any kind between processors.

For the most part coding in C will only help you with the parts that could
also be easily coded in Forth. Most of what is left will either need to be
coded in assembly for performance or will need to be tailored to the
processor/board in use and so will be rewritten regardless of the language.

--

Rick C

Cecil Bayona

unread,
May 28, 2017, 1:14:11 PM5/28/17
to
On 5/28/2017 3:09 AM, Albert van der Horst wrote:
> In article <ogcfde$9qi$1...@dont-email.me>,
> Cecil Bayona <cba...@cbayona.com> wrote:
> <SNIP>
>> Libraries are part of the C development environment. I have no clue what
>> C compilers others are using but with my C compilers I do not need to
>> use assembler at all, libraries are provided to initialize and use the
>> hardware, all I have to change is the CPU in use and the software will
>> work on different CPU devices. Some changes might be needed in some
>> cases but it's minor.
>
> Yes libraries are in the C development environment of about
> every microprocessor.
> Now give me one example of an AD conversion or switching to low
> power mode that is portable between two different micro processors using
> the portable C. 1]
> Then give me one example of a usefull uP application that
> doesn't use one of those.

My last application was an oven controller, it did not need to go in low
power mode as it's AC powered while in use, and it did not need or use
any A/D converters as the temperature was read via a SIO device. So
those are arbitrary requirements that are not always valid.
>
> I'm sick of the "it is C, so it is portable" dogma.

Well then take two aspirins drink plenty of fluids and go to bed early
and you will feel a lot better in the morning. You can also buy an
inexpensive book on C on eBay and burn it so you can feel better.

It's a lot more portable than assembler was my point, the C and Pascal
I currently use take a setting in the project definition as to what CPU
chip, and what clock one desires and the initialization software is set
for you, the Pascal version also take parameters in the project settings
about the power down modes desired and sets the software for you. So
within the limits of the CPU supported by those compilers it is fairly
portable.

Personally I'm not a fan of C even less of C++ I stopped using them a
long time ago and only recently have I started using C for small
projects just to get reacquainted again but I prefer Pascal to C any day
of the week, and prefer Forth even more. At the start of this endeavor
the use of C required fewer changes when porting the software compared
to assembler so it was not a desired option but it was the only one that
made sense at the time. And yes I'm aware that some items require
customization when changing CPUs so it's not 100% portable but so what
when compared to the alternatives, nothing is 100% portable.

I will be looking at alternative use of assembler that minimizes the
needed changes when porting, it it works out then I will not be using C
at all so both of us can be happier.

>
>>
>> --
>> Cecil - k5nwa
>
> 1] A manufacturer may strive for compatibility between her uP's
> and sometimes succeed.
>


--
Cecil - k5nwa

rickman

unread,
May 28, 2017, 1:21:52 PM5/28/17
to
I'm a bit surprised by those numbers. But then they are about the
implementations rather than the ISAs. I would have expected to the two
architectures to be about the same size really. The LSI-11 was a single
chip (well, a few chips counting the microcode) CPU at a very early time in
IC fabrication technology. I don't know how many gates were used, but I'd
have expected it to be on a par with similar CPUs. Much of the size of a
CPU design is in the width of the data path and the complexity of the modes
as well as the extent of parallelism (not in the sense of multiple
instructions in parallel, but in performing the various functions of the
instruction in parallel).

If I get time I may learn something about these two processors and compare
them.


> Modern low cost FPGAs run about 1K LUTs to the dollar.
> And even "small" FPGAs have 10K LUTs plus multipliers and dual port RAM

The $1/1kLUT is only a rough approximation and only holds at the very low
end. Price per LUT goes down very quickly with larger sizes. No small part
of the cost of most ICs relates to putting the durn things in a package with
pins and testing it.

--

Rick C

Cecil Bayona

unread,
May 28, 2017, 1:26:36 PM5/28/17
to
On 5/28/2017 3:23 AM, Albert van der Horst wrote:
> In article <ogcum7$r9t$2...@dont-email.me>, rickman <gnu...@gmail.com> wrote:
>> Cecil Bayona wrote on 5/27/2017 3:20 PM:
> <SNIP>
>>
>> I'm not sure what advantage "portable" assembly language would have over a
>> metacompiled Forth. Both approaches require writing a back end for the
>> tool. A metacompiled Forth has one HUGE advantage for developing a Forth
>> system... it's in Forth.
>
> Truely "portable" or "high level" assembly is a pipe dream.
> Using macro's to make assembly more portable surely is feasible.
> ciforth may be a good example of that, using m4 a lot.
>

Some here have problems accepting that there is no 100% portable
software, some are closer than others but none are 100%.

> I can turn my indirect threaded Forth ciforth into a direct threaded Forth
> rather easily, while Forth in c is probably subroutine threaded.
> (At first sight I would think it infeasible to make an indirect threaded
> Forth in c but apparently gforth has a threaded version.)
>
I'm not familiar with programming under Linux which I assume you use, I
currently use Windows and in Windows there has been a concerted effort
to turn the Intel CPU into a Harvard CPU byt putting more and more
limits on how the software can be written.

Code cannot be executed out of the data space, and the code space is
protected from changes is the direction they are heading in, they
already mentioned that that is direction they are head for and soon it
will not be optional right now it's optional.

Under that scenario Forth will not be able to extend itself in the code
area, and the data area cannot contain code so that leaves Forth in a
hard place.

>
> Groetjes Albert
>


--
Cecil - k5nwa

Cecil Bayona

unread,
May 28, 2017, 1:28:55 PM5/28/17
to
On 5/28/2017 3:23 AM, Albert van der Horst wrote:
> In article <ogcum7$r9t$2...@dont-email.me>, rickman <gnu...@gmail.com> wrote:
>> Cecil Bayona wrote on 5/27/2017 3:20 PM:
> <SNIP>
>>
>> I'm not sure what advantage "portable" assembly language would have over a
>> metacompiled Forth. Both approaches require writing a back end for the
>> tool. A metacompiled Forth has one HUGE advantage for developing a Forth
>> system... it's in Forth.
>
> Truely "portable" or "high level" assembly is a pipe dream.
> Using macro's to make assembly more portable surely is feasible.
> ciforth may be a good example of that, using m4 a lot.

How do you use m4 to create your Forth? Is it used as an external
program to Forth or as a tools used separate from Forth?

>
> I can turn my indirect threaded Forth ciforth into a direct threaded Forth
> rather easily, while Forth in c is probably subroutine threaded.
> (At first sight I would think it infeasible to make an indirect threaded
> Forth in c but apparently gforth has a threaded version.)
>
>>
>> --
>>
>> Rick C
>
> Groetjes Albert
>


--
Cecil - k5nwa

rickman

unread,
May 28, 2017, 1:52:44 PM5/28/17
to
Cecil Bayona wrote on 5/28/2017 12:50 PM:
> On 5/28/2017 1:17 AM, rickman wrote:
>> hughag...@gmail.com wrote on 5/27/2017 11:00 PM:
>
>>> The PDP11 would be another possibility. It has these points in favor of it:
>>>
>>> 1.) the PDP11 has 8 registers rather than 16, which makes it a good
>>> choice for an FPGA (the number of registers is the primary factor in how
>>> much chip resources are needed, and how expensive the FPGA is).
>>
>> Not trying to get on your case, but you are talking outside your realm of
>> familiarity. Many FPGAs provide small RAMs for exactly this sort of
>> thing. In Xilinx derived parts the look up tables used to create logic can
>> be used as register files. Each one is a 16x1 RAM (or in newer parts
>> 64x1). So restricting the register count to 8 is of little value in
>> conserving resources. There are many other things that impact resources
>> in a much greater way.
>>
>>
>
> All kinds of useful information is coming out of this topic, I been using
> Lattice FPGAs so far because its a decent tool for low $, but I did buy one
> Xilinx board for more serious work and it's an Artix 7 board, with a lot of
> LUTS and Memory for use in larger CPUs. That is nice to know in case I want
> to create a more conventional Register based CPU.

All of the Lattice FPGAs have the LUT RAM available as distributed RAM like
the Xilinx parts. The main Lattice FPGA lines are from licenses obtained by
buying the ORCA line of FPGAs from Lucent. These licenses in turn were
bought by Lucent from Xilinx at a time when Lucent was second sourcing the
basic XC3000 and maybe the XC4000 devices.

The iCE40 parts are from Silicon Blue bought some years ago. The basic
design patents on Xilinx FPGAs have expired so many functions of Xilinx LUTs
are available to all including distributed memory.


>>> 2.) There are public-domain implementations of the PDP11 available in
>>> Verilog, which is not true of the MSP430.
>>>
>>> 3.) The PDP11 has a very orthogonal and straight-forward instruction set,
>>> which is not true of the 8086, although it is true of the MSP430.
>>
>> I don't think the issue would be how nice the "virtual" instruction set
>> is. The issue is how well it will map to the plurality of targets. Most
>> FPGA targets will be stack machines which don't even have register files.
>> Most likely programming a stack machine using an assembly language for a
>> register based processor would be difficult to make efficient.
>
> Stack machines is my current line of interest so far the richest machine
> I've used uses the following registers;
>
> TOS top of Data Stack
> TRS top of Return Stack
> W a temporary register
> IX an Index register to use with memory access specially in accessing arrays
> of data.
> IP Instruction Pointer
>
> Add to that a Data and Return Stack but those are not registers but their
> pointers use a small register not directly accessible.
>
> Not a whole lot of registers specially when compared to a MSP430 CPU with 16
> general registers, or an ARM CPU with 32 general registers.

Big difference... The registers in a stack machine need to be separate, so
they use FFs for the registers and LUTs for the input and output muxes. A
RAM is a bunch of registers with output muxes to share the output bus. A
register file can be efficiently implemented in a small RAM which utilizes
the internal muxes rather than LUTs.

Regardless of how many registers a design has, the real driver of logic
usage is usually muxes. You can have one register (top of data stack for
example) which is fed by many sources and the mux will end up being huge. I
know this from experience... ;)

The way to keep your design small and efficient is to focus on the micro-ops
required to implement an instruction to keep these interconnects to a minimum.

The reason why an ARM CPU in an FPGA will be much bigger than an MSP430 is
the complexity of interconnections. I think it is the M1 that is intended
for FPGA usage. I expect this is very stripped own using more cycles with
less happening in each one compared to an M0.


>> Actually, it isn't even just targeting multiple processors with the
>> programming language. The issue is writing a Forth in assembly for a
>> register based machine and then translating that into an efficient Forth
>> for a stack based machine. Maybe this can be done. But I don't see it as
>> being a better solution than just taking the easy route and programming
>> the Forth in assembly for the given target.
>>
>
> Using PAC (Portable Assembler Code) mnemonics when moving the code to
> another CPU the primitives and other assembler code does not need to be
> changed, only the assembler needs to be changed and that would need changes
> no matter what scheme one uses, so it is simpler to port using a PAC
> assembler. It's not the traditional way where you have to re-write all the
> assembly code but times are changing we are not in the 70s anymore.

You seem to be laser focused on the idea that rewriting the tool has to be
easier than rewriting the code. I don't know of any portable assemblers
that work the way you describe. So you will need to write this from scratch.


> I tend to think that this is a superior way to write a Forth that is
> efficient and easy to port qualities that with traditional assemble code are
> at odds with each other. Mind you no matter what one uses there are some CPU
> specific items that need to be update such clock management and I/O but
> those need changing with a new CPU no matter what way one uses so it
> something to be dealt with.

I don't see any advantage at all. Either way you need to generate native
code for the processor you are using. One way you recode a few Forth words
which gives you native code *and* gives you an opportunity to optimize the
code easily. The other way you have existing "portable" assembler code
which now has to be translated/compiled to native code by a tool that needs
to be rewritten for the target processor. Then if you want optimized code
you likely need to rewrite the "portable" assembly code.

I am ready to return to my self-assigned task of documenting Mecrisp on the
MSP430. Let me know how your project goes. If you need any advice on FPGA
CPUs, I'm happy to lend my experience.

--

Rick C

Albert van der Horst

unread,
May 28, 2017, 2:14:00 PM5/28/17
to
In article <ogf166$g4d$2...@dont-email.me>,
Cecil Bayona <cba...@cbayona.com> wrote:
>On 5/28/2017 3:23 AM, Albert van der Horst wrote:
>> In article <ogcum7$r9t$2...@dont-email.me>, rickman <gnu...@gmail.com> wrote:
>>> Cecil Bayona wrote on 5/27/2017 3:20 PM:
>> <SNIP>
>>>
>>> I'm not sure what advantage "portable" assembly language would have over a
>>> metacompiled Forth. Both approaches require writing a back end for the
>>> tool. A metacompiled Forth has one HUGE advantage for developing a Forth
>>> system... it's in Forth.
>>
>> Truely "portable" or "high level" assembly is a pipe dream.
>> Using macro's to make assembly more portable surely is feasible.
>> ciforth may be a good example of that, using m4 a lot.
>
>How do you use m4 to create your Forth? Is it used as an external
>program to Forth or as a tools used separate from Forth?

A rather short document (20 pages) contains about 10 pages
relevant to this question. cifgenps.zip on the site in my sig.
That document is from 2002. It could use an update but it surely
gives the correct idea.
I.a. I use it for selection (a la [IF] ) and as regular
assembler macro's.

>
>>
>> I can turn my indirect threaded Forth ciforth into a direct threaded Forth
>> rather easily, while Forth in c is probably subroutine threaded.
>> (At first sight I would think it infeasible to make an indirect threaded
>> Forth in c but apparently gforth has a threaded version.)
>>
>>>
>>> --
>>>
>>> Rick C
>>
>> Groetjes Albert
>>
>
>
>--
>Cecil - k5nwa

Cecil Bayona

unread,
May 28, 2017, 2:47:32 PM5/28/17
to
On 5/28/2017 12:52 PM, rickman wrote:
> Cecil Bayona wrote on 5/28/2017 12:50 PM:
>> On 5/28/2017 1:17 AM, rickman wrote:

>
> All of the Lattice FPGAs have the LUT RAM available as distributed RAM
> like the Xilinx parts. The main Lattice FPGA lines are from licenses
> obtained by buying the ORCA line of FPGAs from Lucent. These licenses
> in turn were bought by Lucent from Xilinx at a time when Lucent was
> second sourcing the basic XC3000 and maybe the XC4000 devices.
>
> The iCE40 parts are from Silicon Blue bought some years ago. The basic
> design patents on Xilinx FPGAs have expired so many functions of Xilinx
> LUTs are available to all including distributed memory.
>
>
>>
>> Stack machines is my current line of interest so far the richest machine
>> I've used uses the following registers;
>>
>> TOS top of Data Stack
>> TRS top of Return Stack
>> W a temporary register
>> IX an Index register to use with memory access specially in accessing
>> arrays
>> of data.
>> IP Instruction Pointer
>>
>> Add to that a Data and Return Stack but those are not registers but their
>> pointers use a small register not directly accessible.
>>
>> Not a whole lot of registers specially when compared to a MSP430 CPU
>> with 16
>> general registers, or an ARM CPU with 32 general registers.
>
> Big difference... The registers in a stack machine need to be separate,
> so they use FFs for the registers and LUTs for the input and output
> muxes. A RAM is a bunch of registers with output muxes to share the
> output bus. A register file can be efficiently implemented in a small
> RAM which utilizes the internal muxes rather than LUTs.
>

A normal register file uses RAM because they are all wired the same but
a Forth register needs to be FF because the registers are not wired to
the same places? I assume then that in a regular register file CPU the
use of dual ported RAM allows the use of two register at the same time.

> Regardless of how many registers a design has, the real driver of logic
> usage is usually muxes. You can have one register (top of data stack
> for example) which is fed by many sources and the mux will end up being
> huge. I know this from experience... ;)
>
> The way to keep your design small and efficient is to focus on the
> micro-ops required to implement an instruction to keep these
> interconnects to a minimum.
>

Since the CPUs that I'm interested in for the most part single clock to
execute an instruction types then one ends up using an lot of muxes.

>> Using PAC (Portable Assembler Code) mnemonics when moving the code to
>> another CPU the primitives and other assembler code does not need to be
>> changed, only the assembler needs to be changed and that would need
>> changes
>> no matter what scheme one uses, so it is simpler to port using a PAC
>> assembler. It's not the traditional way where you have to re-write all
>> the
>> assembly code but times are changing we are not in the 70s anymore.
>
> You seem to be laser focused on the idea that rewriting the tool has to
> be easier than rewriting the code. I don't know of any portable
> assemblers that work the way you describe. So you will need to write
> this from scratch.

That is because changing the PAC assembler is a fairly simple task
versus re-writing all the primitives. Don't forget that in the
conventional way you have to do massive changes to the assembler and
then you have to rewrite all the primitives and associated assembler
code. While using PAC all we need to change is the code generated by the
assembler and the job is done.

That is a lot easier than a rewrite of the assembler and all the code
words. In either case the tools have to be changed there is no getting
away from that, with PAC the changes are fewer and simpler. In either
case one needs to change a few specific items having to do with I/O and
CPU items like writing to Flash so neither has an advantage there.

>
>
>> I tend to think that this is a superior way to write a Forth that is
>> efficient and easy to port qualities that with traditional assemble
>> code are
>> at odds with each other. Mind you no matter what one uses there are
>> some CPU
>> specific items that need to be update such clock management and I/O but
>> those need changing with a new CPU no matter what way one uses so it
>> something to be dealt with.
>
> I don't see any advantage at all. Either way you need to generate
> native code for the processor you are using. One way you recode a few
> Forth words which gives you native code *and* gives you an opportunity
> to optimize the code easily. The other way you have existing "portable"
> assembler code which now has to be translated/compiled to native code by
> a tool that needs to be rewritten for the target processor. Then if you
> want optimized code you likely need to rewrite the "portable" assembly
> code.

That is because I'm laser focused as you mentioned, PAC code can be
optimized just the same as native code, the assembler generates native
code its just that the mnemonics are the same for many CPUs so the
assembler needs fewer changes to it when porting to a new CPU.
>
> I am ready to return to my self-assigned task of documenting Mecrisp on
> the MSP430. Let me know how your project goes. If you need any advice
> on FPGA CPUs, I'm happy to lend my experience.
>
Not an exciting task but one that needs to be done.


--
Cecil - k5nwa

Mark Wills

unread,
May 28, 2017, 2:49:50 PM5/28/17
to
The solution is obvious. Use a Forth processor. No need for an assembler or C or C++ or Go or a cross-compiler or a meta-compiler. The chip *is* Forth.

I don't think you can get much more portable than that.

jim.bra...@ieee.org

unread,
May 28, 2017, 2:53:38 PM5/28/17
to
First, didn't spend much time on generating these numbers. Much depends on the module you use as top. And a SOC version with many peripherals or memory caching can easily double the LUT count. Generally I run bare cores.

Second the skill of the implementer can easily make a factor of two difference in LUT count or Fmax.

Third, one can trade micro-code for speed.

You can the find outdated spreadsheets at http://opencores.org/project,up_core_list
Goal was to determine designs with best figure of merit (Fmax/LUT count adjusted for data width and number of clocks per instruction).
Do not consider the results more accurate than, say, +/-30%

Cecil Bayona

unread,
May 28, 2017, 3:08:52 PM5/28/17
to
On 5/28/2017 1:14 PM, Albert van der Horst wrote:
> In article <ogf166$g4d$2...@dont-email.me>,
> Cecil Bayona <cba...@cbayona.com> wrote:
>> On 5/28/2017 3:23 AM, Albert van der Horst wrote:
>>> In article <ogcum7$r9t$2...@dont-email.me>, rickman <gnu...@gmail.com> wrote:
>>>> Cecil Bayona wrote on 5/27/2017 3:20 PM:
>>> <SNIP>
>>>>
>>>> I'm not sure what advantage "portable" assembly language would have over a
>>>> metacompiled Forth. Both approaches require writing a back end for the
>>>> tool. A metacompiled Forth has one HUGE advantage for developing a Forth
>>>> system... it's in Forth.
>>>
>>> Truely "portable" or "high level" assembly is a pipe dream.
>>> Using macro's to make assembly more portable surely is feasible.
>>> ciforth may be a good example of that, using m4 a lot.
>>
>> How do you use m4 to create your Forth? Is it used as an external
>> program to Forth or as a tools used separate from Forth?
>
> A rather short document (20 pages) contains about 10 pages
> relevant to this question. cifgenps.zip on the site in my sig.
> That document is from 2002. It could use an update but it surely
> gives the correct idea.
> I.a. I use it for selection (a la [IF] ) and as regular
> assembler macro's.

You have a lot of links on your site so I was not able to find the link
to the file. I found it with Google but it's in Postscript so I will
need to find a reader.

>
>>
>>>
>>> I can turn my indirect threaded Forth ciforth into a direct threaded Forth
>>> rather easily, while Forth in c is probably subroutine threaded.
>>> (At first sight I would think it infeasible to make an indirect threaded
>>> Forth in c but apparently gforth has a threaded version.)
>>>
>>>>
>>>> --
>>>>
>>>> Rick C
>>>
>>> Groetjes Albert
>>>
>>
>>
>> --
>> Cecil - k5nwa


--
Cecil - k5nwa

Cecil Bayona

unread,
May 28, 2017, 3:12:07 PM5/28/17
to
On 5/28/2017 1:49 PM, Mark Wills wrote:
> The solution is obvious. Use a Forth processor. No need for an assembler or C or C++ or Go or a cross-compiler or a meta-compiler. The chip *is* Forth.
>
> I don't think you can get much more portable than that.
>
Even with a Forth CPU you still need an assembler to create the code in
memory, and a meta compiler to create a resident version of Forth that
runs in a CPU. Forth is a lot more that a bunch of primitives.

--
Cecil - k5nwa

hughag...@gmail.com

unread,
May 28, 2017, 5:45:19 PM5/28/17
to
On Sunday, May 28, 2017 at 9:22:57 AM UTC-7, Cecil - k5nwa wrote:
> On 5/28/2017 12:10 AM, hughag...@gmail.com wrote:
> > On Saturday, May 27, 2017 at 8:30:04 PM UTC-7, Cecil - k5nwa wrote:
> >> The PDP11 is very nice for it's day but compared to modern CPUs it is
> >> register starved, I'm mostly interested in Forth CPUs and there are a
> >> few available, some are very simple such as the J1 CPU but with minor
> >> changes it can be improved but then I would need software that works
> >> with it hence the reason why this software is needed.
> >
> > I don't think the J1 supports local variables --- you are going to get Forth code that looks like it was written in the 1970s --- Forth code that passes data between functions in global variables is terrible; you would be better off to forget about Forth and use C instead.
>
> The J1 is a stack CPU so why would one pass data in global variables?
> One would use the Data Stack with Forth.

The data-stack is pretty cumbersome when you have more than three items. You end up with a lot of stack-juggling words --- also, you use >R R> to get data off the data-stack and out of the way temporarily --- the result is horrendously complicated code, even for simple functions, and Forth becomes a nightmare to maintain (even by the original programmer himself).

Forth programming doesn't have to be a brain-buster though! If you want to boggle your mind, you should solve Sudoku puzzles with a pen --- or play Go against me on KGS --- I enjoy creating hugely complex situations on the Go board that confuse the opponent and awe the spectators (this works about half the time; the other half of the time I confuse myself and amuse the spectators).

There are three methods available to prevent Forth from becoming a brain-buster, and turning Forth into an elegant language:

1.) Use local variables. Any function that has more than three parameters is a candidate for local variables. You should never use ROLL but should always use local variables instead.

2.) Pack your data into a struct, then pass the pointer to the struct into the function as a parameter. Oftentimes when you have a function with a lot of parameters, the parameters are related to each other. For example, the X Y and Z coordinates of a point should not be passed in as separate parameters (if you have two points, that's 6 parameters), but should be packed into a struct of type PT and the pointer to the struct passed in (if you have two points, that's 2 parameters).

3.) Create a separate stack dedicated to a common data-type. In my STRING-STACK.4TH package, I provide a stack for strings.

Your typical ANS-Forth programmer is not smart enough to understand the three methods mentioned above. Your typical ANS-Forth programmer will pass data between functions in global variables. This is why PAD was put in the ANS-Forth standard. This is why most ANS-Forth programs are littered with VARIABLE and VALUE words that are used for holding data temporarily, and the functions have various assumptions about which global variables they need set and which global variables they will set (even if these assumptions are documented, the program is still confusing and unreliable).

> > I just came up with this for a PDP11 STC off the top of my head, but it seems like it might work:
> >
> > R0 general-purpose
> > R1 general-purpose
> > R2 top-of-stack
> > R3 local-frame pointer
> > R4 data-stack pointer
> > R5 double-stack pointer
> > R6 return-stack pointer
> > R7 program counter
>
> Having a Doubles Stack is very odd so it would create a lot of software
> compatibility issues but then Forthers are not famous for sharing
> software. What is the justification for such an odd item, does it really
> improve Forth?

I am assuming that you want a good Forth system --- not ANS-Forth, which looks like something from the 1970s.

One of the major flaws of ANS-Forth was that it has single-cell and double-cell data intermixed on the data-stack (it even allows floats on the data-stack, although everybody ignores that and uses a separate float-stack). This is one of the reasons why ANS-Forth code is so badly infected with stack-juggling words and >R R> etc.. For example, if you have two doubles and a single on the data-stack, this is not three items (three would be manageable, as I said before) --- this is five items --- this is going to result in a hard-to-read mess.

The mixed-precision arithmetic words will access both stacks. For example:
S>D ( n -- ) \double: -- n
M* ( a b -- ) \double: -- n
FM/MOD ( divisor -- remainder quotient ) \double: numerator --

It is also possible to store strings on the double-stack as address/count pairs. Note that if you do this, then you can't have COW (copy-on-write) such as I have in STRING-STACK.4TH --- you have to copy the string to a new heap struct when you do DUP$ or OVER$ etc. --- in a micro-controller, you aren't likely working with strings very much though, so this inefficiency isn't a major problem.

All in all, I think that a double-stack greatly improves Forth. There is no point in developing a new Forth unless it is going to be an improvement over ANS-Forth --- improving on ANS-Forth is easy and obvious --- this should always be done.

> I would think if one is going to be odd and add an extra stack it might
> be more useful as a DO LOOP stack so the Data Stack and the Return Stack
> has no extra garbage making the code simpler.

I wouldn't have DO LOOP at all. That is just cruft from the 1970s.

You have local variables, so you should do iteration using BEGIN WHILE REPEAT and hold the index or whatever in local variables. The DO LOOP constructs use I and J as a crude kind of local variable --- this is not necessary if you have actual local variables available.

Also, the application programmer shouldn't normally use BEGIN WHILE REPEAT at all. Code that does iteration using BEGIN WHILE REPEAT should be buried inside of HOFs, which are typically written by code-library writers or "systems programmers" or whatever. The application programmer would do iteration by writing a quotation and giving the quotation to a HOF that does the iteration internally and executes the quotation. I would expect that most programs would not have any explicit iteration with BEGIN WHILE REPEAT but would rely entirely on HOFs.

> Thanks for reminding me about PAC (Portable Assembler Code), it changes
> the whole trajectory of the project, if PAC can generate efficient code
> then it would be an ideal setup for this and other projects. In any case
> it is bound to be faster than using C.

The PDP11 is the grandfather of all register-based processors (MC68000, PIC24, MSP430, etc.). If your assembler is for the PDP11, it can easily be retargeted to to any of these other processors, as all of them are supersets of the PDP11.

You can also retarget it to processors such as the 6812 that have a shortage of registers (are a subset of the PDP11), but in this case some of the PDP11 registers will have to be implemented as pseudo-registers in memory --- this is going to be pretty inefficient, but at least you get portability --- these processors are obsolete nowadays, so nobody is likely to want to use them anyway.

The MSP430 has 16 registers total. I would still use the PDP11 as your assembly-language as I described above. You can, however, have the main-program use some of the registers, and ISRs use the other registers. This means that ISRs don't have to save and restore registers (assuming that ISRs can't be interrupted). This should boost the speed of your system considerably, as a lot of micro-controller programs spend up to 50% of their time servicing interrupts. You will have to write your compiler in such a way that it is able to use the correct set of registers as R0..R7 depending upon whether it is compiling a colon word to be used in the main-program or is compiling an ISR. This should be easy. Put the functions that can be used by the main-program in one vocabulary and the functions that can be used by ISRs in another vocabulary, so there is no confusion if they have the same names.

I think you are totally messing up the efficiency of your Forth system by assuming that you have 16 registers and your Forth should use them all. As I said, an optimizing compiler can make use of extra registers to hold values temporarily, but writing such an optimizing compiler is very difficult (I've never done it, and I wouldn't know how to even begin such a project). A much better use of 16 registers is to have two banks of 8 registers, which are used by the main-program and the ISRs. This is a micro-controller, after all --- most micro-controllers spend significant amounts of time saving and restoring registers as they enter and exit ISRs --- making ISRs efficient is the obvious way to boost the speed, and a lot easier than writing an optimizing compiler.

Anyway --- my way of thinking about Forth is totally alien to that of the ANS-Forth and Forth-200x folks --- they are going to continue to use gForth (written in C) on the ARM under Linux (also written in C) and describe this as a "Forth micro-controller."

hughag...@gmail.com

unread,
May 28, 2017, 6:09:42 PM5/28/17
to
On Sunday, May 28, 2017 at 11:53:38 AM UTC-7, jim.bra...@ieee.org wrote:
> Third, one can trade micro-code for speed.

Well, yeah!

This is why it was possible to put the MiniForth processor on the Lattice isp1048 PLD in 1994 --- nobody else had a processor on that PLD, and this was generally considered to be impossible --- the hardware used pretty minimal chip resources, but the Forth primitives had to be written in assembly-language (what would typically be described as micro-code, although we didn't use that term at the time).

Anyway, I don't think it is meaningful to compare how big of an FPGA is needed for various processors, without considering whether microcode is used or not, or how capable your microcode is, or a multitude of other design decisions. It is not like there is a standard way to implement a processor in an FPGA --- there are several techniques available --- there are a lot of trade-offs that the HDL writer will have to make, in regard to which feature combination (high-speed, low-size, low-price, low-power, etc.) he is trying to maximize (and, no, you can't maximize all of them).

hughag...@gmail.com

unread,
May 28, 2017, 6:40:07 PM5/28/17
to
On Sunday, May 28, 2017 at 9:50:16 AM UTC-7, Cecil - k5nwa wrote:
> a MSP430 CPU
> with 16 general registers, or an ARM CPU with 32 general registers.

Well, the ARM does have 32 registers, but you only have access to 16 of them at a time, so you can't really say that you have "32 general registers." You have register banks that are swapped in and out for the ISRs.

You could do something similar in your FPGA design:

IR0 R0 general-purpose
IR1 R1 general-purpose
IR2 R2 top-of-stack
IR3 R3 local-frame pointer
IR4 R4 data-stack pointer
IR5 R5 double-stack pointer
IR6 R6 return-stack pointer
IR7 R7 program counter

When an interrupt occurs, the IRx registers are swapped in, and when the interrupt ends they are swapped out.

As I said before though, this could also be done by the assembler. For example, when targeting the MSP430, your assembler would use different registers depending upon whether it was assembling code for the main-program or the ISRs. When the interrupt occurs, only the PC and status-flags register have to be saved and restored (in static memory locations)

You said before that portability is your #1 goal. The complexity is buried in the assembler. The programmer who writes the Forth compiler doesn't have to deal with this complexity, but he just assumes that his target is the PDP11. This is called: "information hiding." The programmer of the high-level code (the Forth compiler) doesn't have to worry about, or even know about, the complexity that is hidden in the low-level code (the assembler).

Information hiding! Always a good idea!

Joel Rees

unread,
May 28, 2017, 6:46:46 PM5/28/17
to
On Saturday, May 27, 2017 at 2:09:48 PM UTC+9, rickman wrote:
> [...]
>
> "I would like to have my own software". Why is this important? I don't
> get it. If you have software you can use as you wish, why does it
> matter who wrote it?

Maybe he thinks he'd understand software he wrote better than software
others wrote?

--
Joel Rees

Delusions of being a novelist:
http://reiisi.blogspot.com/p/novels-i-am-writing.html

Paul Rubin

unread,
May 28, 2017, 7:11:50 PM5/28/17
to
alb...@cherry.spenarnc.xs4all.nl (Albert van der Horst) writes:
> Yes libraries are in the C development environment of about every
> microprocessor. Now give me one example of an AD conversion or
> switching to low power mode that is portable between two different
> micro processors using the portable C.

This is sort of what the Arduino environment provides.

Joel Rees

unread,
May 28, 2017, 7:31:56 PM5/28/17
to
Okay, I wasn't sure this would be useful, but having scanned this thread,
I'll ask --

I think you said you looked at my bif-c.

https://sourceforge.net/projects/bif-c/

source here:

https://sourceforge.net/p/bif-c/code/HEAD/tree/trunk/

If I explained something about that, would it help, relative to the idea
of a "portable-as-in-C" Forth?

Another thing you might consider is grabbing the fig-Forth assembly
language sources for a CPU for which you can get an emulator. Then you
can study existing implementations a little more directly.

For instance, I have transcribed the fig-Forth assembly language source
for the 6800, by Dave Lion, et. al. You can find that source in asm68c
project on source forge:

https://ja.osdn.net/projects/bif-c/

here:

https://sourceforge.net/p/asm68c/code/ci/master/tree/fig-forth/

Joe Allen's 6800 emulator works, search for "exorsim" on sourceforge
or github.

And there are other fig-Forth sources available for various processors --
6502, 68k, pdp-11, if I remember right, and even more interesting CPUs.
And I'm not a fan of 8086, but it sure is another option for studying a
fig-Forth on a "real" CPU under emulation.

Working with a variety of real implementations should help you get a
better feel of why things are done the way they are in modern
implementations.

--
Joel Rees

Trying to re-invent the industry all by myself:
http://defining-computers.blogspot.jp/

hughag...@gmail.com

unread,
May 28, 2017, 9:25:05 PM5/28/17
to
On Sunday, May 28, 2017 at 2:45:19 PM UTC-7, hughag...@gmail.com wrote:
> On Sunday, May 28, 2017 at 9:22:57 AM UTC-7, Cecil - k5nwa wrote:
> > On 5/28/2017 12:10 AM, hughag...@gmail.com wrote:
> > > I just came up with this for a PDP11 STC off the top of my head, but it seems like it might work:
> > >
> > > R0 general-purpose
> > > R1 general-purpose
> > > R2 top-of-stack
> > > R3 local-frame pointer
> > > R4 data-stack pointer
> > > R5 double-stack pointer
> > > R6 return-stack pointer
> > > R7 program counter
> > ...
> > Thanks for reminding me about PAC (Portable Assembler Code), it changes
> > the whole trajectory of the project, if PAC can generate efficient code
> > then it would be an ideal setup for this and other projects. In any case
> > it is bound to be faster than using C.
> ...
> The MSP430 has 16 registers total. I would still use the PDP11 as your assembly-language as I described above. You can, however, have the main-program use some of the registers, and ISRs use the other registers. This means that ISRs don't have to save and restore registers (assuming that ISRs can't be interrupted). This should boost the speed of your system considerably, as a lot of micro-controller programs spend up to 50% of their time servicing interrupts. You will have to write your compiler in such a way that it is able to use the correct set of registers as R0..R7 depending upon whether it is compiling a colon word to be used in the main-program or is compiling an ISR. This should be easy. Put the functions that can be used by the main-program in one vocabulary and the functions that can be used by ISRs in another vocabulary, so there is no confusion if they have the same names.

The more that I think about it, the more I like the PDP11 as your portable-assembly-language.

1.) The 8 registers of the PDP11 are adequate for a reasonable Forth implementation (as shown above in the register-dedication table I provided). You do have two general-purpose registers, so you can do code-optimization in which you hold values in general-purpose registers temporarily rather than push them to the data-stack (VFX does code optimization on the 32-bit x86 that has only one more register than the PDP11 has).

2.) On modern processors that have 16 registers (such as the MSP430), you can divide the registers into two banks for the main-program and the ISRs to significantly speed up ISRs while still allowing ISRs to be written in Forth. Your ISRs can't be interrupted though, because there is only one bank of registers available. On the PIC24 you can also have fast ISRs written in assembly-language that only use the lower four registers and are able to interrupt the lower-priority ISRs that are written in Forth.

3.) There are HDL implementations of the PDP11 already available, so if you want an FPGA you can use one of these as a starting point. Considering that you (and I) have little or no experience with HDL, it seems more realistic to start with an existing implementation rather than start from scratch.

4.) There is software available for the PDP11, such as RT11, that could still be useful. Your assembler should be compatible with whatever assembler was used to assemble the RT11 code, except that your assembler generates code for the MSP430, PIC24, etc.. So, if the source-code to RT11 is available (I assume it is), you could run RT11 on an MSP430 or PIC24 or whatever. It will be just like a George Romero movie: the dead will rise and walk again!

Cecil Bayona

unread,
May 28, 2017, 10:07:59 PM5/28/17
to
On 5/28/2017 4:45 PM, hughag...@gmail.com wrote:
> On Sunday, May 28, 2017 at 9:22:57 AM UTC-7, Cecil - k5nwa wrote:
>> On 5/28/2017 12:10 AM, hughag...@gmail.com wrote:

>>
>> The J1 is a stack CPU so why would one pass data in global variables?
>> One would use the Data Stack with Forth.
>
> The data-stack is pretty cumbersome when you have more than three items. You end up with a lot of stack-juggling words --- also, you use >R R> to get data off the data-stack and out of the way temporarily --- the result is horrendously complicated code, even for simple functions, and Forth becomes a nightmare to maintain (even by the original programmer himself).
>
> There are three methods available to prevent Forth from becoming a brain-buster, and turning Forth into an elegant language:
>
> 1.) Use local variables. Any function that has more than three parameters is a candidate for local variables. You should never use ROLL but should always use local variables instead.
>
> 2.) Pack your data into a struct, then pass the pointer to the struct into the function as a parameter. Oftentimes when you have a function with a lot of parameters, the parameters are related to each other. For example, the X Y and Z coordinates of a point should not be passed in as separate parameters (if you have two points, that's 6 parameters), but should be packed into a struct of type PT and the pointer to the struct passed in (if you have two points, that's 2 parameters).
>
> 3.) Create a separate stack dedicated to a common data-type. In my STRING-STACK.4TH package, I provide a stack for strings.
>
> Your typical ANS-Forth programmer is not smart enough to understand the three methods mentioned above. Your typical ANS-Forth programmer will pass data between functions in global variables. This is why PAD was put in the ANS-Forth standard. This is why most ANS-Forth programs are littered with VARIABLE and VALUE words that are used for holding data temporarily, and the functions have various assumptions about which global variables they need set and which global variables they will set (even if these assumptions are documented, the program is still confusing and unreliable).
>

>> Having a Doubles Stack is very odd so it would create a lot of software
>> compatibility issues but then Forthers are not famous for sharing
>> software. What is the justification for such an odd item, does it really
>> improve Forth?
>
> I am assuming that you want a good Forth system --- not ANS-Forth, which looks like something from the 1970s.
>

I wish it did then it would be a decent Forth but as it is they tried to
please everyone and ended with a lot of ambiguity.

> One of the major flaws of ANS-Forth was that it has single-cell and double-cell data intermixed on the data-stack (it even allows floats on the data-stack, although everybody ignores that and uses a separate float-stack). This is one of the reasons why ANS-Forth code is so badly infected with stack-juggling words and >R R> etc.. For example, if you have two doubles and a single on the data-stack, this is not three items (three would be manageable, as I said before) --- this is five items --- this is going to result in a hard-to-read mess.
>
> The mixed-precision arithmetic words will access both stacks. For example:
> S>D ( n -- ) \double: -- n
> M* ( a b -- ) \double: -- n
> FM/MOD ( divisor -- remainder quotient ) \double: numerator --
>

The data shuffling is a royal pain and a killer of efficiency, you end
up running a lot of code that does not solve your application because
data needs to be accessed. That is one reason wy people like Algol like
languages because this is handled for you.

> It is also possible to store strings on the double-stack as address/count pairs. Note that if you do this, then you can't have COW (copy-on-write) such as I have in STRING-STACK.4TH --- you have to copy the string to a new heap struct when you do DUP$ or OVER$ etc. --- in a micro-controller, you aren't likely working with strings very much though, so this inefficiency isn't a major problem.
>
> All in all, I think that a double-stack greatly improves Forth. There is no point in developing a new Forth unless it is going to be an improvement over ANS-Forth --- improving on ANS-Forth is easy and obvious --- this should always be done.
>

If you have registers capable of implementing a stack the why stop at two?

>> I would think if one is going to be odd and add an extra stack it might
>> be more useful as a DO LOOP stack so the Data Stack and the Return Stack
>> has no extra garbage making the code simpler.
>
> I wouldn't have DO LOOP at all. That is just cruft from the 1970s.
>
> You have local variables, so you should do iteration using BEGIN WHILE REPEAT and hold the index or whatever in local variables. The DO LOOP constructs use I and J as a crude kind of local variable --- this is not necessary if you have actual local variables available.
>

OK but I like the DO LOOP because its easy to use and the I local is
very handy at times and helps you avoid doing unnecessary math.

> Also, the application programmer shouldn't normally use BEGIN WHILE REPEAT at all. Code that does iteration using BEGIN WHILE REPEAT should be buried inside of HOFs, which are typically written by code-library writers or "systems programmers" or whatever. The application programmer would do iteration by writing a quotation and giving the quotation to a HOF that does the iteration internally and executes the quotation. I would expect that most programs would not have any explicit iteration with BEGIN WHILE REPEAT but would rely entirely on HOFs.
>

I'm not familiar with these techniques as I mostly have used older Forth
where these are not available. Maybe I have used something similar in
Delphi but they would be called something else, I do recall writing code
where a function defined inside another function can access the data of
the parent and change that data, but I forget what it was called. I used
it to eliminate the passing of a whole lot of data to a function.

>> Thanks for reminding me about PAC (Portab le Assembler Code), it changes
>> the whole trajectory of the project, if PAC can generate efficient code
>> then it would be an ideal setup for this and other projects. In any case
>> it is bound to be faster than using C.
>
> The PDP11 is the grandfather of all register-based processors (MC68000, PIC24, MSP430, etc.). If your assembler is for the PDP11, it can easily be retargeted to to any of these other processors, as all of them are supersets of the PDP11.

All those processors are nice to work with, add to that the dsPIC as it
is an enhanced PIC24, very nice and is also available in DIP packaging
so its easy to experiment with. Somewhere I have a PDF file which is a
copy of the PDP11 programmers manual, I'll look at it, but the MSP430 is
also a good choice. Somewhere filed away is a MSP430 IP for FPGA, the
one advantage it has is it uses a 200MHz clock so it really flies.

>
> You can also retarget it to processors such as the 6812 that have a shortage of registers (are a subset of the PDP11), but in this case some of the PDP11 registers will have to be implemented as pseudo-registers in memory --- this is going to be pretty inefficient, but at least you get portability --- these processors are obsolete nowadays, so nobody is likely to want to use them anyway.
>

There are a couple of old CPUs that eventually I want to build either a
board or a FPGA version, the Z80, MC6809, 6502 or its modern version the
W65C816.

> The MSP430 has 16 registers total. I would still use the PDP11 as your assembly-language as I described above. You can, however, have the main-program use some of the registers, and ISRs use the other registers. This means that ISRs don't have to save and restore registers (assuming that ISRs can't be interrupted). This should boost the speed of your system considerably, as a lot of micro-controller programs spend up to 50% of their time servicing interrupts. You will have to write your compiler in such a way that it is able to use the correct set of registers as R0..R7 depending upon whether it is compiling a colon word to be used in the main-program or is compiling an ISR. This should be easy. Put the functions that can be used by the main-program in one vocabulary and the functions that can be used by ISRs in another vocabulary, so there is no confusion if they have the same names.
>
> I think you are totally messing up the efficiency of your Forth system by assuming that you have 16 registers and your Forth should use them all. As I said, an optimizing compiler can make use of extra registers to hold values temporarily, but writing such an optimizing compiler is very difficult (I've never done it, and I wouldn't know how to even begin such a project). A much better use of 16 registers is to have two banks of 8 registers, which are used by the main-program and the ISRs. This is a micro-controller, after all --- most micro-controllers spend significant amounts of time saving and restoring registers as they enter and exit ISRs --- making ISRs efficient is the obvious way to boost the speed, and a lot easier than writing an optimizing compiler.

There are so many ways to optimize code, many books have been written on
the subject and it is an interesting subject. The times I have written
optimizing code generators which is for about 12 different CPUs I been
off the beaten path and done it my way which generally not how it is
found in compiler books. It may not be the most optimum way of doing it
but I don't care to be a lemming, it works good enough and it's simple
enough. I feel the same way about Forth I like what I like and too bad
if the rest of the world does not agree. But I'm always willing to learn
something new or a better way to do things.

One day you need to try it it's a lot of fun watching simply generated
code turn into an object of beauty and efficiency.

>
> Anyway --- my way of thinking about Forth is totally alien to that of the ANS-Forth and Forth-200x folks --- they are going to continue to use gForth (written in C) on the ARM under Linux (also written in C) and describe this as a "Forth micro-controller."
>

Really, I could not tell. I've heard rumors that you are not a happy
camper when it comes to ANS Forth is there anything to that rumor?

--
Cecil - k5nwa

Cecil Bayona

unread,
May 28, 2017, 10:43:35 PM5/28/17
to
On 5/28/2017 8:25 PM, hughag...@gmail.com wrote:
> On Sunday, May 28, 2017 at 2:45:19 PM UTC-7, hughag...@gmail.com wrote:
>> On Sunday, May 28, 2017 at 9:22:57 AM UTC-7, Cecil - k5nwa wrote:
>> ...
>> The MSP430 has 16 registers total. I would still use the PDP11 as your assembly-language as I described above. You can, however, have the main-program use some of the registers, and ISRs use the other registers. This means that ISRs don't have to save and restore registers (assuming that ISRs can't be interrupted). This should boost the speed of your system considerably, as a lot of micro-controller programs spend up to 50% of their time servicing interrupts. You will have to write your compiler in such a way that it is able to use the correct set of registers as R0..R7 depending upon whether it is compiling a colon word to be used in the main-program or is compiling an ISR. This should be easy. Put the functions that can be used by the main-program in one vocabulary and the functions that can be used by ISRs in another vocabulary, so there is no confusion if they have the same names.
>
> The more that I think about it, the more I like the PDP11 as your portable-assembly-language.

A very nice processor to program in assembler and easy to generate code
for in high level languages. The main modern CPUs that I would like to
implement eventually are PIC32, PIC24, dsPIC, MSP430, and the W65C816,
all of these with exception of the W65C816 have more than 8 registers

Although I already have MPE VFX for the MSP430 and eForth for the same
CPU so that would not be an immediate CPU to target.

> 1.) The 8 registers of the PDP11 are adequate for a reasonable Forth implementation (as shown above in the register-dedication table I provided). You do have two general-purpose registers, so you can do code-optimization in which you hold values in general-purpose registers temporarily rather than push them to the data-stack (VFX does code optimization on the 32-bit x86 that has only one more register than the PDP11 has).
>
> 2.) On modern processors that have 16 registers (such as the MSP430), you can divide the registers into two banks for the main-program and the ISRs to significantly speed up ISRs while still allowing ISRs to be written in Forth. Your ISRs can't be interrupted though, because there is only one bank of registers available. On the PIC24 you can also have fast ISRs written in assembly-language that only use the lower four registers and are able to interrupt the lower-priority ISRs that are written in Forth.
>
> 3.) There are HDL implementations of the PDP11 already available, so if you want an FPGA you can use one of these as a starting point. Considering that you (and I) have little or no experience with HDL, it seems more realistic to start with an existing implementation rather than start from scratch.
>
> 4.) There is software available for the PDP11, such as RT11, that could still be useful. Your assembler should be compatible with whatever assembler was used to assemble the RT11 code, except that your assembler generates code for the MSP430, PIC24, etc.. So, if the source-code to RT11 is available (I assume it is), you could run RT11 on an MSP430 or PIC24 or whatever. It will be just like a George Romero movie: the dead will rise and walk again!
>
I remember seeing some emulators available that ran RT11, good for
testing purposes.

--
Cecil - k5nwa

Joel Rees

unread,
May 28, 2017, 11:17:04 PM5/28/17
to
Oh, never mind. The business with no static initializers supposed to be
allowed with a flexible array in a struct is making the interpreter unstable.

Joel Rees

unread,
May 29, 2017, 12:38:18 AM5/29/17
to
On Monday, May 29, 2017 at 12:17:04 PM UTC+9, Joel Rees
in "Re: Forth Implementations advantages and disadvantages."
wrote:
> On Monday, May 29, 2017 at 8:31:56 AM UTC+9, Joel Rees wrote:
> > Okay, I wasn't sure this would be useful, but having scanned this thread,
> > I'll ask --
> >
> > I think you said you looked at my bif-c.
> >
> > https://sourceforge.net/projects/bif-c/
> >
> > source here:
> >
> > https://sourceforge.net/p/bif-c/code/HEAD/tree/trunk/
> >
> > [...]
> Oh, never mind. The business with no static initializers supposed to be
> allowed with a flexible array in a struct is making the interpreter unstable.

Here is my current header:

-------------------------
typedef struct definition_header_s
{
cell_u nameLink; /* Bits above length are mode flags. Name is not far from header. C init with pointer. */
cell_u interpMode; /* Making the mode bits explicit to help the C source-level initializations. */
cell_u allocLink; /* Want to separate the allocation fields. */
cell_u allocMode; /* Decoupling the allocation, making the C initializations easier. */
cell_u vocabLink; /* Root of this definition's vocabulary. */
cell_u leftLink; /* Binary tree, left child in order. */
cell_u rightLink; /* Right child in order. */
cell_u codeLink; /* Interpretation code for this definition. */
cell_u parameterLink[]; /* Parameters for the code for this definition. */
} definition_header_s;
-------------------------

from https://sourceforge.net/p/bif-c/code/HEAD/tree/trunk/bifu_i.h

An example of how I'm disobeying the rules by using it in a static
header can be found in

https://sourceforge.net/p/bif-c/code/HEAD/tree/trunk/bif2b_a.c

towards the bottome, where I defined IF, ELSE, and ENDIF as lists
of Forth i-codes. I'll show IF:

---------------------------
static character_t sIF[] = "\x2" "IF";
definition_header_s hIF =
{
{ (natural_t) sIF },
{ MIMM | MCOMP },
{ (natural_t) &hQCST },
{ MFORE },
{ (natural_t) &hBIF },
{ (natural_t) &hDO },
{ (natural_t) &hQUERY },
{ (natural_t) XCOL },
{
{ (natural_t) &hCOMP },
{ (natural_t) &hZBR },
{ (natural_t) &hHERE }, /* adr */
{ (natural_t) &hZERO },
{ (natural_t) &hCOMMA },
{ (natural_t) &hLIT },
{ IF_FLAG },
{ (natural_t) &hSEMIS }
}
};
---------------------------

Over at comp.lang.c, they have been kind enough to point out to me
that the standard specifically does not support this kind of static
initialization of flexible arrays. If we want to use flexible arrays,
we must set them up at run time in our own code.

Now, gcc compiled that for me nicely until fairly recently. Actually,
I'm not sure which of the stricter points of the standard are tripping
me up. But, if the code is to remain useful, I'll have to do this a
different way.

One way is to convert all those lists of i-codes to their calls in
function bodies, something roughly like this:

---------------------------
static character_t sIF[] = "\x2" "IF";
definition_header_s hIF =
{
{ (natural_t) sIF },
{ MIMM | MCOMP },
{ (natural_t) &hQCST },
{ MFORE },
{ (natural_t) &hBIF },
{ (natural_t) &hDO },
{ (natural_t) &hQUERY },
{ (natural_t) IF }
};
void IF( void )
{
( * --SP ).icode = ZBR;
COMPILEFROMSTACK();
HERE(); /* adr */
ZERO();
COMMA();
( * --SP ).integer = IF_FLAG;
}
---------------------------

This has the disadvantage that the code no longer tests itself.

However, having it test itself is no longer necessary because I know
the flexible array should work. And if I still want it to test itself
this way, I can add a simulated RAM disk that contains some of the
optional words, like doubles, and have it load those in the startup
code.

The running interpreter would keep the parameters adjacent to the word
headers in the dictionary.

Another option is to split the parameter list from the header, in
the same way that I've split low-level code from the header:

-------------------------
typedef struct definition_header_s
{
cell_u nameLink; /* Bits above length are mode flags. Name is not far from header. C init with pointer. */
cell_u interpMode; /* Making the mode bits explicit to help the C source-level initializations. */
cell_u allocLink; /* Want to separate the allocation fields. */
cell_u allocMode; /* Decoupling the allocation, making the C initializations easier. */
cell_u vocabLink; /* Root of this definition's vocabulary. */
cell_u leftLink; /* Binary tree, left child in order. */
cell_u rightLink; /* Right child in order. */
cell_u codeLink; /* Interpretation code for this definition. */
cell_u parameterLink[ 2 ]; /* Parameters for the code for this definition. */
} definition_header_s;
-------------------------

with the result looking something roughly like this:

---------------------------
static character_t sIF[] = "\x2" "IF";
definition_header_s hIF =
{
{ (natural_t) sIF },
{ MIMM | MCOMP },
{ (natural_t) &hQCST },
{ MFORE },
{ (natural_t) &hBIF },
{ (natural_t) &hDO },
{ (natural_t) &hQUERY },
{ (natural_t) XCOL },
{ { (natural_t) IIF }, 0 }
};
icode_f IIF[] =
{ { (natural_t) &hCOMP },
{ (natural_t) &hZBR },
{ (natural_t) &hHERE }, /* adr */
{ (natural_t) &hZERO },
{ (natural_t) &hCOMMA },
{ (natural_t) &hLIT },
{ IF_FLAG },
{ (natural_t) &hSEMIS }
};
---------------------------

Now, my word headers are a bit bulky to start with, containing binary
tree links and vocabulary parent links in addition to the usual
allocation links. (Yes, FORGETting is tricky, and I never have gotten
it to work in this bif-c. I had it working in bif-6809.)

So, adding a parameter list link is just adding to the bulk. And if
I handle DOES> as I've indicated above, that's two extra links.

But it allows me to keep most of the self-testing aspect intact.

On the other hand, it induces a logical separation of the parameters
from the header. We can keep the parameters next to the headers, still,
but we can also separate them.

(Which, in and of itself, might mean that DOES> links can be handled
similarly to ordinary DOCOLON links, not actually needing the second
link after all. I haven't worked that out, yet.)

There is actually a potential advantage in this separation, but I am
under the impression that it would tend to push my interpreter even
further from actual Forth.

I'm mostly thinking out loud here, but if anyone cares to comment,
I'd be interested.

hughag...@gmail.com

unread,
May 29, 2017, 12:48:46 AM5/29/17
to
On Sunday, May 28, 2017 at 7:07:59 PM UTC-7, Cecil - k5nwa wrote:
> > All in all, I think that a double-stack greatly improves Forth. There is no point in developing a new Forth unless it is going to be an improvement over ANS-Forth --- improving on ANS-Forth is easy and obvious --- this should always be done.
>
> If you have registers capable of implementing a stack the why stop at two?

What primitive data-type does not fit in either one or two cells? I would think that a single-cell data-stack and a double-cell data-stack would pretty much cover every primitive data-type.

If you have data-types that are bigger than two cells, then you are going to have to just make a struct in the heap and hold a pointer on the data-stack. The ALLOCATE and FREE will make this slower, but it is workable, even on a micro-controller.

> > I wouldn't have DO LOOP at all. That is just cruft from the 1970s.
> >
> > You have local variables, so you should do iteration using BEGIN WHILE REPEAT and hold the index or whatever in local variables. The DO LOOP constructs use I and J as a crude kind of local variable --- this is not necessary if you have actual local variables available.
>
> OK but I like the DO LOOP because its easy to use and the I local is
> very handy at times and helps you avoid doing unnecessary math.

I would recommend enhanced versions of BEGIN WHILE REPEAT --- you still use locals --- but the arithmetic is hidden from the user.

Basically, these are macros that generate BEGIN WHILE REPEAT and the code to do the advancement of the index along with the comparison of the index to the limit --- don't worry --- it is easy.

> > Also, the application programmer shouldn't normally use BEGIN WHILE REPEAT at all. Code that does iteration using BEGIN WHILE REPEAT should be buried inside of HOFs, which are typically written by code-library writers or "systems programmers" or whatever. The application programmer would do iteration by writing a quotation and giving the quotation to a HOF that does the iteration internally and executes the quotation. I would expect that most programs would not have any explicit iteration with BEGIN WHILE REPEAT but would rely entirely on HOFs.
>
> I'm not familiar with these techniques as I mostly have used older Forth
> where these are not available. Maybe I have used something similar in
> Delphi but they would be called something else, I do recall writing code
> where a function defined inside another function can access the data of
> the parent and change that data, but I forget what it was called. I used
> it to eliminate the passing of a whole lot of data to a function.

You're not familiar with these techniques because there is no Forth, old or new, that does this --- it is just something that I made up.

I don't know Delphi, but I did read a book on Pascal-S way back in high-school, that provided source-code for a compiler. This Pascal had nested functions. It also had a "display table" that allowed the parent function's locals to be visible in the nested function when it executed. Pretty complicated! My quotations are much simpler, although not as versatile.

> There are a couple of old CPUs that eventually I want to build either a
> board or a FPGA version, the Z80, MC6809, 6502 or its modern version the
> W65C816.

What is your goal? Do you have some application in mind? Or do you just enjoy programming and want to play with one of these old processors because they are cool?

You might try one of those Rabbit boards if you are interested in the Z80 --- they look like fun --- I haven't tried them though.

The 6809 and 65c816 both score high on the coolometer --- they aren't practical though --- the ARM is the practical choice for pretty much everything.

> > I think you are totally messing up the efficiency of your Forth system by assuming that you have 16 registers and your Forth should use them all. As I said, an optimizing compiler can make use of extra registers to hold values temporarily, but writing such an optimizing compiler is very difficult (I've never done it, and I wouldn't know how to even begin such a project). A much better use of 16 registers is to have two banks of 8 registers, which are used by the main-program and the ISRs. This is a micro-controller, after all --- most micro-controllers spend significant amounts of time saving and restoring registers as they enter and exit ISRs --- making ISRs efficient is the obvious way to boost the speed, and a lot easier than writing an optimizing compiler.
>
> There are so many ways to optimize code, many books have been written on
> the subject and it is an interesting subject. The times I have written
> optimizing code generators which is for about 12 different CPUs I been
> off the beaten path and done it my way which generally not how it is
> found in compiler books. It may not be the most optimum way of doing it
> but I don't care to be a lemming, it works good enough and it's simple
> enough. I feel the same way about Forth I like what I like and too bad
> if the rest of the world does not agree. But I'm always willing to learn
> something new or a better way to do things.
>
> One day you need to try it it's a lot of fun watching simply generated
> code turn into an object of beauty and efficiency.

Recently I have been giving some thought to writing a Pascal compiler for either the 80c320 or the PIC18 --- that may be my next project --- write it in VFX using the novice-package, and use a code optimization technique that I thought of way back in 1994 but never implemented.

I actually do know a little bit about Pascal compilers (that book I mentioned, for one thing), although I've only written a few small programs in Pascal (I liked QuickPascal back in MS-DOS days, and Turbo Pascal on the CP/M machines before that).

BTW: Lemmings don't actually follow each other over a cliff in a mass-suicide as most people believe:
http://www.adfg.alaska.gov/index.cfm?adfg=wildlifenews.view_article&articles_id=56

Cecil Bayona

unread,
May 29, 2017, 1:52:58 AM5/29/17
to
On 5/28/2017 11:48 PM, hughag...@gmail.com wrote:
> On Sunday, May 28, 2017 at 7:07:59 PM UTC-7, Cecil - k5nwa wrote:
>>> All in all, I think that a double-stack greatly improves Forth. There is no point in developing a new Forth unless it is going to be an improvement over ANS-Forth --- improving on ANS-Forth is easy and obvious --- this should always be done.
>>
>> If you have registers capable of implementing a stack the why stop at two?
>
> What primitive data-type does not fit in either one or two cells? I would think that a single-cell data-stack and a double-cell data-stack would pretty much cover every primitive data-type.
>
> If you have data-types that are bigger than two cells, then you are going to have to just make a struct in the heap and hold a pointer on the data-stack. The ALLOCATE and FREE will make this slower, but it is workable, even on a micro-controller.
>
>>> I wouldn't have DO LOOP at all. That is just cruft from the 1970s.
>>>
>>> You have local variables, so you should do iteration using BEGIN WHILE REPEAT and hold the index or whatever in local variables. The DO LOOP constructs use I and J as a crude kind of local variable --- this is not necessary if you have actual local variables available.
>>
>> OK but I like the DO LOOP because its easy to use and the I local is
>> very handy at times and helps you avoid doing unnecessary math.
>
> I would recommend enhanced versions of BEGIN WHILE REPEAT --- you still use locals --- but the arithmetic is hidden from the user.
>
> Basically, these are macros that generate BEGIN WHILE REPEAT and the code to do the advancement of the index along with the comparison of the index to the limit --- don't worry --- it is easy.
>
>>> Also, the application programmer shouldn't normally use BEGIN WHILE REPEAT at all. Code that does iteration using BEGIN WHILE REPEAT should be buried inside of HOFs, which are typically written by code-library writers or "systems programmers" or whatever. The application programmer would do iteration by writing a quotation and giving the quotation to a HOF that does the iteration internally and executes the quotation. I would expect that most programs would not have any explicit iteration with BEGIN WHILE REPEAT but would rely entirely on HOFs.
>>
>> I'm not familiar with these techniques as I mostly have used older Forth
>> where these are not available. Maybe I have used something similar in
>> Delphi but they would be called something else, I do recall writing code
>> where a function defined inside another function can access the data of
>> the parent and change that data, but I forget what it was called. I used
>> it to eliminate the passing of a whole lot of data to a function.
>
> You're not familiar with these techniques because there is no Forth, old or new, that does this --- it is just something that I made up.
>
> I don't know Delphi, but I did read a book on Pascal-S way back in high-school, that provided source-code for a compiler. This Pascal had nested functions. It also had a "display table" that allowed the parent function's locals to be visible in the nested function when it executed. Pretty complicated! My quotations are much simpler, although not as versatile.

Delphi is Pascal on steroids, an excellent development environment with
an excellent debugger and tools to deal with Windows, Linux, or MacOS. I
looked it up and Delphi has both HOFs and quotations. Those were very
useful and I used them a lot in a BT+ Database library routines, very
handy passing routines and accessing the parents variables. HOFs I
believe are possible in Forth with no changes, but would not quotations
require changes to Forth?

Is there even a standard way of storing locals?

>> There are a couple of old CPUs that eventually I want to build either a
>> board or a FPGA version, the Z80, MC6809, 6502 or its modern version the
>> W65C816.
>
> What is your goal? Do you have some application in mind? Or do you just enjoy programming and want to play with one of these old processors because they are cool?
>
> You might try one of those Rabbit boards if you are interested in the Z80 --- they look like fun --- I haven't tried them though.
>
> The 6809 and 65c816 both score high on the coolometer --- they aren't practical though --- the ARM is the practical choice for pretty much everything.
>
There are some FPGA MC6809 implementations that are free and extremely
fast. For the 65c816 the chip cost around $7 at Mouser, add some RAM and
some EPROMs with a small amount of logic and you are in business. That
chip is very nice comes up in 6502 compatibility mode then you can turn
the extra features.

I'm just having fun, I'm retired due to health issues and I have a very
long list of things I would like to try out. I don't have a ton of money
but these kinds of projects are low cost so I can indulge away. For a
real project I would use something more current with an ARM, MSP430, or
dsPIC device they are all pretty inexpensive specially the ARM boards.

The Rabbit is fairly fast for the money some decent ones are $40 to $50
and all I need is one, the rest is pretty much free, make some changes
to a Forth compiler and voila a native compiler no expenses involved
just a little bit of time.

>>> I think you are totally messing up the efficiency of your Forth system by assuming that you have 16 registers and your Forth should use them all. As I said, an optimizing compiler can make use of extra registers to hold values temporarily, but writing such an optimizing compiler is very difficult (I've never done it, and I wouldn't know how to even begin such a project). A much better use of 16 registers is to have two banks of 8 registers, which are used by the main-program and the ISRs. This is a micro-controller, after all --- most micro-controllers spend significant amounts of time saving and restoring registers as they enter and exit ISRs --- making ISRs efficient is the obvious way to boost the speed, and a lot easier than writing an optimizing compiler.
>>
>> There are so many ways to optimize code, many books have been written on
>> the subject and it is an interesting subject. The times I have written
>> optimizing code generators which is for about 12 different CPUs I been
>> off the beaten path and done it my way which generally not how it is
>> found in compiler books. It may not be the most optimum way of doing it
>> but I don't care to be a lemming, it works good enough and it's simple
>> enough. I feel the same way about Forth I like what I like and too bad
>> if the rest of the world does not agree. But I'm always willing to learn
>> something new or a better way to do things.
>>
>> One day you need to try it it's a lot of fun watching simply generated
>> code turn into an object of beauty and efficiency.
>
> Recently I have been giving some thought to writing a Pascal compiler for either the 80c320 or the PIC18 --- that may be my next project --- write it in VFX using the novice-package, and use a code optimization technique that I thought of way back in 1994 but never implemented.
>
> I actually do know a little bit about Pascal compilers (that book I mentioned, for one thing), although I've only written a few small programs in Pascal (I liked QuickPascal back in MS-DOS days, and Turbo Pascal on the CP/M machines before that).

Borland made Turbo Pascal and other Turbo products like Turbo C and
Turbo Prolog I own them all, later it evolved into the Delphi and C++
Builder development environment. I have several copies of Delphi and C++
Builder the latest being version 7 but it won't run in Windows 10 64
bits, I need when I have some time install it on my 32 bit Windows 7
machine, I believe it will run there just fine. The people that bought
Borland (Embarcadero) think too much of themselves and a copy of Delphi
now cost around $1700.

>
> BTW: Lemmings don't actually follow each other over a cliff in a mass-suicide as most people believe:
> http://www.adfg.alaska.gov/index.cfm?adfg=wildlifenews.view_article&articles_id=56
>

I know that but is now means to most people, following the crowd without
thinking to disastrous results, sounds familiar?

--
Cecil - k5nwa

rickman

unread,
May 29, 2017, 2:11:23 AM5/29/17
to
Isn't the Arduino written for AVR processors? Other people may have written
Arduino like libraries, but if the thing being controlled doesn't work the
same way, you can't control it using the same code. I suppose if you
abstract away the hardware differences you can use different hardware the
same way, but at what cost? There are tons of ADCs for example. They
aren't intended for the same tasks and don't have the same functionality.
So there is no library that will utilize them properly without changes in
the calling code.

I guess this is becoming a bit of beating a dead horse.

I will be interested in seeing what Cecil comes up with. :)

--

Rick C

rickman

unread,
May 29, 2017, 2:35:32 AM5/29/17
to
Mark Wills wrote on 5/28/2017 2:49 PM:
> The solution is obvious. Use a Forth processor. No need for an assembler or C or C++ or Go or a cross-compiler or a meta-compiler. The chip *is* Forth.
>
> I don't think you can get much more portable than that.

I don't think such a processor has ever been built. Do you know of one?

--

Rick C

rickman

unread,
May 29, 2017, 2:40:45 AM5/29/17
to
Yeah, that's why I said the numbers reflected the "implementations rather
than the ISAs".


> You can the find outdated spreadsheets at http://opencores.org/project,up_core_list
> Goal was to determine designs with best figure of merit (Fmax/LUT count adjusted for data width and number of clocks per instruction).
> Do not consider the results more accurate than, say, +/-30%

Interesting. I will try to take a look at it. I would have worked on
something like this myself, but there are so many crap cores at opencores
that are poorly documented (nearly all of them) or just plain incomplete. I
don't know how many are clones of some old CPU. I was turned off from
looking at them further. This was maybe 2002-2005 I think. I do remember
as time passed the signal to noise ratio got worse and not better.

--

Rick C

Cecil Bayona

unread,
May 29, 2017, 2:54:12 AM5/29/17
to
The Arduino software platform and its libraries are available for AVR,
MSP430, PIC, dsPIC, PIC 32, MIPS, ARM, and esp8266 that I know off,
there maybe others. They all program the same way.


--
Cecil - k5nwa

rickman

unread,
May 29, 2017, 3:19:07 AM5/29/17
to
It's not exactly a question of wiring. It's a question of access. Even in
a dual ported memory, you can only write to two registers at the same time
and some implementations only let you write to one location at a time (dual
port can be 1 read and 1 write). You can have as many reads at once as you
wish by duplicating the register file RAM. Always write to both, but reads
can be separate and different. Separate writes to different addresses can
be done, but it is complex, very complex.


>> Regardless of how many registers a design has, the real driver of logic
>> usage is usually muxes. You can have one register (top of data stack for
>> example) which is fed by many sources and the mux will end up being huge.
>> I know this from experience... ;)
>>
>> The way to keep your design small and efficient is to focus on the
>> micro-ops required to implement an instruction to keep these interconnects
>> to a minimum.
>>
>
> Since the CPUs that I'm interested in for the most part single clock to
> execute an instruction types then one ends up using an lot of muxes.

Not necessarily. If you design you ISA to use limited data paths
efficiently you don't need a bazillion muxes. Also, if you are designing a
stack machine, consider what you want it to be able to do rather than trying
to emulate the Forth virtual machine. For example, in one of my designs I
push literals onto the return stack. Often literals are addresses. The
return stack was treated as the source of addresses for any memory operation
so the literal was already there and Bob's your uncle. This made address
handling the same for calls, jumps, returns as well as memory variable
access. The return stack could do autoincrement for loop and move
operations. This allowed addresses to not go through the data stack at all
reducing the data paths required.


>>> Using PAC (Portable Assembler Code) mnemonics when moving the code to
>>> another CPU the primitives and other assembler code does not need to be
>>> changed, only the assembler needs to be changed and that would need changes
>>> no matter what scheme one uses, so it is simpler to port using a PAC
>>> assembler. It's not the traditional way where you have to re-write all the
>>> assembly code but times are changing we are not in the 70s anymore.
>>
>> You seem to be laser focused on the idea that rewriting the tool has to be
>> easier than rewriting the code. I don't know of any portable assemblers
>> that work the way you describe. So you will need to write this from scratch.
>
> That is because changing the PAC assembler is a fairly simple task versus
> re-writing all the primitives.

Why is that any more simple than any of the other methods? I think it is
the opposite. You will be using one assembly language for many processes
with diverse instruction sets. That can be very awkward and in the end
inefficient.

I also don't agree it will be in any way more simple. Rewriting the few
primitives will be straightforward being able to take advantage of
similarities in instruction sets without regard to the "common" assembler
instruction set.


> Don't forget that in the conventional way you
> have to do massive changes to the assembler and then you have to rewrite all
> the primitives and associated assembler code.

I don't need to write an assembler at all. For any existing processor an
assembler is provided.


> While using PAC all we need to
> change is the code generated by the assembler and the job is done.

I find it funny that you keep saying how simple it will be to modify the
special "portable assembler" that currently doesn't even exist. This is
*not* an assembler anyway. It is a compiler. You will be writing code in a
language that is not related to the CPU. It will have to be translated to
assembly language for that CPU. This is no different from what Forth
definitions do. If you can write the code in an abstract language, why use
"assembly" at all? Use Forth!


> That is a lot easier than a rewrite of the assembler and all the code words.
> In either case the tools have to be changed there is no getting away from
> that, with PAC the changes are fewer and simpler. In either case one needs
> to change a few specific items having to do with I/O and CPU items like
> writing to Flash so neither has an advantage there.

I don't know why you would write an assembler when one is already available.
I don't know why you feel the portable compiler is any easier to write
than Forth.


>>> I tend to think that this is a superior way to write a Forth that is
>>> efficient and easy to port qualities that with traditional assemble code are
>>> at odds with each other. Mind you no matter what one uses there are some CPU
>>> specific items that need to be update such clock management and I/O but
>>> those need changing with a new CPU no matter what way one uses so it
>>> something to be dealt with.
>>
>> I don't see any advantage at all. Either way you need to generate native
>> code for the processor you are using. One way you recode a few Forth
>> words which gives you native code *and* gives you an opportunity to
>> optimize the code easily. The other way you have existing "portable"
>> assembler code which now has to be translated/compiled to native code by a
>> tool that needs to be rewritten for the target processor. Then if you
>> want optimized code you likely need to rewrite the "portable" assembly code.
>
> That is because I'm laser focused as you mentioned, PAC code can be
> optimized just the same as native code, the assembler generates native code
> its just that the mnemonics are the same for many CPUs so the assembler
> needs fewer changes to it when porting to a new CPU.

You are thinking of a very limited set of processors, ones that are all
similar. But your statement of intent is to support all embedded
processors, including custom ISAs in FPGAs - ones that are *not* so similar
and won't have remotely similar instructions. Not only will your portable
compiler need to change likely you will need to rewrite the source code for
so vastly different machines.


>> I am ready to return to my self-assigned task of documenting Mecrisp on
>> the MSP430. Let me know how your project goes. If you need any advice on
>> FPGA CPUs, I'm happy to lend my experience.
>>
> Not an exciting task but one that needs to be done.

I prefer to do something useful rather than duplicate what others have done.
I tried my hand at designing stack CPUs and found the space to be very
well explored. The effectiveness of the J1 is pretty good for such a simple
processor. My ideas did not produce an appreciably smaller, faster or
easier to use processor. I do have one new idea I have not fleshed out yet.
But I want to do some things with Mecrisp first.

--

Rick C

rickman

unread,
May 29, 2017, 3:22:23 AM5/29/17
to
Really, so you can just take source code for an application and it will run
on any of those processors without modification? Then I guess your job is
done!

--

Rick C

Albert van der Horst

unread,
May 29, 2017, 4:51:49 AM5/29/17
to
In article <ogf71j$5g4$1...@dont-email.me>,
Cecil Bayona <cba...@cbayona.com> wrote:
<SNIP>

<question about the basic approach regards macro's of ciforth>

>> A rather short document (20 pages) contains about 10 pages
>> relevant to this question. cifgenps.zip on the site in my sig.
>> That document is from 2002. It could use an update but it surely
>> gives the correct idea.
>> I.a. I use it for selection (a la [IF] ) and as regular
>> assembler macro's.
>
>You have a lot of links on your site so I was not able to find the link
>to the file. I found it with Google but it's in Postscript so I will
>need to find a reader.

In my Debian Wheezy I need just click on a ps file. I'm not aware that
I needed to install anything.
gv is the official tool for postscript. That surely works.

For a quick look, go to github.com, search for ciforth and look at the
latest version in its unformatted source file (approximate texinfo)
cifgen.mi

If you get ciforth from github your can have the file converted to
pdf or info:
make cifgen.info cifgen.ps cifgen.pdf

Groetjes Albert

>--
>Cecil - k5nwa
--

hughag...@gmail.com

unread,
May 29, 2017, 12:17:12 PM5/29/17
to
On Sunday, May 28, 2017 at 10:52:58 PM UTC-7, Cecil - k5nwa wrote:
> On 5/28/2017 11:48 PM, hughag...@gmail.com wrote:
> > I don't know Delphi, but I did read a book on Pascal-S way back in high-school, that provided source-code for a compiler. This Pascal had nested functions. It also had a "display table" that allowed the parent function's locals to be visible in the nested function when it executed. Pretty complicated! My quotations are much simpler, although not as versatile.
>
> Delphi is Pascal on steroids, an excellent development environment with
> an excellent debugger and tools to deal with Windows, Linux, or MacOS. I
> looked it up and Delphi has both HOFs and quotations. Those were very
> useful and I used them a lot in a BT+ Database library routines, very
> handy passing routines and accessing the parents variables.

I actually bought a copy of Kylix, which is the Linux version of Borland Delphi, when CompUSA was going out of business and they had all those shrink-wrapped boxes of disks and manuals in the bargain-bin for $5. In never used it though. AFAIK, Borland Delphi and Kylix were quite powerful --- everybody spoke well of them. Java became the standard and killed off Pascal and (to a lessor extent) C++. Weirdly enough, everybody speaks ill of Java --- it doesn't have anything like quotations or HOFs. I think languages mostly become popular because they are perceived as being "the next big thing" --- a classic example of being famous for being famous.

Have you tried any of the free versions of Pascal, such as Lazerus? If I do write a Pascal compiler, I should have a Pascal available on the desktop-computer to help me relearn it.

> HOFs I
> believe are possible in Forth with no changes, but would not quotations
> require changes to Forth?
>
> Is there even a standard way of storing locals?

How could you have HOFs without quotations???

I have my rquotations working under VFX and SwiftForth. It should be possible to implement them under any Forth compiler, but carnal knowledge is required. It is just a matter of declaring them to be standard --- then the carnal knowledge is hidden from the user --- same as everything else (for example, division requires carnal knowledge, but that doesn't prevent us from having division in the standard).

The Forth-200x committee will never accept rquotations --- the committe is 100% committed to the Paysan-faked quotations that are utterly useless --- Stephen Pelc wrote an article in which he said that quotations aren't possible in Forth and so they have to be faked (this article was the basis for the Paysan-faked quotations, and the RfD is pretty much just the article copied word-for-word).

> For the 65c816 the chip cost around $7 at Mouser, add some RAM and
> some EPROMs with a small amount of logic and you are in business. That
> chip is very nice comes up in 6502 compatibility mode then you can turn
> the extra features.

If you build a 65c816 experimenter board, you can likely sell it to everybody (including myself) on the 6502 forum. This is not a big market, but it is infinitely larger than zero!

The 65c816 is not the best choice for serious work, because the ARM dominates. It is not a bad choice though --- somebody could build a product based on the 65c816 though, and it would be reasonably competitive --- so the 65c816 shouldn't be totally dismissed as obsolete.

The STM8 is pretty popular for low-performance applications that need a lot of memory, which is also what the 65c816 is used for --- in many cases, waiting a few microseconds for a result is okay --- not every project needs the most powerful processor available, that can bend space-time and provide you with a result before you ask for it.

> The Rabbit is fairly fast for the money some decent ones are $40 to $50
> and all I need is one, the rest is pretty much free, make some changes
> to a Forth compiler and voila a native compiler no expenses involved
> just a little bit of time.

Most of the cost of the Rabbit is there because you get to use Dynamic C that only works on the Rabbit.

If you are not going to use Dynamic C, but are going to write your own Forth, then you would be better off to buy an eZ80 from Zilog that is more powerful and costs less. I have an experimenter board for the eZ80 --- I attended a seminar at Zilog in San Jose and bought it there --- I have never really done anything with the eZ80 though, and it is in the same category as the 65c816 now (pretty much obsolete).

> The people that bought
> Borland (Embarcadero) think too much of themselves and a copy of Delphi
> now cost around $1700.

VFX is also pretty pricey --- I'm not going to buy it either --- this is why Juergen Pintaske says that I "don't understand how the corporate world works" and that I'm a "Forth killer" because I write Forth code and distribute it in the novice-package.

Cecil Bayona

unread,
May 29, 2017, 1:17:03 PM5/29/17
to
On 5/29/2017 11:17 AM, hughag...@gmail.com wrote:
> On Sunday, May 28, 2017 at 10:52:58 PM UTC-7, Cecil - k5nwa wrote:

>> Delphi is Pascal on steroids, an excellent development environment with
>> an excellent debugger and tools to deal with Windows, Linux, or MacOS. I
>> looked it up and Delphi has both HOFs and quotations. Those were very
>> useful and I used them a lot in a BT+ Database library routines, very
>> handy passing routines and accessing the parents variables.
>
> I actually bought a copy of Kylix, which is the Linux version of Borland Delphi, when CompUSA was going out of business and they had all those shrink-wrapped boxes of disks and manuals in the bargain-bin for $5. In never used it though. AFAIK, Borland Delphi and Kylix were quite powerful --- everybody spoke well of them. Java became the standard and killed off Pascal and (to a lessor extent) C++. Weirdly enough, everybody speaks ill of Java --- it doesn't have anything like quotations or HOFs. I think languages mostly become popular because they are perceived as being "the next big thing" --- a classic example of being famous for being famous.
>
> Have you tried any of the free versions of Pascal, such as Lazerus? If I do write a Pascal compiler, I should have a Pascal available on the desktop-computer to help me relearn it.
>

Only for a few small test programs and it worked fine, it emulates an
older version of Delphi but it does install and work in Windows 10 and
Linux. I been told by some that use it on a regular basis that it works
quite well and is very reliable so it might be something in my future,
Pascal unlike C or C++ can have optional run time checks that makes life
easier at catching some type of normally hard to find problems.

I'm building a Linux system on one of my nicest CPUs an i7, 3.4GHz, 24GB
RAM and I installed FreePascal and Lazarus on it, it is part of
evaluating the use of Linux as a everyday/programming platform instead
of Windows, it's a low priority project, a couple of days ago I
installed Go, and the Visual Studio Code software, so far everything is
doing well and the PC is quite fast. I also figured out how to move
VirtualBox and vmWare licensed VMs from Windows to Linux and not loose
the license, I had to do it a little different than what people
suggested but its working rather well.


>> HOFs I
>> believe are possible in Forth with no changes, but would not quotations
>> require changes to Forth?
>>
>> Is there even a standard way of storing locals?
>
> How could you have HOFs without quotations???
>
> I have my rquotations working under VFX and SwiftForth. It should be possible to implement them under any Forth compiler, but carnal knowledge is required. It is just a matter of declaring them to be standard --- then the carnal knowledge is hidden from the user --- same as everything else (for example, division requires carnal knowledge, but that doesn't prevent us from having division in the standard).
>

Maybe I don't understand Forth HOFs then, the term has existed for a
while and Delphi and C have the capability. In the classical sense a HOF
is a function that can have pointers to functions passed to it, it also
has the ability to return pointers to functions. In that sense Forth has
HOFs already, and there is nothing new needed. They are handy is some
types of programs. Classical quotations are functions that defined
inside a function so when executed they have access to their parents
data, both reading and writing. Again a very useful tool. In Delphi the
two are separate items and need not be used together but they often are.

> The Forth-200x committee will never accept rquotations --- the committe is 100% committed to the Paysan-faked quotations that are utterly useless --- Stephen Pelc wrote an article in which he said that quotations aren't possible in Forth and so they have to be faked (this article was the basis for the Paysan-faked quotations, and the RfD is pretty much just the article copied word-for-word).
>

I look at the discussions on the subject and wonder why they want to put
in quotations that don't work, whats the point, in Delphi and other
languages the whole purpose behind quotations it to access or change the
parents data. I think it's another case of 1970 thinking.

>> For the 65c816 the chip cost around $7 at Mouser, add some RAM and
>> some EPROMs with a small amount of logic and you are in business. That
>> chip is very nice comes up in 6502 compatibility mode then you can turn
>> the extra features.
>
> If you build a 65c816 experimenter board, you can likely sell it to everybody (including myself) on the 6502 forum. This is not a big market, but it is infinitely larger than zero!
>
> The 65c816 is not the best choice for serious work, because the ARM dominates. It is not a bad choice though --- somebody could build a product based on the 65c816 though, and it would be reasonably competitive --- so the 65c816 shouldn't be totally dismissed as obsolete.
>
> The STM8 is pretty popular for low-performance applications that need a lot of memory, which is also what the 65c816 is used for --- in many cases, waiting a few microseconds for a result is okay --- not every project needs the most powerful processor available, that can bend space-time and provide you with a result before you ask for it.
>

Its just for fun and a learning experience, the STM8 devices are
interesting you can buy some boards for less than $2 that are quite
useful for small projects.

>> The Rabbit is fairly fast for the money some decent ones are $40 to $50
>> and all I need is one, the rest is pretty much free, make some changes
>> to a Forth compiler and voila a native compiler no expenses involved
>> just a little bit of time.
>
> Most of the cost of the Rabbit is there because you get to use Dynamic C that only works on the Rabbit.
>
> If you are not going to use Dynamic C, but are going to write your own Forth, then you would be better off to buy an eZ80 from Zilog that is more powerful and costs less. I have an experimenter board for the eZ80 --- I attended a seminar at Zilog in San Jose and bought it there --- I have never really done anything with the eZ80 though, and it is in the same category as the 65c816 now (pretty much obsolete).

I have some ez80 boards on my Mouser Project list, one of these days
I'll get one.

>
>> The people that bought
>> Borland (Embarcadero) think too much of themselves and a copy of Delphi
>> now cost around $1700.
>
> VFX is also pretty pricey --- I'm not going to buy it either --- this is why Juergen Pintaske says that I "don't understand how the corporate world works" and that I'm a "Forth killer" because I write Forth code and distribute it in the novice-package.
>

If you are going to eventually write your own Pascal I would look at the
Borland/Lazarus software as models they are very similar, Lazarus source
is available for one to look at for ideas. Lazarus is written in
Lazarus, if you are going to use MPEs VFX to write it that should be an
interesting project, pretty involved.

One thing about doing it that way is the powerful tools built into Forth
that can make your life easier like using their built in code generator
and optimizer but that only works for a Intel CPU version. The easiest
way to build a Pascal compiler is using a recursive decent parser which
naturally generates as it's output RPN code how about that for nicely
generating object code with a Forth Compiler.

I will be spending some time today becoming familiar again with my Macro
Processors and used them to translate PAC code to a real CPU code and
see how well it works, but all of that will take some time, over the
next few days my task will be to familiarize myself with software that
will be an interesting test of my memory which I think is not as good as
it used to be. Unfortunately I have the source code to the software but
not some of the sample projects, that would help me remember me but they
are history. I do have some very old computers in the garage but the
really old ones that would have the software were given away so
hopefully there is an old macro processor project in there somewhere.



--
Cecil - k5nwa

Cecil Bayona

unread,
May 29, 2017, 1:50:53 PM5/29/17
to
You are running Linux, I am running Windows which doesn't have a
PostScript viewer built in like Linux does. Actually Linux has a lot
more tools built in when compared to Windows yet Linux is a lot smaller
that says a lot.

Right now I'm thinking about switching to Linux so I'm building a fast
PC with Linux Mint on it to give Linux a thorough test. The one thing
that keeps holding me back is the money I spent on Windows Licenses and
software, I have a lot of PCs so I hate to waste that money. But at some
point I will be aggravated with Windows enough to dump it on most PCs.

Anyway I installed a viewer and looked at the document, so you are using
M4 as a tool to create a special version of ciforth according to ones
desire. I have used macro processors in the past for a different purpose
and that is to translate software from on language to another, and to
take existing assembler code and optimize it. My oldest macro processor
was capable enough that I wrote a Forth Cross Compiler with it which
generated optimized assembler code.

--
Cecil - k5nwa

Alex

unread,
May 29, 2017, 2:02:28 PM5/29/17
to
On 5/29/2017 17:17, hughag...@gmail.com wrote:
>> HOFs I believe are possible in Forth with no changes, but would not
>> quotations require changes to Forth?
>>
>> Is there even a standard way of storing locals?
> How could you have HOFs without quotations???

I'd like to understand what you mean by HOF (higher order functions) and
why only quotations can provide them, because the answer is, if you're
using the usual meaning of the phrase -- quite easily.

>
> I have my rquotations working under VFX and SwiftForth. It should be
> possible to implement them under any Forth compiler, but carnal
> knowledge is required. It is just a matter of declaring them to be
> standard --- then the carnal knowledge is hidden from the user ---
> same as everything else (for example, division requires carnal
> knowledge, but that doesn't prevent us from having division in the
> standard).

How does division require "carnal knowledge" (that is, knowledge of a
specific system's internals not covered by the standard)?

>
> The Forth-200x committee will never accept rquotations --- the > committe is 100% committed to the Paysan-faked quotations that are
> utterly useless --- Stephen Pelc wrote an article in which he said
> that quotations aren't possible in Forth and so they have to be faked
> (this article was the basis for the Paysan-faked quotations, and the
> RfD is pretty much just the article copied word-for-word).
>

If I remember correctly, the XT your rquotations provided couldn't be
executed outside the runtime scope of the enclosing word.

--
Alex

Raimond Dragomir

unread,
May 29, 2017, 2:06:50 PM5/29/17
to
> Most of the cost of the Rabbit is there because you get to use Dynamic C that only works on the Rabbit.
>
> If you are not going to use Dynamic C, but are going to write your own Forth, then you would be better off to buy an eZ80 from Zilog that is more powerful and costs less. I have an experimenter board for the eZ80 --- I attended a seminar at Zilog in San Jose and bought it there --- I have never really done anything with the eZ80 though, and it is in the same category as the 65c816 now (pretty much obsolete).

eZ80 is pretty much dead, rabbit is not so yet. Digi has some really good
and modern modules based on rabbit6000. Especially if you want ethernet
and tcp/ip. Dynamic C is not standard and quite low quality in today
stadards but can be just the tool for the job.

Rabbit was always more popular than the eZ80. I used rabbit2000 quite a lot,
in the mid 2000. I still have over 200 devices in the field with the
rabbits. I was first exposed to forth due to rabbit, I was searching for
Dynamic C alternatives and I found a port of a Z80 DTC eForth. I even
done a real application in it, almost completely, and quite a big one.
But at some point I realized that something is missing in my toolbox,
and I had two variants: a PC application to deal with the source downloading
(or a kind of an umbillical link) or a cross-compiler. Both was beyond
my capabilities at that time and i give up. I made the application in
Dynamic C, but my style was influenced by the forth experience.


Alex

unread,
May 29, 2017, 2:06:53 PM5/29/17
to
On 5/29/2017 18:50, Cecil Bayona wrote:
> You are running Linux, I am running Windows which doesn't have a
> PostScript viewer built in like Linux does. Actually Linux has a lot
> more tools built in when compared to Windows yet Linux is a lot smaller
> that says a lot.

Windows 10 Edge provides the default PDF viewer; it's part of the
distribution (built in in your parlance).

--
Alex

jim.bra...@ieee.org

unread,
May 29, 2017, 4:10:37 PM5/29/17
to
]>there are so many crap cores at opencores that are poorly documented

About 400 microprocessor cores at opencores or elsewhere on the web
About 200 or so give reasonable results.
Anything with less than 16 instructions is usually too simple to be useful
Only about 40 written to run without modifications on any FPGA family
Most of the time, a design will run on Altera or Xilinx and not both
Have found about 70 Forth cores and only have results on ~20

BTW
It took several months to make all the runs.
Don't relish repeating the effort.
It would be much easier if each design had complete project files:(

Paul Rubin

unread,
May 29, 2017, 4:59:10 PM5/29/17
to
Cecil Bayona <cba...@cbayona.com> writes:
> Borland made Turbo Pascal and other Turbo products like Turbo C and
> Turbo Prolog... won't run in Windows 10 64 bits

There's a free download of Turbo Pascal 5.5 that will probably
run on a DOS emulator:

http://edn.embarcadero.com/article/20803

James Hague wrote a famous comparison of code size between Turbo Pascal
and newer software:

http://prog21.dadgum.com/116.html

I've been wanting to try Turbo Pascal sometime.

Cecil Bayona

unread,
May 29, 2017, 6:03:19 PM5/29/17
to
You can get a free copy now of Delphi 7 which is for Windows, and you
can also a free version of the current software Delphi 10.2 for Windows,
or Linux but there are massive changes to the interface that makes it
totally different from Delphi 7 which I liked a lot.

--
Cecil - k5nwa

hughag...@gmail.com

unread,
May 29, 2017, 10:21:44 PM5/29/17
to
On Monday, May 29, 2017 at 10:17:03 AM UTC-7, Cecil - k5nwa wrote:
> On 5/29/2017 11:17 AM, hughag...@gmail.com wrote:
> >> HOFs I
> >> believe are possible in Forth with no changes, but would not quotations
> >> require changes to Forth?
> >>
> >> Is there even a standard way of storing locals?
> >
> > How could you have HOFs without quotations???
> >
> > I have my rquotations working under VFX and SwiftForth. It should be possible to implement them under any Forth compiler, but carnal knowledge is required. It is just a matter of declaring them to be standard --- then the carnal knowledge is hidden from the user --- same as everything else (for example, division requires carnal knowledge, but that doesn't prevent us from having division in the standard).
>
> Maybe I don't understand Forth HOFs then, the term has existed for a
> while and Delphi and C have the capability. In the classical sense a HOF
> is a function that can have pointers to functions passed to it, it also
> has the ability to return pointers to functions. In that sense Forth has
> HOFs already, and there is nothing new needed. They are handy is some
> types of programs. Classical quotations are functions that defined
> inside a function so when executed they have access to their parents
> data, both reading and writing. Again a very useful tool. In Delphi the
> two are separate items and need not be used together but they often are.

Yes, Forth has always had the ability to pass an XT into function, and that function is a HOF. I do this a lot in the novice-package, but the XT is just a pseudo-quotation because it is just an ordinary colon word or :NONAME word. The Paysan-faked quotations are also pseudo-quotations because they are just :NONAME words with some syntactic sugar.

So, I was incorrect to say that you can't have HOFs without quotations --- you can have HOFs with pseudo-quotations too --- they are a lot more useful with real quotations though (quotations that can access the parent function's local variables).

Note that my rquotations are neither real quotations nor pseudo-quotations --- lets call them realish quotations! They are significantly more useful than pseudo-quotations because they do have access to the parent function's local variables. They do have some limitations though:

1.) They aren't XT values, so they aren't known at compile-time (mostly this means that they can't be used with <SWITCH structures).

2.) The HOF called by the parent function has to have local variables, and it has to execute the rquotation (it can't call another function that has local variables and that function executes the rquotation).

For the most part, these limitations are not a problem. Not being known at compile-time (#1 above) is a minor problem because <SWITCH has to use :NONAME words that can't share local variables, but have to use global variables to communicate with each other. This is somewhat clunky, but not a big problem. I'm writing a simulator for the 65c02 right now, and it won't be reentrant. This would be a problem if you wanted to simulate more than one 65c02 at the same time, but this is somewhat unlikely. Also, there are ways to work around this problem anyway --- it is just somewhat clunky. As for #2 above, I can't think of any case in which this would be a problem.

All in all, rquotations do everything that I really need --- just for the sake of purity, I would rather have real quotations rather than realish quotations --- but the realish ones are, from a practical standpoint, adequate. By comparison, the Paysan-faked quotations are worse than useless --- I say "worse than useless" because they pretend to be quotations when they are just pseudo-quotations --- they give the Forth community the reputation of being liars who fake language features that they are too dumb to implement.

> > The Forth-200x committee will never accept rquotations --- the committe is 100% committed to the Paysan-faked quotations that are utterly useless --- Stephen Pelc wrote an article in which he said that quotations aren't possible in Forth and so they have to be faked (this article was the basis for the Paysan-faked quotations, and the RfD is pretty much just the article copied word-for-word).
>
> I look at the discussions on the subject and wonder why they want to put
> in quotations that don't work, whats the point, in Delphi and other
> languages the whole purpose behind quotations it to access or change the
> parents data. I think it's another case of 1970 thinking.

They committed themselves to the Paysan-faked quotations because they didn't know how to do rquotations --- if they had thought of rquotations, they would have done that instead --- but now that I have thought of rquotations, they aren't going to accept rquotations, but will instead remain steadfast on the Paysan-faked quotations.

This is human-nature --- the Forth-200x committee can't admit that they were wrong --- they can't admit that somebody else (myself and HumptyDumpty) can figure things out that they are too dumb to figure out (because they are the "leading experts" of Forth and are hence superior to all other Forth programmers, or so they claim).

The Forth-200x committee complain that this is a thankless job --- that is because they are screwing it up, and then white-washing their screw-ups --- if they did a better job, they might get thanked!

hughag...@gmail.com

unread,
May 29, 2017, 10:29:41 PM5/29/17
to
The 65c816 would be a more interesting target for Forth than the eZ80 --- both are pretty challenging as they are both funky non-orthogonal architectures --- but the 65c816, I think, is a better design.

The 65c816 is also low-power and, I think, a better choice as a micro-controller. The 65c816 is an off-beat choice --- it is like Forth in that it isn't something you would want to mention on your resume --- but it is reasonable in many cases, and would be pretty fun.

hughag...@gmail.com

unread,
May 29, 2017, 10:37:07 PM5/29/17
to
Well, if you use the word lemming incorrectly, just because you are following the crowd who use the word lemming incorrectly, then that would make you a lemming!

But, wait --- if I say that you are a lemming because you use the word lemming incorrectly, then I am using the word lemming incorrectly too, and this makes me a lemming as well (assuming the incorrect usage of the word lemming).

If lemmings could talk, what would they use the word "human" to mean?

Cecil Bayona

unread,
May 29, 2017, 11:52:48 PM5/29/17
to
A bunch of crazy animals that often don't think and follow others to bad
consequences.


--
Cecil - k5nwa

Cecil Bayona

unread,
May 30, 2017, 12:01:06 AM5/30/17
to
On 5/29/2017 9:29 PM, hughag...@gmail.com wrote:

> The 65c816 would be a more interesting target for Forth than the eZ80 --- both are pretty challenging as they are both funky non-orthogonal architectures --- but the 65c816, I think, is a better design.
>
> The 65c816 is also low-power and, I think, a better choice as a micro-controller. The 65c816 is an off-beat choice --- it is like Forth in that it isn't something you would want to mention on your resume --- but it is reasonable in many cases, and would be pretty fun.
>
In the early days of microprocessors I did not get to work with the 6502
CPUs very much, a mistake but I want to fix it, there were other weird
CPUs and I played with them some but I want to try it, slow clock at the
time but most instructions did not take many clocks. Most of my early
work with micros were with the Intel and Motorola families I really
liked the MC6809 and the MC68000.

--
Cecil - k5nwa

Cecil Bayona

unread,
May 30, 2017, 12:13:31 AM5/30/17
to
I have not read on it but how are ANS locals implemented?

Once I implemented locals in a very poor way I think, I created a word
that allocated a buffer area, then the local creating word would
allocate space from that area but at runtime it would calculate the
address of the variable and fetch it or store data for you. Did think
much about it but I was doing an application and the stack data was
getting out of hand hard to keep track and get to the data so I had
named variables that were easy to use, it worked. If I used the user
area as the buffer they were global variables, if I used a private
buffer then they were local to the word that created them. It was a
little more complex than that but they did the trick.


--
Cecil - k5nwa

rickman

unread,
May 30, 2017, 12:57:40 AM5/30/17
to
I feel your pain.

--

Rick C

Paul Rubin

unread,
May 30, 2017, 4:07:38 AM5/30/17
to
Cecil Bayona <cba...@cbayona.com> writes:
> I have not read on it but how are ANS locals implemented?

I don't think they prescribe an implementation technique, but the usual
approaches are put them in the return stack (maybe with a frame
pointer), or put them in a separate locals stack. Either way you need a
temporary wordlist, and stuff to clean it all up on returning from the
function or if something throws an exception.

Andrew Haley

unread,
May 30, 2017, 5:23:04 AM5/30/17
to
Cecil Bayona <cba...@cbayona.com> wrote:
>>
> I'm not familiar with programming under Linux which I assume you use, I
> currently use Windows and in Windows there has been a concerted effort
> to turn the Intel CPU into a Harvard CPU byt putting more and more
> limits on how the software can be written.
>
> Code cannot be executed out of the data space, and the code space is
> protected from changes is the direction they are heading in, they
> already mentioned that that is direction they are head for and soon it
> will not be optional right now it's optional.
>
> Under that scenario Forth will not be able to extend itself in the code
> area, and the data area cannot contain code so that leaves Forth in a
> hard place.

Microsoft's very own CLR depends on the ability to generate code on
the fly and to patch it as it runs, so this ability is not going away
any time soon. Plenty of other language runtimes (Java, Javascript,
etc.) need to do this too.

Andrew.

Albert van der Horst

unread,
May 30, 2017, 5:49:14 AM5/30/17
to
In article <YradnReRhdNvpLDE...@supernews.com>,
I'm presenting ciforth to Debian. They are definitely a bit upset
to see a program that has one section that is readable, writable and
executable. Tools get upset too. ( In wheezy `strip' strips lina
to nothing.) In one of the reactions it was mentioned that googles
`go' does something similar, so that wouldn't not block admission
of ciforth as a Debian package.

>
>Andrew.

Groetjes Albert

Andrew Haley

unread,
May 30, 2017, 6:07:45 AM5/30/17
to
Albert van der Horst <alb...@cherry.spenarnc.xs4all.nl> wrote:
>>
>>Microsoft's very own CLR depends on the ability to generate code on
>>the fly and to patch it as it runs, so this ability is not going away
>>any time soon. Plenty of other language runtimes (Java, Javascript,
>>etc.) need to do this too.
>
> I'm presenting ciforth to Debian. They are definitely a bit upset
> to see a program that has one section that is readable, writable and
> executable.

Is that really necessary? I would have thought to you allocate that
at startup.

> Tools get upset too. ( In wheezy `strip' strips lina to nothing.)

Wow. Either that's a serious bug or there is something very wrong
with the lina binary. One way or other it must be a bug.

> In one of the reactions it was mentioned that googles `go' does
> something similar, so that wouldn't not block admission of ciforth
> as a Debian package.

Indeed not. Really, this anti-JIT attitude from the OS distros is
getting to be tiresome.

Andrew.

Alex

unread,
May 30, 2017, 10:54:31 AM5/30/17
to
On 5/30/2017 03:21, hughag...@gmail.com wrote:
> On Monday, May 29, 2017 at 10:17:03 AM UTC-7, Cecil - k5nwa wrote:
>> On 5/29/2017 11:17 AM, hughag...@gmail.com wrote:

>
> Yes, Forth has always had the ability to pass an XT into function,
> and that function is a HOF. I do this a lot in the novice-package,
> but the XT is just a pseudo-quotation because it is just an ordinary
> colon word or :NONAME word. The Paysan-faked quotations are also
> pseudo-quotations because they are just :NONAME words with some
> syntactic sugar.
>
> So, I was incorrect to say that you can't have HOFs without
> quotations

That's a welcome start.

>
> Note that my rquotations are neither real quotations nor
> pseudo-quotations --- lets call them realish quotations! They are
> significantly more useful than pseudo-quotations because they do have
> access to the parent function's local variables. They do have some
> limitations though:
>
> 1.) They aren't XT values, so they aren't known at compile-time
> (mostly this means that they can't be used with <SWITCH structures).

If they're not XTs, what are they? The can be executed, and the only
thing you can execute is an XT.

>
> 2.) The HOF called by the parent function has to have local
> variables, and it has to execute the rquotation (it can't call
> another function that has local variables and that function executes
> the rquotation).
>
> For the most part, these limitations are not a problem.

Well, a library of functions like this would be a minefield.

>
> All in all, rquotations do everything that I really need --- just for
> the sake of purity, I would rather have real quotations rather than
> realish quotations --- but the realish ones are, from a practical
> standpoint, adequate.

I think what you mean is a closure. It's a perfectly serviceable word
and saves you from making up phrases like "real quotations".

> By comparison, the Paysan-faked quotations are
> worse than useless --- I say "worse than useless" because they

[ and it's off piste on the ski slope of insanity again ]


--
Alex

Lars Brinkhoff

unread,
May 30, 2017, 12:58:02 PM5/30/17
to
Andrew Haley wrote:
> Albert van der Horst wrote:
>> Tools get upset too. ( In wheezy `strip' strips lina to nothing.)
>
> Wow. Either that's a serious bug or there is something very wrong
> with the lina binary.

Strip also does something damaging to my Forth image files. But I
suppose I have myself to blame. Here's what readelf -a says:

[ELF Header looks ok]

There are no sections in this file.

There are no sections to group in this file.

Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0x029e8 0x16468 RWE 0x1000

There is no dynamic section in this file.

There are no relocations in this file.

Dynamic symbol information is not available for displaying symbols.

No version information found in this file.

hughag...@gmail.com

unread,
May 30, 2017, 5:53:53 PM5/30/17
to
Over on the 6502 forum there are several people who have written Forth compilers for the 65c02 or 65c816. This is the only forum I know of where Forth is discussed seriously (I don't really count comp.lang.forth because it is mostly about ANS-Forth and Forth-200x). There is a lot of enthusiasm for Forth on the 65c816 on the 6502 forum. I'm the only one who is enthusiastic for Forth on the 65c02 though, as most of the guys decided a long time ago that the 65c816 with its 16-bit registers was better for Forth. They are interested in the 65c02, of course, but they seem to mostly be interested in assembly-language on it --- nothing wrong with that!

If you liked the MC68000, why don't you just upgrade to the ColdFire?

The 65c816 and eZ80 are both quirky non-orthogonal 8-bit processors with a 24-bit address bus --- 20th century technology --- the 21st century is all about 32-bit micro-controllers!

Cecil Bayona

unread,
Jun 1, 2017, 12:27:50 PM6/1/17
to
On 5/28/2017 8:25 PM, hughag...@gmail.com wrote:
> On Sunday, May 28, 2017 at 2:45:19 PM UTC-7, hughag...@gmail.com wrote:
>> On Sunday, May 28, 2017 at 9:22:57 AM UTC-7, Cecil - k5nwa wrote:
>>> On 5/28/2017 12:10 AM, hughag...@gmail.com wrote:
>>>> I just came up with this for a PDP11 STC off the top of my head, but it seems like it might work:
>>>>
>>>> R0 general-purpose
>>>> R1 general-purpose
>>>> R2 top-of-stack
>>>> R3 local-frame pointer
>>>> R4 data-stack pointer
>>>> R5 double-stack pointer
>>>> R6 return-stack pointer
>>>> R7 program counter
>>> ...
>>> Thanks for reminding me about PAC (Portable Assembler Code), it changes
>>> the whole trajectory of the project, if PAC can generate efficient code
>>> then it would be an ideal setup for this and other projects. In any case
>>> it is bound to be faster than using C.
>> ...
>> The MSP430 has 16 registers total. I would still use the PDP11 as your assembly-language as I described above. You can, however, have the main-program use some of the registers, and ISRs use the other registers. This means that ISRs don't have to save and restore registers (assuming that ISRs can't be interrupted). This should boost the speed of your system considerably, as a lot of micro-controller programs spend up to 50% of their time servicing interrupts. You will have to write your compiler in such a way that it is able to use the correct set of registers as R0..R7 depending upon whether it is compiling a colon word to be used in the main-program or is compiling an ISR. This should be easy. Put the functions that can be used by the main-program in one vocabulary and the functions that can be used by ISRs in another vocabulary, so there is no confusion if they have the same names.
>
> The more that I think about it, the more I like the PDP11 as your portable-assembly-language.
>
> 1.) The 8 registers of the PDP11 are adequate for a reasonable Forth implementation (as shown above in the register-dedication table I provided). You do have two general-purpose registers, so you can do code-optimization in which you hold values in general-purpose registers temporarily rather than push them to the data-stack (VFX does code optimization on the 32-bit x86 that has only one more register than the PDP11 has).
>
> 2.) On modern processors that have 16 registers (such as the MSP430), you can divide the registers into two banks for the main-program and the ISRs to significantly speed up ISRs while still allowing ISRs to be written in Forth. Your ISRs can't be interrupted though, because there is only one bank of registers available. On the PIC24 you can also have fast ISRs written in assembly-language that only use the lower four registers and are able to interrupt the lower-priority ISRs that are written in Forth.
>
> 3.) There are HDL implementations of the PDP11 already available, so if you want an FPGA you can use one of these as a starting point. Considering that you (and I) have little or no experience with HDL, it seems more realistic to start with an existing implementation rather than start from scratch.
>
> 4.) There is software available for the PDP11, such as RT11, that could still be useful. Your assembler should be compatible with whatever assembler was used to assemble the RT11 code, except that your assembler generates code for the MSP430, PIC24, etc.. So, if the source-code to RT11 is available (I assume it is), you could run RT11 on an MSP430 or PIC24 or whatever. It will be just like a George Romero movie: the dead will rise and walk again!
>

I downloaded some PDP11 programming manuals and read them over several
days and come to the conclusion the the PDP11 is not a good choice
because is has features that a lot of modern 16 bit device do not
possess mostly in the area of addressing modes, but also unique
instructions.

The process also impressed me why I used to love the PDP11 when I first
started working with computers, my first computer I worked with was the
PDP8e and the PDP11 was such a refreshing improvement, now the 64KB
direct addressing limit is a pain.

Right off the bat on the PDP11 all registers are equal so any register
has all addressing modes, that is inefficient to implement in modern
CPUs. The PDP11 also has independent addressing for each of two operands
so for example an ADD instruction can have both sources to use indexed
modes for the data for memory to memory operation while most modern
CPUs uses a register as one of the sources/destination and the other one
can be indexed but not both so in some cases it takes two instructions
to do the same as one PDP11 instruction, not the end of the world but it
makes things more complicated.

So the choices are;

1, To map one instruction to many in some cases and use the PDP11
instruction set.
2. Use a more limited CPU like the MSP430 as a guide to the instructions
instead.
3. Just invent my own mnemonics like the Go language that maps closely
to existing CPUs.
4. Just plain create the primitives in native assembler like it's always
been done.

I still see an advantage to use a PAC (1-3) coding as a lot of code
written in it is easily portable to other 16 bit CPUs.

More reading and comparing is required so I will play some more with the
PDP11 to modern CPU instruct instruction mapping to see how practical it
all is.

This whole project is getting more complicated and messy than
anticipated, such is life.

--
Cecil - k5nwa

rickman

unread,
Jun 1, 2017, 12:50:28 PM6/1/17
to
How is this distinguished from writing words in Forth?


> 4. Just plain create the primitives in native assembler like it's always
> been done.
>
> I still see an advantage to use a PAC (1-3) coding as a lot of code written
> in it is easily portable to other 16 bit CPUs.
>
> More reading and comparing is required so I will play some more with the
> PDP11 to modern CPU instruct instruction mapping to see how practical it all
> is.
>
> This whole project is getting more complicated and messy than anticipated,
> such is life.

What a surprise!

--

Rick C

Cecil Bayona

unread,
Jun 1, 2017, 1:47:45 PM6/1/17
to
At some point the Forth is created by creating set of primitives word,
one creates Forth primitives from assembler or High level language. Even
a Meta compiler at some level needs words written in assembler.

>
>
>> 4. Just plain create the primitives in native assembler like it's always
>> been done.
>>
>> I still see an advantage to use a PAC (1-3) coding as a lot of code
>> written
>> in it is easily portable to other 16 bit CPUs.
>>
>> More reading and comparing is required so I will play some more with the
>> PDP11 to modern CPU instruct instruction mapping to see how practical
>> it all
>> is.
>>
>> This whole project is getting more complicated and messy than
>> anticipated,
>> such is life.
>
> What a surprise!
>

Have you created your own Forth from scratch before? If you have not
then having an assembler doesn't make any sense it's vital create a
Forth written mostly in Forth.


--
Cecil - k5nwa

hughag...@gmail.com

unread,
Jun 1, 2017, 3:08:02 PM6/1/17
to
On Thursday, June 1, 2017 at 9:27:50 AM UTC-7, Cecil - k5nwa wrote:
> On 5/28/2017 8:25 PM, hughag...@gmail.com wrote:
> > On Sunday, May 28, 2017 at 2:45:19 PM UTC-7, hughag...@gmail.com wrote:
> >> On Sunday, May 28, 2017 at 9:22:57 AM UTC-7, Cecil - k5nwa wrote:
> >>> On 5/28/2017 12:10 AM, hughag...@gmail.com wrote:
> >>>> I just came up with this for a PDP11 STC off the top of my head, but it seems like it might work:
> >>>>
> >>>> R0 general-purpose
> >>>> R1 general-purpose
> >>>> R2 top-of-stack
> >>>> R3 local-frame pointer
> >>>> R4 data-stack pointer
> >>>> R5 double-stack pointer
> >>>> R6 return-stack pointer
> >>>> R7 program counter
> ...
> I downloaded some PDP11 programming manuals and read them over several
> days and come to the conclusion the the PDP11 is not a good choice
> because is has features that a lot of modern 16 bit device do not
> possess mostly in the area of addressing modes, but also unique
> instructions.
> ...
> Right off the bat on the PDP11 all registers are equal so any register
> has all addressing modes, that is inefficient to implement in modern
> CPUs. The PDP11 also has independent addressing for each of two operands
> so for example an ADD instruction can have both sources to use indexed
> modes for the data for memory to memory operation while most modern
> CPUs uses a register as one of the sources/destination and the other one
> can be indexed but not both so in some cases it takes two instructions
> to do the same as one PDP11 instruction, not the end of the world but it
> makes things more complicated.

The PDP11 is over-generalized, as you say. This is why most of the 1980s processors (6502, Z80, 8086) used non-orthogonal designs. The MC68000 was the cleanest design of that era --- I always thought of the 68K as a PDP11 upgrade.

Just write your Forth system in PDP11 assembly-language, then afterward take note as to how you only used some of the features of the PDP11. Call this: PDP11GP --- that's 'GP' as in "good parts" --- this will be your portable-assembly-language!

If you don't support the entire PDP11 instruction-set, then you can't run legacy PDP11 assembly-language programs (such as RT11) --- this may not be a concern anyway --- that is 1970s technology, so who cares?

There are some cases in which two or more instructions are needed on the PDP11 for what one instruction would do on a modern processor. In this case, go ahead and add the new instruction to you PDP11GP assembler. You can still run your Forth on a PDP11 soft-core in an FPGA, but you will have to have your PDP11 version of the assembler generate the multiple instructions for the new instruction (treat it as a macro) --- alternatively, you could upgrade the HDL for the PDP11 soft-core to support your new instruction.

The PDP11 is more of a loose framework to build on --- you can take away or add instructions as needed --- it is just a starting-point for the portable-assembler.

> This whole project is getting more complicated and messy than
> anticipated, such is life.

I don't think it is that complicated and messy. Everything seems complicated and messy when it is in your head --- write down a design and begin writing code --- that usually sweeps away the messiness.

I've been meaning to do this project myself, but have been distracted by other things (such is life). It is difficult to build up any enthusiasm for Forth innovation because ANS-Forth is the standard --- the purpose of ANS-Forth is to denounce all Forth innovation as being non-standard and meaningless --- the Forth-200x committee will do everything in their power to discredit a portable-assembler project because they hate the idea of portable Forth programs, and their goal is to trap the Forth community in vendor lock-in. The Forth-200x committee are the #1 enemy of Forth!
It is loading more messages.
0 new messages