6. Shift Instructions

Part of the Hawk Manual
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

Contents

6.1. Shift Format
6.2. Left Shift
6.3. Right Shift
6.4. Bit Testing


6.1. Shift Format

07060504 03020100 15141312 11100908
1 0 - - dst s1 s2

Shift instructions are 16 bits each, specifying a source register (s1), a destination register (dst) and a shift count s derived from (s2).

if (s2 ≠ 0)
then s = s2
else s = 16

Note that shift counts from 1 to 15 use the conventional binary encoding, but a count of 16 is encoded as zero. Assemblers should automatically limit shift counts to the range 1 to 16 and take care of the encoding.

6.2. Left Shift

07060504 03020100 15141312 11100908                        
1 0 1 1 dst (x) s1 (nz) s2 (16) MOVESL dst,s1,s r[dst] = r[s1]«s
1 0 1 0 dst (nz) s1 (0) s2 (16) ADDSL dst,s1,s r[dst] = r[dst]«s + r[s1]

MOVESL    N = r[dst]:31  — result is negative                    
Z = (r[dst] = 0)  — result is zero
V = (r[dst]:31 ≠ r[src]':31)
C = (r[s1]'«s) > 232-1
 
ADDSL N = r[dst]:31
Z = (r[dst] = 0)
V = ( r[dst]:31 ⊕ ( r[dst]':31 ≡ r[s1]':31 ))
C = (r[dst]'«s + r[s1]') > 232-1

MOVESL (move and shift left) moves an operand from the source register r[s1] to register r[dst] while shifting left. The source must not be r[0]; if r[0] is used, it will cause an illegal instruction trap (see Chapter 13). Assemblers should flag MOVESL Rd,R0,c as an error.

ADDSL (add and shift left) first shifts the destination register r[dst] left and then adds in the source register r[s1]. The destination must not be r[0]; if r[0] is used, it will cause an illegal instruction trap (see Chapter 13). Assemblers should flag ADDSL R0,Rs,c as an error.

After MOVESL and ADDSL, the conditon codes will be set to reflect the result; if any one bits are shifted out of r[dst] or if the add results in a carry out, the C bit will be set; if the sign of r[dst] is different from the expected sign, the V bit will be set, and N and Z will be set if the result is negative or zero.

When r[0] is used as a source register for ADDSL, the constant zero is used. The net result is that the destination register r[dst] is simply shifted left. Because of this, assemblers should support SL Rd,c (shift left) as a synonym for ADDSL Rd,R0,c.

07060504 03020100 15141312 11100908                        
1 0 1 0 dst (nz) 0 0 0 0 s2 (16) SL dst,s r[dst] = r[dst] « s

ADDSL is useful for array indexing. Given that R3 points to an array and R4 contains a displacement into the array, if array elements have sizes that are powers of two, ADDSL R4,R3,c can be used to compute the address of the correct array element in R4.

Single ADDSL and SL instructions can be used to multiply by many common constants (see Section 14.1):

        SL     R1,1       ; multiply R1 by 2
        ADDSL  R1,R1,1    ; multiply R1 by 3
        SL     R1,2       ; multiply R1 by 4
        ADDSL  R1,R1,2    ; multiply R1 by 5
        SL     R1,3       ; multiply R1 by 8
        ADDSL  R1,R1,3    ; multiply R1 by 9

6.3. Right Shift

07060504 03020100 15141312 11100908                        
1 0 0 1 dst (x) s1 (0) s2 (16) ADDSR dst,s1,s r[dst] = (r[dst]+r[s1])»s
1 0 0 0 dst (x) s1 (0) s2 (16) ADDSRU dst,s1,s r[dst] = (r[dst]+r[s1])›»s

ADDSR    
ADDSRU
N = r[dst]:31  — result is negative                    
Z = (r[dst] = 0)  — result is zero
V = ((r[dst]' + r[s1]'):s-1:0 ≠ 0)
C = (r[dst]' + r[s1]'):s-1

ADDSR (add and shift right) ADDSRU (add and shift right, unsigned) both add r[src] to r[dst] and then shift r[dst] to the right. ADDSR uses a signed shift, duplicating the sign bit, while ADDSRU uses an unsigned shift, shifting zeros into the left end of the result. The intermediate result between the add and shift is a 33 bit quantity, and as a result, overflow will not occur.

After ADDSR and ADDSRU, N and Z will be set as usual to report results that are negative or zero. Note that ADDSR never has a negative result. V will be set if any one bits are shifted out of the result, and C will be set to the last bit shifted out.

When r[0] is used as a source register for ADDSR or ADDSRU, the constant zero is used. The net result is that the destination register r[dst] is simply shifted right. Because of this, assemblers should support SR Rd,c (shift right) as a synonym for ADDSR Rd,R0,c and SRU Rd,c (shift right unsigned) as a synonym for ADDSRU Rd,R0,c.

07060504 03020100 15141312 11100908                        
1 0 0 1 dst (x) 0 0 0 0 s2 (16) SR dst,s r[dst] = r[dst] » s
1 0 0 0 dst (x) 0 0 0 0 s2 (16) SRU dst,s r[dst] = r[dst] ›» s

SRU allows fast division of unsigned numbers by powers of two (see Section 14.1).

        SRU    R1,1       ; unsigned divide by 2, truncated
        SRU    R1,2       ; unsigned divide by 4, truncated
        SRU    R1,3       ; unsigned divide by 8, truncated

ADDC can be used to round the quotient to the nearest integer (see Section 10.3):

        SRU    R1,1       ; unsigned divide by 2, truncated
        ADDC   R1,R0      ; round to nearest integer

SR allows division of signed numbers by powers of two, but note that the result will be truncated down toward negative values, not truncated toward zero. Thus (–3)/2 will be –2 with a remainder of 1 instead of –1 with a remainder of –1.

        SR     R1,1       ; signed divide by 2, truncated down
        SR     R1,2       ; signed divide by 4, truncated down

ADDC works with SR to round the result to the nearest integer:

        SR     R1,1       ; unsigned divide by 2, truncated
        ADDC   R1,R0      ; round to nearest integer
ADJUST works with SR to truncate the result toward zero (see Section 11.2):
        SR     R1,2       ; unsigned divide by 4, truncated
        ADJUST R1,SSQ     ; truncate result toward zero

6.4. Bit Testing

Any bit in a register can be tested using one of three instructions:

In each case, the test is done with register zero as the destination register. It is confusing that a different condition code is set when testing different bits of a word. To simplify this, assemblers should support BITTST src,b as a synonym for one of the above, depending on the bit number b being tested.

07060504 03020100 15141312 11100908                        
1 0 0 1 0 0 0 0 s1 (0) s2 (16) BITTST s1,s-1 0 ≤ b ≤ 15: s = b + 1
1 0 1 1 0 0 0 0 s1 (nz) s2 (16) BITTST s1,31-s 16 ≤ b ≤ 30: s = 31 - b
1 1 1 1 0 0 0 0 1 1 1 0 x BITTST x,31 b = 31

The assembler should generate one or the other of the above BITTST instructions, depending on the bit number provided. BITTST r,0 tests the least significant bit and BITTST r,31 tests the most significant bit.

Because the condition code to be tested depends on the bit that was tested, BITTST should define or redefine the BBS (branch on bit set) instruction to be equivalent to either BCS or BNS, and the BBR (branch on bit reset) instruction to be equivalent to either the BCR or BNR instruction, depending on the bit tested (see Section 12.2). BITTST followed immediately by BBS or BBR will always check the correct condition code.