2010-08-26 288 views
8

这是(AFAIK)this general topic中的一个特定问题。如何使用32位除法指令执行64位除法?

这里的情况:

我有一个基于32位RISC微控制器的嵌入式系统(视频游戏控制台)(NEC的V810的变体)。我想写一个定点数学库。我读this article,但随附的源代码是用386汇编编写的,所以它既不可直接使用也不易修改。

V810内置了整数乘法/除法,但我想使用上述文章中提到的18.14格式。这要求将一个64位整数除以一个32位整数,并且V810只做(有符号或无符号)32位/ 32位除法(产生一个32位商和一个32位余数)。

所以,我的问题是:如何模拟一个32位/ 32位的64位/ 32位除法(以允许预先移动除数)?或者,从另一个角度来看待问题,使用标准32位算术/逻辑运算来划分另一个18.14定点的最佳方法是什么? (“最好”意思是最快,最小或两者)。

代数,(V810)程序集和伪代码都很好。我会打电话给代码C.

在此先感谢!

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

+0

[32/16位除法处理器上的64/32位除法](https://stackoverflow.com/q/ 4771823/995714) – 2017-05-23 08:59:15

回答

5

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

+0

这似乎正是我所需要的。感谢您链接到相关的代码!顺便说一句,我使用GCC,但我使用的是newlib,它不包含这些东西。 – RunnerPack 2010-08-31 08:39:28

0

如果被除数是无符号的64位,您的除数是无符号的32位,该体系结构是I386(86),所述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不能为您编译,请使用Linux内核的__div64_32函数:https://github.com/torvalds/linux/blob/master/lib/div64.c