summaryrefslogtreecommitdiff
path: root/Optimizing-assembly-code.md
diff options
context:
space:
mode:
authorDamian Yerrick <git@pineight.com>2020-04-14 12:02:45 -0400
committerDamian Yerrick <git@pineight.com>2020-04-14 12:02:45 -0400
commite1307134920e8c020a19a9c66117012c80194b61 (patch)
treefbc662fa262ab76b081a1ea8ec991f6f180f3681 /Optimizing-assembly-code.md
parentf3aa34c74561eff5fc66905b4611c6450e519228 (diff)
Fix byte/cycle in "Multiply `hl` by 2"; explain principle of sbc a; replace FOO and BAR with more locally meaningful CVAL and NCVAL
Diffstat (limited to 'Optimizing-assembly-code.md')
-rw-r--r--Optimizing-assembly-code.md84
1 files changed, 50 insertions, 34 deletions
diff --git a/Optimizing-assembly-code.md b/Optimizing-assembly-code.md
index a608c15..2c308b7 100644
--- a/Optimizing-assembly-code.md
+++ b/Optimizing-assembly-code.md
@@ -189,15 +189,15 @@ But do:
### Set `a` to one constant or another depending on the carry flag
-(The example sets `a` to `FOO` if the carry flag is set (`c`), or `BAR` is the carry flag is not set (`nc`).)
+(The example sets `a` to `CVAL` if the carry flag is set (`c`), or `NCVAL` is the carry flag is not set (`nc`).)
Don't do:
```asm
; 6 bytes, 6 or 7 cycles
- ld a, FOO
+ ld a, CVAL
jr c, .carry
- ld a, BAR
+ ld a, NCVAL
.carry
```
@@ -205,9 +205,9 @@ And don't do:
```asm
; 6 bytes, 6 or 7 cycles
- ld a, BAR
+ ld a, NCVAL
jr nc, .no_carry
- ld a, FOO
+ ld a, CVAL
.no_carry
```
@@ -215,64 +215,81 @@ And if either is 0, don't do:
```asm
; 5 bytes, 5 or 6 cycles
- ld a, FOO ; nor BAR
+ ld a, CVAL ; nor NCVAL
jr c, .carry ; nor jr nc
xor a
.carry
```
-But do:
+Instead use `sbc a`, which copies the carry flag to all bits of `a`. Thus do:
```asm
; 5 bytes, 5 cycles
- sbc a ; if carry, then $ff, else 0
- and FOO - BAR ; $ff becomes FOO - BAR, 0 stays 0
- add BAR ; FOO - BAR becomes FOO, 0 becomes BAR
+ sbc a ; if carry, then $ff, else 0
+ and CVAL - NCVAL ; $ff becomes CVAL - NCVAL, 0 stays 0
+ add NCVAL ; CVAL - NCVAL becomes CVAL, 0 becomes NCVAL
```
Or do:
```asm
; 5 bytes, 5 cycles
- sbc a ; if carry, then $ff, else 0
- and FOO ^ BAR ; $ff becomes FOO ^ BAR, 0 stays 0
- xor BAR ; FOO ^ BAR becomes FOO, 0 becomes BAR
+ sbc a ; if carry, then $ff, else 0
+ and CVAL ^ NCVAL ; $ff becomes CVAL ^ NCVAL, 0 stays 0
+ xor NCVAL ; CVAL ^ NCVAL becomes CVAL, 0 becomes NCVAL
```
-If `FOO` is 0 (i.e. set `a` to 0 if carry), then do:
+If `NCVAL` is 0 (i.e. set `a` to 0 if not carry), then do:
+
+```asm
+ ; 3 bytes, 3 cycles
+ sbc a ; if carry, then $ff, else 0
+ and CVAL ; $ff becomes CVAL, 0 stays 0
+```
+
+If `CVAL` is 0 (i.e. set `a` to 0 if carry), invert carry and do the same:
```asm
; 4 bytes, 4 cycles
- ccf ; invert carry flag
- sbc a ; if originally carry, then 0, else $ff
- and BAR ; 0 stays 0, $ff becomes BAR
+ ccf ; invert carry flag
+ sbc a ; if originally carry, then 0, else $ff
+ and NCVAL ; 0 stays 0, $ff becomes NCVAL
```
-If `BAR` is 0 (i.e. set `a` to 0 if not carry), then do:
+If `CVAL` is $FF (i.e. set `a` to $FF if carry), then do:
```asm
; 3 bytes, 3 cycles
- sbc a ; if carry, then $ff, else 0
- and FOO ; $ff becomes FOO, 0 stays 0
+ sbc a ; if carry, then $ff, else 0
+ or NCVAL ; $ff stays $ff, $00 becomes NCVAL
+```
+
+If `NCVAL` is $FF (i.e. set `a` to $FF if not carry), invert carry and do the same:
+
+```asm
+ ; 4 bytes, 4 cycles
+ ccf ; invert carry flag
+ sbc a ; if originally carry, then 0, else $ff
+ or CVAL ; $00 becomes CVAL, $ff stays $ff
```
-If `FOO` equals `BAR - 1`, then do:
+If `CVAL` equals `NCVAL - 1`, then do:
```asm
; 3 bytes, 3 cycles
- sbc a ; if carry, then $ff aka -1, else 0
- add BAR ; -1 becomes BAR - 1 aka FOO, 0 becomes BAR
+ sbc a ; if carry, then $ff aka -1, else 0
+ add NCVAL ; -1 becomes NCVAL - 1 aka CVAL, 0 becomes NCVAL
```
-If `FOO` equals `BAR - 2`, then do:
+If `CVAL` equals `NCVAL - 2`, then do:
```asm
; 3 bytes, 3 cycles
- sbc a ; if carry, then $ff aka -1, else 0; doesn't change the carry flag
- sbc -BAR ; -1 becomes BAR - 2 aka FOO, 0 becomes BAR
+ sbc a ; if carry, then $ff aka -1, else 0; doesn't change the carry flag
+ sbc -NCVAL ; -1 becomes NCVAL - 2 aka CVAL, 0 becomes NCVAL
```
-If `FOO` is 0 and `BAR` is 1 (i.e. set `a` to 0 if carry, or 1 if not carry), then do:
+If `CVAL` is 0 and `NCVAL` is 1 (i.e. set `a` to 0 if carry, or 1 if not carry), then do:
```asm
; 2 bytes, 2 cycles
@@ -281,7 +298,6 @@ If `FOO` is 0 and `BAR` is 1 (i.e. set `a` to 0 if carry, or 1 if not carry), th
```
-
### Shift `a` right by 3 bits
Don't do:
@@ -394,7 +410,7 @@ But do:
Don't do:
```asm
- ; 6 bytes, 6 cycles
+ ; 4 bytes, 4 cycles
sla l
rl h
```
@@ -521,7 +537,7 @@ Don't do:
```asm
; 8 bytes, 10 cycles
- ld a, [Address]
+ ld a, [Address] ; LSB first
ld l, a
ld a, [Address+1]
ld h, a
@@ -541,7 +557,7 @@ And don't do:
```asm
; 8 bytes, 10 cycles
- ld a, [Address]
+ ld a, [Address] ; MSB first
ld h, a
ld a, [Address+1]
ld l, a
@@ -730,7 +746,7 @@ Or do:
cp 1 ; 2 bytes, 2 cycles
```
-If you don't care about the value in `a`:
+If you don't care about carry or the value in `a`:
```asm
@@ -761,7 +777,7 @@ with:
cp $ff ; 2 bytes, 2 cycles
```
-If you don't care about the value in `a`:
+If you don't care about carry or the value in `a`:
```asm
inc a ; 1 byte, 1 cycle, increments a
@@ -912,7 +928,7 @@ Function:
ret
```
-You can still `call Function` elsewhere, but one tail call can be optimized into a fallthrough.
+Fallthrough is what you get when you combine inlining with tail calls. You can still `call Function` elsewhere, but one tail call can be optimized into a fallthrough.
## Conditional fallthrough