Section 06 Part 01 – The CCR (Conditional Code Register)

 

 “Never make friends with people who are above or below you in status. Such friendships will never give you any happiness.” ~Chanakya

 

 

 

Introduction

 

Most (If not all) processors have some form of CCR (Conditional Code Register) to keep track of conditions.  These conditions may help determine things like; “Was the byte changed to 00?”, “Is the word now signed negative?”, “Is this byte higher or lower than another byte?”.

 

The purpose of the CCR is to allow you to get the CPU to perform a different action under certain conditions.

 

 

 

Brief Example

 

We’ll have a brief example here using two new instructions, just so you better understand the purpose:

 

 

          cmp.b     #$20,d0

          beq.s     ValueIs20

          move.b    d0,d1

 

ValueIs20:

         

 

The two instructions here are CMP and BEQ.  CMP is CoMPare, which in this example will compare the byte 20 with the byte that is in d0.

 

 

The next instruction BEQ is Branch on Equal, if the result of our CMP is Zero (Equal), then the 68k will branch to the lableValueIs20:” and will continue from there.  If the result of out CMP is Non-Zero (Not Equal), then the 68k will simply continue to the next instruction “move.b d0,d1”, it will not branch.

 

These new instructions will be explained more thoroughly in due time.  The point is, you understand how the 68k can branch off and read other instructions if a byte, word or long-word does not meet the right conditions.

 

 

 

The flags

 

The CCR itself is a byte big, in binary that gives you:

 

CCR – In binary

 

-

-

-

X

N

Z

V

C

0

0

0

0

0

0

0

0

 

As you can see, the 68k has 5 conditional flags:

 

  1. C – Carry
  2. V - oVerflow
  3. Z - Zero
  4. N - Negative
  5. X - eXtended

 

Most instructions of the 68k might set (1), clear (0), reversed, or leave these flags untouched.  Depending on the result.

 

 

 

Carry

 

Let’s say for example, we add a byte to a register:

 

          addi.b    #$04,d0

 

Now, we’ll pretend that d0 contains 000000FE for this example.  So you should know by now, FE + 04 = 102, you should also know that only the 02 is saved into d0, making d0 00000002.   The 1 on the end of 102 (in binary 0001) is saved into the carry flag, because it cannot fit into the byte, it is therefore “carried over”.  The carry flag is set.

 

If d0 contained 00000090 instead, 90 + 04 = 94, d0 now contains 00000094, and the “carried over” value is 0 (0000).  The carry flag is cleared.

 

The same applies to using instructions such as LSR, for shifting right.  Any bit that gets shifted out of the register/memory space, is carried over into the carry flag.

 

 

 

Overflow

 

Imagine for a moment that d0 contains 0000007D:

 

          addi.b    #$04,d0

 

After this d0 will contain 00000081, now, if you treat the byte as signed, 7D is positive, while 81 is negative.  This change from positive to negative will set the overflow.

 

The idea is, 7D + 04 = 0081, Positive + Positive = Positive.

 

But since only a byte of 0081 is saved, that means the answer is 81, it is not negative, which makes no sense from a mathematical point of view.  You can’t have Positive + Positive = Negative.  So, the overflow flag is set.

 

The same will apply if Negative + Negative = Positive.

 

 

 

Zero

 

This is the simplest of them all, we’ll pretend that d0 contains 0024000C:

 

          subi.b    #$0C,d0

 

After this d0 will contain 00240000, 0C – 0C = 00.  Because the byte is zero, the Zero flag is set.  If the byte were not zero, then the Zero flag would be cleared.

 

 

 

Negative

 

This one is quite simple too, we’ll imagine that d0 contains 00049044:

 

          addi.w    #$0100,d0

 

9044 + 0100 = 9144.

 

The word in d0 is negative, so the Negative flag is set.  If the result were positive, the Negative flag would be cleared.

 

 

 

Extended

 

This is the same as the carry flag; it will be set or cleared depending on the value that is “carried over”.

 

However, not all instructions that change the carry flag will change the extended flag.  The idea is that you can have an instruction that will change the conditions of both C and X, and then later have an instruction that will change the condition of the C flag, but leaving the X flag alone un-tampered with.

 

 

 

Debriefing

 

Here’s another set of instructions including the BEQ instruction:

 

          addi.b    #$20,d0

          beq.s     ValueIsNull

          move.b    d0,d1

 

ValueIsNull:

         

 

Now, we’ll pretend that d0 contains 0048F0F0.  The ADD instruction adds byte 20 to d0, so 20 + F0 = 110.  Of course, only the 10 is saved, so now d0 contains 0048F010.

 

Now, the CCR is dealt with, so first the C and X flags.  They are both set here because 110 is too big to fit into a byte, so the 1 on the end (in binary 0001) is saved into the C and X.

 

Next, the Z flag, since the resulting byte is 10, that is not zero, therefore the Z flag is cleared.

 

Next, the V flag, since the equation is positive + negative = positive (20 + F0 = 10), it is perfectly valid, therefore the V flag is cleared.

 

Finally, the N flag, since the resulting byte is 10, which is a positive byte, the N flag is cleared for not being negative.

 

CCR – In binary

 

-

-

-

X

N

Z

V

C

0

0

0

1

0

0

0

1

 

So that’s the CCR sorted.  The next instruction “beq.s ValueIsNull” Branch on Equal, this will check the Z flag.  Is the Z flag set?  No, so the result is non-zero (Not equal).  And so, the 68k will not branch, and instead will continue to the “move.b d0,d1” instruction.

 

 

 

Reference

 

Since all instructions set/clear/change different flags for different reasons, you must NOT rely on the above debriefing as an example for all situations.  I strongly suggest picking up a 68k quick reference manual from somewhere (you can find them easily online).  It will tell you which instructions will set/clear which CCR flags.

 

 

 

Previous Part

Main Page

Next Part