|
|
View previous topic :: View next topic |
Author |
Message |
hhoebel Guest
|
Multiply 8-bit*8-bit = 16-bit |
Posted: Wed Jul 09, 2003 3:47 am |
|
|
I want to multiply a 8-bit var with a 8-bit litteral using a PIC18F1320 with hardware-multiplier (var16 = var8 * const.). CCS 3.165 produces the correct call of MULLW, but the result is truncated to 8-bit. Example code:
0014 0D36 00017 MULLW 36
0016 50F3 00018 MOVF FF3,W
0018 6A07 00019 CLRF 07
001A 6E06 00020 MOVWF 06
As you can see the ccs clears the upper byte of the 16-bit var. When using var16 = (unsigned int16)var8 * const instead it works, but ccs uses much more code for this instead of simply using the 16-bit-result of the hardware-multiplier.
This is really odd :-(
Any idea how to get around this?
regards,
Heiko
___________________________
This message was ported from CCS's old forum
Original Post ID: 144515805 |
|
|
R.J.Hamlett Guest
|
Re: Multiply 8-bit*8-bit = 16-bit |
Posted: Wed Jul 09, 2003 4:06 am |
|
|
:=I want to multiply a 8-bit var with a 8-bit litteral using a PIC18F1320 with hardware-multiplier (var16 = var8 * const.). CCS 3.165 produces the correct call of MULLW, but the result is truncated to 8-bit. Example code:
:=
:=0014 0D36 00017 MULLW 36
:=0016 50F3 00018 MOVF FF3,W
:=0018 6A07 00019 CLRF 07
:=001A 6E06 00020 MOVWF 06
:=
:=As you can see the ccs clears the upper byte of the 16-bit var. When using var16 = (unsigned int16)var8 * const instead it works, but ccs uses much more code for this instead of simply using the 16-bit-result of the hardware-multiplier.
:=This is really odd :-(
:=
:=Any idea how to get around this?
:=
:=regards,
:=
:=Heiko
Yes.
Remember the default integer type is 8bit. You are multiplying two 8bit values (which implies 8bit multiplication), and then transferring the result to a 16bit value. Hence the truncation. To avoid this, you need to tell the compiler to treat the values as 16bit.
Hence (using two 8bit values 'a', and 'b', and the 16bit result in 'c'):
c=(int16)a*(int16)b;
Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 144515807 |
|
|
hhoebel Guest
|
Multiply 8-bit*8-bit = 16-bit |
Posted: Wed Jul 09, 2003 4:12 am |
|
|
:=c=(int16)a*(int16)b;
Sure, i know that this works, but the ccs compiles this to a much to long constuction. It uses two hardware multiplies to get the result which isn't really needed. A single multiply will provide the correct result.
I'm tending to make a multiply-subroutine for this myself.
If would look like this:
unsigned int16 Mul(unsigned int8 A, unsigned int8 B)
{
#asm
movf A,W
mulwf B
movff 0xFF3,_return_
movff 0xFF4,_return_+1
#endasm
}
This works with exception of the "_return_+1" (compiler says: Expression must evaluate to a constant). Any idea how to return a 16-bit-result from assembler?
___________________________
This message was ported from CCS's old forum
Original Post ID: 144515809 |
|
|
hhoebel Guest
|
Multiply 8-bit*8-bit = 16-bit |
Posted: Wed Jul 09, 2003 4:34 am |
|
|
:= movff 0xFF4,_return_+1
I've found how to do this: movff 0xFF4,(&_return_+1).
Never used C-syntax from within assembler before:-(
___________________________
This message was ported from CCS's old forum
Original Post ID: 144515811 |
|
|
R.J.Hamlett Guest
|
Re: Multiply 8-bit*8-bit = 16-bit |
Posted: Wed Jul 09, 2003 4:45 am |
|
|
:=:=c=(int16)a*(int16)b;
:=
:=Sure, i know that this works, but the ccs compiles this to a much to long constuction. It uses two hardware multiplies to get the result which isn't really needed. A single multiply will provide the correct result.
:=
:=I'm tending to make a multiply-subroutine for this myself.
:=If would look like this:
:=
:=unsigned int16 Mul(unsigned int8 A, unsigned int8 B)
:={
:= #asm
:= movf A,W
:= mulwf B
:= movff 0xFF3,_return_
:= movff 0xFF4,_return_+1
:= #endasm
:=}
:=
:=This works with exception of the "_return_+1" (compiler says: Expression must evaluate to a constant). Any idea how to return a 16-bit-result from assembler?
Yes.
It is beautifully 'undocumented'...
Try this:
unsigned int16 Mul(unsigned int8 A, unsigned int8 B)
{
#asm
movf A,W
mulwf B
movff 0xFF3,_return_
movff 0xFF4,&_return_+1
#endasm
}
The '&', used in this context, seems to make the compiler add one to the address reflected by '_return_', and use this!...
Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 144515812 |
|
|
Chang-Huei Wu Guest
|
Re: Multiply 8-bit*8-bit = 16-bit |
Posted: Wed Jul 09, 2003 9:29 am |
|
|
:=:= movff 0xFF4,_return_+1
:=
:=I've found how to do this: movff 0xFF4,(&_return_+1).
:=
:=Never used C-syntax from within assembler before:-(
one more funny way to do it with CCS ...
int16 mul_prod ;
#byte mul_prod = 0x0ff3
int16 mul_u8(int8 a, int8 b)
{
a * b; return ( mul_prod );
}
it turns out to be ...
.................... int16 mul_u8(int8 a, int8 b)
.................... {
.................... a * b; return ( mul_prod );
*
0022: MOVF 11,W
0024: MULWF 12
0026: MOVF FF3,W
0028: MOVWF 01
002A: MOVF FF4,W
002C: MOVWF 02
.................... }
002E: GOTO 1030 (RETURN)
and I got a warning ... Code has no effect
but, it works with exactly the same speed and ROM size as
the in-line assembly.
Best wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 144515822 |
|
|
hhoebel Guest
|
Multiply 8-bit*8-bit = 16-bit |
Posted: Thu Jul 10, 2003 2:46 am |
|
|
:=one more funny way to do it with CCS ...
Many thanks for that. Helps to understand what the compiler does.
regards,
Heiko
___________________________
This message was ported from CCS's old forum
Original Post ID: 144515834 |
|
|
R.J.Hamlett Guest
|
Re: Multiply 8-bit*8-bit = 16-bit |
Posted: Thu Jul 10, 2003 3:46 am |
|
|
:=:=:= movff 0xFF4,_return_+1
:=:=
:=:=I've found how to do this: movff 0xFF4,(&_return_+1).
:=:=
:=:=Never used C-syntax from within assembler before:-(
:=
:=one more funny way to do it with CCS ...
:=
:=int16 mul_prod ;
:=#byte mul_prod = 0x0ff3
:=
:=int16 mul_u8(int8 a, int8 b)
:={
:= a * b; return ( mul_prod );
:=}
:=
:=it turns out to be ...
:=
:=.................... int16 mul_u8(int8 a, int8 b)
:=.................... {
:=.................... a * b; return ( mul_prod );
:=*
:=0022: MOVF 11,W
:=0024: MULWF 12
:=0026: MOVF FF3,W
:=0028: MOVWF 01
:=002A: MOVF FF4,W
:=002C: MOVWF 02
:=.................... }
:=002E: GOTO 1030 (RETURN)
:=
:=and I got a warning ... Code has no effect
:=
:=but, it works with exactly the same speed and ROM size as
:=the in-line assembly.
:=
:=
:=Best wishes
That is very elegant. The 'warning', is because the compiler can't see you doing anything with 'a*b'. As far as it is concerned, this statement generates no effect. However it does make a rather useful 'shortcut' in this context. It might be worth declaring the function as 'inline'. I'd not expect the compiler to seperate it (since it is so short), but it might lead to problems if it did.
Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 144515835 |
|
|
Chang-Huei Wu Guest
|
Re: Multiply 8-bit*8-bit = 16-bit |
Posted: Thu Jul 10, 2003 4:05 am |
|
|
<font face="Courier New" size=-1>:=:=one more funny way to do it with CCS ...
:=:=
:=:=int16 mul_prod ;
:=:=#byte mul_prod = 0x0ff3
:=:=
:=:=int16 mul_u8(int8 a, int8 b)
:=:={
:=:= a * b; return ( mul_prod );
:=:=}
:=:=
:=:=it turns out to be ...
:=:=
:=:=.................... int16 mul_u8(int8 a, int8 b)
:=:=.................... {
:=:=.................... a * b; return ( mul_prod );
:=:=*
:=:=0022: MOVF 11,W
:=:=0024: MULWF 12
:=:=0026: MOVF FF3,W
:=:=0028: MOVWF 01
:=:=002A: MOVF FF4,W
:=:=002C: MOVWF 02
:=:=.................... }
:=:=002E: GOTO 1030 (RETURN)
:=:=
:=:=and I got a warning ... Code has no effect
:=:=
:=:=but, it works with exactly the same speed and ROM size as
:=:=the in-line assembly.
:=:=
:=:=
:=:=Best wishes
:=That is very elegant. The 'warning', is because the compiler can't see you doing anything with 'a*b'. As far as it is concerned, this statement generates no effect. However it does make a rather useful 'shortcut' in this context. It might be worth declaring the function as 'inline'. I'd not expect the compiler to seperate it (since it is so short), but it might lead to problems if it did.
:=
:=Best Wishes
One more not so funny thing, the real potential danger is in case of interrupt, if mul_u8() is interrupted with an ISR also using multiplication, then ... it really hurt, and worse ... very hard to debug. CCS's ISR handling routine does NOT push 0xFF3 and 0xFF4 into safe place, so, it won't be restored after ISR, you have to do it all by yourself.
Best wishes and ... be careful !
p.s. I was planning to use this kind of algorithm for fast floating multiplication, however, exclusively inside my ISR.</font>
___________________________
This message was ported from CCS's old forum
Original Post ID: 144515836 |
|
|
R.J.Hamlett Guest
|
Re: Multiply 8-bit*8-bit = 16-bit |
Posted: Thu Jul 10, 2003 5:08 am |
|
|
:=<font face="Courier New" size=-1>:=:=one more funny way to do it with CCS ...
:=:=:=
:=:=:=int16 mul_prod ;
:=:=:=#byte mul_prod = 0x0ff3
:=:=:=
:=:=:=int16 mul_u8(int8 a, int8 b)
:=:=:={
:=:=:= a * b; return ( mul_prod );
:=:=:=}
:=:=:=
:=:=:=it turns out to be ...
:=:=:=
:=:=:=.................... int16 mul_u8(int8 a, int8 b)
:=:=:=.................... {
:=:=:=.................... a * b; return ( mul_prod );
:=:=:=*
:=:=:=0022: MOVF 11,W
:=:=:=0024: MULWF 12
:=:=:=0026: MOVF FF3,W
:=:=:=0028: MOVWF 01
:=:=:=002A: MOVF FF4,W
:=:=:=002C: MOVWF 02
:=:=:=.................... }
:=:=:=002E: GOTO 1030 (RETURN)
:=:=:=
:=:=:=and I got a warning ... Code has no effect
:=:=:=
:=:=:=but, it works with exactly the same speed and ROM size as
:=:=:=the in-line assembly.
:=:=:=
:=:=:=
:=:=:=Best wishes
:=:=That is very elegant. The 'warning', is because the compiler can't see you doing anything with 'a*b'. As far as it is concerned, this statement generates no effect. However it does make a rather useful 'shortcut' in this context. It might be worth declaring the function as 'inline'. I'd not expect the compiler to seperate it (since it is so short), but it might lead to problems if it did.
:=:=
:=:=Best Wishes
:=
:=One more not so funny thing, the real potential danger is in case of interrupt, if mul_u8() is interrupted with an ISR also using multiplication, then ... it really hurt, and worse ... very hard to debug. CCS's ISR handling routine does NOT push 0xFF3 and 0xFF4 into safe place, so, it won't be restored after ISR, you have to do it all by yourself.
:=
:=Best wishes and ... be careful !
:=
:=p.s. I was planning to use this kind of algorithm for fast floating multiplication, however, exclusively inside my ISR.</font>
The compiler should (!), put protection around the routine, and disable interrupts for it, when the same routine is called both inside and outside the ISR. However (obviously), if you use your routine in one place, and use the 'standard' routine in the other, this won't happen. The same problem will exist with all the proposed solutions. One obvious solution, would be to add a 'DIY' save of the registers, by adding something like:
static int16 save;
save=mul_prod;
at the start of the interrupt routine,
and:
mul_prod=save;
at the end, to ensure the registers are protected.
Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 144515840 |
|
|
Chang-Huei Wu Guest
|
Re: Multiply 8-bit*8-bit = 16-bit |
Posted: Thu Jul 10, 2003 7:43 am |
|
|
:=The compiler should (!), put protection around the routine, and disable interrupts for it, when the same routine is called both inside and outside the ISR. However (obviously), if you use your routine in one place, and use the 'standard' routine in the other, this won't happen. The same problem will exist with all the proposed solutions. One obvious solution, would be to add a 'DIY' save of the registers, by adding something like:
Yes, the compiler SHOULD provide this protection as what had been written in the manual and FAQ, however, PCH 3.123(?) does NOT (!) do it, but, PCH 3.148 switched this feature back ON. It was a really horrible learning experience with 3.12x, the atof() in main() is randomly corruptted by a simple z = (float)x * (float)y in ISR. Well, now I have a special test program in my pocket preparing for surprise whenever I upgrade to a new version. I also did modified the stdlib.h with my own protection while tracing CCS's evolution, there was a warning message for this situation around 3.15x, however, they turned OFF this warning since 3.16x. It is fun to observe how considerate CCS is, and, fun to play with CCS. Last of all, it is really good to have you guys on this forum.
Thanks a lot,
C-H Wu
:=
:=static int16 save;
:=save=mul_prod;
:=
:=at the start of the interrupt routine,
:=and:
:=
:=mul_prod=save;
:=
:=at the end, to ensure the registers are protected.
:=
:=Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 144515843 |
|
|
Chang-Huei Wu Guest
|
Thanks for 3.170 |
Posted: Wed Aug 06, 2003 8:04 am |
|
|
<font face="Courier New" size=-1>Good news, PCH 3.170 fixed it !
3.170 A problem with hw multiply on PIC18 between interrupt and non-interrupt functions is fixed.
see ... <a href="http://www.ccsinfo.com/versions.shtml" TARGET="_blank"> <a href="http://www.ccsinfo.com/versions.shtml" TARGET="_blank">http://www.ccsinfo.com/versions.shtml</a></a>
the 'DIY' patch suggested by R.J.Hamlett is no longer necessary.
Cheers
PIC18F452 ISR dispatcher:
0018: MOVWF 05
001A: MOVFF STATUS,06
001E: MOVF FSR0L,W
0020: MOVWF 07
0022: MOVF FSR0H,W
0024: MOVWF 08
0026: MOVF FSR1L,W
0028: MOVWF 09
002A: MOVF FSR1H,W
002C: MOVWF 0A
002E: MOVF FSR2L,W
0030: MOVWF 0B
0032: MOVF FSR2H,W
0034: MOVWF 0C
0036: MOVF PRODL,W <--- here
0038: MOVWF 13
003A: MOVF PRODH,W <--- and here
003C: MOVWF 14
003E: MOVF BSR,W
0040: MOVWF 0D
...
:=:=The compiler should (!), put protection around the routine, and disable interrupts for it, when the same routine is called both inside and outside the ISR. However (obviously), if you use your routine in one place, and use the 'standard' routine in the other, this won't happen. The same problem will exist with all the proposed solutions. One obvious solution, would be to add a 'DIY' save of the registers, by adding something like:
:=
:=Yes, the compiler SHOULD provide this protection as what had been written in the manual and FAQ, however, PCH 3.123(?) does NOT (!) do it, but, PCH 3.148 switched this feature back ON. It was a really horrible learning experience with 3.12x, the atof() in main() is randomly corruptted by a simple z = (float)x * (float)y in ISR. Well, now I have a special test program in my pocket preparing for surprise whenever I upgrade to a new version. I also did modified the stdlib.h with my own protection while tracing CCS's evolution, there was a warning message for this situation around 3.15x, however, they turned OFF this warning since 3.16x. It is fun to observe how considerate CCS is, and, fun to play with CCS. Last of all, it is really good to have you guys on this forum.
:=
:=
:=Thanks a lot,
:=
:=
:=C-H Wu
:=
:=:=
:=:=static int16 save;
:=:=save=mul_prod;
:=:=
:=:=at the start of the interrupt routine,
:=:=and:
:=:=
:=:=mul_prod=save;
:=:=
:=:=at the end, to ensure the registers are protected.
:=:=
:=:=Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 144516708 |
|
|
kypec
Joined: 20 Sep 2003 Posts: 54
|
another approach to fast 8x8 bit hardware multiply |
Posted: Wed Nov 19, 2003 4:54 am |
|
|
Here is what I find quite easy and handy for PIC18.
You define the macro below and then use it in your
code like this:
int8 var1,var2;
int16 result;
mul8x8(var1,var2,result) //two variables multiplied
or
mul8x8(var1,const,result) //variable and constant multiplied
CONS:
only one asm instruction overhead, as
MOVF 0xff3, W, ACCESS
is inserted just after the multiplication
PROS:
compiler properly decides whether to use
MULWF or MULLW instruction
best wishes to everybody,
kypec
Code: |
////////////////////////////////////////////////////////////////////////////////
//MACRO for fast multiply 8-bit*8-bit=16-bit
////////////////////////////////////////////////////////////////////////////////
#define mul8x8(A8,B8,P16) A8*B8;P16=make16(PRODH,PRODL);
//compiles to MULWF or MULLW mnemonics
|
|
|
|
|
|
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
|