8

There was a question like this before, in 2011: Exotic architectures the standards committees care about

Now, I'd like to ask a very similar question, but this time, I'm asking it from the programmer's view of perspective, and in the perspective of C++11.

Which hardwares exist currently, which has a C++11 compiler for it, and can be considered exotic?

What do I consider exotic?

  • where a char is not 8 bit
  • where IEEE 754 float number format not available
  • where the integer numbers aren't encoded in two complement
  • where there is no 8, 16 or 32 bit types supported by the compiler
  • where the memory model is not linear (so, you cannot compare/subtract any pointers)

So anything, which is not the standard, which we see on x86/ARM world, where we have:

  • have 8/16/32-bit two complement integers
  • IEEE754 floats, some fully compliant, some don't, but use the IEEE754 format
  • linear memory model

Note: I'd like to have answers, where a C++11 conformant compiler exists for the hardware, not where a C++ compiler exists, but isn't fully conformant.

I'm asking this, because a lot of times, I get answers like "you cannot depend on that, it is implementation defined", and I'd like to know, that actually, in the real world, how much I can depend on the standard. Just an example: whenever I write std::uint16_t, I may worry (as this feature is optional), that on a platform, this type is non-existent. But, is there an actual platform, where this type doesn't exist?

geza
  • 28,403
  • 6
  • 61
  • 135
  • I guess they are not that popular. I cant think of any modern exotic C++ hardware, they all use C. – Sv Sv Jul 15 '17 at 15:41
  • I like the question and would love to hear the answers for this, but I'm torn on whether it's fit for the site per the rules. Might be more appropriate on /r/cpp. – tambre Jul 15 '17 at 15:42
  • @tambre: I asked here, because I thought that if the linked question was OK, then my question is OK too, 6 years later – geza Jul 15 '17 at 15:48
  • @tambre: what is /r/cpp? – geza Jul 15 '17 at 15:48
  • @geza [The C++ subreddit](https://www.reddit.com/r/cpp). Rules on SO have changed over years. Some questions that were considered appropriate years ago aren't anymore. – tambre Jul 15 '17 at 15:49
  • @tambre: Actually, I don't find what's against this question, but there is already a close (1), and negative votes... – geza Jul 15 '17 at 15:55
  • The close vote is for "too broad", which, frankly, is quite accurate. – Hatted Rooster Jul 15 '17 at 15:56
  • I've re-read the rules and quite can't see why this would be off-topic/not fit for the site. The problem is uniquely related to programming and the question states what should be considered exotic. This question would require a fair bit of research, but would be really good content. I disagree with this being "too broad" due to the clear question statement. – tambre Jul 15 '17 at 15:59
  • 1
    @RickAstley: "too broad" is subjective. If I read the description of "too broad" at the help, I don't see, how my question "too broad". The most perfect answer for this question is a list, with specific information about why a HW is exotic. Of course, no-one create this list for me, so each answer will contain some HW's. And then, someone (perhaps me), can merge the answers to a definitive list, which can be accepted then. Too bad that SO had changed, if this question is not appropriate (like it was 6 years ago). – geza Jul 15 '17 at 17:45

4 Answers4

6

Go looking for DSP cores, that's your best bet for "exotic" architectures.

For example, the Motorola/Freescale/NXP 56720 has a C++ compiler available from Tasking, but has 24-bit memory on three or more buses. I think the stack model on the device (at least the older 56K devices) was a hardware stack and didn't really fit the C/C++ model.

edit: more details...

The register model on this beast is odd:

  1. Accumulators (56 bits, broken up in to 8bit, 24 bit, 24 bit sub registers)
  2. data registers (24 or 48 bits)
  3. address registers (R0..7, M0..7, and N0..7) For the address, modulo, and step size

The modulo and step size registers don't map to anything intrinsically modeled in C/C++, so there's always some oddball constructs and #pragma to help the compiler along to support circular buffers.

There's no stack pointer (no push or pop instruction). There's a hardware stack for function return addresses, but that's only 16 calls deep. The software has to manage overflows and local variables don't live in on the stack.

Because there's no stack, the compiler does weird things like static call tree analysis and puts local variables in overlayed memory pools. This means no re-entrant functions and necessarily only one context without much weirdness or severe performance penalties.

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

This means no byte access (at least on the old 56002, not sure about the 56300). I think it takes about 24 cycles to read/write a specific byte from an array of 24-bit integers. This core is not good and barrel shifting, masking, and or-ing

Not ALL DSP cores are like this of course, but they're usually varying degrees of 'weird' from the standard of 32/64 bit unified memory and sizeof(char)=1 expectations of GCC because of the intrinsic modulo pointers and multiple memory buses.

Russ Schultz
  • 2,545
  • 20
  • 22
  • 1
    What does this mean in practice? What things differ? Does a pointer take 3 bytes? – geza Jul 15 '17 at 16:03
  • Thanks Russ! But, as I see, this DSP cannot have a conforming C++11 implementation, right? For example, 16 calls deep is a little low. – geza Jul 15 '17 at 19:40
  • @geza "16 calls deep" is the hardware stack. "The software has to manage overflows and local variables don't live in on the stack." So the hardware stack has a complicated relationship with the C++ stack. – Eric Towers Jul 15 '17 at 20:49
  • I've seen a DSP with no native 16-bit type. Either 8 or 32-bit only. Don't expect code to be portable to these architectures. – marko Jul 16 '17 at 08:51
4

There are computers that have different bit widths for their registers.

The CDC Cyber series uses 6-bits to represent common characters and an extended 12-bits for non-common characters.

However, in order to be compliant with the C language standards, the compiler would need to use 12-bit characters because 6-bits does not satisfy the minimum range.

As for other requirements, you are talking about a small portion of the universe: custom implementations. Some platforms may have 80 bit floating point. Some platforms may use 4-bits as their minimal addressable unit.

Most hardware component manufacturers have standardized on 8-bit, 16-bit, 32-bit, 64-bit or 128-bit units. To get other non-standard units you may have to augment existing standard sizes. The standardization lowers the cost of integrated circuits.

Some hardware components, such as Digital to Analog converters (DAC), and Analog to Digital Converters (ADC) have bit widths that are not divisible by 8. For example, a 12-bit ADC is very common.

Let's talk really custom: Programmable Gate Arrays, e.g. FPGAs. Basically, you can program the device to have any number of bits for input or output or internal busses.

Summary:
In order to be C or C++ compliant, there are a minimum set of standards that must be met. The compiler is in responsible for allocating registers and memory to meet the standards. If a character is 6-bits, the compiler will have to use two 6-bit units in order to satisfy the minimum range of a character.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
2

When people say that something is implementation defined, this doesn't apply only to memory model, basic variable sizes etc. (i.e. hardware implementation), but rather the fact it may depend on a particular compiler implementation (different compilers may handle some things differently and they often do) and/or operating system the program is compiled for. So even though the overwhelming majority of hardware may be non-exotic according to your definition, still "you cannot depend on that, it is implementation defined" ;)

Example: C++ standard states that the long double type has to be at least as large as regular double (i.e. 8 bytes), but it's implementation defined, and, in fact, whereas g++ implements long double as 16 byte long for x64 platform, latest VC++ compiler sticks to the minimum and as for now long double is only 8 byte long just like double, but this may change in the future - you never know as it's implementation defined and Microsoft is free to change it anytime they want and the standard will still be adhered to.

It's not the exact answer to the question you have asked, but answers the last paragraphs of your question ("how much can I depend on the standard?") and clearly this may make you review the way you think of this problem. Also it's a bit long to be a comment and would be less readable, so I'll just leave it here.

KjMag
  • 2,650
  • 16
  • 16
  • 1
    Yes, I understand that. But there is a currently common *standard*, which is available almost everywhere. Even if the C++ standard doesn't guarantee that, in the real world, it is almost guaranteed. Like, there is a **int16_t** everywhere. Even, it is optional. But, I've lied, not everywhere. There are exotic hardwares, where it might not be available. That's what I'm asking. Of course, you can find some features in the language, which could differ a lot, like `long double`, but there are other features, which don't. – geza Jul 15 '17 at 16:18
  • Furthermore, there is common sense. Compiler vendors don't change things at their will. They could change `int` to be 16-bit. Does the standard allow this? Yes? Will they change it? I bet they won't. – geza Jul 15 '17 at 16:22
  • It's not almost guaranteed. If you use long double, you can't depend on it's size - in a very real scenario you get different size on two different compilers, and this is just a simple example. There are many less obvious examples that will make your program behave unpredictably when switching compilers or even update the one you use now. The point is, if the standard says it's implementation defined, well... it is, and it is very likely it will differ. This list won't tell you much as you would have to point out which features you expect to be unchanged between platforms. – KjMag Jul 15 '17 at 16:23
  • And such a list would only be valid on the day the item is added to it - in theory it might get invalidated even the next day. – KjMag Jul 15 '17 at 16:24
  • I dont' want to depend on `long double`'s size. But, I might want to depend on, that for example, a 32-bit integer exists. If I'm not mistaken, this is not guaranteed by the standard. But all the compilers I've worked on, it all has 32-bit integer. Maybe it's called `int`, maybe it's called `long`, but I have it. That's my question is about. – geza Jul 15 '17 at 16:27
  • a list can be updated. Furthermore, I see a lot of old C++ questions, for which the answers are wrong now, because we have C++11. – geza Jul 15 '17 at 16:31
  • As I've mentioned, you would have to list the features you expect to be unchanged, because as for now your question refers to something different than you've written in the comments. As for the C++11, these answers are not wrong now - they are still good if for some reason you don't use C++11, and there are significant number of platforms and tools that don't support it. As for integers, if I have to think if the variable I'm about to use is called int or long on different platforms, I would say the code is not platform-independent. – KjMag Jul 15 '17 at 16:43
  • They are wrong partly, because there are a lot of platforms, where C++11 is available. Just like my desired list. It won't invalidate the whole list, just the list become incomplete. About platform independece: yes, you are right. That's why I asked this question. Maybe I don't want a fully platform independent code. I just want to know, which platform gets excluded, if for example, my code presumes, that a float is a 32-bit IEEE754 number. A not fully platform independent code is not automatically a bad code. Maybe I do it on purpose, because the solution is cheaper this way – geza Jul 15 '17 at 17:31
  • As a side note: In practice the smart move is to formulate your assumptions in code to be checked at compilation time (which often can be done with C++11 or later). It will fail the build with a human-readable message when porting to some "exotic" platforms. Imho debating over "what can change" can only be pure academic discussion. – Sergey.quixoticaxis.Ivanov Oct 31 '17 at 15:47
1

Random examples:

  • AVR GCC has only 32 bit doubles. So GCC targeting Atmel AVR microcontrollers deviates from the Standard. (They deviate even more if -mint8 is set.) Arduinos are based on ATmega328s, which are AVRs. I hear there are a lot of Arduinos "in the wild".

  • 8051/80251 family microcontrollers have bit-addressable memory. This storage is also accessed with different widths through other ranges of addresses. The memory model is explicitly nonlinear. Even trying to limit discussion of these to wildly successful parts yields a list longer than I'm willing to transcribe here. Start here and keep reading and following the references. Approximate number in the wild: too many.

  • x86 32-bit protected mode allows 48-bit segment:offset pointers. Digital Mars C++ exposes these via __far, __huge, and __handle when targeting 32-bit. See Table 7.2 at Digital Mars's "Choosing a Memory Model". So even the "x86 world" has nonlinear memory. This was present since the Pentium, so "all the computers" would be a starting estimate for the number of these in the wild (and is the right order of magnitude).

  • One of the standard examples of nonlinear memory is the MC68000. (Exception thrown for odd addresses because there isn't even a pin for bit0 on the address bus.) The TI-89 and -92 calculators were built on the MC68000. There were several million of each sold (and many are still in use).

Eric Towers
  • 4,175
  • 1
  • 15
  • 17