首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

理解 x87 FPU 的执行环境(3)

理解 x87 FPU 的执行环境(3)

3. 浮点数据寄存器与 TOP 状态在 x86/x64 的机器的 x87 FPU 执行环境中有一组由 8 个 float pointer register(浮点寄存器)组成的 register stack

每个浮点寄存器 80-bit 宽,这些浮点寄存器存贮的格式被称作扩展双精度浮点格式
  • double extended-precision floating-point
扩展双精度浮点数是 80-bit 的,当 32 位的 single float point(单精度浮点数)和 64 位的 double float point(双精度浮点数)被装载到浮点寄存器时,会被自动转换为 80 位的扩展双精度浮点数。
这些浮点寄存器组成一个寄存器栈,x87 FPU 以 stack 结构的形式使用这些物理的浮点寄存器,由 status word 寄存器中的 TOP 部分指出这个寄存器栈当前的 stack top(栈顶)。
3.1 stack registers由 8 个 物理的浮点数据寄存器组成的 stack,每个物理浮点数据寄存器对应一个 stack register,从 st(0) - st(7),栈顶是 st(0) 寄存器,这些 stack register 的虚拟的,它们实际上只是 st(0) 的偏移值,st(0) 具体对应哪个物理浮点寄存器由 status word 中的 TOP 部分决定。

在上图这个 16 位的 status word 寄存器中,我们关注其中的 Bit13 - Bit11 TOP(top of stack pointer)它的取值范围是:
  • 000 - 111
TOP 值指示一个物理的浮点寄存器,TOP 的值给出当前的栈顶,每入栈一次,TOP 的值减 1,以下面为例
  • TOP = 011 时,表明当前的 stack top 对应的是 fpr3 寄存器
下面是关于 stack register 的使用,在 Intel manual 上的例子:
a = 5.6
b = 2.4
c = 3.8
d = 10.3
式子:(a * b) + (c * d) = (5.6 * 2.4) + (3.8 * 10.3) = ?
下面的 x87 指令序列用来完成这项任务:
fld a                      ; st(0) = a
fmul b                     ; st(0) = st(0) * b
fld c                      ; st(0) = c, st(1) = a * b
fmul d                     ; st(0) = st(0) * d
fadd st(1)                 ; st(0) = st(0) + st(1)
假设在这段代码执行之前,当前的 TOP = 3,也就是说 st(0) = fpr3, st(1) = fpr4 那么:
  • fld a
TOP - 1 此时 TOP = 2 指示 st(0) 将是 fpr2 寄存器,将 a 压入 stack 中, 那么结果是 fpr2 寄存器的值是 5.6
  • fmul b
指令将栈顶 st(0) = st(0) * 2.4 = 5.6 * 2.4 = 13.44 此时 fpr2 寄存器的值是 13.44 栈顶依然是 fpr2 寄存器
  • fld c
TOP - 1 此时 TOP = 1 指示 st(0) 将是 fpr1 寄存器,将 c 压入 stack 中,结果 fpr1 寄存器的值是 3.8,在这里 st(0) = fpr1st(1) = fpr2,fpr2 寄存器已经不是栈顶了。
  • fmul d
结果是 st(0) = st(0) * 10.3 = 39.14,栈顶的值是 39.14
  • fadd st(1)
指令执行 st(0) = st(0) + st(1),结果是 fpr1 + fpr2 = 13.44 + 39.14 = 52.58
3.2 TOP 的回卷当 TOP = 0 时,也就是说 st(0) 在 fpr0 寄存器上,就是遭遇到回卷的问题:
  • st(0) - st(7) 分别对应 fpr0 - fpr7
当再执行入栈操作后,结果为:
  • st(0) = fpr7,st(1) = fpr0 ...... st(7) = fpr6
每个 stack register 相应地减 1 向下移一位,st(0) 则回卷至 fpr7

4. x87 Environment 初始化状态现在我们来看看 processor 在加电初始化的 x87 environment:
  • control word = 0040
  • status word = 0000
  • tag word = 5555
  • instruction pointer = 0
  • instruction pointer selector = 0
  • opcode = 0
  • data pointer = 0
  • data pointer selector = 0
control word 为 0040 表明所有的 exception mask 为 0,不接受这些异常,精度控制不可用,TOP 初始状态为 0,指向 fpr0,所有的 stack register 都是无效的。
经过 finit/fninit 指令初始化后,x87 environment 状态为:
  • control word = 037F
  • status word = 0000
  • tag word = FFFF
  • instruction pointer = 0
  • instruction pointer selector = 0
  • opcode = 0
  • data pointer = 0
  • data pointer selector = 0
finit/fninit 后的所有 stack registers 状态为空,是可用状态,接受所有的 x87 异常。
继承事业,薪火相传
返回列表