logoalt Hacker News

kibwenlast Wednesday at 1:19 PM1 replyview on HN

> But what if we want to represent a number larger than 12 bits? Well, the add instruction doesn't let us represent all such numbers; but setting sh to 1 lets us shift our number by 12 bits. So for example we can represent 172032172032 by leaving our 42 alone and setting sh to 1. This is a clever technique for encoding larger numbers in a small space.

This is whacky. So presumably adding with a 24-bit constant whose value isn't representable in this compressed 13-bit format would then expand to two add instructions? Or would it store a constant to a register and then use that? Or is there a different single instruction that would get used?

(Also, typo, 42 << 12 is 172032).


Replies

Joker_vDlast Wednesday at 3:45 PM

Yes, it would:

    add_large_const:
            add     w8, w0, #43, lsl #12
            add     w0, w8, #42
            ret
The same happens e.g. on RISC-V:

    add_large_const:
            lui     a5,43   
            addi    a5,a5,42
            add     a0,a0,a5
            ret
Because there are only 32 bits in an instruction, you can't fit a whole 32-bit immediate into it. Contrast it with x86 which uses variable-length instructions (up to 15 bytes per instruction):

    add_large_const:
            lea     eax, [rdi+176170]    # this instruction takes 6 bytes
            ret
P.S. Some people seem to be really puzzled by LEA instructions. It's intended use is to correspond to C's "dest = &base[offset]" which semantically is just "dest = base + offset", of course — but it allows one to express base and/or offset using available addressing modes.
show 1 reply