← Back to context

Comment by brucehoult

3 hours ago

Also I haven't looked closely but I don't know if you could find space to fit it in the remaining Aarch64 encoding space.

The existing a64 conditional branch instructions use a 19 bit field to hold the offset. Add two registers to compare (10 bits) and 3 bits to choose between EQ, NE, LT, LTU, GE, GEU and you're already at 32 bits before having an "opcode" field to choose "RISC-V style conditional branch".

Of course you could reduce the branch offset size down to RISC-V's ±4k which only needs 11 bits when you only have 4 byte instructions, but that's still a 24 bit chunk of unused opcode space to find.

Oh .. looks like 0b10xx is still completely unused. We could grab maybe 1/4 of it

So could do ...

    [31:28] (4 bits):  0b1000 (Fixed primary opcode .. or 0b1001, 0b1010, 0b1011)
    [27:23] (5 bits):  Rs1
    [22:18] (5 bits):  Rs2
    [17:15] (3 bits):  Cond (EQ, NE, LT, GE, LTU, GEU, + possible 2 more)
    [14:4]  (11 bits): Offset (Signed ±4k PC-relative offset)
    [3:0]   (4 bits):  0b0000 (Fixed minor opcode/extension identifier)

One problem here is this doesn't allow both 32 bit and 64 bit compares. And also the Rs1 and Rs2 are not in the usual places.

Maybe...

    [31:28] (4 bits): 0b1000 (Fixed primary opcode)
    [27:21] (7 bits): Offset[12:6]
    [20:16] (5 bits): Rm
    [15:13] (3 bits): Cond (EQ, NE, LT, GE, LTU, GEU, etc)
    [12:10] (3 bits): Offset[5:3]
    [9:5]   (5 bits): Rn
    [4:2]   (3 bits): Offset[2:0]
    [1]     (1 bit):  sf (Size flag: 0 = 32-bit compare, 1 = 64-bit compare)
    [0]     (1 bit):  0b0 (Fixed)

I think this fits other instruction formats better .. and gives a ±16k branch range.

Some ::coff:: would criticise the split up offset field. Not RISC-V fans of course. And this puts sf in a non-standard place.

Some more playing around is needed .. over to you Arm.