6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun May 05, 2024 3:07 pm

All times are UTC




Post new topic Reply to topic  [ 264 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7 ... 18  Next
Author Message
PostPosted: Sat Jan 24, 2015 8:42 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3352
Location: Ontario, Canada
The behaviors of the 'C02 NOPs certainly do seem enigmatic. I puzzled over the matter for quite a while before hitting on a plausible back story. If we were flies on the wall back when the 'C02 was on the drawing board, here's roughly what I think we would've heard:

    "What are we gonna do about undefined opcodes? On the NMOS 6502 they had bizarre behaviors but folks managed to find a use for them anyway. Now they're an impediment to progress because there's a market segment that won't buy new chips unless the old behavior is preserved! Let's show more foresight than the NMOS team did. With the 'C02, let's make all the undefined opcodes into NOPs."

    "Yikes! That could entail a lot of changes! Do they have to be "genuine" NOPs in the sense of doing absolutely nothing except wasting time and advancing the PC?"

    "No. The goal is merely to remove motivation for using them. So it's alright to allow some of the undefined ops to inherit similarities to normal ops -- such as doing a memory access. As long as nothing gets written to the registers, flags or to memory then we can say they're NOPs and no-one will have a reason to use them."


Here's a speculation I don't find plausible. Some of the NMOS undefined opcodes have side effects such as crashing the CPU and requiring a reset. I've heard it suggested that rendering all undefined opcodes as NOPs would remedy this because NOPs execute harmlessly. But that's flawed thinking. Your program shouldn't be fetching anything unexpected in the first place! :roll: If the PC has gotten fouled up so as to point someplace inappropriate then you might as well hit reset anyway, since cogent results can't be expected.

MichaelM wrote:
Note: my processor core can support these behaviors with some minor updates to the microprogram
Interesting. The 'C02 design team wanted the undefined ops to be useless, but $DC and $FC turned out to be even better than the legitimate opcode $2C (BIT absolute) for the trick of skipping two bytes of code. And $02, $22, $42, $62, $82, $C2, and $E2 turned out to be useful for skipping over one byte of code. Michael, now you face a dilemma like that faced by the 'C02 design team! Will you choose to support the unorthodox usages or will you suppress them? :)

-- Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 24, 2015 9:24 pm 
Offline
User avatar

Joined: Mon Apr 23, 2012 12:28 am
Posts: 760
Location: Huntsville, AL
Dr Jeffyll wrote:
MichaelM wrote:
Note: my processor core can support these behaviors with some minor updates to the microprogram

Interesting. The 'C02 design team wanted the undefined ops to be useless, but $DC and $FC turned out to be even better than the legitimate opcode $2C (BIT absolute) for the trick of skipping two bytes of code. And $02, $22, $42, $62, $82, $C2, and $E2 turned out to be useful for skipping over one byte of code. Michael, now you face a dilemma like that faced by the 'C02 design team! Will you choose to support the unorthodox usages or will you suppress them? :)

As I am moving toward completion of my second core, there are no free opcodes left with which to support the "unorthodox" behaviors. Therefore, I will avoid that dilemma altogether. :)

I prefer to leave those changes to others. Personally, I have an aversion to those types of side effects. I can understand how they came about in both the 6502 and 65C02, but with today's design tools, I can't understand why anyone would implement those type of side effects.

_________________
Michael A.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 26, 2015 6:42 am 
Offline

Joined: Mon Jan 26, 2015 6:19 am
Posts: 85
This is fascinating. I thought I was the only person still working on a new version of FORTH for the 6502 (in my case for the Commodore 64). I named my version DCFORTH64. It still needs an editor and file I/O before it can be useful but it has so far met all my expectations and the assembler works remarkably well.

Like Tali Forth, DCFORTH64 is a STC language. The main difference is that my version has separate name, data and code spaces (user programmable). This makes it relatively easy to write "stand alone" programs (ones that don't need the forth interpreter). You can even write ROMmable code.

One of the nicest features of STC coding is that you can switch between compiler mode and assembly mode at will. You can even write macros that lay down assembly code in either mode.

For example, : DROP, INX, INX, ; IMMEDIATE will code the DROP, instruction inline instead of coding a subroutine call to the DROP instruction.

In the interests of speed, every time a word pushes a number on the stack, assembly language instructions are compiled in line - regardless of whether the word is a CONSTANT, VARIABLE, S" or part of an instruction in another word. You can always save space with commonly used numbers by doing things like 5 CONSTANT 5.

I don't know if anybody is interested in the code I have written so far. It might be interesting to compare notes between these two versions.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 26, 2015 7:24 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8432
Location: Southern California
Quote:
One of the nicest features of STC coding is that you can switch between compiler mode and assembly mode at will. You can even write macros that lay down assembly code in either mode.

I do that in ITC Forth, started from this topic, but there's some overhead in ITC of course. And probably any Forth assembler, being Forth, can naturally do macros very easily. STC is not necessary (although I would like to write an STC 6502 Forth if time were no object).

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 26, 2015 8:23 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10797
Location: England
Welcome to our world, theGSman!


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 26, 2015 12:02 pm 
Offline

Joined: Mon Jan 26, 2015 6:19 am
Posts: 85
BigEd wrote:
Welcome to our world, theGSman!

Thanks.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 26, 2015 7:30 pm 
Offline

Joined: Mon Jan 07, 2013 2:42 pm
Posts: 576
Location: Just outside Berlin, Germany
Hello theGSman, and welcome. A fellow STC soul :D !
Quote:
I don't know if anybody is interested in the code I have written so far. It might be interesting to compare notes between these two versions.
I'd love to see the code. You might have seen that Tali is hosted on GitHub (https://github.com/scotws/TaliForth), with three more words to go before I call it BETA -- ?DO, LEAVE, and RECURSE (though LEAVE is turning out to be a nightmare, I might have to rewrite a bunch of LOOP stuff). Is yours more ANS Forth or a FIG Forth?

STC stuff is pretty rare, unfortunately. Give us a bit, though, and it looks like we'll be changing that :D .


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 27, 2015 2:23 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1928
Location: Sacramento, CA, USA
Hey Scot. Could you explain how your unloop works? I can't make heads or tails of it, but it looks like it would always have to be in-lined to have much chance to work properly in an STC context.
Code:
a_unloop:       ; drop top two entries off the Return Stack
                pla
                pla
                pla
                pla

z_unloop:       rts


Would you like for me to keep crunching your source for your approval? I don't mind, but my spare time is a bit limited, so it could be a while between updates.

Mike B.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 27, 2015 3:45 am 
Offline

Joined: Mon Jan 26, 2015 6:19 am
Posts: 85
scotws wrote:
Is yours more ANS Forth or a FIG Forth?

The words are based on the Forth-83 standard (I learned a lot from Leo Brodie) but "under the hood" is radically different (obviously). One consequence of separating the code and data spaces is that defining words like HERE and , (comma) become problematic since they could refer to either code or data. My brilliantly clever solution is to leave it up to the user to code these however he wishes :D. The CP, DP and NP variables are all available for the user to examine and change at will.

I haven't figured out how to make LEAVE work in my version and I am not making that a priority. In my experience, if you don't intend to run a counted loop in its entirety then you are better off using a WHILE loop and not relying on the ability of your compiler/interpreter to bail you out (minimizes portability issues). Unfortunately, EXITing a word from the middle of of the counted LOOP is also problematic although R>DROP EXIT will work for a singly nested loop.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 27, 2015 4:37 pm 
Offline

Joined: Mon Jan 07, 2013 2:42 pm
Posts: 576
Location: Just outside Berlin, Germany
barrym95838 wrote:
Could you explain how your unloop works?
It basically just takes the two loop parameters off the Return Stack. Since A is not conserved between words, that's all it should take. Note I use the "fudged" loop control for the ANS Forth version of DO/LOOP (so 0 0 DO loop through the whole number space) with the V-flag, so it's not comparable to the FIG versions.

However, LEAVE is not working at all at the moment, so I might have to rewrite the loop stuff anyway. If you see somebody banging his head in frustration against the side of a subway train on Berlin public transport these days, that would be me ...
Quote:
Would you like for me to keep crunching your source for your approval? I don't mind, but my spare time is a bit limited, so it could be a while between updates.

I'd be most grateful for any time you might have to spare, whenever, and no worries about the time. There is enough stuff in my life that is on the clock, so all this isn't, by design :D . Thanks again!


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 27, 2015 9:06 pm 
Offline

Joined: Mon Jan 26, 2015 6:19 am
Posts: 85
scotws wrote:
If you see somebody banging his head in frustration against the side of a subway train on Berlin public transport these days, that would be me ...!

LOL That doesn't surprise me.

When I first tackled LEAVE I thought, "no problem, just set the loop counter equal to the loop limit and skip over the remainder of the DO loop". Then the questions came:
- LOOP will have to behave differently if there was a LEAVE statement - how do I let LOOP know?
- What if there is more than one LEAVE statement within the loop?
- What if LEAVE was inserted into nested IF statements?
- etc

I soon realized that coding for these contingencies meant that I was planning for a situation that goes far away from the FORTH philosophy that words should be simple. I could have stipulated a bunch of caveats that would have to apply before you could use a LEAVE statement but decided that leaving the LEAVE statement out altogether was a way of enforcing a stricter discipline on my programming style.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 27, 2015 10:09 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8432
Location: Southern California
I haven't tried it in STC, but leave (the internal compiled by LEAVE) for 6502 ITC Forth is just:
Code:
leave:  PLA
        PLA
        PLA
        PLA

        PLA
        STA  IP
        PLA
        STA  IP+1

        JMP  NEXT
 ;-------------------

LEAVE which compiles it is just:
Code:
: LEAVE   ?COMP   COMPILE leave   ;  IMMEDIATE

You can have as many LEAVEs as you want in a loop.  LEAVE does not affect DO, ?DO, LOOP, or +LOOP.  The LEAVEs can be inside another structure too, as long as it's not another loop (since that would put more things on the return stack), and don't put LEAVE between >R and R>.  I do like to have however ?LEAVE which is just IF LEAVE THEN (but I do it as a primitive, and it's only five assembly-language instructions in my '816 ITC Forth,), and I like to add a variable LOOP_LEAVE which loop and ploop (the internals compiled by LOOP and +LOOP) zero and LEAVE sets to -1 and so does ?LEAVE if it leaves, so you can test later to see if the loop finished or was aborted.  Otherwise LOOP doesn't care if there's a LEAVE (or any number of LEAVEs) in the loop.  It's not complex (at least in ITC Forth).  There are some things that are complex but make the language more powerful and make your application more clear and maintainable.  That's good, not bad. DOES> and VOCABULARY (and friends) are the prime examples.  I know Chuck Moore doesn't (or at least didn't use to) like the CASE structure, but I think it's extremely valuable.  The way I do it is much more efficient than a set of nested IF...THENs.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 28, 2015 12:59 am 
Offline

Joined: Mon Jan 07, 2013 2:42 pm
Posts: 576
Location: Just outside Berlin, Germany
I've got a version working now, though it's ugly -- it requires an IF/THEN (no "DO LEAVE LOOP" as with Gforth), and it uses a flag to see if we have a LEAVE. Something is still very, very wrong, but it works and I have to get to bed. Also, if Garth is right with his most very simple solution, I might be prone to screaming at this point :-) ...

(I'm obviously too tired, but wouldn't there be a problem with a word such as
Code:
: COUNTTOFROG  10 0 DO  I DUP . 3 = IF LEAVE THEN  LOOP ." Frog!" ;

if you just jump out of the word at the moment of the LEAVE? How do you get to any stuff right after the LOOP?)

This might be a STC problem, with all the jumping around and using the Return Stack. I'm going to get my last two words coded -- ?DO and RECURSE -- and then see if I can figure out something cleaner during the rewrite.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 28, 2015 2:18 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1928
Location: Sacramento, CA, USA
My point is that STC would JSR unloop, and the return address for that JSR would be in your way unless you did something with it too (or only used unloop in-line). Maybe I'm missing something, because I have become a bit befuddled with my DTC translation, in which my machine code stack and Forth return stack are one-and-the-same.

I briefly considered using a separate register like U for the return stack pointer, but my processor is not "register-rich" (which is just the way I like it) and I'm worried that I might need U for my Forth W register (although W seems so far to be much less important in DTC than in ITC). I think that I can make it work, but it's just a bit of extra effort, because my CamelForth DTC sources (from which I'm drawing inspiration) are Z80 in standard syntax and 6809 in Forth assembler syntax, and they are both a bit confusing to my old brain (Z80 because it's Z80, and Forth assembler syntax because it's Forth assembler syntax).

Mike B.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 28, 2015 2:47 am 
Offline

Joined: Mon Jan 26, 2015 6:19 am
Posts: 85
scotws wrote:
(I'm obviously too tired, but wouldn't there be a problem with a word such as
Code:
: COUNTTOFROG  10 0 DO  I DUP . 3 = IF LEAVE THEN  LOOP ." Frog!" ;

if you just jump out of the word at the moment of the LEAVE? How do you get to any stuff right after the LOOP?)

Tired or not, you are correct. If the purpose of LEAVE was to exit the word entirely then coding it would be a trivial matter. However, the purpose of LEAVE is to exit the loop and continue with the code following LOOP.

This is the example that Leo Brodie gives in Starting Forth:
Code:
 : DOUBLED   
          6 1000 21 1 DO  CR ." YEAR " I 2 U.R
                          2DUP R% +  DUP ."    BALANCE " .
                          DUP 2000 > IF  CR CR ." more than doubled in "
                                            I . ." years " LEAVE 
                                   THEN
                     LOOP 2DROP ;

The result will look like this:

   DOUBLED
        YEAR  1   BALANCE 1060
        YEAR  2   BALANCE 1124
        YEAR  3   BALANCE 1191
        YEAR  4   BALANCE 1262
        YEAR  5   BALANCE 1338
        YEAR  6   BALANCE 1418
        YEAR  7   BALANCE 1503
        YEAR  8   BALANCE 1593
        YEAR  9   BALANCE 1689
        YEAR 10   BALANCE 1790
        YEAR 11   BALANCE 1897
        YEAR 12   BALANCE 2011

        more than doubled in 12 years ok
Cleaning up the stack is a common necessity at the end of a word.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 264 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7 ... 18  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: