11

这是(AFAIK)这个一般主题中的一个特定问题。

情况如下:

我有一个基于 32 位 RISC 微控制器(NEC V810 的变体)的嵌入式系统(视频游戏机)。我想写一个定点数学库。我看了这篇文章,但是随附的源代码是用 386 汇编编写的,因此既不能直接使用也不能轻易修改。

V810 内置了整数乘除法,但我想使用上面文章中提到的 18.14 格式。这需要将 64 位整数除以 32 位整数,而 V810 仅执行(有符号或无符号)32 位/32 位除法(产生 32 位商和 32 位余数)。

所以,我的问题是:如何用 32 位/32 位除法模拟 64 位/32 位除法(以允许预移动被除数)?或者,从另一种方式来看问题,使用标准 32 位算术/逻辑运算将 18.14 定点除以另一个定点的最佳方法是什么?(“最佳”表示最快、最小或两者兼而有之)。

代数、(V810)汇编和伪代码都很好。我将从 C 调用代码。

提前致谢!

编辑:不知何故我错过了这个问题......但是,它仍然需要一些修改才能超级高效(它必须比 v810 提供的浮点 div 更快,尽管它可能已经是......),因此,请随时为我做我的工作以换取声誉积分;)(当然还有我的图书馆文档中的信用)。

4

2 回答 2

6

GCC 对许多处理器都有这样的例程,名为 _divdi3(通常使用通用的 divmod 调用实现)。这是一个。一些 Unix 内核也有一个实现,例如FreeBSD

于 2010-08-26T07:52:46.647 回答
2

如果你的被除数是无符号 64 位,你的除数是无符号 32 位,架构是 i386 (x86),div汇编指令可以帮助你做一些准备:

#include <stdint.h>
/* Returns *a % b, and sets *a = *a_old / b; */
uint32_t UInt64DivAndGetMod(uint64_t *a, uint32_t b) {
#ifdef __i386__  /* u64 / u32 division with little i386 machine code. */
  uint32_t upper = ((uint32_t*)a)[1], r;
  ((uint32_t*)a)[1] = 0;
  if (upper >= b) {   
    ((uint32_t*)a)[1] = upper / b;
    upper %= b;
  }
  __asm__("divl %2" : "=a" (((uint32_t*)a)[0]), "=d" (r) :
      "rm" (b), "0" (((uint32_t*)a)[0]), "1" (upper));
  return r;
#else
  const uint64_t q = *a / b;  /* Calls __udivdi3 in libgcc. */
  const uint32_t r = *a - b * q;  /* `r = *a % b' would use __umoddi3. */
  *a = q;
  return r;
#endif
}

如果上面的行__udivdi3无法为您编译,请使用__div64_32Linux 内核中的函数:https ://github.com/torvalds/linux/blob/master/lib/div64.c

于 2017-02-01T14:34:21.400 回答