DevBlogs
August 8th, 2019

# The SuperH-3, part 4: Basic arithmetic

Okay, we’re ready to do some arithmetic. Due to the limited instruction encoding space, there isn’t room for any three-operand instructions.Â¹ All of the arithmetic instructions are two-operand, where the second source operand also acts as the destination.

```    ADD     Rm, Rn      ; Rn += Rm    , no effect on T
ADD     #imm, Rn    ; Rn += imm   , no effect on T
ADDC    Rm, Rn      ; Rn += Rm + T, T receives carry
ADDV    Rm, Rn      ; Rn += Rm    , T receives signed overflow
```

The `ADD` instructions add two values and put the result in the second register. You can add two registers together, or you can add a signed 8-bit immediate to the destination register.

The `ADDC` instruction treats the T flag as a carry flag: It is added to the sum, and it receives the carry of the result.

The `ADDV` instruction treats the T flag as an overflow flag: It reports whether a signed overflow occurred.

Okay, subtraction is going to look really similar now.

```    SUB     Rm, Rn      ; Rn -= Rm    , no effect on T
SUB     #imm, Rn    ; Rn -= imm   , no effect on T
SUBC    Rm, Rn      ; Rn -= Rm + T, T receives borrow
SUBV    Rm, Rn      ; Rn -= Rm    , T receives signed underflow
```

Basically the same as addition, except you’re now subtracting. The SH-3 treats T as a borrow flag in the case of `SUBC`, whereas for `SUBV` it reports whether a signed underflow occurred.

Arithmetic negation is up next.

```    NEG     Rm, Rn      ; Rn = -Rm    , no effect on T
NEGC    Rm, Rn      ; Rn = -Rm - T, T receives borrow
```

There is no `NEGV`, but overflow occurs only if the value is `0x80000000`, so I guess you could test for that value specifically.

There is a special instruction for for decrementing a register:

```    DT      Rn          ; Rn = Rn - 1, T  = (Rn == 0)
```

The decrement and test instruction decrements a register and compares the result against zero. This is presumably for counted loops.

Next come the comparison instructions.

```    CMP/EQ #imm, r0     ; T = (r0 == signed 8-bit immediate)
CMP/EQ Rm, Rn       ; T = (Rn == Rm)
CMP/HS Rm, Rn       ; T = (Rn â‰¥ Rm), unsigned comparison
CMP/GE Rm, Rn       ; T = (Rn â‰¥ Rm),   signed comparison
CMP/HI Rm, Rn       ; T = (Rn > Rm), unsigned comparison
CMP/GT Rm, Rn       ; T = (Rn > Rm),   signed comparison
CMP/PZ Rn           ; T = (Rn â‰¥ 0),    signed comparison
CMP/PL Rn           ; T = (Rn > 0),    signed comparison
CMP/STR Rm, Rn      ; T = 1 iff any corresponding bytes are equal
```

These instructions set the T flag according to a particular comparison. Note that the comparison is backward! For example, `CMP/GE r1, r2` does not check whether r1Â â‰¥Â r2; rather, it checks whether r2Â â‰¥Â r1. This takes a lot of getting used to.

You have the special ability to compare r0 for equality with a signed 8-bit immediate. Otherwise, you can compare two registers against each other, or a register against zero.

The special `CMP/STR` compares two registers to determine whether any of the four component bytes are equal. It’s clear from the mnemonic that the intended purpose is to search for a null terminator in a string. You set Rn to zero and then do a `CMP/STR` against every longword in the string until it says, “Hey, I found a zero byte!” and then you can study that longword to see where the zero byte is.

The processor documentation doesn’t explain why they chose the names for the mnemonics, but I can guess.

Condition Meaning
`EQ` equal
`HS` high or same
`GE` greater or equal
`HI` high
`GT` greater than
`PZ` plus or zero
`PL` plus
`STR` string

It took me a while to come up with a plausible explanation for `HS`.

Exercise 1: Synthesize the `SETT` and `CLRT` instructions.

Exercise 2: Perform the opposite of the `MOVT` instruction: Set the T register to 0 if a register is zero, or 1 if the register is nonzero.

The last arithmetic instructions are the extension instructions.

```    EXTS.B Rm, Rn       ; sign extend byte in Rm to Rn
EXTS.W Rm, Rn       ; sign extend word in Rm to Rn
EXTU.B Rm, Rn       ; zero extend byte in Rm to Rn
EXTU.W Rm, Rn       ; zero extend word in Rm to Rn
```

That’s it for the basic arithmetic instructions. We’ll start looking at the more complicated arithmetic instructions next time, starting with multiplication.

Â¹ Well, okay, you can have three-operand instructions if some of them are hard-coded! But that’s not what I mean. I mean three-operand instructions where the programmer can choose all three of the operands.

Topics
History

## Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

Popular
Oldest
• Alex Nesemann

The comparison mnemonics come from the Motorola 68000's branch instructions. Hitachi was a major second source of 68Ks, so it's not much of a suprise that they borrowed from it.
CMP/STR is handy when searching for any byte, not just zeroes. Just replicate the byte value in the register. If you're looking for ASCII 'a', you would compare with 0x61616161.
SETT -> CMP/EQ R0, R0
CLRTT -> CMP/NE R0, R0

• Kasper Brandt

> T receives signed underflowAn underflow is when a floating point number is too small to be representable. A negative overflow is still an overflow.

• Neil Rashbrook

> It took me a while to come up with a plausible explanation for `HS`.

I think ARM uses `HS` as a synonym for `CS` (carry set). (But then again it use a single comparison operator corresponding to (most of) these with multiple conditions on instructions.)

• Harry Johnston

I think this will work for exercise 2, but I’m not certain that I’ve understood the meaning of “borrow” correctly:

```CLRT
NEGC R0, R0
NEG R0, R0```
• Daniel Sturm

I had to look up the exact semantics too. The ISA description gives it as follows (this will look awful I’m sure but I hope it’ll be readable)

```NEGC(long m,long n) /* NEGC Rm,Rn */
{
unsigned long temp;
temp=0-R[m];
R[n]=temp-T;
if (0<temp) T=1; else T=0;
if (temp<R[n]) T=1;
PC+=2;
}```
• Zak Larue-Buckley

Exercise 1:
CMP/EQ r0, r0 => T = 1
CMP/HI r0, r0 => T = 0

Exercise 2:
CMP/PL Rx => T = Rx > 0…but won’t work for negative Rx. Can’t think of way to solve without destroying Rx.