Using more than a 32 bit integer with CW on the S12P MCU

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

Using more than a 32 bit integer with CW on the S12P MCU

跳至解决方案
1,893 次查看
datamstr
Contributor II

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

标签 (1)
0 项奖励
回复
1 解答
821 次查看
kef
Specialist I

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(&quot, &product, 0xEDAB);

 EnableInterrupts;


  for(;:smileywink: {
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}

在原帖中查看解决方案

0 项奖励
回复
5 回复数
822 次查看
kef
Specialist I

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(&quot, &product, 0xEDAB);

 EnableInterrupts;


  for(;:smileywink: {
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}

0 项奖励
回复
821 次查看
datamstr
Contributor II

Hey kef,

 

Works great!!!

 

Thanks so much!!

 

David

0 项奖励
回复
821 次查看
datamstr
Contributor II

Hi kef,

 

Do you have a divide routine for 48 bits divided by 24 bits?

 

Thanks,
David

0 项奖励
回复
821 次查看
kef
Specialist I

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.

 

0 项奖励
回复
821 次查看
datamstr
Contributor II

I am avoiding use the floating point math library to keep the code smaller.

 

Thanks,
David

0 项奖励
回复