6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 16, 2024 2:34 pm

All times are UTC




Post new topic Reply to topic  [ 32 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
PostPosted: Wed May 24, 2017 10:58 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10980
Location: England
Well, if you have carry, you can test for zero by adding FF and then testing the carry - so zero is optional. But I agree, it's very useful!

In a recent but very recently superseded effort at a minimal CPU, we had predicates for carry and non-zero. (We thought that branching on non-zero is just a little more valuable than branching on zero.)

Interestingly, in an accumulator machine you could have a test for zero which tests the accumulator directly, and yet omit the zero flag. So that's an intermediate situation - you have a test, but no flag bit. Once you start adding other registers, like the 6502's X and Y, then a zero flag looks more useful - only being able to test the accumulator is limiting.


Top
 Profile  
Reply with quote  
PostPosted: Wed May 24, 2017 8:58 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8541
Location: Southern California
furrykef wrote:
The V flag is often considered the 6502's least useful flag. Even large programs may never use it at all.

The main thing I've used V for is branching following a BIT instruction for hardware input (since BIT transfers bit 6 to V, regardless of what's in A). Jeff Laughton uses it also in his 65c02 designs for ultrafast I/O as shown at http://wilsonminesco.com/6502primer/potpourri.html#Jeff .

_________________
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: Thu May 25, 2017 12:57 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8491
Location: Midwestern USA
GARTHWILSON wrote:
furrykef wrote:
The V flag is often considered the 6502's least useful flag. Even large programs may never use it at all.

The main thing I've used V for is branching following a BIT instruction for hardware input (since BIT transfers bit 6 to V, regardless of what's in A). Jeff Laughton uses it also in his 65c02 designs for ultrafast I/O as shown at http://wilsonminesco.com/6502primer/potpourri.html#Jeff .

I extensively use flags in POC's firmware in which both bits 7 and 6 are significant. Testing with a BIT instruction is fast and economical in such cases.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 03, 2017 1:35 pm 
Offline

Joined: Sat Mar 27, 2010 7:50 pm
Posts: 149
Location: Chexbres, VD, Switzerland
The processor flags as a whole are completely unnecessary if a CPU instruction set is designed that way. Instead of having instructions like "branch if ... flag is set/clear", we have "branch if RegX > RegY" or "brankch if RegX is zero/nonzero". We could even do it 65xx style and have "branch if A is higher than MEM" or stuff like that. It's just as intuitive, and removes the need for flags. The major inconvenient is that it needs a wider set of instructions to reach the same functionality, and is harder to delay decisions (rather than just store the decision in the flag and use later, we have to keep the comparison source in registers).


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 03, 2017 6:14 pm 
Offline

Joined: Tue Nov 10, 2015 5:46 am
Posts: 230
Location: Kent, UK
BigEd wrote:
Mulling over alternative CPU designs, it feels like the four flags are not equal in usefulness. The following is a thought experiment.

If you could have a CPU that's 10% faster, 10% cheaper, would you give up one of the four flags? Which one?
If I had a fixed function project that had certain timing to meet, I was within 10% of it but just couldn't get there, then goodbye V flag.

I don't think I'd want to lose any of the other flags as it would make all reference code incompatible, and make writing code more painful. That said, if I _had_ to choose:

  • 3 flags: N, Z, C
  • 2 flags: Z, C
  • 1 flag: C

On the last one, the C flag alone gives me both multi-byte arithmetic and BCC, BCS, which should be the basis for a lot of derived functionality. But like the "One Instruction Set Computer" approaches, simple operations can explode without the right tools. Something as simple as branching if A == some_value becomes a challenge without Z. How would I do it?... Hmmm.. Ok, here's one idea:

This is what I'd like to do, but I can't because no Z:
Code:
        LDA this_variable
        CMP that_variable
        BEQ this_that_equal
        ; not equal
        ...
this_that_equal:
        ; equal
        ...


So instead, I'm going to make a function called cmpz, which returns equality in the C flag. If C=1 then equal, else not equal. cmpz EORs the two variables and then uses the result to branch into a 16-entry table that, at the [0] index, sets the C flag, and otherwise clear the C flag. As that comprises two instructions (e.g. SEC; RTS or CLC; RTS), I'll do it in two steps - first checking bits [3:0] of the EOR result and then [7:4]. The original pattern only uses A, and preserves it, and the function pattern will do the same.

Code:
        .MACRO CMPZ  OP
        PHA
        LDA \OP
        JSR fcmpz
        PLA
        .ENDMACRO

        ; client application
        LDA this_variable
        CMPZ that_variable
        BCS this_that_equal
        ; not equal
        ...
this_that_equal:
        ; equal
        ...

fcmpz:
        PHA
        TXA
        PHA
        TSX                  ; X->[-, X, that_variable, ret_lo, ret_hi, this_variable]
        LDA $102,X
        EOR $105,X
        AND #$0F
        LSL
        STA cmpzcall1 + 1
cmpzcall1:
        JSR cmpztab
        BCS cmpzend
        LDA $102,X
        EOR $105,X
        AND #$F0
        LSR
        LSR
        LSR
        STA cmpzcall2 + 1
cmpzcall2:
        JSR cmpztab
cmpzend:
        PLA
        TAX
        PLA
        RTS

        .ALIGN 256
cmpztab:
        SEC
        RTS
        .REPEAT 15
        CLC
        RTS
        .ENDREPEAT


Ugh, that looks awful. Can someone with more current 6502 experience save me from my 30 year atrophy?


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 03, 2017 6:41 pm 
Offline

Joined: Tue Nov 10, 2015 5:46 am
Posts: 230
Location: Kent, UK
sark02 wrote:
Ugh, that looks awful.
Ha! Then I read BigEd's comment. Add #$FF. Of course.

Code:
        LDA this_variable
        EOR that_variable
        CLC
        ADC #$FF
        BCC this_equals_that
        ; this_not_equal_to_that


Doesn't preserve the original pattern, but you get the idea.

"Hello, my name is dummy. Nice to meet you." - me.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 03, 2017 8:06 pm 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 679
If you don't have a Z flag, you can always create a "Branch if A is zero" instruction instead, which uses the entire register as a simulated flag. Forth does this with TOS a lot for decisions, for example. Without a C flag, you could also overwrite X or Y with carry. This obviously tramples a lot of state, but might reuse a lot of data paths in the CPU instead of routing to specialized flag registers.

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 04, 2017 6:20 am 
Offline

Joined: Tue Jun 08, 2004 11:51 pm
Posts: 213
Not all processors even have a V flag.
Add minus 1 and a C test for to replace Z. ( 2's complement )
N can be tested with an add to one self and a C test.
That leaves only C for every thing.
Dwight


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 04, 2017 9:12 pm 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
MIPS processors (as in the PIC32) have no flags at all. There are a few conditional instructions (e.g. branch if reg1 == reg2, compare and set register, etc.) and a register that always contains zero and which can be compared against.

The compiler derives carry from intermediate results, for example 64-bit add on a 32-bit device.
Code:
11:                  long long add (long long a, long long b)
12:                  {
13:                      return (a + b);
9D000234  00C41021   ADDU V0, A2, A0
9D000238  00E52821   ADDU A1, A3, A1
9D00023C  0046182B   SLTU V1, V0, A2
14:                  }
9D000240  03E00008   JR RA
9D000244  00651821   ADDU V1, V1, A1

The first ADDU add the low words, the second the high words. The SLTU sets V1 to one if a carry occurred otherwise zero. The final ADDU (in the delay slot after the jump to return address) propagates it into the result.

One of the add instructions can trigger an overflow interrupt but many languages like C don't use it.

_________________
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 05, 2017 12:17 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Back in the 20th century I worked with minimalist CPU's that did multi-axis motion control, and the technology was 7400 series TTL (no microprocessor). Program memory was a pair of bipolar PROM's, and each 16-bit instruction included only three opcode bits. :shock: There were a few wrinkles that allowed eleven possible instructions, not just eight, but it was definitely minimal.

The machine had just a single status flag, and its meaning depended on the context (Dwight and Sark02 mentioned points along this line). The flag got its data from two possible sources. An ADD instruction would write its Carry result to the flag, whereas a BIT instruction caused the flag to update reflecting the Zero result.

There was only one instruction to test the flag -- a conditional branch. I don't recall whether it branched on flag set or on flag clear.

-- 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: Mon Jun 05, 2017 5:51 am 
Offline

Joined: Tue Jun 08, 2004 11:51 pm
Posts: 213
Hi Dr.
As often with me, I missed that there was a page 2.
I get to excited to post and don't look.
Even Z can do all but a little different. I suspect
that one could even use N or V as well with a little
thought.
Dwight


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 05, 2017 6:23 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8491
Location: Midwestern USA
Dr Jefyll wrote:
Back in the 20th century I worked with minimalist CPU's that did multi-axis motion control, and the technology was 7400 series TTL (no microprocessor).

Ah, yes. The infamous Diablo printer. :D

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 05, 2017 5:25 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10980
Location: England
Very interesting thoughts and observations, everyone! I hadn't realised PIC32/MIPS was flag-free. I know RISC-V is.

For the OPC series of CPUs, it looks like we're going with Z and C at present, and just C for the minimal machine.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 08, 2017 3:39 pm 
Offline
User avatar

Joined: Tue Oct 25, 2016 8:56 pm
Posts: 362
I've got a homebrew architecture which has four flags:
C - Carry
V - Overflow
I - Interrupt Enable
U - User

C & V are provided by the ALU chip I'm using. I is obvious what it does. U is never set or cleared by the hardware at all, but the programmer can do so, and it has its own set of branch instructions. I originally intended to have U be a Z flag, but the way i've implemented the flags register unfortunately makes this impossible. :( At least, I recall there being a reason but I cannot remember what it is now....

I did consider not using V and providing C and Z instead, but it does seem to me that V is particularly hard to simulate if you are using signed arithmetic and don't have the flag. Whereas Z is relatively easy to simulate.

EDIT: had a look at my circuit diagrams - its because it can't modify the U/Z flag without also clearing the I flag, which is not a good idea....

_________________
Want to design a PCB for your project? I strongly recommend KiCad. Its free, its multiplatform, and its easy to learn!
Also, I maintain KiCad libraries of Retro Computing and Arduino components you might find useful.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 08, 2017 4:27 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10980
Location: England
Interesting! Have you written anything about your architecture?


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 32 posts ]  Go to page Previous  1, 2, 3  Next

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 5 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: