2

I'm writing program in C language for mipsisa32 architecture that works with ECOS operating system. This is the first time I'm working with ecos and mips, and I get strange problem. I use dynamically allocated chunk of memory and I write some data to it. But when I try to write double value to address that is not aligned to 8 bytes, I get exception number 5, which is declared in hal_intr.h as CYGNUM_HAL_VECTOR_STORE_ADDRESS, and later redefined as CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE.

If I take pointers to destination and source and cast them to long long*, and them assign value from one to another then I don't get exception.

Same thing happens when reading double from unaligned address, but only with double, and not with long long. It does make sense, because assembly code really does use different instructions. I don't know mips assembly but from what I've seen I concluded that when storing/reading long long it does so in two chunks of 4bytes, but for double it does it in one step.

So what do you suggest? Is this normal behavior?

My last resort is to make sure myself, that addresses are aligned, which would add extra overhead since I write to many dynamically allocated buffers.

Marko
  • 1,267
  • 1
  • 16
  • 25
  • It seems that on that hardware writes of doubles must be 8 byte aligned. It's a hardware requirement. – Jabberwocky Aug 07 '15 at 13:19
  • IIRC MIPS does not support unaligned memory accesses. You might be violating the requirement for `malloc` to return blocks properly aligned for any datatype. For `long long`: on a 32 bit architecture, that is emulated using two registers with 32 bit memory accesses. I presume you are aligning to this boundary. – too honest for this site Aug 07 '15 at 13:20
  • 1
    BTW the name _mipsisa32 _ suggests that this is a 32 bit system, so the `long long` type is probably implemented by software and then a write of a `long long` boils down to two writes of a `long` which must be aligned to a 4 bytes boudary and therefore it works with `long long`. – Jabberwocky Aug 07 '15 at 13:23
  • @Olaf Yes, I checked, addresses are 4bytes aligned. What should I do? What is problem? Should malloc return addresses that are 8bytes aligned? – Marko Aug 07 '15 at 13:25
  • 1
    I'd say the solution is obvious. Please read my former comment **carefully** again and think about the implications of the second sentence. – too honest for this site Aug 07 '15 at 13:27
  • @Olaf I've found macro definition in systems source code which I could use to set alignment requirements for functions that dynamically allocate memory (malloc). It seems that it's custom allocation library or something. But it works now. Thank you. – Marko Aug 07 '15 at 13:35
  • "I use dynamically allocated chunk of memory": Is this a system `malloc()` or some derived code? Suspect the allocator is incorrectly providing unaligned data and _it_ needs repair. – chux - Reinstate Monica Aug 07 '15 at 13:52
  • @chux I got the system from other people so I didn't know what it uses. Is seems that is custom malloc that uses BGET. So I found I macro definition that I need to change to make returned memory aligned to 8 bytes. – Marko Aug 07 '15 at 15:17

1 Answers1

1

IIRC MIPS does not support unaligned memory accesses. You might be violating the requirement for malloc to return blocks properly aligned for any datatype.

double as fetched as a single 64 bit word. So it requires an alignment of 8 bytes (here: 8 bits). For long long: on a 32 bit (word) architecture, that is emulated using two registers with 32 bit memory accesses (a load double-word instruction as LDRD on ARM is basically two word load instructions). So 4 bytes is a sufficientl (yet possibly not optimal) alignment.

I assume you are currently aligning to word-boundaries. You should align to max_align_t (C11) or similar (pre-C11) to be on the safe side.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
  • 1
    I got your answer right, but for other people to know how to solve it. My problem was that malloc returned memory aligned to 4 bytes, but 8 bytes alignment is need because at least double data type needs that alignment. So I found SizeQuant macro definition and set it to 8. – Marko Aug 07 '15 at 15:25
  • 1
    @Marko: That sounds very toolkit-specific. I added some details which might help more generally. – too honest for this site Aug 07 '15 at 15:55
  • Yes, my solution is specific I forgot to mention it for others to know. I hoped that if anyone else has this problem he will try to find similar solution. The underlying allocation library in my case is called BGET. – Marko Aug 07 '15 at 21:09
  • And thank you for references to documentation, I like answer that contain links to some form of documentation. – Marko Aug 07 '15 at 21:09
  • @Marko: Welcome. Note that this is not just _some_ documentation, but actually **the** documentation for C: (tarraahh) **The ISO-Standard** :-) - well, actually as far as you can post online without violating copyright (funny, as these organizations are actually paid by our taxes). it is the final draft (no relevant changes). – too honest for this site Aug 07 '15 at 23:00