奇异硬件上的C ++ 11

时间:2017-07-15 15:38:04

标签: c++ c++11

2011年之前有一个类似的问题:Exotic architectures the standards committees care about

现在,我想问一个非常相似的问题,但这一次,我是从程序员的角度和C ++ 11的角度来看问题。

目前存在哪些硬件,它有一个C ++ 11编译器,可以被认为是异国情调?

我认为什么是异国情调?

  • 其中char不是8位
  • 其中IEEE 754浮点数格式不可用
  • 其中整数不以两个补码编码
  • 其中编译器不支持8位,16位或32位类型
  • 其中内存模型不是线性的(因此,您无法比较/减去任何指针)

所以我们在x86 / ARM世界中看到的不是标准的任何东西,我们在哪里:

  • 有8/16/32位两个补码整数
  • IEEE754浮动,一些完全兼容,一些不,但使用IEEE754格式
  • 线性记忆模型

注意:我想得到答案,其中存在符合C ++ 11标准的编译器用于硬件,而不是存在C ++编译器的地方,但不完全符合。

我问这个,因为很多时候,我得到的答案就像“你不能依赖它,它是实现定义的”,我想知道,实际上,在现实世界中,多少我可以依赖标准。举个例子:每当我写std::uint16_t时,我可能会担心(因为此功能可选),在平台上,这种类型是不存在的。但是,是否存在这种类型不存在的实际平台?

4 个答案:

答案 0 :(得分:6)

去寻找DSP内核,这是“异国情调”架构的最佳选择。

例如,Motorola / Freescale / NXP 56720有一个可从Tasking获得的C ++编译器,但在三个或更多总线上有24位内存。我认为设备上的堆栈模型(至少是较旧的56K设备)是硬件堆栈,并不适合C / C ++模型。

编辑:更多细节...

这头野兽的登记模型是奇怪的:

  1. 累加器(56位,分为8位,24位,24位子寄存器)
  2. 数据寄存器(24或48位)
  3. 地址寄存器(R0..7,M0..7和N0..7)用于地址,模数和步长
  4. 模数和步长寄存器不会映射到C / C ++中本质建模的任何东西,因此总会有一些奇怪的构造和#pragma来帮助编译器支持循环缓冲区。

    没有堆栈指针(没有push或pop指令)。有一个用于函数返回地址的硬件堆栈,但这只有16个深度调用。该软件必须管理溢出,并且本地变量不会存在于堆栈中。

    因为没有堆栈,编译器会做一些奇怪的事情,比如静态调用树分析,并将局部变量放在重叠的内存池中。这意味着没有重入功能,只需要一个上下文,没有太多的怪异或严重的性能损失。

    sizeof(int) = sizeof(char) = sizeof(short) = 1 = 24位

    这意味着没有字节访问(至少在旧的56002上,不确定56300)。我认为从24位整数数组中读取/写入特定字节大约需要24个周期。这个核心并不好,还有桶式移动,屏蔽和移动

    当然不是所有的DSP内核都是这样的,但是它们通常与32/64位统一内存的标准有不同程度的“怪异”,并且由于内在的模数指针,它们的大小(char)= 1对GCC的期望和多个内存总线。

答案 1 :(得分:4)

有些计算机的寄存器位宽不同。

CDC Cyber​​系列使用6位表示常见字符,使用扩展12位表示非常见字符。

但是,为了符合C语言标准,编译器需要使用12位字符,因为6位不满足最小范围。

至于其他要求,您谈论的是宇宙的一小部分:自定义实现。某些平台可能有80位浮点。某些平台可能使用4位作为其最小可寻址单元。

大多数硬件组件制造商已对8位,16位,32位,64位或128位单元进行了标准化。要获得其他非标准单位,您可能需要增加现有的标准尺寸。标准化降低了集成电路的成本。

某些硬件组件(如数模转换器(DAC)和模数转换器(ADC))的位宽不能被8整除。例如,12位ADC非常常见。

让我们的谈话真正定制:可编程门阵列,例如FPGA中。基本上,您可以将器件编程为具有任意数量的位用于输入或输出或内部总线。

要点:
为了符合C或C ++标准,必须满足一组最低标准。编译器负责分配寄存器和内存以满足标准。如果字符是6位,则编译器必须使用两个6位单元才能满足字符的最小范围。

答案 2 :(得分:2)

当人们说某些内容是实现定义时,这并不仅适用于内存模型,基本变量大小等(即硬件实现),而是它可能依赖于一个特定的编译器实现(不同的编译器可能会以不同的方式处理某些事情而他们经常执行)和/或编译该程序的操作系统。因此,即使根据您的定义,绝大多数硬件可能都不具有异国情调,但仍然"您不能依赖它,它是实现定义的" ;)

示例:C ++标准规定long double类型必须至少与常规double一样大(即8个字节),但它<\ n < strong>实现定义,实际上,对于x64平台,g ++实现long double为16字节长,最新的VC ++编译器最小化,而现在long double只有8字节很久就像double一样,但这可能会在将来发生变化 - 你永远不会知道它的实现定义,微软可以随时随地改变它,标准仍然可以坚持。

这不是您提出的问题的确切答案,但是回答了问题的最后几段(&#34;我可以依赖标准多少?&#34;)并且显然可能让你回顾一下你对这个问题的看法。此外,评论时间有点长,而且可读性较差,所以我只是把它放在这里。

答案 3 :(得分:1)

随机例子:

  • AVR GCConly 32 bit doubles。因此,针对Atmel AVR microcontrollers的GCC偏离了标准。 (如果-mint8已设置,则deviate even more。)Arduinos基于ATmega328,即AVR。我听说有很多Arduinos“在野外”。

  • 8051/80251系列微控制器具有bit-addressable memory。通过其他地址范围也可以使用不同的宽度访问此存储。内存模型明确是非线性的。即使试图将这些讨论限制在非常成功的部分,也会产生比我愿意在这里转录更长的清单。开始here并继续阅读和关注参考文献。野外的近似数字:太多了。

  • x86 32位保护模式允许48位段:偏移指针。当针对32位时,Digital Mars C ++会通过__far__huge__handle公开这些内容。见Digital Mars's "Choosing a Memory Model"表7.2。所以即使是“x86世界”也有非线性记忆。自Pentium以来就存在这种情况,因此“所有计算机”都是对野外数量的起始估计(并且是正确的数量级)。

  • 非线性存储器的标准示例之一是MC68000。 (奇数地址抛出异常,因为地址总线上的bit0甚至没有引脚。)TI-89和-92计算器是在MC68000上构建的。每个售出数百万(其中许多仍在使用中)。