How do C compilers provide access to several memories?

Viewed 176

If a computer has more than one address space which is used for data, how have C compilers provided access to these?

The context

Some real-life architectures I am thinking about:

KR580VM1 or КР580ВМ1

This is basically an Intel 8080 with the addition of a few registers and a 17th address line. An instruction prefix asserts the 17th address line after the opcode is fetched until the instruction ends; since a pointer is still only 16 bits wide, this naturally divides the address space in two halves. The lower half of the address space may contain code and both halves may contain data.

The peripheral processors of the CDC 6000

These have a 12-bit address bus and can therefore access 4096 machine words of local memory. They also have an 18-bit address bus for addressing a central memory bank.

Cell Processor

These are used in the PlayStation 3 and from what I understand have a similar arrangement to the CDC I mentioned. I'm not sure, but I think the SPEs' address spaces may overlap the PPE's.

The questions

In my head, a pointer is something which kind of looks like an integer since it has discrete values and can count up or down, and it is something which will eventually be put on the address bus. My problem is that for the architectures I described, for various reasons, a pointer does not uniquely identify a memory location. This means that a code generator will need to be concerned in a different way about how to generate the code to dereference a pointer.

So is there an implementation of a C compiler which concerns itself with this problem? Can you describe their solution to me?

2 Answers

The 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 on old 16 bits PCs...)

Details are compiler and target architecture specific.

You might even extend GCC with your own GCC plugin (this is not easy).

But, the CDC6000 predated C by a long time.

In some cases, the co-processors are getting their own programs and the data transfers are explicit. Look into OpenCL for an example.

In other cases, specific #pragmas are guiding the compiler. See OpenMP, OpenACC.

Of course, you could just have an API for shared memory. See for example shm_overview(7).

Sometimes, you might have strange ABIs. Look into x32 for example.

At last, C is not as universal as you want it to be. Some architectures don't fit well into it.

Without listing all these exotic architectures, this is a fairly common situation for 8/16 bit microcontrollers that need to address more flash memory than the 64kib that their 16 bit address bus would allow. MS DOS + early x86 had similar problems.

There's two possible solutions, neither is good:

  • Compile all pointers in the program for the larger address range. This will make the binary size much bigger, and will possibly also affect performance.
  • Use non-standard extensions for different address areas, such as non-standard near pointers for accessing the smaller addresses and far for the larger ones. That is, near and far becomes non-standard type qualifiers for pointers: int* far ptr;
Related