为什么ARM7上MUL表达式的前两个参数不能相同?

时间:2015-10-09 20:44:57

标签: assembly arm multiplication arm7

我一直在帮助实验室学习ARM7汇编语言的课程,今天遇到了学生输入以下表达式的问题:

MUL R0, R0, R1

代码没有编译。解决方案是将表达式更改为:

MUL R0, R1, R0

即。 MUL的前两个参数不能是同一个寄存器。我已经知道这是因为它是ARM文档的一部分: http://infocenter.arm.com/help/topic/com.arm.doc.dui0489i/DUI0489I_arm_assembler_reference.pdf

学生很开心,他们的问题已得到解决,但我很沮丧,因为我不知道为什么 ARM7需要像这样传递参数。我认为这可能与其中一个用于存储中间值的寄存器有关,而乘法器正在移位和添加,但我甚至不确定这是否是乘法如何在ARM上运行(在事实上,我相当肯定它不是)。为什么参数的顺序在这里如此重要?

2 个答案:

答案 0 :(得分:1)

我的猜测是这是一个或多个核心的ip中的错误。

在arm 7天中,你给了一个从arm而不是源代码到核心的布局,让编译器解决ip bug,而不是修复bug,召回所有单位,废弃如果在供应商投资了面具或已经投入生产之后发现了这个错误,那么正在进行中。

随着时间的推移(和其他人)有更多东西你可以阅读并确定你拥有哪个特定的核心,并遵循勘误(虽然像Linux这样的软件在这方面做得很糟糕,将错误的勘误应用于错误的核心)来了解什么错误避免。

一些“不可预测的结果”实际上是可以预测的,只是被破坏了,并且可以被手臂用来确定这是克隆还是被盗的ip。

答案 1 :(得分:1)

Rn 必须与ARMv6之前的架构中的 Rd 不同”这一事实表明,这是对原始三级ARM管道中如何实现乘法的设计限制。在ARMv6意味着具有ARM7或更早版本设计的CPU之前,这些都使用了简单的三级流水线。与大多数指令不同,乘法需要多个周期才能执行,并且根据指令集限制,您的怀疑是正确的,每个周期都会修改目标寄存器 Rd 以计算结果。

论文Verifying ARM6 Multiplication by Anthony Fox通过在图4中显示(下面重新格式化以适应Stack Exchange标记的限制)来支持这一点,在ARM6执行乘法指令期间如何修改 Rd

  
      
  • t 3

         
        
    • 获取指令
    •   
    • 增加程序计数器
    •   
    • mul1设为reg[Rs]
    •   
    • borrow设为false
    •   
    • count1设为零

           
    •   
    • 如果累积,请将reg[Rd]设置为reg[Rn],否则为零

    •   
    • mul设为mul1[1:0]
    •   
    • mul2设为mul1[31:2]
    •   
    • borrow2设为borrow
    •   
    • mshift设为MSHIFT2(borrow,mul,count1)
    •   
  •   
  • 吨<子>名词

         
        
    • alub设置为reg[Rm]左移mshift
    •   
    • alua设为reg[Rd]
    •   
    • mul1设为mul2[29:0]
    •   
    • borrow设为mul[1]
    •   
    • count1设为mshift[4:1] + 1

           
    •   
    • reg[Rd]设为ALU6*(borrow2,mul,alua,alub)

    •   
    • mul设为mul1[1:0]
    •   
    • mul2设为mul1[31:2]
    •   
    • borrow2设为borrow
    •   
    • mshift设为MSHIFT2(borrow,mul,count1)
    •   
    • 更新NZC的{​​{1}}标记(如果设置了CPSR标记)
    •   
    • 如果最后一次迭代,则解码下一条指令
    •   
  •   
     

图。 4:ARM6执行乘法指令。每个周期都是分开的   分为两个阶段。重复 t n 循环,直到   S是真的。   当MULX(mul2,borrow,mshift)等于Rd或十五时,注册Rd不会更新。

由于Rm在初始设置周期 t 3 期间和重复的 t n 期间被修改循环结果将是reg[Rd]的垃圾,因为“设置Rd == Rmalua向左移动reg[Rm]”的步骤预计会读取<的原始未修改值< em> Rm ,而不是存储在 Rd 中的当前中间值。

如上所述,某些ARM7 CPU有一个“快速乘法器”,每个周期处理8位而不是每个周期2位,但它似乎也在计算过程中修改了寄存器。