# Section 3 / Bit Fields / Review of Newly Described Instructions

## Overview

Our discussion of implementing ourselves what the C / C++ compiler gives
us led us to use six new instructions. This chapter reviews those
instructions. In addition to describing what an instruction does, we
will try to indicate what the instruction is "good for."

## `and`

The `and` instruction is pretty much what you would expect. It
implements the `&` operator from C and C++. That is, the bitwise and
operator.

The `and` instruction comes in a number of flavors including for
use with immediate values.

### `and` Immediate

This is the form of the instruction we used.

```asm
    and    rd, rs, imm
```

This performs a bitwise and of the `imm` value with the source register
`rs` placing the result in the destination register `rd`.

There are limits to the bit width of `imm` because it has to fit within
the `and` instruction. If you exceed the allowable width of `imm`, the
assembler will be glad to insult you.

It is possible that a `mov` instruction will allow your immediate value.
You'd follow up with an `and` using a register than an immediate value.

If your immediate value is too large for a `mov` then put the value in
RAM and `ldr` it into a register and proceed.

We would love to tell you what the rules are for an immediate value in
the `and` instruction, but they are not obvious and in fact are very
complex. Our advice, try the immediate value you have in mind and if it
works, great. Otherwise, see above.

A slight variation on this `and` instruction uses a register where the
preceding one uses an immediate value.

```asm
    and    rd, rs, rm
```

This ands `rm` to `rs` and places the result in `rd`.

This instruction has a variation:

```asm
    and    rd, rs, rm, *shift* num_bits
```

`*shift*` can be one of `lsl`, `lsr`, `asr` or `ror`.

These mean:

| `*shift*` | Meaning | Meaning of the Meaning |
| --------- | ------- | ---------------------- |
| `lsl` | logical shift left | shifts left introducing zeros on the right |
| `lsr` | logical shift right | shifts right introducing zeros on the left |
| `asr` | arithmetic shift right | shifts right introducing duplicates of the previous most significant bit |
| `ror` | rotate right | shifts right introducing the bits shifted out back in from the left |

There are other two similar `and` instructions. These are the immediate
and the register versions of `ands`. `ands` is the same as `and` with
the addition that the CPU's condition bits are updated by the
instruction permitting a conditional branch to follow the instruction.

*`and` is the basis of bit bashing and is used to clear bits.
Put `and` together  with the or instructions and a couple of other basic
logic instructions, out pops a computer.*

A shorthand way of clearing specific bits is the `bic` instruction.
Use of `bic` can avoid having to negate the bits in a mask prior to
and'ing.

## `bfi`

This instruction mnemonic stands for Bit Field Insert. The word *Insert*
should really be copy. The official ARM
[documentation](https://developer.arm.com/documentation/dui0801/g/A64-General-Instructions/BFI)
explains this instruction very well so we'll repeat it here:

*Bit Field Insert copies any number of low-order bits from a source
register into the same number of adjacent bits at any position in the
destination register, leaving other bits unchanged.*

The instruction has the following format:

```asm
    bfi    rd, rs, lsb, width
```

Starting at bit 0 of `rs`, `width` bits are copied to `rd` starting at
bit `lsb`.

The `bfi` instruction replaces as many as three instructions: likely a
shift, an `and` and an `orr`.

*The preceding has described what `bfi` does but what is it for? Suppose
you have a multiple bit field in a device register. Using `bfi` makes
it easy to copy the right number of bits from a source directly into
the bits in the middle of the destination without need of other
bit-bashing.*

The *opposite* of `bfi` is `bfx`.

`ubfiz` first zeros the destination register then copies in the
specified bits from the source. The `u` means don't consider the
sign bit as special. The `z` is what causes the zero fill first and
sets it apart from `bfi`.

See bottom for an example.

## `mvn`

This instruction takes only takes two operands (but permits an optional
shift to be explained below).

The basic syntax is:

```asm
    mvn    rd, rs
```

This flips all the bits in the source and copies them to the
destination.

In addition to the basic instruction, there is also:

```asm
    mvn    rd, rs, *shift* num_bits
```

The *shift* and `num_bits` function the same way as described above
including the option to use `*shift*` as one of `lsl`, `lsr`, `asr` or
`ror`.

*Note the `mvn` is different from `neg` in that `mvn` is a bitwise
operation while `neg` is aware of what makes a negative integer value.
That is, if your goal is to turn a positive integer into a negative
integer, use `neg`. If your goal is to negate bits for bit bashing
purposes, use `mvn`.*

See bottom for an example.

## `lsl`

**Logical Shift Left** moves bits to the left shifting 0 into any
vacated positions.

```asm
	lsl		rd, rs, *number of bits*
```

*`lsl` is most often used for bit bashing as well as for a fast
multiplication by a power of 2.*

The instruction `asl` is a synonym for `lsl`. The `a` is `asl` means
"arithmetic". There is no difference between a logical and
an arithmetic shift in the **leftward** direction. There is, however,
a difference in the **rightward** direction in that `asr` replicates
the sign bit where `lsr` still moves in zeros in any bit positions
vacated.

## `orr`

This is the plain vanilla *or* instruction. It is used extensively
for bit bashing as it is how bits can be set to 1.

```asm
	orr		rd, rs, rm  # rm is another register
	orr		rd, rs, imm
```

## Example

[Here](./ubfiz.s) is the code to an example:

```asm
        .global        main                                             // 1 
        .text                                                           // 2 
        .align        2                                                 // 3 
/*    This demo should be run from gdb. `layout regs` would be helpful. // 4 
    This demo shows:                                                    // 5 
    bfi - bit field insert                                              // 6 
*/                                                                      // 7 
main:   mov         w1, wzr        //                                   // 8 
        mvn         w1, w1         // set w1 to 0xFFFFFFFF              // 9 
        mov         w3, w1         // save for reuse                    // 10 
        mov         w2, 3          // set bits 0 and 1                  // 11 
        bfi         w1, w2, 4, 4                                        // 12 
        // Look at w1. You will note that the bottom                    // 13 
        // 4 bits of w2 (0011) have been copied into the second         // 14 
        // 4 bits of w1 including the zeros.                            // 15 
        //                                                              // 16 
        // NEXT DEMO                                                    // 17 
        mov         w1, w3         // reset w1                          // 18 
        mov         w2, 3          // set bits 0 and 1                  // 19 
        ubfiz       w1, w2, 4, 2                                        // 20 
        // Look at w1. You will note that all the bits were             // 21 
        // zeroed and then 2 bits from w2 are copied into w1            // 22 
        // starting at bit 4. Compare this to bfi.                      // 23 
        //                                                              // 24 
        // NEXT DEMO                                                    // 25 
        bfxil       w3, w1, 4, 4                                        // 26 
        // Look at w3. You will note that 4 bits (0011) from            // 27 
        // w1 were put into w3 starting at bit 0.                       // 28 
        mov         w0, wzr                                             // 29 
        ret                                                             // 30
```
