ASMB,L,C,R HED HASH SUBROUTINE FOR IMAGE/1000 NAM HASH,7 92069-16157 REV.1912 790130 * * ******************************************************************* * (C) COPYRIGHT HEWLETT-PACKARD COMPANY 1979. ALL RIGHTS RESERVED. * NO PART OF THIS PROGRAM MAY BE PHOTOCOPIED, REPRODUCED, OR * TRANSLATED TO ANOTHER PROGRAM LANGUAGE WITHOUT THE PRIOR WRITTEN * CONSENT OF HEWLETT-PACKARD COMPANY. ******************************************************************* * * * SOURCE: 92069-18157 * RELOC: 92069-16157 * * PRGMR: CEJ * * ******************************************************************* * * * * Hash is a doubleword integer function which accepts a key item value * (either real, integer, or character string) and transforms the value * into a doubleword positive integer. Hash performs the following func- * tion. * * 1) Running function value = first doubleword in value. If odd # of * words in value, pad first word of Running function value with * nulls to make item an integeral number of doublewords long. * 2) Shift Running function value left logically by 1. * 3) If no words remaining in item value then go to 9. * 4) Doubleword = last remaining doubleword of item value (work with * doublewords beginning at the right end and working left from here * on out). * 5) Rotate Running function value left circular by: * (MOD(Doubleword,31) + 1). * 6) Running function value = Running function value + Doubleword. * 7) Go to 4. * 8) Shift function value logically right by 1 (make sure value is * positive). * 9) Return - function value in A & B registers. * * The calling sequence for HASH is: * * JSB HASH * DEF *+3 return point * DEF LENTH item length in words * DEF VALUE item value * EXT .DAD,.ENTR ENT HASH A EQU 0 B EQU 1 * LENTH NOP VALUE NOP * * Get true parameter and return addresses * HASH NOP JSB .ENTR DEF LENTH * * Determine doubleword counter with item length. * LDA LENTH,I INA # of doublewords = # of words ARS plus one divided by two. CMA,INA Negate for easy loop counting. STA #DBWS * * Calculate address of last doublewrod in item. * LDA VALUE Last doubleword address = ADA LENTH,I address of beginning of item plus ADA M2 length of item minus two. STA LAST * * Get first doubleword in item. If odd # of words in item, compensate * for the missing word by padding the item with preceding nulls. * LDA LENTH,I If odd # words SLA,RSS (least significant bit set) JMP HASH3 CLA set first word of first doubleword LDB VALUE,I to zero and second word to first JMP HASH4 word of item value. * HASH3 DLD VALUE,I Else, use what is there. * * Logically shift the doubleword value left 1 bit. * HASH4 CLE,ELB E<-bit 15 of B,bit 0 of B<-0 ELA bit 0 of A<-E=bit 15 of B * * This becomes the running function value. * DST RSULT * * ENTER MAIN LOOP HERE * See if any doublewords left in item. * HASH5 ISZ #DBWS RSS JMP HASH7 If not, we are almost done. * * Get the rightmost remaining doubleword in item. (From here on out, * all doublewords are picked up from the end of the item working towards * the beginning.) * LDA LAST LDB A,I INA LDA A,I * * Calculate MOD of the doubleword by 31. * * This code is somewhat cryptic, but performs the following: * * Get the 20 most significant bits of the doubleword and * make them the 20 least significant bits, extending the sign. * Divide them by 31. * Save the remainder in the B register. * Get the remaining 12 least significant bits of the doubleword * and concatenate them onto the remainder in the B register as * the 12 least significant bits. * Divide this by 31. * If the remainder in the B register is now negative add 31 to it * to get the true MOD. * * The above order of processing is followed because, in the case of a * doubleword whose absolute maginitude is larger than 2**19-1, the DIV * instruction might not perform properly since the quotient could be * larger than 2**15-1. * ASR 12 Shift out least significant 12 bits. DIV D31 First divide. * LDA LAST Get the least significant INA 12 bits back again. LDA A,I (We just discard the quotient.) ALF * ASR 4 Concatenate with the remainder. DIV D31 Second divide. SSB ADB D31 B = true MOD. * * Get the rotate count by adding one to the above computed MOD. * INB STB RCNT * Rotate the running function value left circular by MOD + 1. * * This code is also somewhat cryptic, but performs the following: * * If (RCNT > 16) * Then Begin: * RCNT := RCNT - 16 * Swap high and low order words of running value. * End * Rotate running value left circular by RCNT. * LDA RCNT LDB RSULT+1 B = 2nd word of running value. ADA M17 See if RCNT <= 16. SSA,INA JMP HASH6 yes - simple case of rotate * STA RCNT no - swap high & low order words. LDA RSULT A = 1st word of running value STB RSULT Put 2nd word into first word area. LDB A B = new 2nd word of running value. LDA RCNT Get remainder of ((MOD + 1) - 16). * HASH6 AND LOFOR Only the low 4 bits of RCNT are meaningful. IOR RRL16 Form the rotate instruction. STA INSTR Put it into the Run Time code. LDA RSULT A = first word of running value. INSTR ABS *-* <> * * Add in the doubleword used in the MOD and this becomes the new running * function value. * JSB .DAD DEF LAST,I DST RSULT * * Get address of next to last used doubleword in item and repeat for each * doubleword in item. * LDA LAST ADA M2 STA LAST JMP HASH5 * * When loop is finished, shift the result right logically one bit to * clear sign bit (result must be positive) and return. * HASH7 DLD RSULT CLE,ERA ERB JMP HASH,I * * Constants and variables * M17 DEC -17 M2 DEC -2 D31 DEC 31 LOFOR OCT 000017 * RSULT BSS 2 RRL16 RRL 16 Used to create Run Time rotate instruction. #DBWS NOP LAST NOP RCNT NOP END