6

As I work on implementing support for old architectures for the Reko decompiler (https://github.com/uxmal/reko) I notice over and over how consistently most 1980's CPUs echo a pattern.

Since an overflow or carry cannot result from a logical operation like AND or OR, it seems like the designers could have chosen to design the CPU to not change the "carry" and "overflow" bits. However what I'm seeing almost universally is that whenever a logical operation like AND or OR is performed, the "carry" flag and the "overflow" status flags are cleared, while the "sign" or "negative" and "zero" flags are set according to the result of the operation.

I remember, from my old Z80 programming days, using this side effect to clear the carry flag with an and a instruction; this was already common practice back in the 1980's.

When was this convention of clearing the carry and overflow flags after a logical operation introduced, how deliberate was it, and which CPU architecture implemented it?

9
  • 3
    In the Z80's case overflow is an add-on that shares physical space with with the parity carry-over from the 8080. So that explains why overflow isn't generally preserved there; wherever an operation populated the parity bit on an 8080 it must overwrite any existing overflow state in order to preserve backwards compatibility. Comment not answer because the question isn't about the Z80's specific decisions.
    – Tommy
    Jul 25 at 15:24
  • 1
    Another comment-not-answer: If preserving flags for some operations would have required more gates and wasn't needed enough to justify the transistor count, then it wasn't done. Jul 25 at 15:43
  • 1
    Given that not all CPUs had those bits, the question must be rephrased.
    – Leo B.
    Jul 25 at 16:14
  • 2
    It may be useful to narrow down what the restrictions of '1980s' and 'most' are based on and how they are to be answered. I can come up with quite some CPU designes that do not fit that assumption (6800, 6502, Z8, 2650, ...)
    – Raffzahn
    Jul 25 at 17:57
  • Are you just looking at microprocessors or are you interested in CPUs of older minis/mainframes like Prime, Data General, IBM, ICL, Burroughs etc.
    – cup
    Jul 26 at 5:12

1 Answer 1

8

TL;DR:

I wonder if that observation is heavily biased by looking at today's all-influencing x86 architecture and its direct predecessors (x80). From my memory the described behaviour is only shown by a small minority of CPU designs. That is unless 'most' is measured by sold units (*1).


Details

Which CPU was the first to clear the carry and overflow bits after performing logical operations?

Asking for a first only makes sense if there is a linage (see below) but not in general.

notice over and over how consistently most 1980's CPUs echo a pattern.

Well, no designer lives on an island.

Since an overflow or carry cannot result from a logical operation like AND or OR, it seems like the designers could have chosen to design the CPU to not change the "carry" and "overflow" bits.

Which is what many did.

However what I'm seeing almost universally is that whenever a logical operation like AND or OR is performed, the "carry" flag and the "overflow" status flags are cleared, while the "sign" or "negative" and "zero" flags are set according to the result of the operation.

It may be very helpful if you could add some information on which you base this claim of being 'almost universal' as I can come up with many CPUs not clearing one or both of them.

If possible with a separation between original designs and designs that inherited that behaviour due to the need for compatibility.

I remember, from my old Z80 programming days, using this side effect to clear the carry flag with an and a instruction; this was already common practice back in the 1980's.

Not sure why this should be called 'common practice' as it's the explicit behaviour of the Z80, which inherited it, due to the requirement of full compatibility of carry handling from the 8080, and it in turn from the 8008. Thus the Z80 couldn't introduce an OV of its own but had to repurpose the Parity flag. And in turn the 8086 and all its offspring also had to work that way. No freedom of choice here.

When was this convention of clearing the carry and overflow flags after a logical operation introduced,

That's the first time I'm hearing of that being a convention.

how deliberate was it,

While there are many independent designs, not all had the freedom to decide - especially not the ones that were all about preserving compatibility, foremost visible here the 8008/8080/Z80/8086 lineage.

and which CPU architecture implemented it?

Since you already state that a majority according to your own research does it, it might be more useful to ask which didn't.

The World According to Flags

I can right from the top of my mind come up with a whole lot of CPUs with different behaviour:

  • No change at all, except arithmetic (i.e. non logical):

  • Partial change outside of arithmetic (in most cases clearing OV leaving C unchanged)

    • Zilog Z8 - All ALU operations, i.e including logical (*4)
    • Motorola 68xx - All instructions loading a register (that is including logical)
    • PDP-11 - Most instructions clear OV
    • PDP-11 - All shift set OV to Carry XOR Negative (*3)
  • And then there are those that update all flags with all ALU operations with the result of that operation - or a default value where that flag has no meaningful value. Usually 0.

    • Motorola 68000 - Clear both
    • Z80/8086/etc. - Clears both (*4)

    Interesting that the two most dominant microprocessors of the 1980s fall into that group... that wouldn't by accident create a bias, or would it?

  • Then there are similar ones but without an Overflow Flag, so only Carry gets modified with each ALU operation

    • 8008/8080/8085

    And there you also got one lineage coming from a first, Datapoint 2200 clearing Carry with logic instructions and going all the way to today's (somewhat) most used designs.

  • And then there's the odd bunch:

    • Transputer - A single Error Flag does everything :))
    • NS 16/32xxx - Logical operations change no flags at all

Looking below

Especially the (in)famous PDP-11 gives insight about a basic difference between

  • machines that produce a full or partial condition code and
  • machines that handle and update status flags.

The first is a class where each and every (non-special) instruction results in a new condition code, which may or may not include previous information. The IBM /360 might be the most clear and well known. Here instructions do not set flags but result in an abstract condition code in form of a single value (0..3). The PDP-11 is also a condition-code machine, but here it's represented as 4 bits which may be handled separately depending on instruction.

The second class handles flags as single bits and updates them independently according to instruction and only when either bit is meaningful to that instruction - except they are so simple that they update it always after an ALU operation.


*1 - Even then, the answer may still be some other family hidden in anything from toothbrushes all the way to forklifts :))

*2 - Which funnily enough only got Carry and Overflow as fixed ALU flags :))

*3 - It might be established that I'm not exactly a fan of the PDP-11, but that little piece always intrigued me. Noting a sign change can be quite handy after some operations.

*4 - The Z8 behaving differently from the 8080/Z80 is a nice hint that at least one of the 8080 creators wasn't all that happy with setting both by all ALU operations.

5
  • 1
    The 68000 is more complicated. It has two carry flags: C and X. Some operations (AND, MOVE are examples) clear C and V but leave X unaffected. ABCD changes C and X but leaves V apparently in an undefined state. I take that to mean V is set as if you were doing a normal ADD but it is meaningless for binary coded decimal.
    – JeremyP
    Jul 26 at 9:00
  • @JeremyP 'more complicated' can be said about next to any of those (the 8080 does as well do a Half Carry) as none is just about Carry and Overflow -but the question is.
    – Raffzahn
    Jul 26 at 9:59
  • 1
    You can add Sharp ESR-H (SC61860) embedded CPU family used in the Sharp Pocket Computers of the '80s to the family of those that do not touch the C flag for logical instructions (the cpu does not have a V flag). Jul 26 at 10:35
  • 1
    @PatrickSchlüter yeah, nice one. Above was just a quick list from memory to show there being a whole lot of CPUs showing a different behaviour. IMHO, if one really want's to fine a majority behaviour, then it may be rather not clearing C/OV for logic operations.
    – Raffzahn
    Jul 26 at 10:48
  • Z80 introduced P/V flag as to allow JP PO/PE jumps sense the overflow without introducing completely new jumps, and the binary compatibility actually was broken here: in 8080 ADD/SUB would still set parity flag with the parity of the result. Apart from keeping JP PO/PE, there was no reason in sticking overflow to already existing flag, in fact Z80 introduced a new flag in a flag register (add/subtract one) and made unused bits there effectively random, in contrast with being perfectly constant in 8080.
    – lvd
    Jul 27 at 15:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .