riscv64-gen-cvt-sxtw.after (945B)
1 ST_FUNC void gen_cvt_sxtw(void) 2 { 3 /* int -> long widening on riscv64. RV64 32-bit ops sign-extend their 4 results into bits 63:32, so for *signed* int -> long the register is 5 already correctly extended (a no-op suffices, or a defensive 6 addiw r,r,0). For *unsigned* int -> ulong we must explicitly zero 7 the upper 32 bits via slli;srli — otherwise an unsigned value with 8 bit 31 set (e.g. 0x80000000) is read back as 0xffffffff80000000. 9 Without this, kernel.c's `((u64)be32(p) << 32) | (u64)be32(p+4)` 10 produces sign-extended garbage for any DTB cell whose top bit is 11 set, which the seed kernel hits on the riscv64 virt machine. */ 12 int r = ireg(gv(RC_INT)); 13 if (vtop->type.t & VT_UNSIGNED) { 14 EI(0x13, 1, r, r, 32); // slli r, r, 32 15 EI(0x13, 5, r, r, 32); // srli r, r, 32 16 } else { 17 EI(0x1b, 0, r, r, 0); // addiw r, r, 0 (sign-extend low 32) 18 } 19 }