# Shift and rotate instructions

Opcode | P/U | Category | Description |

`ASL` |
user | ALU: shift-rotate | arithmetic shift left |

`ASR` |
user | ALU: shift-rotate | arithmetic shift right |

`LSL` |
user | ALU: shift-rotate | logical shift left |

`LSR` |
user | ALU: shift-rotate | logical shift right |

`ROL` |
user | ALU: shift-rotate | rotate left |

`DSL`

(double shift left) is a multiply instruction, not a shift and rotate instruction.

Dauug|36’s shift instructions have unconventional terminology.

**Arithmetic shift** means multiplication or division by a power of two, rounding towards negative infinity in the case of division. In traditional forums, arithmetic shift means that a signed number is being shifted. But my position is that it’s moot whether the number is unsigned or unsigned. What is important is whether the intent is to perform arithmetic, and if this is the intent, the result must be tested for overrange irrespective of signedness.

**Logical shift** means a shift in the absence of any intent to multiply or divide. Logical shifts are not tested for overflow, because the bits involved do not represent quantities.

The architecture does not need or have an `ROR`

instruction to rotate right, because `ROL`

does that just fine.

`ASL`

Arithmetic shift left

Syntax |

`c = a asl cw` |

Register | Signedness |

Left | unsigned or signed |

Right | ignored |

Destination | unsigned or signed |

4 opcodes total |

Flag | Set if and only if |

`N` |
`a` < 0 |

`Z` |
`a` = 0 |

`T` |
`c` cannot fit entire result |

`R` |
`T` is set or `R` is already set |

The 2-instruction `PSL`

(prepare to shift left) and `ASL`

(arithmetic shift left) sequence enables safe, range-checked power-of-two multiplication, despite its many signedness combinations and corner cases. `ASL`

multiplies left operand `a`

by a non-negative power of two, and writes the product’s 36 least significant bits to destination `c`

. If the full result does not fit in `c`

without loss of information, the `T`

and `R`

flags will be set. Otherwise, `T`

is cleared and `R`

does not change.

The `PSL`

macro is used to convert the desired exponent of two into control word `cw`

. This exponent is clamped to a maximum of 36, and then copied into all tribbles.

*Note: PSL, like all macros, is not yet implemented. Construct cw another way.*

`ASR`

Arithmetic shift right

Syntax |

`c = a asr cw` |

Register | Signedness |

Left | unsigned or signed |

Right | ignored |

Destination | unsigned or signed |

4 opcodes total |

Flag | Set if and only if |

`N` |
`a` < 0 |

`Z` |
`a` = 0 |

`T` |
`c` cannot fit entire result |

`R` |
`T` is set or `R` is already set |

The 2-instruction `PSR`

(prepare to shift right) and `ASR`

(arithmetic shift right) sequence enables safe, range-checked division by powers of two, despite its many signedness combinations and corner cases. `ASR`

divides left operand `a`

by a non-negative power of two with rounding towards negative infinity, and writes the quotient’s 36 least significant bits (the 36 bits left of the radix mark, that is, the integer part of the quotient) to destination `c`

. If the rounded quotient does not fit in `c`

without loss of information, the `T`

and `R`

flags will be set, otherwise `T`

is cleared and `R`

does not change.

Note that because of the rounding towards negative infinity, `ASR`

is not (for most purposes) a stand-alone means for dividing by powers of two numbers that are or may be negative.

The `PSR`

macro is used to convert the desired exponent of two into control word `cw`

. If the exponent is 36 or more, it is clamped to 36. If the exponent is zero, it is left as zero. Otherwise, the exponent is subtracted from 36 in order to represent it from the internal hardware perspective of a left rotation. After this clamping, leaving as zero, or subtracting, the exponent is copied to all tribbles.

*Note: PSR, like all macros, is not yet implemented. Construct cw another way.*

`LSL`

Logical shift left

Syntax |

`c = a lsl cw` |

Register | Signedness |

All | ignored |

1 opcode only |

Flag | Set if and only if |

`N` |
bit 35 of the result is set |

`Z` |
all result bits are zero |

`T` |
flag does not change |

`R` |
flag does not change |

`LSL`

(logical shift left) shifts the bits of register `a`

left. Bits shifted out are discarded, and bits shifted in are zeros. The number of positions to shift may not be negative, and must be copied into every tribble of control word `cw`

.

The `PSL`

macro can convert any unsigned value into a suitable control word. `N`

and `Z`

are set as if the destination is a signed register. `T`

and `R`

are not changed by `LSL`

or any preceding `PSL`

.

*Note: PSL, like all macros, is not yet implemented. Construct cw another way.*

`LSR`

Logical shift right

Syntax |

`c = a lsr cw` |

Register | Signedness |

All | ignored |

1 opcode only |

Flag | Set if and only if |

`N` |
bit 35 of the result is set |

`Z` |
all result bits are zero |

`T` |
flag does not change |

`R` |
flag does not change |

`LSR`

(logical shift right) shifts the bits of register `a`

right. Bits shifted out are discarded, and bits shifted in are zeros. The number of positions to shift may not be negative, is specified from the perspective of a *left* rotation, and must be copied into every tribble of control word `cw`

.

The `PSR`

macro can convert any unsigned value into a suitable control word. `N`

and `Z`

are set as if the destination is a signed register. `T`

and `R`

are not changed by `LSR`

or any preceding `PSR`

.

*Note: PSR, like all macros, is not yet implemented. Construct cw another way.*

`ROL`

Rotate left

Syntax |

`c = a rol cw` |

Register | Signedness |

All | ignored |

1 opcode only |

Flag | Set if and only if |

`N` |
bit 35 of the result is set |

`Z` |
all result bits are zero |

`T` |
flag does not change |

`R` |
flag does not change |

`ROL`

(rotate left) rotates the bits of `a`

. The number of positions to rotate must be specified from the perspective of a left rotation, may not be negative, and must be copied into every tribble of control word cw. The `PRL`

and `PRR`

macros offer a range-checked mechanism to set up the control word for left and right rotations. `N`

and `Z`

are set as if the destination is a signed register. `ROL`

will not change `T`

or `R`

, although a preceding `PRL`

and `PRR`

may.

Unlike left and right shifts, left and right rotations are limited to 63 positions due to their repetition modulo 36. Evaluating a shift of more than 63 positions modulo 36 is computationally expensive and is not directly supported by Dauug|36. This is why `PRL`

and `PRR`

have to include a range check.

Again, there is no `ROR`

instruction to rotate right. `ROL`

is the instruction to rotate right or left. Remember also that the amount to rotate by is never negative.

*Note: PRL and PRR, like all macros, is not yet implemented. Construct cw another way.*