??? 12/24/99 11:17 Read: times |
#1086 - RE: 32bit maths on 8052 |
Hi Igor,
This is the code we are currently working on. There is a call from a high level language to this routine, the HLL sends a 16 bit speed request, this routine returns two things: 1.) The highest power of two in the speed ( ctr, a byte) 2.) The timer reload value (Divideby, a 16 bit word) The timer reload is equivalent to (($1000000 SHR (14-ctr) )/ speed) + MinIntPeriod The highest power of two is extracted by rotating the sixteen bit speed through the carry flag Then you will see we have a lookup table to find the numerator of the expression, and are left with the divide to do. The 16 and 32 bit math ops are from an Intel App note published in 1988. They operate on a 32 bit number with 16 bit ones, so I can divide, multiply add and subtract a 16 bit number on a 32 bit number. Lets see this fast divide routine ! Very best regards Steve ;MAth library functions for controller project NAME viscomath PUBLIC frequency,speed PUBLIC ?frequency?byte,?speed?byte Visc_data SEGMENT DATA Visc_code SEGMENT CODE rseg visc_data MinIntPeriod EQU 6000 ?frequency?byte: DS 0 freqA: DS 2 freqB: DS 2 divideby: DS 2 ?Load_16?byte: DS 2 ?Load_32?byte: DS 4 ?Mul_16?byte: DS 2 ?Div_16?byte: DS 2 ?Add_16?byte: DS 2 ?Sub_16?byte: DS 2 ?Add_32?byte: DS 4 ?Sub_32?byte: DS 4 OP_0: DS 1 ;lsb OP_1: DS 1 OP_2: DS 1 OP_3: DS 1 ;msb ctr: DS 1 TMP_0: DS 1 TMP_1: DS 1 TMP_2: DS 1 TMP_3: DS 1 ?speed?byte: ds 0 spspeed: DS 2 DummyW: DS 2 DummW2: DS 1 RSEG visc_code Speed: ;Calculate timer reloads and step divisor for a motor speed ;Speed is passed in multiples of the minimum speed in speed and speed+1 ;First calculate the highest power of 2 in the number. MOV ctr,#255 MOV A,spspeed+1 JZ rotateLSB ;There is a MSB MOV ctr,#7 ;So there must be at least 2^7 in the word loop_msb: CLR C RRC A ;rotate INC CTR JNZ loop_msb SJMP endstep rotateLSB:MOV A,spspeed loop_lsb: CLR C RRC A inc ctr JNZ loop_lsb endstep: MOV r0,dummw2 MOV @r0,ctr MOV A,ctr RL A RL A RL A MOV op_3,#0 MOV op_2,#0 MOV op_1,#0 MOV op_0,#0 MOV DPH,#HIGH(lookup) MOV DPL,#LOW(lookup) JMP @A+DPTR Lookup: MOV op_1,#40h sjmp endlook NOP NOP NOP MOV op_1,#80h sjmp endlook NOP NOP NOP MOV op_2,#1 sjmp endlook NOP NOP NOP MOV op_2,#2 sjmp endlook NOP NOP NOP MOV op_2,#4 sjmp endlook NOP NOP NOP MOV op_2,#8 sjmp endlook NOP NOP NOP MOV op_2,#10h sjmp endlook NOP NOP NOP MOV op_2,#20h sjmp endlook NOP NOP NOP MOV op_2,#40h sjmp endlook NOP NOP NOP MOV op_2,#80h sjmp endlook NOP NOP NOP MOV op_3,#1 sjmp endlook NOP NOP NOP MOV op_3,#2 sjmp endlook NOP NOP NOP MOV op_3,#4 sjmp endlook NOP NOP NOP MOV op_3,#8 sjmp endlook NOP NOP NOP MOV op_3,#10h endlook: NOP NOP NOP NOP NOP NOP NOP NOP ;divided big number by appropriate power of two MOV R1,spspeed+1 ;load divisor MOV R0,spSpeed LCALL Div_16 ;divided by speed to give counter load MOV ?add_16?byte,#High(MinIntPeriod) MOV ?add_16?byte+1,#Low(MinIntPeriod) LCALL ADD_16 MOV r0,dummyW MOV @r0,op_0 inc r0 MOV @r0,op_1 RET frequency: ;the ratio of frequency A to frequency B is calculated;. ;The result is returned in freq result as a 32bit number Add_16: ;Add the 16 bits supplied by the caller to the OP registers CLR C MOV A,OP_0 ADDC A,?Add_16?byte+1 ;low byte first MOV OP_0,A MOV A,OP_1 ADDC A,?Add_16?byte ;high byte + carry MOV OP_1,A MOV A,OP_2 ADDC A,#0 ;propagate carry only MOV OP_2,A MOV A,OP_3 ADDC A,#0 ;propagate carry only MOV OP_3,A RET Add_32: ;Add the 32 bits supplied by the caller to the OP registers CLR C MOV A,OP_0 ADDC A,?Add_32?byte+3 ;lowest byte first MOV OP_0,A MOV A,OP_1 ADDC A,?Add_32?byte+2 ;mid-lowest byte + carry MOV OP_1,A MOV A,OP_2 ADDC A,?Add_32?byte+1 ;mid-highest byte + carry MOV OP_2,A MOV A,OP_3 ADDC A,?Add_32?byte ;highest byte + carry MOV OP_3,A RET Sub_16: ;Subtract the 16 bits supplied by the caller to the OP registers CLR C MOV A,OP_0 SUBB A,?Sub_16?byte+1 ;low byte first MOV OP_0,A MOV A,OP_1 SUBB A,?Sub_16?byte ;high byte + carry MOV OP_1,A MOV A,OP_2 SUBB A,#0 ;propagate carry only MOV OP_2,A MOV A,OP_3 SUBB A,#0 ;propagate carry only MOV OP_3,A RET Sub_32: ;Subtract the 32 bits supplied by the caller to the OP registers CLR C MOV A,OP_0 SUBB A,?Sub_32?byte+3 ;lowest byte first MOV OP_0,A MOV A,OP_1 SUBB A,?Sub_32?byte+2 ;mid-lowest byte + carry MOV OP_1,A MOV A,OP_2 SUBB A,?Sub_32?byte+1 ;mid-highest byte + carry MOV OP_2,A MOV A,OP_3 SUBB A,?Sub_32?byte ;highest byte + carry MOV OP_3,A RET Mul_16: ;Multiply the 32 bit OP with the 16 value supplied MOV TMP_3,#0 ;clear out upper 16 bits MOV TMP_2,#0 ;Generate the lowest byte of the result MOV B,OP_0 MOV A,?Mul_16?byte+1 MUL AB MOV TMP_0,A ;low-order result MOV TMP_1,B ;high-order result ;now generate the next higher order byte MOV B,OP_1 MOV A,?Mul_16?byte+1 MUL AB ADD A,TMP_1 ;low-order result MOV TMP_1,A ;save MOV A,B ;get high-order result ADDC A,TMP_2 ;include carry from previous operation MOV TMP_2,A ;save JNC Mul_loop1 INC TMP_3 ;propagate carry into TMP_3 Mul_loop1: MOV B,OP_0 MOV A,?Mul_16?byte MUL AB ADD A,TMP_1 ;low-order result MOV TMP_1,A ;save MOV A,B ;get high-order result ADDC A,TMP_2 ;include carry from previous operation MOV TMP_2,A ;save JNC Mul_loop2 INC TMP_3 ;propagate carry into TMP_3 Mul_loop2: ;Now start working on the 3rd byte MOV B,OP_2 MOV A,?Mul_16?byte+1 MUL AB ADD A,TMP_2 ;low-order result MOV TMP_2,A ;save MOV A,B ;get high-order result ADDC A,TMP_3 ;include carry from previous operation MOV TMP_3,A ;save ;now the other half MOV B,OP_1 MOV A,?Mul_16?byte MUL AB ADD A,TMP_2 ;low-order result MOV TMP_2,A ;save MOV A,B ;get high-order result ADDC A,TMP_3 ;include carry from previous operation MOV TMP_3,A ;save ;Now finish off the highest order byte MOV B,OP_3 MOV A,?Mul_16?byte+1 MUL AB ADD A,TMP_3 ;low-order result MOV TMP_3,A ;save ;Forget about the high-order result, this is only 32 bit math! MOV B,OP_2 MOV A,?Mul_16?byte MUL AB ADD A,TMP_3 ;low-order result MOV TMP_3,A ;save ;Now we are all done, move the TMP values back into OP MOV OP_0,TMP_0 MOV OP_1,TMP_1 MOV OP_2,TMP_2 MOV OP_3,TMP_3 RET Div_16: ;This divides the 32 bit OP register by the value supplied ;R0 div_16 msb, R1 div_16 lsb MOV R7,#0 MOV R6,#0 ;zero out partial remainder MOV TMP_0,#0 MOV TMP_1,#0 MOV TMP_2,#0 MOV TMP_3,#0 ; MOV R1,?Div_16?byte ;load divisor ; MOV R0,?Div_16?byte+1 MOV R5,#32 ;loop count ;This begins the loop Div_loop: CALL Shift_D ;shift the dividend the return MSB in C MOV A,R6 ;shift carry into LSB of partial remainder RLC A MOV R6,A MOV A,R7 RLC A MOV R7,A ;now test to see if R7:R6 >= R1:R0 CLR C MOV A,R7 ;subtract R1 from R7 to see if R1 < R7 SUBB A,R1 ;A=R7-R1, carry set if R7<R1 JC Cant_sub ;at this point R7>R1 or R7=R1 JNZ Can_sub ;jump if R7>R1 ;if R7=R1, test for R6>=R0 CLR C MOV A,R6 SUBB A,R0 ;A=R6-R0, carry set if R6<R0 JC CANT_SUB Can_sub: ;Subtract the divisor from the partial remainder CLR C MOV A,r6 SUBB A,r0 ;A= r6-r0 MOV r6,A MOV A,r7 SUBB A,r1 ;a =R7-R1-borrow MOV r7,A SETB C jmp quot Cant_sub: ;Shift 0 into the quotient CLR C QUOT: ;shift carry into the quotient CALL shift_q ;test for competition djnz r5,div_loop ;Now we're all done, move the temp values back into op MOV op_0,tmp_0 MOV op_1,tmp_1 MOV op_2,tmp_2 MOV op_3,tmp_3 RET SHIFT_D:;shift the dividend one bit to the left and return the result in C CLR C MOV A,op_0 RLC A MOV op_0,A MOV A,OP_1 RLC A MOV op_1,A MOV A,op_2 RLC A MOV op_2,A MOV A, OP_3 RLC A MOV op_3,A RET SHIFT_Q:; Shift the quotient one bit left and return result in C MOV A,tmp_0 RLC A MOV tmp_0,A MOV A,TMP_1 RLC A MOV tmp_1,A MOV A,tmp_2 RLC A MOV tmp_2,A MOV A, TMP_3 RLC A MOV TMP_3,A RET END. |
Topic | Author | Date |
32bit maths on 8052 | 01/01/70 00:00 | |
RE: 32bit maths on 8052 | 01/01/70 00:00 | |
RE: 32bit maths on 8052 | 01/01/70 00:00 | |
RE: 32bit maths on 8052 | 01/01/70 00:00 | |
RE: 32bit maths on 8052 | 01/01/70 00:00 | |
RE: 32bit maths on 8052 | 01/01/70 00:00 | |
RE: 32bit maths on 8052![]() | 01/01/70 00:00 |