3 ms·
Very cool and clever scheme. But what happens to immediates that can't be encoded that way?
by AshleysBrain 13y ago
Very cool and clever scheme. But what happens to immediates that can't be encoded that way?
- Tuna-Fish 13y agoYou have to place them in a constant pool and load them.
- ColinWright 13y agoAs others have said, that's not the case. All constants can be constructed by ORing together a small collection of expressible constants. With a little ingenuity "most" require very few instructions to build. FWIW, I have written real-time radar processing embedded software, and rarely had to resort to stored constants.
- stephencanon 13y agoThere are a few options for producing other values: 1. load them from a constant pool in memory (often this is put nearly inline in the instruction stream so that it can be addressed via a small constant offset from PC). If your code doesn't saturate the LSU locally, this is usually the best option. 2. assemble them via bitwise or arithmetic combinations of literals that you can represent (or already in-register values that you know something about). If you can do it with just a few operations, and the LSU is otherwise occupied, you should do this instead. This is also preferred on some limited cores that can dual-issue logical and arithmetic ops but not LSU ops. 3. in recent revisions of the instruction set, there are a pair of instructions MOVW and MOVT; MOVW conjures a 16b immediate, and MOVT sets the high 16b, so with these two instructions you can conjure any 32b value. There is a bit of subtlety to choosing the correct approach. Some assemblers provide a "conjure this value" pseudo-operation where the assembler will choose what it thinks is the best option to materialize a constant; that way the programmer doesn't need to worry about these details. This looks something like the following: LDR R0, =0xff0000ff the assembler might actually stash the constant somewhere and generate a load instruction, or it might instead do: MOV R0, 0xff000000 ORR R0, R0, 0x000000ff and assemble the value via a couple instructions with immediates.
- cnvogel 13y agoHere's what you can do to add a "complicated" constant stored elsewhere, in hand-crafted assembler: add_something: ; function starts here (argument r0 == some number) ldr r1, __tmp ; get complicated constant, store in r1 add r0, r0, r1 ; do the addition r0 = r0 + r1 bx lr ; == return result (in r0) __tmp: .word 0x12345678 ; store complicated constant here You can play with your compiler, if you call gcc as "gcc -Os -S -o- file.c" if will spit out generated assembler code (-S) on stdout "-o-" for the c-code in file.c. (but then, gcc prefers to have 4 "compact" adds, instead of loading a constant...) $ cat dummy.c int add_random_number(int a) { return a + 0x12345678; /* guaranteed to be random */ } $ arm-none-eabi-gcc -S -o- -Os dummy.c (...) add_random_number: @ Function supports interworking. @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. add r0, r0, #301989888 add r0, r0, #3424256 add r0, r0, #5696 add r0, r0, #56 bx lr
- userbinator 13y agoFrom my experience on x86, GCC's -Os isn't that great - looks like it's the same for ARM.
- yuubi 13y agoIn at least the ADT assembler and gas a few years back, the assembler provided syntactic sugar: ldr r0,=0x123456578 assembles to ldr r0,pc+xxx ... and then somewhere later ... .word 0x12345678 The assembler had some default places it would put constant pools (end of a module?), or you could explicitly tell it to generate a constant pool if the default place would be outside the limit of the pc-relative addressing mode.