Hi all,
I need to multiply a 32 bit integer by a 16 bit integer and divide that result by a 16 bit integer. For the intermediate result I need more than 32 bits. I am programming in C using CW. Any ideas on implementing an unsigned long long variable?
Thanks,
David
Solved! Go to Solution.
You didn't say if you tolerate assembler. Here's my code:
#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */
typedef struct
{
   unsigned short hibits;
   unsigned long  lobits;
}  u48;
// *product  = m32 * m16
void mul32x16_48(u48 *product, unsigned long m32, unsigned short m16)
{
   asm
   {
      LDX   product
      LDD   m32:2
      LDY   m16
      EMUL
      STD   4,x
      STY   2,x
      LDD   m32
      LDY   m16
      EMUL
      ADDD  2,x
      STD   2,x
      TFR   Y,D
      ADCB  #0
      ADCA  #0
      STD   0,x
   }
}
// *q = *nom / denom
void div48x16(u48 *q, u48 *nom, unsigned short denom)
{
u48 qtmp;
   asm
   {
      LDY   nom
      LDD   0,y
      LDX   denom
      IDIV 
      STX   qtmp:0
      TFR   D,X
      LDD   2,y
      LDY   denom
      EXG   Y,X
      EDIV
      STY   qtmp:2
      LDY   nom
      LDY   4,y
      EXG   D,Y
      EDIV
      STY   qtmp:4
   }
   *q = qtmp;
}
u48 product;
u48 quot;
void main(void) {
  /* put your own code here */
 
   mul32x16_48(&product, 0x9876543F, 0xF765);
   div48x16(", &product, 0xEDAB);
EnableInterrupts;
  for(;
 {
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}
You didn't say if you tolerate assembler. Here's my code:
#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */
typedef struct
{
   unsigned short hibits;
   unsigned long  lobits;
}  u48;
// *product  = m32 * m16
void mul32x16_48(u48 *product, unsigned long m32, unsigned short m16)
{
   asm
   {
      LDX   product
      LDD   m32:2
      LDY   m16
      EMUL
      STD   4,x
      STY   2,x
      LDD   m32
      LDY   m16
      EMUL
      ADDD  2,x
      STD   2,x
      TFR   Y,D
      ADCB  #0
      ADCA  #0
      STD   0,x
   }
}
// *q = *nom / denom
void div48x16(u48 *q, u48 *nom, unsigned short denom)
{
u48 qtmp;
   asm
   {
      LDY   nom
      LDD   0,y
      LDX   denom
      IDIV 
      STX   qtmp:0
      TFR   D,X
      LDD   2,y
      LDY   denom
      EXG   Y,X
      EDIV
      STY   qtmp:2
      LDY   nom
      LDY   4,y
      EXG   D,Y
      EDIV
      STY   qtmp:4
   }
   *q = qtmp;
}
u48 product;
u48 quot;
void main(void) {
  /* put your own code here */
 
   mul32x16_48(&product, 0x9876543F, 0xF765);
   div48x16(", &product, 0xEDAB);
EnableInterrupts;
  for(;
 {
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}
Hey kef,
Works great!!!
Thanks so much!!
David
Hi kef,
Do you have a divide routine for 48 bits divided by 24 bits?
Thanks,
David
No, I don't. 24bits divider is well more complicated using S12 division instructions. Shift-subtract loop is the easy way to go. But shift-subtract is slow and new code requires some debugging. Then why not just using double precision floating point arithmetics? Since double mantissa is 52bits wide, double can contain up to 52bits wide integers without any rounding or loss of precision issues.
I am avoiding use the floating point math library to keep the code smaller.
Thanks,
David