Using, learning, programming and modding the Gigatron and anything related.
Forum rules
Be nice. No drama.
-
dwesti
- Posts: 15
- Joined: 31 Jan 2020, 05:37
Post
by dwesti »
Anyone knew a clever way for reverse 16 bit except right shift?
Code: Select all
; reverse
vd equ 0x30
v1 equ vd+2 ; counter
v2 equ v1+2 ; original value
v3 equ v2+2 ; reversed 16bit
v4 equ v3+2 ; for bitweight
v5 equ v4+2 ; for and value
;init values
LDWI 0x800
STW vd
LDWI 0x8000
STW v5
LDWI 0xAA55
STW v2
LDWI 0
STW v3
STW v1
revlp LDW v2
ANDW v5
BNE no_set
; LDWI biw
; STW v4
; LDW v1
; ADDW v4
LDWI biw
ADDW v1
STW v4
DEEK v4
ORW v3
STW v3
no_set LDW v2
LSLW
STW v2
LDW v1
ADDI 2
STW v1
SUBI 0x20
BNE revlp
LDW v3
DOKE vd
zu BRA zu
;bit weight
biw dw 0x8000 0x4000 0x2000 0x1000 0x0800 0x0400 0x0200 0x0100
dw 0x80 0x40 0x20 0x10 8 4 2 1
-
marcelk
- Posts: 488
- Joined: 13 May 2018, 08:26
Post
by marcelk »
It's alway a bit easier to test on the highest bit. So I end up with this:
Code: Select all
0200 2b 30 STW $30 |+0|
0202 59 00 LDI 0 |Y.|
0204 2b 32 STW $32 |+2|
0206 59 01 LDI 1 |Y.|
0208 2b 34 STW $34 |+4|
020a 21 30 LDW $30 |!0|
020c 35 53 13 BGE $0215 |5S.|
020f 21 32 LDW $32 |!2|
0211 fa 34 ORW $34 |.4|
0213 2b 32 STW $32 |+2|
0215 21 34 LDW $34 |!4|
0217 e9 LSLW |.|
0218 2b 34 STW $34 |+4|
021a 21 30 LDW $30 |!0|
021c e9 LSLW |.|
021d 2b 30 STW $30 |+0|
021f 35 72 0a BNE $020c |5r.|
0222 21 32 LDW $32 |!4|
0224 ff RET |.|
* 37 bytes
-
at67
- Site Admin
- Posts: 647
- Joined: 14 May 2018, 08:29
Post
by at67 »
If you need to do it fast and don't mind using a 256 byte LUT then:
Code: Select all
rev[] = create reversed 8 bit LUT
out.hi = rev[in.lo]
out.lo = rev[in.hi]
It costs a lot in space, but will probably be the fastest way to do it.
You could do the same sort of thing using a 4 bit LUT to save space.
-
at67
- Site Admin
- Posts: 647
- Joined: 14 May 2018, 08:29
Post
by at67 »
I added a few more functions to the BASIC compiler's DEF function generator, (REV4, REV8 and REV16), and now it can do stuff like this:
Code: Select all
const ADDR = &h0600
const SIZE = 256
def byte(ADDR, x, 0, SIZE, SIZE) = REV8(x)
Which when compiled produces assembly code like this:
Code: Select all
; Define Bytes
def_bytes_0x0600 EQU 0x0600
def_bytes_0x0600 DB 0 128 64 192 32 160 96 224 16 144 80 208 48 176 112 240
8 136 72 200 40 168 104 232 24 152 88 216 56 184 120 248
4 132 68 196 36 164 100 228 20 148 84 212 52 180 116 244
12 140 76 204 44 172 108 236 28 156 92 220 60 188 124 252
2 130 66 194 34 162 98 226 18 146 82 210 50 178 114 242
10 138 74 202 42 170 106 234 26 154 90 218 58 186 122 250
6 134 70 198 38 166 102 230 22 150 86 214 54 182 118 246
14 142 78 206 46 174 110 238 30 158 94 222 62 190 126 254
1 129 65 193 33 161 97 225 17 145 81 209 49 177 113 241
9 137 73 201 41 169 105 233 25 153 89 217 57 185 121 249
5 133 69 197 37 165 101 229 21 149 85 213 53 181 117 245
13 141 77 205 45 173 109 237 29 157 93 221 61 189 125 253
3 131 67 195 35 163 99 227 19 147 83 211 51 179 115 243
11 139 75 203 43 171 107 235 27 155 91 219 59 187 123 251
7 135 71 199 39 167 103 231 23 151 87 215 55 183 119 247
15 143 79 207 47 175 111 239 31 159 95 223 63 191 127 255
i.e. trivially generating bit reversing LUT's
So to bit reverse a 16 bit number, this would do it:
Code: Select all
const ADDR = &h0600
const SIZE = 256
def byte(ADDR, x, 0, SIZE, SIZE) = REV8(x)
in16 = &h0001
out16 = 0
out16.hi = peek(ADDR + in16.lo)
out16.lo = peek(ADDR + in16.hi)