When I examine a hex file created by elf2hex, the contents match the objdump file. However, the instruction set reference is quite different. For example, an I-type instruction is supposed to have the IMM16 field in bits 21..6, but in the HEX file they are in 31..16. To me the instruction set reference makes little sense. I sure would not put the immediate data unaligned in the middle of the instruction. Which is correct?
In the attachment is a screenshot of the description of the ORI instruction taken from "Nios II Processor Reference Guide Updated for Intel ® Quartus ® Prime Design Suite: 19.4", page 217. Notice where the IMM16 field is located.
Here is a an ORI instruction the .objump file from my first test program:
ori gp, gp, %lo(_gp)
2c: 8000d694 ori gp,gp,32768.
Here is the matching line from the .hex file created by elf2hex with the instruction in bold (32-bit hex file, so the instruction is at 0x2c/4=11):
Clearly the instruction set reference and the .hex file do not match. The IMM16 field in the .hex file is the most significant two bytes of the word. The instruction set reference shows it in the middle of the word.
I'm using Quartus 18.1, not 19.x, but I can't believe the instruction format would be changed like that.
The reason I asked was that I could not get Platform Designer+Quartus to initialize the program ROM from the .hex file. I thought I might have to hand assemble some code to get the NIOS to do something. I did not not know which to believe because the .hex did not match the documentation. I was afraid I had some option wrong in the EDS resulting in a bad .hex file.
I've since discovered what I believe to be a file caching problem in PD+Quartus that prevented my .hex file from being incorporated into the SOF file, but that's a separate issue. I have a workaround, so I finally got a very simple program running using the .hex file above. Now it's just a curiosity why the documentation does not agree with the compiler output.
Ah, the answer is that I was using Architecture Revision 2 (R2) which is selected by a hidden parameter. Maybe the reason it's hidden is that it's not ready for prime time yet. There do not seem to be compatible runtime libraries. I reverted to R1 and the object matches the documentation. Too bad, I find the original instruction set bit assignments rather peculiar. R2 is much easier to decode manually.