Skip to content

Arithmetic instructions

wassekaran edited this page Mar 31, 2018 · 10 revisions

You will see this CPU supports only few kinds of operations - additions, shifts and inversion of bits. Let us start with simplest of them.

###Inversion

  • CMC - complements (inverts) Carry;
  • CMA - complements (inverts) Accumulator;

These two are quite straightforward. We can rewrite them in Python in several ways:

#CMC:
cy = 1 - cy
#or
cy ^= 1

#CMA:
acc = 15 - acc
#or
acc ^= 0xF

###Addition

  • ADD - adds some register (and Carry flag) to Accumulator (i.e. add r2)

This is more complicated than you may expect. It sums 3 operands:

result = acc + reg + cy

And then result is stored in Accumulator (lower 4 bits) and Carry (highest bit):

cy = result >> 4
acc = result & 0xF

So before addition Carry should be cleared if it is not wanted. After operation it could be used for summation of higher digits. Let us see an example of adding 0x59 to 0x38:

fim r0 $59   ; r0 = 5  and  r1 = 9
fim r2 $38   ; r2 = 3  and  r3 = 8

; summing lower digits (9 and 8)
clc          ; carry = 0
ld r1        ; acc = r1
add r3       ; acc += r3
xch r1       ; store result back to r1
             ; we do not clear carry after that!
; summing higher digits (5 and 3)
ld r0        ; acc = r0
add r2       ; acc += r2
xch r0       ; store result to r0

see demo

After these operations r0:r1 shows results of $91. You see that when we summed higher nibbles (5+3) the Carry was also added from previous summation. You can check correctness with your calculator (if it supports hexadecimal values).

###Subtraction

As a matter of fact CPU performs this operation via addition and inversion:

  • SUB - subtracts some register (and Carry) from Accumulator (i.e. sub r3)

it is logically the same as:

result = acc + inversion(reg) + cy
#or
result = acc + (reg^0xF) + cy

Further the result is processed in the same way as with normal addition, so the SUB instruction is really a shorthand for sequence of CMA and ADD. Note that Carry should be set before this operation.

What is the meaning of Carry after this operation? If you will study it with pencil and paper you will find that:

  • Carry is set to 1 if Acc was greater than or equal to reg - i.e. if there was no "borrow";
  • Carry is set to 0 otherwise (e.g. if we calculate 3 - 5) - meaning that borrow was generated.

This means that Carry could be used for subtracting long values digit-by-digit. We start subtracting lowest digits and if borrow was generated, Carry is 0 instead of 1 and hence the next-higher digit is automatically decremented by 1 during the next subtraction.

###Increment and Decrement

As there are no instructions to add or subtract constant (without loading it to register), few shorthand instructions for changing value by 1 exist:

  • IAC - increments accumulator by 1
  • DAC - decrements accumulator by 1
  • INC - increments some register (i.e. inc r12)

Carry is changed by IAC and DAC in the same manner as by ADD and SUB. (however it itself does not affect result so you need not clear it first)

Meanwhile INC does not change Carry at all.

Note there is ISZ - a special version of increment for register, which is discussed in article about jumps (because it also is a jump instruction).

###Shifts or Rotations

These operations are bitwise shifts. The only tricky moment is that Carry is involved along with Accumulator. See the following diagram:

a3 - a2 - a1 - a0
|               |
\----- cy ------/

Bits of Accumulator (4 at all) are linked into loop (or necklace) with Carry. So when they are rotated left or right one of the bits is moved to Carry, while previous value of Carry itself is copied to Accumulator.

  • RAL - shifts (rotates) Accumulator left, moving its highest bit to Carry and previous value of Carry itself to the lowest bit of Accumulator
  • RAR - shifts (rotates) Accumulator right, moving its lowest bit to Carry and previous value of Carry to the highest bit of Accumulator

See this example to understand these operations better.

There is also a special instruction which is somewhat related to shifts:

  • TCC - "transfer carry and clear" - moves Carry to Accumulator (while highest bits of Acc and Carry itself are cleared to zeroes)

It could be used in Addition operations, especially in increment of long value.


Next: If and GoTo - or Jump instructions