|
|
View previous topic :: View next topic |
Author |
Message |
anestho
Joined: 27 Dec 2006 Posts: 28
|
Fast multiply without hardware multiplier |
Posted: Sun Sep 09, 2007 1:45 pm |
|
|
Hi,
I was reading the thread below:
http://www.ccsinfo.com/forum/viewtopic.php?t=6131&highlight=fast+multiplication
I know there is a function _mul (x,y) where x and y is 8 bit and the result is 16 bit. I am confused on how this is done on 12F chips with 14bit core without the assembly MULWF or MULLW instruction.
I looked at the .lst file, but it calls the mult8*8 function. Not sure if it stores the high byte of the result. Could someone confirm this? Does _mult work with 12F chips????
Should I just stick to 16 bit result = 16 bit * 16 bit ?
Will 16 bit var = _mul(8bit * 8bit) be equal to above if both the 16bit operand and the 8bit operand are equal?
How can I stick and debug the file in asm? I can do it with CC5x since it generates asm, but CCS doesn't.
I am looking for the fastest possible multiplication of 8*8 bit. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
anestho
Joined: 27 Dec 2006 Posts: 28
|
|
Posted: Sun Sep 09, 2007 5:54 pm |
|
|
Thanks, PCM _programmer;
Here is what I found
Code: |
;***************************************************************************
;** time efficient multiplication 8 bit x 8 bit = 16 bit (unsigned)
;**
;** company: elektronik 21 GmbH
;** programmer: Martin Schaefer (idea from Andrew Warren)
;**
;** execution time: fixed 38 cycles (with jump in and jump out) !!!
;** code length: 35 words
;** multiplier: w
;** multiplicand: resultlo
;** result: resulthi:resultlo
;***************************************************************************
MUL8X8 CODE
Mul8x8 ;* 2 cycles for call - instruction
GLOBAL Mul8x8, resulthi, resultlo
mult MACRO
btfsc STATUS,C
addwf resulthi,F
rrf resulthi,F
rrf resultlo,F
ENDM
clrf resulthi ;* 1 cycle
rrf resultlo,F ;* 1 cycle
mult ;* 4 cycles
mult ;* 4 cycles
mult ;* 4 cycles
mult ;* 4 cycles
mult ;* 4 cycles
mult ;* 4 cycles
mult ;* 4 cycles
mult ;* 4 cycles
retlw 0 ;* 2 cycles
|
I am having trouble converting it to CCS #asm format.
I am using a PIC12F683
I defined these at the beginning of the code.
#byte STATUS = 0x03
#bit CARRY = STATUS.0
#bit ZERO = STATUS.2
Here is what I got so far:
Code: |
/// *************************************************************
//multiplier = W (accumilator)
//multiplicand= result_lo
//result: result_hi:result_lo
int16 mult8x8 (int8 result_lo, char W)
{
int8 result_hi=0;
int16 result = 0;
#asm
rrf result_lo,F
// #1
btfsc STATUS,CARRY
addwf result_hi,F
rrf result_hi,F
rrf result_lo,F
// #2
btfsc STATUS,CARRY
addwf result_hi,F
rrf result_hi,F
rrf result_lo,F
// #3
btfsc STATUS,CARRY
addwf result_hi,F
rrf result_hi,F
rrf result_lo,F
// #4
btfsc STATUS,CARRY
addwf result_hi,F
rrf result_hi,F
rrf result_lo,F
// #5
btfsc STATUS,CARRY
addwf result_hi,F
rrf result_hi,F
rrf result_lo,F
// #6
btfsc STATUS,CARRY
addwf result_hi,F
rrf result_hi,F
rrf result_lo,F
// #7
btfsc STATUS,CARRY
addwf result_hi,F
rrf result_hi,F
rrf result_lo,F
// #8
btfsc STATUS,CARRY
addwf result_hi,F
rrf result_hi,F
rrf result_lo,F
#endasm
result = result_hi*256+result_low;
return result;
}
|
I get an error on the 2nd line of the #asm addwf result_hi,F saying "expression must evaluate to a constant"
I am using version 3.249 PCWH compiler. |
|
|
anestho
Joined: 27 Dec 2006 Posts: 28
|
|
Posted: Sun Sep 09, 2007 6:01 pm |
|
|
This does the same thing as:
Code: | uns16 operator* _multM8_8( uns8 arg1, char W)
{
uns16 rval = 0;
Carry = 0;
#define addRR(rval,arg,bit) if(arg&((uns8)1<<bit)) rval.high8+=W; rval=rr(rval);
addRR( rval, arg1, 0);
addRR( rval, arg1, 1);
addRR( rval, arg1, 2);
addRR( rval, arg1, 3);
addRR( rval, arg1, 4);
addRR( rval, arg1, 5);
addRR( rval, arg1, 6);
addRR( rval, arg1, 7);
#undef addRR
return rval;
} | [/code]
this is from CC5x math lib MATH16M.h
If you can get either to work, that would be great, or at least some suggestions.
Here is how I understand it:
1. compare the 0 bit with 1, if it is 1, then add 1 to the MSB and rotate right the bits
2. same thing with bit 1.. etc to bit 7 |
|
|
anestho
Joined: 27 Dec 2006 Posts: 28
|
|
Posted: Sun Sep 09, 2007 6:53 pm |
|
|
I got it to compile finally. Mistake was using STATUS, CARRY instead of STATUS,0.
Will report if it works. |
|
|
anestho
Joined: 27 Dec 2006 Posts: 28
|
|
Posted: Sun Sep 09, 2007 7:02 pm |
|
|
Here is what I am using now. Still need to test it, but it compiles.
Code: |
// Begin Multiplier Routine
int16 mult8x8(int8 mulcnd, int8 mulplr) // 35 instruction cycles = 0.5 x 35 = 17us
{
int8 H_byte = 0;
int8 L_byte = 0;
#asm
//clrf H_byte
//clrf L_byte
movf mulcnd,W // move the multiplicand to W reg.
bcf STATUS,0 // Clear the carry bit in the status Reg.
btfsc mulplr,0
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
btfsc mulplr,1
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
btfsc mulplr,2
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
btfsc mulplr,3
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
btfsc mulplr,4
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
btfsc mulplr,5
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
btfsc mulplr,6
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
btfsc mulplr,7
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
#endasm
return H_byte*256+L_byte;
} |
Last edited by anestho on Sun Sep 09, 2007 7:08 pm; edited 1 time in total |
|
|
anestho
Joined: 27 Dec 2006 Posts: 28
|
|
Posted: Sun Sep 09, 2007 7:07 pm |
|
|
I eliminated the clrf for the H_byte and L_byte since I clear them above, and its duplicate code in .lst
I also reduced the instruction count by using W for one of the arguments.
CAN someone with a UART connection please test this routine for me? I only have 12F683 and it doesn't have a built in UART.
Code: | / Begin Multiplier Routine
int16 mult8x8(int8 mulcnd, int8 W) // 35 instruction cycles = 0.5 x 35 = 17us
{
int8 H_byte = 0;
int8 L_byte = 0;
#asm
//clrf H_byte // removed, not needed
//cllrf L_byte // removed, not needed
//movf mulcnd,W // removed, not needed
bcf STATUS,0 // Clear carry bit
btfsc W,0 // compare W 0 bit with 0, if 1 goes to next line
addwf H_byte,1 // add 1 to MSB
rrf H_byte,1
rrf L_byte,1
btfsc W,1 // compare W 1 bit with 0, if 1 goes to next line
addwf H_byte,1 // add 1 to MSB
rrf H_byte,1
rrf L_byte,1
btfsc W,2
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
btfsc W,3
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
btfsc W,4
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
btfsc W,5
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
btfsc W,6
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
btfsc W,7
addwf H_byte,1
rrf H_byte,1
rrf L_byte,1
#endasm
return H_byte*256+L_byte;
}
|
Also, how do I handle an interrupt while in this function? My interrupt uses the W register. Should I turn off the interrupt prior to entering this routine? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Sep 10, 2007 1:18 am |
|
|
Your code doesn't work because the function parameter with the name W is not the same as register W.
Quote: | CAN someone with a UART connection please test this routine for me? I only have 12F683 and it doesn't have a built in UART. | You can test it yourself using the simulator in MPLAB.
Quote: | Also, how do I handle an interrupt while in this function? My interrupt uses the W register. Should I turn off the interrupt prior to entering this routine? | It is the interrupt routine's responsibility for not changing any registers. You don't have to do anything. |
|
|
Guest
|
|
Posted: Wed Oct 10, 2007 10:39 am |
|
|
I am not getting any answer. All variables are assigned zero when the fucntion is accessed. So how do I fix this? use movwf instead of movf? |
|
|
Guest
|
|
Posted: Wed Oct 10, 2007 11:03 am |
|
|
Is there a way to do this in CCS C instead of asm? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Oct 10, 2007 11:53 am |
|
|
Yes, there is. Use the _mul() function.
Here is the description of the _mul() function from the CCS manual:
Quote: |
Performs an optimized multiplication. By accepting a different type than it
returns, this function avoids the overhead of converting the parameters
to a larger type. |
Quote: | #include <16F877.H>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//======================================
void main()
{
int16 result;
int8 a, b;
a = 100;
b = 234;
result = _mul(a, b);
printf("result = %lu \n\r", result);
while(1);
} |
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|