C 编译器如何提供对多个存储器的访问?
How do C compilers provide access to several memories?
如果一台计算机有多个用于数据的地址 space,C 编译器如何提供对这些地址的访问?
上下文
我正在考虑的一些现实生活中的架构:
KR580VM1 或 КР580ВМ1
这基本上是一个 Intel 8080,增加了一些寄存器和第 17 条地址线。指令前缀在获取操作码后断言第 17 地址行,直到指令结束;由于指针仍然只有 16 位宽,这自然会将地址 space 分成两半。地址的下半部分 space 可能包含代码,两半部分都可能包含数据。
CDC 6000的外围处理器
它们有一个 12 位地址总线,因此可以访问本地内存的 4096 个机器字。它们还有一个 18 位地址总线,用于寻址中央存储库。
单元格处理器
这些在 PlayStation 3 中使用,据我了解与我提到的 CDC 有类似的安排。我不确定,但我认为 SPE 的地址 space 可能与 PPE 的地址重叠。
问题
在我看来,指针是一种看起来像整数的东西,因为它具有离散值并且可以向上或向下计数,并且它最终将被放在地址总线上。我的问题是,对于我描述的体系结构,由于各种原因,指针不能唯一标识内存位置。这意味着代码生成器需要以不同的方式关注如何生成代码以取消引用指针。
那么是否有一个 C 编译器的实现与这个问题有关?你能向我描述一下他们的解决方案吗?
旧的 16 位 PC 上的 GCC compiler provides as an extension named address spaces (and also function attributes, variable attributes, type attributes, target-specific builtins, ...). This is probably useful in your context. Sometimes, you have other kind of extensions (e.g. far pointers...)
详细信息是特定于编译器和目标体系结构的。
您甚至可以使用自己的 GCC plugin 扩展 GCC(这并不容易)。
但是,CDC6000 比 C 早了很长时间。
在某些情况下,协处理器正在获取自己的程序并且数据传输是显式的。查看 OpenCL 的示例。
在其他情况下,特定的 #pragma
正在指导编译器。参见 OpenMP, OpenACC。
当然,您可以只使用 API 共享内存。例如参见 [=15=].
有时候,你可能会有奇怪的例子ABIs. Look into x32。
最后,C 并没有你想要的那么通用。有些架构不太适合它。
在不列出所有这些奇异架构的情况下,对于需要寻址比其 16 位地址总线允许的 64kib 更多闪存的 8/16 位微控制器来说,这是一种相当普遍的情况。 MS DOS + 早期的 x86 也有类似的问题。
有两种可能的解决方案,都不好:
- 为更大的地址范围编译程序中的所有指针。这将使二进制文件更大,并且可能还会影响性能。
- 对不同的地址区域使用非标准扩展,例如非标准
near
指针用于访问较小的地址,far
用于访问较大的地址。也就是说,near
和 far
成为指针的非标准类型限定符:int* far ptr;
如果一台计算机有多个用于数据的地址 space,C 编译器如何提供对这些地址的访问?
上下文
我正在考虑的一些现实生活中的架构:
KR580VM1 或 КР580ВМ1
这基本上是一个 Intel 8080,增加了一些寄存器和第 17 条地址线。指令前缀在获取操作码后断言第 17 地址行,直到指令结束;由于指针仍然只有 16 位宽,这自然会将地址 space 分成两半。地址的下半部分 space 可能包含代码,两半部分都可能包含数据。
CDC 6000的外围处理器
它们有一个 12 位地址总线,因此可以访问本地内存的 4096 个机器字。它们还有一个 18 位地址总线,用于寻址中央存储库。
单元格处理器
这些在 PlayStation 3 中使用,据我了解与我提到的 CDC 有类似的安排。我不确定,但我认为 SPE 的地址 space 可能与 PPE 的地址重叠。
问题
在我看来,指针是一种看起来像整数的东西,因为它具有离散值并且可以向上或向下计数,并且它最终将被放在地址总线上。我的问题是,对于我描述的体系结构,由于各种原因,指针不能唯一标识内存位置。这意味着代码生成器需要以不同的方式关注如何生成代码以取消引用指针。
那么是否有一个 C 编译器的实现与这个问题有关?你能向我描述一下他们的解决方案吗?
旧的 16 位 PC 上的 GCC compiler provides as an extension named address spaces (and also function attributes, variable attributes, type attributes, target-specific builtins, ...). This is probably useful in your context. Sometimes, you have other kind of extensions (e.g. far pointers...)
详细信息是特定于编译器和目标体系结构的。
您甚至可以使用自己的 GCC plugin 扩展 GCC(这并不容易)。
但是,CDC6000 比 C 早了很长时间。
在某些情况下,协处理器正在获取自己的程序并且数据传输是显式的。查看 OpenCL 的示例。
在其他情况下,特定的 #pragma
正在指导编译器。参见 OpenMP, OpenACC。
当然,您可以只使用 API 共享内存。例如参见 [=15=].
有时候,你可能会有奇怪的例子ABIs. Look into x32。
最后,C 并没有你想要的那么通用。有些架构不太适合它。
在不列出所有这些奇异架构的情况下,对于需要寻址比其 16 位地址总线允许的 64kib 更多闪存的 8/16 位微控制器来说,这是一种相当普遍的情况。 MS DOS + 早期的 x86 也有类似的问题。
有两种可能的解决方案,都不好:
- 为更大的地址范围编译程序中的所有指针。这将使二进制文件更大,并且可能还会影响性能。
- 对不同的地址区域使用非标准扩展,例如非标准
near
指针用于访问较小的地址,far
用于访问较大的地址。也就是说,near
和far
成为指针的非标准类型限定符:int* far ptr;