;BIT manipulation routines to set, reset, and test a ; bit in a byte in memory, to set bit (A) in A ;Module Name: BITMATH ;Author: Al Hawley ;Date: 10/31/89 ;This module contains the following routines: public res_m,set_m,tst_m public exp_a,mask8,andm2m,orm2m,xorm2m public mirror,mask16 ; (A) means 'the contents of the A register' ; 1) set, reset, and test a bit in the byte at HL ; SET_M, RES_M, TST_M ; 2) set bit (A) in A, reset others. This is the EXP function ; EXP_A ; 3) Return LOG(A) in A, ignoring all but highest bit. ; LOG2_A ; 4) set (A) least significant bits in A, others reset. ; MASK8 this is equivalent to binary [[LOG(A+1)] -1] ; 5) set (A) least significant bits in BC, others reset. ; MASK16 Same as MASK8, but returns 16 bit instead of 8. ; 6) logical AND, OR, XOR with (HL), result in (HL) ; ANDM2M, ORM2M, XORM2M routines ; 7) reverse the bit order in the byte at HL. (mirror image) ; MIRROR routine ;================================================= ;routines to set, reset, or test a bit. ;on entry: ; a = bit number (0-7) ; hl = address of the byte ;on exit: ; hl, de are preserved ; b = 46h(test) or 0c6h(set) or 86h(res) ;if z, c = a = 0 ;if nz, c = a = 0ffh ; the z/nz returns are significant only when ; the test operation is performed. ;these routines work by synthesizing the opcode ;for a z80 'cb' instruction. res_m: ;entry point to reset a bit ld b,86h jr makop set_m: ;entry point to set a bit ld b,0c6h makop: rlc a ;rotate the bit number rlc a ;into the 3-4-5 rlc a ;position in the accumulator or a,b ld (opcode),a ;install the opcode db 0cbh ;and execute the instruction opcode: db 0 ;..to do a bit, res, or set ret tst_m: ;entry point to test a bit ld b,46h call makop ;do the test ld c,0ffh ;adjust regs c and a ld a,c ret nz inc c ld a,c ret ;================================================= exp_a: ;set a single bit in reg A, reset all others. ;on entry, ; a = bit position to set (0-7) ;on exit, ; a = requested bit set, others 0 ; flags are undefined ;all other registers preserved. push bc ld b,a inc b xor a scf expa1: rla djnz expa1 pop bc ret ;================================================= ;convert a byte with a single bit set to the ordinal ;number in binary corresponding to the bit position. ;this is a special case of log n, where n= 0...7 ;on entry the byte to convert is in reg A. ;on exit, reg A contains the log of A (bit position) log2_a: push bc ld b,7 ;7 bits to decrement at most or a,a ;clear carry log2a: rl a ;rotate left through carry jr c,log2ax ;done if bit shifted into cy djnz log2a ;the 8th dec never occurs log2ax: ld a,b or a ;reset cy pop bc ret ;================================================= mask16: ;set the n least significant bits ;in register pair BC according to the ;value (0..15) in A. A is not preserved ld b,a ;save for test of bit 3 and 7 ;use 3 lsbits call mask8 ;return mask in A ld c,a xor a ;make a zero bit 3,b ;high byte? ld b,a ;in case not ret z ;low byte has the mask ld b,c ;mask in high byte dec a ;make 0ff for low byte ld c,a ;low byte ret ;================================================= mask8: ;set n least significant bits in reg A. ;Remaining bits are reset. ; n is specified as a number, 0-7 which ; defines the highest bit set. ;on entry, ; a = highest bit to set (0-7) ;on exit, ; a = filled with 1's from position ; 0 up through position specified ; all other registers preserved push bc ld b,a inc b xor a bcmsk1: scf rla djnz bcmsk1 pop bc or a ;reset cy (=no error) ret ;================================================= andm2m: ;perform the logical and of the byte ;in the accumulator with the byte @hl ;preserves all registers push af and a,(hl) ld (hl),a pop af ret ;================================================= orm2m: ;perform the logical or of the byte ;in the accumulator with the byte @hl ;preserves all registers push af or a,(hl) ld (hl),a pop af ret ;================================================= xorm2m: ;perform the logical xor of the byte ;in the accumulator with the byte @hl ;preserves all registers push af xor a,(hl) ld (hl),a pop af ret ;================================================= mirror: ;invert the order of the bits at (hl) ;input: hl = addr of byte to invert ;output: mirror image in (hl) ; swap bits 0-7,1-6,2-5,3-4 ; reg a is destroyed ;all other registers preserved ;test for common symetrical cases and ;do nothing (it's faster) ld a,(hl) or a ;00000000b? ret z cp 0ffh ;11111111b? ret z ;probably not symetrical. make mirror image. push bc rra ;lsb->cy, rotate right rl c ;cy-lsb, rotate left rra ;..repeat 7 more times rl c rra rl c ;this code would be shorter rra ;..if done in a loop, but rl c ;..also slower rra rl c rra rl c rra rl c rra rl c ;reversed pattern in c ld (hl),c ;store at memory loc pop bc ret ;================================================= end