16bit reverse

Using, learning, programming and modding the Gigatron and anything related.
Forum rules
Be nice. No drama.
Post Reply
dwesti
Posts: 15
Joined: 31 Jan 2020, 05:37

16bit reverse

Post by dwesti » 02 Feb 2020, 15:36

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

User avatar
marcelk
Posts: 490
Joined: 13 May 2018, 08:26

Re: 16bit reverse

Post by marcelk » 02 Feb 2020, 17:30

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
Posts: 129
Joined: 14 May 2018, 08:29

Re: 16bit reverse

Post by at67 » 02 Feb 2020, 19:53

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
Posts: 129
Joined: 14 May 2018, 08:29

Re: 16bit reverse

Post by at67 » 02 Feb 2020, 23:55

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)

Post Reply