This led to me looking at the right shift table in page 5 of the ROM. I think I understand how to use it (although I think doing so would require fitting my own code in page 6). But what I don't get is how it works. Marcel's code is as follows:
Code: Select all
# Lookup table for i>>n, with n in 1..6
# Indexing ix = i & ~b | (b-1), where b = 1<<(n-1)
# ...
# ld <.ret
# st [vTmp]
# ld >shiftTable,y
# <calculate ix>
# jmp y,ac
# bra $ff
# .ret: ...
#
# i >> 7 can be always be done with RAM: [i&128]
# ...
# anda $80,x
# ld [x]
# ...
label('shiftTable')
shiftTable = pc()
for ix in range(255):
for n in range(1,7): # Find first zero
if ~ix & (1 << (n-1)):
break
pattern = ['x' if i<n else '1' if ix&(1<<i) else '0' for i in range(8)]
ld(ix>>n); C('0b%s >> %d' % (''.join(reversed(pattern)), n))
Code: Select all
shiftTable: 0500 0000 ld $00 ;0b0000000x >> 1
0501 0000 ld $00 ;0b000000xx >> 2
0502 0001 ld $01 ;0b0000001x >> 1
0503 0000 ld $00 ;0b00000xxx >> 3
0504 0002 ld $02 ;0b0000010x >> 1
0505 0001 ld $01 ;0b000001xx >> 2
0506 0003 ld $03 ;0b0000011x >> 1
0507 0000 ld $00 ;0b0000xxxx >> 4
0508 0004 ld $04 ;0b0000100x >> 1
0509 0002 ld $02 ;0b000010xx >> 2
050a 0005 ld $05 ;0b0000101x >> 1
050b 0001 ld $01 ;0b00001xxx >> 3
050c 0006 ld $06 ;0b0000110x >> 1
050d 0003 ld $03 ;0b000011xx >> 2
050e 0007 ld $07 ;0b0000111x >> 1
...
Is this a well known technique? Why does it work? It seems very mysterious to me!