Behavior of the zero and negative/sign flags on classic instruction setsWhy did the PDP-11 include a JMP instruction?PDP-11 instruction set inconsistenciesUses for the halt instruction?Hardware multipliers on classic CPUsWhat is the format of a TurboGrafX instruction (modified 6502 instruction set)?Why does an instruction include the address of the next instruction on the IBM 650?Why does the 6502 have the BIT instruction?What did the 8086 (and 8088) do upon encountering an illegal instruction?SYNC and the 65CE02 instruction timingHow is PETSCII used by assembly-language programs?

Why does the single dot entry exist in file systems?

Comparison of two Japanese Bible translations of Genesis 1:1

Why is it possible to teach real numbers before even rigorously defining them?

How do I protect myself from bad contracting jobs?

What is an advantage of getting dividends from stock?

Cooking octopus: simple boil or broth?

Lat/Long co-ordinates are not plotting onto EPSG:3857 OSM basemap correctly

How would an unethical corporation go about extracting resources from a nation unwilling to co-operate?

Effects of quantum computing on parallel universes

Do airplanes need brakes in the air?

Why do we have 0.0 and -0.0 in Ruby?

What music is this?

Novel where a serial killer lives (almost) forever by swapping bodies

Formatting Date and TIME in French

Finding price of the power option

A list has been obtained from an outside soft (from COMSOL - to Mathematica). Let us make a continuous function out of it

If a creature has advantage against spells and magical effects, is it resistant to magical attacks?

Can abstractions and good code practice in embedded C++ eliminate the need for the debugger?

Can I travel from Brussels to Ghent using the JUMP card?

Everybody knows how to make magical items. What about magical "places"?

Writing "thank you" note to professor who will write more LOR's?

Hoping for a satisfying conclusion (a musical connect wall)

Why is the block size is not filled with transactions

Printing Command Line Unicode Chess Board



Behavior of the zero and negative/sign flags on classic instruction sets


Why did the PDP-11 include a JMP instruction?PDP-11 instruction set inconsistenciesUses for the halt instruction?Hardware multipliers on classic CPUsWhat is the format of a TurboGrafX instruction (modified 6502 instruction set)?Why does an instruction include the address of the next instruction on the IBM 650?Why does the 6502 have the BIT instruction?What did the 8086 (and 8088) do upon encountering an illegal instruction?SYNC and the 65CE02 instruction timingHow is PETSCII used by assembly-language programs?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;









8

















It seems to me that there's effectively two ways that the zero bit could work.




  1. Z is set iff the result of a computation is mathematically equal to 0.


  2. Z is set iff a bit pattern consisting entirely of 0 is stored in the destination (whatever that may be)

These may seem identical, but consider the following fragment of 6502 assembly:



LDA #$FF
CLC
ADC #$01


So what's Z for this? Mathematically, 0xFF + 0x01 = 0x100, but 256 doesn't fit in an 8-bit register, so the C flag gets set, and the bit pattern 0b00000000 is stored in A. Often time, manuals will say something like "The Z flag is set if the result is zero" but that seems hopelessly ambiguous to mean. I'm very curious, cross-architecturally, how this has varied.



Similarly, it's unclear how the N (negative/sign) flag "should behave. Is it set according to the "actual" sign of the result, or does it literally just reflect the MSB of the result actually stored in the destination, irrespective of whether signed overflow occurred?










share|improve this question





















  • 1





    Mathematically, computers use modular arithmetic so the answer is both.

    – Ross Ridge
    Jul 14 at 13:12











  • I get the feeling that the question is not really ask about the 6502 in particular.

    – Raffzahn
    Jul 14 at 14:12

















8

















It seems to me that there's effectively two ways that the zero bit could work.




  1. Z is set iff the result of a computation is mathematically equal to 0.


  2. Z is set iff a bit pattern consisting entirely of 0 is stored in the destination (whatever that may be)

These may seem identical, but consider the following fragment of 6502 assembly:



LDA #$FF
CLC
ADC #$01


So what's Z for this? Mathematically, 0xFF + 0x01 = 0x100, but 256 doesn't fit in an 8-bit register, so the C flag gets set, and the bit pattern 0b00000000 is stored in A. Often time, manuals will say something like "The Z flag is set if the result is zero" but that seems hopelessly ambiguous to mean. I'm very curious, cross-architecturally, how this has varied.



Similarly, it's unclear how the N (negative/sign) flag "should behave. Is it set according to the "actual" sign of the result, or does it literally just reflect the MSB of the result actually stored in the destination, irrespective of whether signed overflow occurred?










share|improve this question





















  • 1





    Mathematically, computers use modular arithmetic so the answer is both.

    – Ross Ridge
    Jul 14 at 13:12











  • I get the feeling that the question is not really ask about the 6502 in particular.

    – Raffzahn
    Jul 14 at 14:12













8












8








8


1






It seems to me that there's effectively two ways that the zero bit could work.




  1. Z is set iff the result of a computation is mathematically equal to 0.


  2. Z is set iff a bit pattern consisting entirely of 0 is stored in the destination (whatever that may be)

These may seem identical, but consider the following fragment of 6502 assembly:



LDA #$FF
CLC
ADC #$01


So what's Z for this? Mathematically, 0xFF + 0x01 = 0x100, but 256 doesn't fit in an 8-bit register, so the C flag gets set, and the bit pattern 0b00000000 is stored in A. Often time, manuals will say something like "The Z flag is set if the result is zero" but that seems hopelessly ambiguous to mean. I'm very curious, cross-architecturally, how this has varied.



Similarly, it's unclear how the N (negative/sign) flag "should behave. Is it set according to the "actual" sign of the result, or does it literally just reflect the MSB of the result actually stored in the destination, irrespective of whether signed overflow occurred?










share|improve this question















It seems to me that there's effectively two ways that the zero bit could work.




  1. Z is set iff the result of a computation is mathematically equal to 0.


  2. Z is set iff a bit pattern consisting entirely of 0 is stored in the destination (whatever that may be)

These may seem identical, but consider the following fragment of 6502 assembly:



LDA #$FF
CLC
ADC #$01


So what's Z for this? Mathematically, 0xFF + 0x01 = 0x100, but 256 doesn't fit in an 8-bit register, so the C flag gets set, and the bit pattern 0b00000000 is stored in A. Often time, manuals will say something like "The Z flag is set if the result is zero" but that seems hopelessly ambiguous to mean. I'm very curious, cross-architecturally, how this has varied.



Similarly, it's unclear how the N (negative/sign) flag "should behave. Is it set according to the "actual" sign of the result, or does it literally just reflect the MSB of the result actually stored in the destination, irrespective of whether signed overflow occurred?







6502 instruction-set






share|improve this question














share|improve this question











share|improve this question




share|improve this question










asked Jul 14 at 4:37









Kevin KeithKevin Keith

1863 bronze badges




1863 bronze badges










  • 1





    Mathematically, computers use modular arithmetic so the answer is both.

    – Ross Ridge
    Jul 14 at 13:12











  • I get the feeling that the question is not really ask about the 6502 in particular.

    – Raffzahn
    Jul 14 at 14:12












  • 1





    Mathematically, computers use modular arithmetic so the answer is both.

    – Ross Ridge
    Jul 14 at 13:12











  • I get the feeling that the question is not really ask about the 6502 in particular.

    – Raffzahn
    Jul 14 at 14:12







1




1





Mathematically, computers use modular arithmetic so the answer is both.

– Ross Ridge
Jul 14 at 13:12





Mathematically, computers use modular arithmetic so the answer is both.

– Ross Ridge
Jul 14 at 13:12













I get the feeling that the question is not really ask about the 6502 in particular.

– Raffzahn
Jul 14 at 14:12





I get the feeling that the question is not really ask about the 6502 in particular.

– Raffzahn
Jul 14 at 14:12










3 Answers
3






active

oldest

votes


















11


















Neither. In the 6502, the Z flag is set if there's an all-zero pattern on the internal data bus in the last instruction cycle and cleared if it isn't. This means specifically instructions as PLA or TAX affect the Z flag. On the 65C02, e.g. PLX does, too.



You can see this from the CMP, CPX, CPY, BIT instructions, which store nothing.



Same for the N flag, it's simply copied from bit 7 of the internal data bus.






share|improve this answer




























  • Instructions that modify the Z flag behave in that fashion, but not all instructions modify the Z flag.

    – supercat
    Jul 15 at 16:39











  • All instructions but that ones storing data into memory, flag manipulation, jumps and TXS behave that way. See oxyron.de/html/opcodes02.html.

    – Janka
    Jul 15 at 18:00



















7


















While Wilson and Janka already explain the arithmetic and 6502 related (*1) implication, I somehow get the feeling this question is not about the 6502




Behavior of the zero and negative/sign flags on classic instruction sets




but rather some generic, absolute meaning.




I'm very curious, cross-architecturally, how this has varied.




There is no variation, as there is no absolute meaning (*2) what Z should be, or that Z even stands for Zero.



So short answer:



There is no one size fits all. One has to look at every ISA on its own, as similar naming will may mean different things based on different assumptions for each architecture.




[Insert...



If at all, one may think of it as with languages. There can be words with similar meanings in different languages, but they rarely overlap exactly, even for simple things. Even if these words sound (almost) the same and their meaning seems quite similar, they are not - like for Z and flags.



Think of English 'Hound' and German 'Hund'. Both are about a dog, but while the German Hund means dog in general, English Hound is a subset of dog. Much like the Z80 Z flag is a subset of the 76502 Z flag, isn't it? (*2)



...back to CPUs and conditions]




Long Answer:



There are CPUs



  • without flags at all - like some VLIW

  • without flags but relational tests - like DEC ALPHA

  • without flags but conditional traps

  • with condition codes instead of flags - like IBM /360ish (it can't get more classic :))

  • with flags much like 6502 or Z80 but many different compositions

(I guess with some thinking the list may be extended many more ways.)



As well as combinations thereof, where MIPS is a great example (*3) again:



  • basic MIPS with relations and traps

  • MIPS II and traps

  • or MIPS SIMD with relations, traps and VLIW like flagless operation

Bottom line: CPU architectures with flags are just one case of many, rather a minority among all designs - that is, unless we count the number of delivered devices (even considering MIPS working hard in many cheap consumer products won't change this).



The reason is rather simple, as using flags is the least effort hardware wise. Basically flags are just cached output signals of the ALU (like on Z80) sometimes enriched by additional test logic(*4). They only make very basic observations available to software. Fine as long as there are only a few and rather basic 'notifications' to be made about the result of an operation. But as soon as we leave the very basic domain and the number of resulting conditions may become quite crowded, hard to be handled in a systematic way - even less in similar ways across architectures.



While a 'simple' Zero or the mentioned Negative introduces only minor differences between architectures, it gets quite messy when the meaning to be transported gets more and more complex. Just take a look at the handling of signed numbers and overflow in 8080 vs. 6502. Here several new flags with only minor overlap are introduced. And this is still only integer arithmetic.



Architectures offering a more diverse set of operations (*5) usually drop the whole flag part and go either for generation of a more abstract operation result, like a condition code, to be used on a case-by-case basis(*6), or move the whole result/condition testing away from the operation completely (like MIPS, Alpha)



Doing away with flags can



  • simplify software structure and

  • improve performance


*1 - Well, both contain part of the workings within a 6502. The signal for Zero (DBZ) is generated by an 8-input NAND, but that Z not always reflect what's (in the last cycle) on the internal data bus (DB part). After all, this would mean that (for example) in case of a JMP instruction Z would be set according to the high byte of the address.



To avoid this the control logic enable flag setting for Z in a case by case situation via distinct control signals. Within the Hanson diagram they are mentioned as DBI/Z in case of input operations (like LDA #) and DBZ/Z for arithmetic. In hardware it's an OR combination driven by several lines from the decoder PLA detecting certain opcode/sequence cases.



*2 - But beware Gift vs Gift :))



*3 - A rare case where a Wiki entry has at least some information to serve as pointer for details.



*4 - Like parity on a 8080 or zero detection for data by the 6800/6500 series.



*5 - By initial design that is, as 'grown' architectures like x86 have to squeeze them in.



*6 - Basically the same number of markers (avoiding the term Flag on purpose) gets used differently on different instructions. For example on a /370



  • an arithmetic operation produced CC=0 for result zero, CC=1 for negative and CC=2 for positive and CC=3 for overflow

  • A compare operation produces CC=0 for equal, CC=1 for less than and CC=2 for greater than

  • a logic operation produces CC=0 for zero and CC=1 for non zero

  • a bit test operation produces CC=0 for all-zero, CC=1 for mixed and CC=3 for all-one

  • a move long produces CC=0 for all transferred, CC=1 for receive-is-too-short and CC=2 for receive-field-was-padded

  • and so on...

As a result only two bits of condition code are needed to store such an abstract result - and only a single set of test instructions are necessary to act, no matter how different the instruction results are.






share|improve this answer























  • 1





    Great answer that addresses the question behind the question.

    – Wayne Conrad
    Jul 15 at 16:53


















5


















In the case you describe, the 6502 will set the Zero flag (in other words, the Z flag will be one if the operation left the accumulator equal to 0 mod 256). That's convenient, because usually a programmer is interested either in Z, to test for an actual zero condition, or in C, to test for a carry.



The Z80 works in the same way.



My understanding is that it's also easier to implement, since that's effectively an 8-input NAND.






share|improve this answer


























  • For what it's worth, the 68000 acts the same way, even in intentionally open-ended instructions like ADDX — they either clear the zero flag or leave it alone so that the end result is correct for the net total of all handled [bytes/words/long words], but they do it only based on the [8/16/32]-bit result, with no regard for the generated carry/extend.

    – Tommy
    Jul 14 at 13:30












Your Answer








StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "648"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
noCode: true, onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);














draft saved

draft discarded
















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fretrocomputing.stackexchange.com%2fquestions%2f11659%2fbehavior-of-the-zero-and-negative-sign-flags-on-classic-instruction-sets%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown


























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









11


















Neither. In the 6502, the Z flag is set if there's an all-zero pattern on the internal data bus in the last instruction cycle and cleared if it isn't. This means specifically instructions as PLA or TAX affect the Z flag. On the 65C02, e.g. PLX does, too.



You can see this from the CMP, CPX, CPY, BIT instructions, which store nothing.



Same for the N flag, it's simply copied from bit 7 of the internal data bus.






share|improve this answer




























  • Instructions that modify the Z flag behave in that fashion, but not all instructions modify the Z flag.

    – supercat
    Jul 15 at 16:39











  • All instructions but that ones storing data into memory, flag manipulation, jumps and TXS behave that way. See oxyron.de/html/opcodes02.html.

    – Janka
    Jul 15 at 18:00
















11


















Neither. In the 6502, the Z flag is set if there's an all-zero pattern on the internal data bus in the last instruction cycle and cleared if it isn't. This means specifically instructions as PLA or TAX affect the Z flag. On the 65C02, e.g. PLX does, too.



You can see this from the CMP, CPX, CPY, BIT instructions, which store nothing.



Same for the N flag, it's simply copied from bit 7 of the internal data bus.






share|improve this answer




























  • Instructions that modify the Z flag behave in that fashion, but not all instructions modify the Z flag.

    – supercat
    Jul 15 at 16:39











  • All instructions but that ones storing data into memory, flag manipulation, jumps and TXS behave that way. See oxyron.de/html/opcodes02.html.

    – Janka
    Jul 15 at 18:00














11














11










11









Neither. In the 6502, the Z flag is set if there's an all-zero pattern on the internal data bus in the last instruction cycle and cleared if it isn't. This means specifically instructions as PLA or TAX affect the Z flag. On the 65C02, e.g. PLX does, too.



You can see this from the CMP, CPX, CPY, BIT instructions, which store nothing.



Same for the N flag, it's simply copied from bit 7 of the internal data bus.






share|improve this answer
















Neither. In the 6502, the Z flag is set if there's an all-zero pattern on the internal data bus in the last instruction cycle and cleared if it isn't. This means specifically instructions as PLA or TAX affect the Z flag. On the 65C02, e.g. PLX does, too.



You can see this from the CMP, CPX, CPY, BIT instructions, which store nothing.



Same for the N flag, it's simply copied from bit 7 of the internal data bus.







share|improve this answer















share|improve this answer




share|improve this answer








edited Jul 14 at 11:58

























answered Jul 14 at 9:47









JankaJanka

1,7845 silver badges9 bronze badges




1,7845 silver badges9 bronze badges















  • Instructions that modify the Z flag behave in that fashion, but not all instructions modify the Z flag.

    – supercat
    Jul 15 at 16:39











  • All instructions but that ones storing data into memory, flag manipulation, jumps and TXS behave that way. See oxyron.de/html/opcodes02.html.

    – Janka
    Jul 15 at 18:00


















  • Instructions that modify the Z flag behave in that fashion, but not all instructions modify the Z flag.

    – supercat
    Jul 15 at 16:39











  • All instructions but that ones storing data into memory, flag manipulation, jumps and TXS behave that way. See oxyron.de/html/opcodes02.html.

    – Janka
    Jul 15 at 18:00

















Instructions that modify the Z flag behave in that fashion, but not all instructions modify the Z flag.

– supercat
Jul 15 at 16:39





Instructions that modify the Z flag behave in that fashion, but not all instructions modify the Z flag.

– supercat
Jul 15 at 16:39













All instructions but that ones storing data into memory, flag manipulation, jumps and TXS behave that way. See oxyron.de/html/opcodes02.html.

– Janka
Jul 15 at 18:00






All instructions but that ones storing data into memory, flag manipulation, jumps and TXS behave that way. See oxyron.de/html/opcodes02.html.

– Janka
Jul 15 at 18:00














7


















While Wilson and Janka already explain the arithmetic and 6502 related (*1) implication, I somehow get the feeling this question is not about the 6502




Behavior of the zero and negative/sign flags on classic instruction sets




but rather some generic, absolute meaning.




I'm very curious, cross-architecturally, how this has varied.




There is no variation, as there is no absolute meaning (*2) what Z should be, or that Z even stands for Zero.



So short answer:



There is no one size fits all. One has to look at every ISA on its own, as similar naming will may mean different things based on different assumptions for each architecture.




[Insert...



If at all, one may think of it as with languages. There can be words with similar meanings in different languages, but they rarely overlap exactly, even for simple things. Even if these words sound (almost) the same and their meaning seems quite similar, they are not - like for Z and flags.



Think of English 'Hound' and German 'Hund'. Both are about a dog, but while the German Hund means dog in general, English Hound is a subset of dog. Much like the Z80 Z flag is a subset of the 76502 Z flag, isn't it? (*2)



...back to CPUs and conditions]




Long Answer:



There are CPUs



  • without flags at all - like some VLIW

  • without flags but relational tests - like DEC ALPHA

  • without flags but conditional traps

  • with condition codes instead of flags - like IBM /360ish (it can't get more classic :))

  • with flags much like 6502 or Z80 but many different compositions

(I guess with some thinking the list may be extended many more ways.)



As well as combinations thereof, where MIPS is a great example (*3) again:



  • basic MIPS with relations and traps

  • MIPS II and traps

  • or MIPS SIMD with relations, traps and VLIW like flagless operation

Bottom line: CPU architectures with flags are just one case of many, rather a minority among all designs - that is, unless we count the number of delivered devices (even considering MIPS working hard in many cheap consumer products won't change this).



The reason is rather simple, as using flags is the least effort hardware wise. Basically flags are just cached output signals of the ALU (like on Z80) sometimes enriched by additional test logic(*4). They only make very basic observations available to software. Fine as long as there are only a few and rather basic 'notifications' to be made about the result of an operation. But as soon as we leave the very basic domain and the number of resulting conditions may become quite crowded, hard to be handled in a systematic way - even less in similar ways across architectures.



While a 'simple' Zero or the mentioned Negative introduces only minor differences between architectures, it gets quite messy when the meaning to be transported gets more and more complex. Just take a look at the handling of signed numbers and overflow in 8080 vs. 6502. Here several new flags with only minor overlap are introduced. And this is still only integer arithmetic.



Architectures offering a more diverse set of operations (*5) usually drop the whole flag part and go either for generation of a more abstract operation result, like a condition code, to be used on a case-by-case basis(*6), or move the whole result/condition testing away from the operation completely (like MIPS, Alpha)



Doing away with flags can



  • simplify software structure and

  • improve performance


*1 - Well, both contain part of the workings within a 6502. The signal for Zero (DBZ) is generated by an 8-input NAND, but that Z not always reflect what's (in the last cycle) on the internal data bus (DB part). After all, this would mean that (for example) in case of a JMP instruction Z would be set according to the high byte of the address.



To avoid this the control logic enable flag setting for Z in a case by case situation via distinct control signals. Within the Hanson diagram they are mentioned as DBI/Z in case of input operations (like LDA #) and DBZ/Z for arithmetic. In hardware it's an OR combination driven by several lines from the decoder PLA detecting certain opcode/sequence cases.



*2 - But beware Gift vs Gift :))



*3 - A rare case where a Wiki entry has at least some information to serve as pointer for details.



*4 - Like parity on a 8080 or zero detection for data by the 6800/6500 series.



*5 - By initial design that is, as 'grown' architectures like x86 have to squeeze them in.



*6 - Basically the same number of markers (avoiding the term Flag on purpose) gets used differently on different instructions. For example on a /370



  • an arithmetic operation produced CC=0 for result zero, CC=1 for negative and CC=2 for positive and CC=3 for overflow

  • A compare operation produces CC=0 for equal, CC=1 for less than and CC=2 for greater than

  • a logic operation produces CC=0 for zero and CC=1 for non zero

  • a bit test operation produces CC=0 for all-zero, CC=1 for mixed and CC=3 for all-one

  • a move long produces CC=0 for all transferred, CC=1 for receive-is-too-short and CC=2 for receive-field-was-padded

  • and so on...

As a result only two bits of condition code are needed to store such an abstract result - and only a single set of test instructions are necessary to act, no matter how different the instruction results are.






share|improve this answer























  • 1





    Great answer that addresses the question behind the question.

    – Wayne Conrad
    Jul 15 at 16:53















7


















While Wilson and Janka already explain the arithmetic and 6502 related (*1) implication, I somehow get the feeling this question is not about the 6502




Behavior of the zero and negative/sign flags on classic instruction sets




but rather some generic, absolute meaning.




I'm very curious, cross-architecturally, how this has varied.




There is no variation, as there is no absolute meaning (*2) what Z should be, or that Z even stands for Zero.



So short answer:



There is no one size fits all. One has to look at every ISA on its own, as similar naming will may mean different things based on different assumptions for each architecture.




[Insert...



If at all, one may think of it as with languages. There can be words with similar meanings in different languages, but they rarely overlap exactly, even for simple things. Even if these words sound (almost) the same and their meaning seems quite similar, they are not - like for Z and flags.



Think of English 'Hound' and German 'Hund'. Both are about a dog, but while the German Hund means dog in general, English Hound is a subset of dog. Much like the Z80 Z flag is a subset of the 76502 Z flag, isn't it? (*2)



...back to CPUs and conditions]




Long Answer:



There are CPUs



  • without flags at all - like some VLIW

  • without flags but relational tests - like DEC ALPHA

  • without flags but conditional traps

  • with condition codes instead of flags - like IBM /360ish (it can't get more classic :))

  • with flags much like 6502 or Z80 but many different compositions

(I guess with some thinking the list may be extended many more ways.)



As well as combinations thereof, where MIPS is a great example (*3) again:



  • basic MIPS with relations and traps

  • MIPS II and traps

  • or MIPS SIMD with relations, traps and VLIW like flagless operation

Bottom line: CPU architectures with flags are just one case of many, rather a minority among all designs - that is, unless we count the number of delivered devices (even considering MIPS working hard in many cheap consumer products won't change this).



The reason is rather simple, as using flags is the least effort hardware wise. Basically flags are just cached output signals of the ALU (like on Z80) sometimes enriched by additional test logic(*4). They only make very basic observations available to software. Fine as long as there are only a few and rather basic 'notifications' to be made about the result of an operation. But as soon as we leave the very basic domain and the number of resulting conditions may become quite crowded, hard to be handled in a systematic way - even less in similar ways across architectures.



While a 'simple' Zero or the mentioned Negative introduces only minor differences between architectures, it gets quite messy when the meaning to be transported gets more and more complex. Just take a look at the handling of signed numbers and overflow in 8080 vs. 6502. Here several new flags with only minor overlap are introduced. And this is still only integer arithmetic.



Architectures offering a more diverse set of operations (*5) usually drop the whole flag part and go either for generation of a more abstract operation result, like a condition code, to be used on a case-by-case basis(*6), or move the whole result/condition testing away from the operation completely (like MIPS, Alpha)



Doing away with flags can



  • simplify software structure and

  • improve performance


*1 - Well, both contain part of the workings within a 6502. The signal for Zero (DBZ) is generated by an 8-input NAND, but that Z not always reflect what's (in the last cycle) on the internal data bus (DB part). After all, this would mean that (for example) in case of a JMP instruction Z would be set according to the high byte of the address.



To avoid this the control logic enable flag setting for Z in a case by case situation via distinct control signals. Within the Hanson diagram they are mentioned as DBI/Z in case of input operations (like LDA #) and DBZ/Z for arithmetic. In hardware it's an OR combination driven by several lines from the decoder PLA detecting certain opcode/sequence cases.



*2 - But beware Gift vs Gift :))



*3 - A rare case where a Wiki entry has at least some information to serve as pointer for details.



*4 - Like parity on a 8080 or zero detection for data by the 6800/6500 series.



*5 - By initial design that is, as 'grown' architectures like x86 have to squeeze them in.



*6 - Basically the same number of markers (avoiding the term Flag on purpose) gets used differently on different instructions. For example on a /370



  • an arithmetic operation produced CC=0 for result zero, CC=1 for negative and CC=2 for positive and CC=3 for overflow

  • A compare operation produces CC=0 for equal, CC=1 for less than and CC=2 for greater than

  • a logic operation produces CC=0 for zero and CC=1 for non zero

  • a bit test operation produces CC=0 for all-zero, CC=1 for mixed and CC=3 for all-one

  • a move long produces CC=0 for all transferred, CC=1 for receive-is-too-short and CC=2 for receive-field-was-padded

  • and so on...

As a result only two bits of condition code are needed to store such an abstract result - and only a single set of test instructions are necessary to act, no matter how different the instruction results are.






share|improve this answer























  • 1





    Great answer that addresses the question behind the question.

    – Wayne Conrad
    Jul 15 at 16:53













7














7










7









While Wilson and Janka already explain the arithmetic and 6502 related (*1) implication, I somehow get the feeling this question is not about the 6502




Behavior of the zero and negative/sign flags on classic instruction sets




but rather some generic, absolute meaning.




I'm very curious, cross-architecturally, how this has varied.




There is no variation, as there is no absolute meaning (*2) what Z should be, or that Z even stands for Zero.



So short answer:



There is no one size fits all. One has to look at every ISA on its own, as similar naming will may mean different things based on different assumptions for each architecture.




[Insert...



If at all, one may think of it as with languages. There can be words with similar meanings in different languages, but they rarely overlap exactly, even for simple things. Even if these words sound (almost) the same and their meaning seems quite similar, they are not - like for Z and flags.



Think of English 'Hound' and German 'Hund'. Both are about a dog, but while the German Hund means dog in general, English Hound is a subset of dog. Much like the Z80 Z flag is a subset of the 76502 Z flag, isn't it? (*2)



...back to CPUs and conditions]




Long Answer:



There are CPUs



  • without flags at all - like some VLIW

  • without flags but relational tests - like DEC ALPHA

  • without flags but conditional traps

  • with condition codes instead of flags - like IBM /360ish (it can't get more classic :))

  • with flags much like 6502 or Z80 but many different compositions

(I guess with some thinking the list may be extended many more ways.)



As well as combinations thereof, where MIPS is a great example (*3) again:



  • basic MIPS with relations and traps

  • MIPS II and traps

  • or MIPS SIMD with relations, traps and VLIW like flagless operation

Bottom line: CPU architectures with flags are just one case of many, rather a minority among all designs - that is, unless we count the number of delivered devices (even considering MIPS working hard in many cheap consumer products won't change this).



The reason is rather simple, as using flags is the least effort hardware wise. Basically flags are just cached output signals of the ALU (like on Z80) sometimes enriched by additional test logic(*4). They only make very basic observations available to software. Fine as long as there are only a few and rather basic 'notifications' to be made about the result of an operation. But as soon as we leave the very basic domain and the number of resulting conditions may become quite crowded, hard to be handled in a systematic way - even less in similar ways across architectures.



While a 'simple' Zero or the mentioned Negative introduces only minor differences between architectures, it gets quite messy when the meaning to be transported gets more and more complex. Just take a look at the handling of signed numbers and overflow in 8080 vs. 6502. Here several new flags with only minor overlap are introduced. And this is still only integer arithmetic.



Architectures offering a more diverse set of operations (*5) usually drop the whole flag part and go either for generation of a more abstract operation result, like a condition code, to be used on a case-by-case basis(*6), or move the whole result/condition testing away from the operation completely (like MIPS, Alpha)



Doing away with flags can



  • simplify software structure and

  • improve performance


*1 - Well, both contain part of the workings within a 6502. The signal for Zero (DBZ) is generated by an 8-input NAND, but that Z not always reflect what's (in the last cycle) on the internal data bus (DB part). After all, this would mean that (for example) in case of a JMP instruction Z would be set according to the high byte of the address.



To avoid this the control logic enable flag setting for Z in a case by case situation via distinct control signals. Within the Hanson diagram they are mentioned as DBI/Z in case of input operations (like LDA #) and DBZ/Z for arithmetic. In hardware it's an OR combination driven by several lines from the decoder PLA detecting certain opcode/sequence cases.



*2 - But beware Gift vs Gift :))



*3 - A rare case where a Wiki entry has at least some information to serve as pointer for details.



*4 - Like parity on a 8080 or zero detection for data by the 6800/6500 series.



*5 - By initial design that is, as 'grown' architectures like x86 have to squeeze them in.



*6 - Basically the same number of markers (avoiding the term Flag on purpose) gets used differently on different instructions. For example on a /370



  • an arithmetic operation produced CC=0 for result zero, CC=1 for negative and CC=2 for positive and CC=3 for overflow

  • A compare operation produces CC=0 for equal, CC=1 for less than and CC=2 for greater than

  • a logic operation produces CC=0 for zero and CC=1 for non zero

  • a bit test operation produces CC=0 for all-zero, CC=1 for mixed and CC=3 for all-one

  • a move long produces CC=0 for all transferred, CC=1 for receive-is-too-short and CC=2 for receive-field-was-padded

  • and so on...

As a result only two bits of condition code are needed to store such an abstract result - and only a single set of test instructions are necessary to act, no matter how different the instruction results are.






share|improve this answer
















While Wilson and Janka already explain the arithmetic and 6502 related (*1) implication, I somehow get the feeling this question is not about the 6502




Behavior of the zero and negative/sign flags on classic instruction sets




but rather some generic, absolute meaning.




I'm very curious, cross-architecturally, how this has varied.




There is no variation, as there is no absolute meaning (*2) what Z should be, or that Z even stands for Zero.



So short answer:



There is no one size fits all. One has to look at every ISA on its own, as similar naming will may mean different things based on different assumptions for each architecture.




[Insert...



If at all, one may think of it as with languages. There can be words with similar meanings in different languages, but they rarely overlap exactly, even for simple things. Even if these words sound (almost) the same and their meaning seems quite similar, they are not - like for Z and flags.



Think of English 'Hound' and German 'Hund'. Both are about a dog, but while the German Hund means dog in general, English Hound is a subset of dog. Much like the Z80 Z flag is a subset of the 76502 Z flag, isn't it? (*2)



...back to CPUs and conditions]




Long Answer:



There are CPUs



  • without flags at all - like some VLIW

  • without flags but relational tests - like DEC ALPHA

  • without flags but conditional traps

  • with condition codes instead of flags - like IBM /360ish (it can't get more classic :))

  • with flags much like 6502 or Z80 but many different compositions

(I guess with some thinking the list may be extended many more ways.)



As well as combinations thereof, where MIPS is a great example (*3) again:



  • basic MIPS with relations and traps

  • MIPS II and traps

  • or MIPS SIMD with relations, traps and VLIW like flagless operation

Bottom line: CPU architectures with flags are just one case of many, rather a minority among all designs - that is, unless we count the number of delivered devices (even considering MIPS working hard in many cheap consumer products won't change this).



The reason is rather simple, as using flags is the least effort hardware wise. Basically flags are just cached output signals of the ALU (like on Z80) sometimes enriched by additional test logic(*4). They only make very basic observations available to software. Fine as long as there are only a few and rather basic 'notifications' to be made about the result of an operation. But as soon as we leave the very basic domain and the number of resulting conditions may become quite crowded, hard to be handled in a systematic way - even less in similar ways across architectures.



While a 'simple' Zero or the mentioned Negative introduces only minor differences between architectures, it gets quite messy when the meaning to be transported gets more and more complex. Just take a look at the handling of signed numbers and overflow in 8080 vs. 6502. Here several new flags with only minor overlap are introduced. And this is still only integer arithmetic.



Architectures offering a more diverse set of operations (*5) usually drop the whole flag part and go either for generation of a more abstract operation result, like a condition code, to be used on a case-by-case basis(*6), or move the whole result/condition testing away from the operation completely (like MIPS, Alpha)



Doing away with flags can



  • simplify software structure and

  • improve performance


*1 - Well, both contain part of the workings within a 6502. The signal for Zero (DBZ) is generated by an 8-input NAND, but that Z not always reflect what's (in the last cycle) on the internal data bus (DB part). After all, this would mean that (for example) in case of a JMP instruction Z would be set according to the high byte of the address.



To avoid this the control logic enable flag setting for Z in a case by case situation via distinct control signals. Within the Hanson diagram they are mentioned as DBI/Z in case of input operations (like LDA #) and DBZ/Z for arithmetic. In hardware it's an OR combination driven by several lines from the decoder PLA detecting certain opcode/sequence cases.



*2 - But beware Gift vs Gift :))



*3 - A rare case where a Wiki entry has at least some information to serve as pointer for details.



*4 - Like parity on a 8080 or zero detection for data by the 6800/6500 series.



*5 - By initial design that is, as 'grown' architectures like x86 have to squeeze them in.



*6 - Basically the same number of markers (avoiding the term Flag on purpose) gets used differently on different instructions. For example on a /370



  • an arithmetic operation produced CC=0 for result zero, CC=1 for negative and CC=2 for positive and CC=3 for overflow

  • A compare operation produces CC=0 for equal, CC=1 for less than and CC=2 for greater than

  • a logic operation produces CC=0 for zero and CC=1 for non zero

  • a bit test operation produces CC=0 for all-zero, CC=1 for mixed and CC=3 for all-one

  • a move long produces CC=0 for all transferred, CC=1 for receive-is-too-short and CC=2 for receive-field-was-padded

  • and so on...

As a result only two bits of condition code are needed to store such an abstract result - and only a single set of test instructions are necessary to act, no matter how different the instruction results are.







share|improve this answer















share|improve this answer




share|improve this answer








edited Jul 15 at 15:11









Community

1




1










answered Jul 14 at 14:34









RaffzahnRaffzahn

74.3k8 gold badges187 silver badges311 bronze badges




74.3k8 gold badges187 silver badges311 bronze badges










  • 1





    Great answer that addresses the question behind the question.

    – Wayne Conrad
    Jul 15 at 16:53












  • 1





    Great answer that addresses the question behind the question.

    – Wayne Conrad
    Jul 15 at 16:53







1




1





Great answer that addresses the question behind the question.

– Wayne Conrad
Jul 15 at 16:53





Great answer that addresses the question behind the question.

– Wayne Conrad
Jul 15 at 16:53











5


















In the case you describe, the 6502 will set the Zero flag (in other words, the Z flag will be one if the operation left the accumulator equal to 0 mod 256). That's convenient, because usually a programmer is interested either in Z, to test for an actual zero condition, or in C, to test for a carry.



The Z80 works in the same way.



My understanding is that it's also easier to implement, since that's effectively an 8-input NAND.






share|improve this answer


























  • For what it's worth, the 68000 acts the same way, even in intentionally open-ended instructions like ADDX — they either clear the zero flag or leave it alone so that the end result is correct for the net total of all handled [bytes/words/long words], but they do it only based on the [8/16/32]-bit result, with no regard for the generated carry/extend.

    – Tommy
    Jul 14 at 13:30















5


















In the case you describe, the 6502 will set the Zero flag (in other words, the Z flag will be one if the operation left the accumulator equal to 0 mod 256). That's convenient, because usually a programmer is interested either in Z, to test for an actual zero condition, or in C, to test for a carry.



The Z80 works in the same way.



My understanding is that it's also easier to implement, since that's effectively an 8-input NAND.






share|improve this answer


























  • For what it's worth, the 68000 acts the same way, even in intentionally open-ended instructions like ADDX — they either clear the zero flag or leave it alone so that the end result is correct for the net total of all handled [bytes/words/long words], but they do it only based on the [8/16/32]-bit result, with no regard for the generated carry/extend.

    – Tommy
    Jul 14 at 13:30













5














5










5









In the case you describe, the 6502 will set the Zero flag (in other words, the Z flag will be one if the operation left the accumulator equal to 0 mod 256). That's convenient, because usually a programmer is interested either in Z, to test for an actual zero condition, or in C, to test for a carry.



The Z80 works in the same way.



My understanding is that it's also easier to implement, since that's effectively an 8-input NAND.






share|improve this answer














In the case you describe, the 6502 will set the Zero flag (in other words, the Z flag will be one if the operation left the accumulator equal to 0 mod 256). That's convenient, because usually a programmer is interested either in Z, to test for an actual zero condition, or in C, to test for a carry.



The Z80 works in the same way.



My understanding is that it's also easier to implement, since that's effectively an 8-input NAND.







share|improve this answer













share|improve this answer




share|improve this answer










answered Jul 14 at 6:33









WilsonWilson

15k7 gold badges70 silver badges164 bronze badges




15k7 gold badges70 silver badges164 bronze badges















  • For what it's worth, the 68000 acts the same way, even in intentionally open-ended instructions like ADDX — they either clear the zero flag or leave it alone so that the end result is correct for the net total of all handled [bytes/words/long words], but they do it only based on the [8/16/32]-bit result, with no regard for the generated carry/extend.

    – Tommy
    Jul 14 at 13:30

















  • For what it's worth, the 68000 acts the same way, even in intentionally open-ended instructions like ADDX — they either clear the zero flag or leave it alone so that the end result is correct for the net total of all handled [bytes/words/long words], but they do it only based on the [8/16/32]-bit result, with no regard for the generated carry/extend.

    – Tommy
    Jul 14 at 13:30
















For what it's worth, the 68000 acts the same way, even in intentionally open-ended instructions like ADDX — they either clear the zero flag or leave it alone so that the end result is correct for the net total of all handled [bytes/words/long words], but they do it only based on the [8/16/32]-bit result, with no regard for the generated carry/extend.

– Tommy
Jul 14 at 13:30





For what it's worth, the 68000 acts the same way, even in intentionally open-ended instructions like ADDX — they either clear the zero flag or leave it alone so that the end result is correct for the net total of all handled [bytes/words/long words], but they do it only based on the [8/16/32]-bit result, with no regard for the generated carry/extend.

– Tommy
Jul 14 at 13:30


















draft saved

draft discarded















































Thanks for contributing an answer to Retrocomputing Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fretrocomputing.stackexchange.com%2fquestions%2f11659%2fbehavior-of-the-zero-and-negative-sign-flags-on-classic-instruction-sets%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown









Popular posts from this blog

Distance measures on a map of a game The 2019 Stack Overflow Developer Survey Results Are Inmin distance in a graphShortest distance path on contour plotHow to plot a tilted map?Finding points outside of a diskDelaunay link distanceAnnulus from GeoDisks: drawing a ring on a mapNegative Correlation DistanceFind distance along a path (GPS coordinates)Finding position at given distance in a GeoPathMathematics behind distance estimation using camera

How to get a smooth, uniform ParametricPlot of a 2D Region?How to plot a complicated Region?How to exclude a region from ParametricPlotHow discretize a region placing vertices on a specific non-uniform gridHow to transform a Plot or a ParametricPlot into a RegionHow can I get a smooth plot of a bounded region?Smooth ParametricPlot3D with RegionFunction?Smooth border of a region ParametricPlotSmooth region boundarySmooth region plot from list of pointsGet minimum y of a certain x in a region

Genealogie vun de Merowenger Vum Merowech bis zum Chilperich I. | Navigatiounsmenü