|
|
View previous topic :: View next topic |
Author |
Message |
yo4hsp
Joined: 12 Sep 2008 Posts: 7
|
mul 16x16 |
Posted: Sat Nov 07, 2009 5:55 am |
|
|
Hello,
For my FIR filter, I need a multiplier. I use pic18f2455 and I found on his datasheet (pp 98). This is asm code for hardware multiplier.
Code: |
#asm
MOVF ARG1L, W
MULWF ARG2L ; ARG1L * ARG2L ->
; PRODH:PRODL
MOVFF PRODH, RES1 ;
MOVFF PRODL, RES0 ;
;
MOVF ARG1H, W
MULWF ARG2H ; ARG1H * ARG2H ->
; PRODH:PRODL
MOVFF PRODH, RES3 ;
MOVFF PRODL, RES2 ;
;
MOVF ARG1L,W
MULWF ARG2H ; ARG1L * ARG2H ->
; PRODH:PRODL
MOVF PRODL, W ;
ADDWF RES1, F ; Add cross
MOVF PRODH, W ; products
ADDWFC RES2, F ;
CLRF WREG ;
ADDWFC RES3, F ;
;
MOVF ARG1H, W ;
MULWF ARG2L ; ARG1H * ARG2L ->
; PRODH:PRODL
MOVF PRODL, W ;
ADDWF RES1, F ; Add cross
MOVF PRODH, W ; products
ADDWFC RES2, F ;
CLRF WREG ;
ADDWFC RES3, F ;
;
BTFSS ARG2H, 7 ; ARG2H:ARG2L neg?
BRA SIGN_ARG1 ; no, check ARG1
MOVF ARG1L, W ;
SUBWF RES2 ;
MOVF ARG1H, W ;
SUBWFB RES3
;
SIGN_ARG1
BTFSS ARG1H, 7 ; ARG1H:ARG1L neg?
BRA CONT_CODE ; no, done
MOVF ARG2L, W ;
SUBWF RES2 ;
MOVF ARG2H, W ;
SUBWFB RES3
;
#endasm
|
This code is not running in my CCS compiler, with errors:
"This must be a Microchip mnemonic such as MOVLW or BTFSC". I have only the BTFSS, and this mnemonic is defined on my ccs compiler. What is the problem?
Then, I tried this asm code on mplab, and it works.
Thanks |
|
|
yo4hsp
Joined: 12 Sep 2008 Posts: 7
|
|
Posted: Sat Nov 07, 2009 5:56 am |
|
|
I need a 16x 16 multiplier with sign. For up side code, the formula is:
Code: |
RES3:RES0 = ARG1H:ARG1L • ARG2H:ARG2L
= (ARG1H • ARG2H • 216) +
(ARG1H • ARG2L • 28) +
(ARG1L • ARG2H • 28) +
(ARG1L • ARG2L) +
(-1 • ARG2H<7> • ARG1H:ARG1L • 216) +
(-1 • ARG1H<7> • ARG2H:ARG2L • 216)
|
Thanks |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sat Nov 07, 2009 7:08 am |
|
|
Generally, you can expect your C compiler to know how to imlement signed int16 mupltiply.
What's the purpose of a DIY assembler implementation? |
|
|
Guest
|
mul 16x16 with sign |
Posted: Mon Nov 09, 2009 2:14 am |
|
|
Hello,
I need to multiply two large numbers with sign (on 16 bits), and the
results will be on 32 bits. I try the hardware multiply (pic18f2455
datasheet) and I receive lots of errors from unrecognized mnemonics.
I used pic18f2455. |
|
|
bungee-
Joined: 27 Jun 2007 Posts: 206
|
|
Posted: Mon Nov 09, 2009 3:17 am |
|
|
Like:
Code: |
signed int16 a,b;
signed int32 c;
c= a*b;
| |
|
|
Ttelmah Guest
|
|
Posted: Mon Nov 09, 2009 10:19 am |
|
|
var = _mul(x,y);
This is a built in function, that multiplies two 8 bit values, producing a 16bit result, or two 16bit values, producing a 32 bit result - exactly what you want...
A lot more efficient than using 32bit internal arithmetic.
Best Wishes |
|
|
yo4hsp
Joined: 12 Sep 2008 Posts: 7
|
multiply 16 x 16 with sign |
Posted: Mon Nov 09, 2009 12:55 pm |
|
|
ok, but "var = _mul(x,y);" is for unsigned numbers. in my filter i have a lots of coefficients and samples signed. whas i have to use??? so, i need "mul" or anything like multiplier for signed numbers with 16 bits, and results on 32 bits...
thanks, |
|
|
Ttelmah Guest
|
|
Posted: Mon Nov 09, 2009 1:43 pm |
|
|
If you look at your assembler example, all it does is test the top bits to verify the possible results that give a signed result.
Best Wishes |
|
|
Guest
|
|
Posted: Mon Nov 09, 2009 2:34 pm |
|
|
Thanks, I see the testing for sign:
...
(-1 • ARG2H<7> • ARG1H:ARG1L • 2^16) +
(-1 • ARG1H<7> • ARG2H:ARG2L • 2^16)
I hope is another function for multiply with signed numbers like "_mul" for unsigned. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Nov 09, 2009 3:41 pm |
|
|
I think you missed the point. Ttelmah gave you a hint to solve your problem.
Let me establish a bit more: It is basic mathematics to create signed multiply when you have a routine for unsigned multiply. Only the couple of if-statements from your assembly program... |
|
|
Ttelmah Guest
|
|
Posted: Tue Nov 10, 2009 3:10 am |
|
|
and, as a further hint, the CCS #bit directive, gives an 'assembly efficient' way of testing/clearing individual bits in a variable...
Best Wishes |
|
|
yo4hsp
Joined: 12 Sep 2008 Posts: 7
|
thanks |
Posted: Sun Nov 15, 2009 4:42 am |
|
|
thanks..
here my code, butt is still with errors. i think my mcu is slow for my application.
signed int32 inmultit;
signed int32 inmultire (signed int16 ARG1H, int16 ARG1L, signed int16 ARG2H, int16 ARG2L)
{ int32 PRODH = 0;
int32 PRODL = 0;
int32 PRODN = 0;
int32 PRODM = 0;
PRODH = _mul( (int16)ARG1H, (int16)ARG2H); //primii 2 octeti (0 si 1) va fi pe 16 biti
PRODM = _mul( (int16)ARG1H, (int16)ARG2L); //cei 2 octeti de mijloc (1 si 2)
PRODN = _mul( (int16)ARG1L, (int16)ARG2H); //cei 2 octeti de mijloc (1 si 2)
PRODL = _mul( (int16)ARG1L, (int16)ARG2L); //ultimii 2 octeti (2 si 3) va fi pe 16 biti
inmultit = _mul( (int16)PRODH, (int16)0x10000) + _mul( (int16)PRODM, (int16)0x100) + _mul( (int16)PRODN, (int16)0x100 ) + (int16)PRODL
- _mul( ( _mul (!bit_test(ARG1H, 3), (int16)ARG2H) ), (int16)0x10000)
- _mul( ( _mul (!bit_test(ARG1H, 3), (int16)ARG2L) ), (int16)0x100 )
- _mul( ( _mul (!bit_test(ARG2H, 3), (int16)ARG1H) ), (int16)0x10000)
- _mul( ( _mul (!bit_test(ARG2H, 3), (int16)ARG1L) ), (int16)0x100 );
return inmultit;
}
///////------------------------------------------------------------------------------ |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Nov 15, 2009 5:42 am |
|
|
Quote: | inmultit = _mul( (int16)PRODH, (int16)0x10000) + _mul( (int16)PRODM, (int16)0x100) + _mul( (int16)PRODN, (int16)0x100 ) + (int16)PRODL
- _mul( ( _mul (!bit_test(ARG1H, 3), (int16)ARG2H) ), (int16)0x10000)
- _mul( ( _mul (!bit_test(ARG1H, 3), (int16)ARG2L) ), (int16)0x100 )
- _mul( ( _mul (!bit_test(ARG2H, 3), (int16)ARG1H) ), )
- _mul( ( _mul (!bit_test(ARG2H, 3), (int16)ARG1L) ), (int16)0x100 ); | Here I am losing you... What are you trying to do?
Can you show the original mathematical equation?
This is a bug. After the cast you will only yield the lowest 16 bits, which is 0x0000 == 0
11 multiplications will be slow and can be made a lot faster when you know that multiplying by 0x10 is the same as shifting left by 4 bits. Multiplying by 0x100 is shifting left by 8 bits, etc. |
|
|
|
|
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
|