x86 P6上下文中的字节寄存器是什么



我正试图将OpenJDK交叉编译到一个旧的32位VIA Geode LX处理器上,我一直在使用这个断言:

assert(VM_Version::is_P6() || dest_reg->has_byte_register(), 
"must use byte registers if not P6");

很明显,我两次测试都失败了,但如果我用-XX:c1_LIRAssembler.cpp:1313覆盖警告,应用程序运行得很好,所以我认为我不知怎么错配了内核,但我不知道我错了。其中一个必须为真,断言才能通过

第1部分-VM_Version::is_P6((

VIA Geode LX应该是一个686处理器(减去一条指令(,但这不应该影响这里做出的决定,这取决于它可以访问的寄存器数量,而不是指令集。不过,OpenJDK确实测试了某些类型的寄存器,以确定处理器系列

它定义了注释中列出的CPU:

//       6   -  PentiumPro, Pentium II, Celeron, Xeon, Pentium III, Athlon,
//              Pentium M, Core Solo, Core Duo, Core2 Duo

我已经为"Pentium Pro"编译了内核,所以这应该会成功:

static int  cpu_family()        { return _cpu;}
static bool is_P6()             { return cpu_family() >= 6; }

_cpuextended_cpu_family():分配

static uint32_t extended_cpu_family() {
uint32_t result = _cpuid_info.std_cpuid1_eax.bits.family;
result += _cpuid_info.std_cpuid1_eax.bits.ext_family;
return result;
}

然后我们去兔子洞。。。。可以说,我明白为什么断言的这一部分会失败。VIA Geode LX模拟了Intel x86的指令集,但在许多情况下都失败了,所以我理解为什么它在技术上不符合P6的资格,正如函数extended_cpu_family()所定义的,这意味着它回到了类4。

第2部分-has_byte_register((

这是检查字节寄存器的代码:

public:
enum {
#ifndef AMD64
number_of_registers      = 8,
number_of_byte_registers = 4,
max_slots_per_register   = 1
#else
number_of_registers      = 16,
number_of_byte_registers = 16,
max_slots_per_register   = 1
#endif // AMD64
};
...
bool  has_byte_register() const                
{ return 0 <= (intptr_t)this && (intptr_t)this < number_of_byte_registers; }
...

其中intptr_t定义为:

typedef int                     intptr_t;

所以基本上看起来是has_byte_registers()失败了。不过,我看不出它怎么会成功,因为看起来"this"必须解析到一个内存位置,该位置将始终高于16。

然而,非64位处理器的预期字节寄存器数量是64位处理器字节寄存器数量的4倍,这似乎很奇怪。

我的内核配置错了吗,是其中一个测试错了吗(这样我就可以提交补丁了(,还是只是OpenJDK没有考虑像这样的"不太兼容"的旧CPU

然而,非64位处理器的预期字节寄存器数量是64位处理器字节寄存器数量的4倍,这似乎很奇怪。

是的,但在某种程度上确实发生了。

如果没有REX前缀,则有8个字节的寄存器,分为两组:

  • 低字节寄存器:ALDLCLBL(AX的低字节等(
  • 高字节寄存器:AHDHCHBH(AX的高字节等(

高字节寄存器通常具有比低字节寄存器更奇怪的属性,跟踪同一寄存器不同部分的分配是一个令人讨厌的额外复杂性。为了简化混乱,不使用它们可能是一个合理的选择,但这确实意味着字节寄存器计数降至4。

有了REX前缀(在64位模式中,否则就没有REX(,所有16个GPR中的最低字节可以用作字节寄存器。

高字节寄存器也仍然以64位模式存在(因此在某种意义上,在64位模式下有16+4字节寄存器(,但不能由具有REX前缀的指令访问(即使没有设置REX标志(。在64位中使用高字节寄存器是非常痛苦的,因为例如add ah, sil是不可能的,因为sil需要REX前缀,而ah需要缺少REX前缀。将计数设置为16与从不使用高字节寄存器是一致的。

不过,我不确定其余的是怎么回事。

最新更新