• v0.30.0
    Test / vet (push) Successful in 43s
    Test / test (push) Failing after 1m55s
    Test / build (push) Skipped
    Release / build (amd64, linux) (push) Successful in 40s
    Release / build (arm64, linux) (push) Successful in 37s
    Release / build (loong64, linux) (push) Successful in 38s
    Release / build (riscv64, linux) (push) Successful in 58s
    Release / release (push) Successful in 22s
    Stable

    petrbalvin released this 2026-08-13 16:34:20 +00:00 | 206 commits to main since this release

    The LoongArch encoder (Phase 5) ships with ELF64 and GOOBJ emission, verified
    byte-for-byte against GOARCH=loong64 go tool asm and linked into a real
    go build; the shared GOOBJ emitter now writes the per-function DWARF symbols
    the linker's DWARF pass reads. The RISC-V encoder reaches byte-for-byte parity
    with go tool asm: the frame model, operand ordering, RVC compression,
    large-immediate and MOV $imm materialisation, branch/jump encodings, and
    CALL sym(SB) (now a JAL with an R_RISCV_JAL relocation). The debugger
    tracks four hardware watchpoint slots, and the toolkit is Linux-only.

    Added

    • LoongArch encoder (Phase 5). gasm asm can now assemble _loong64.s
      files: the full LoongArch64 instruction set with the dual-form arithmetic
      mnemonics, the 16/21-bit branch families, the MOV pseudo-instruction and
      its immediate-constant expansions, FP/SP frame mapping, SB/global symbol
      references (pcalau12i pairs) and ELF64 emission
      (gasm asm --format elf). Ground-truth verification against
      GOARCH=loong64 go tool asm matches byte-for-byte; GOOBJ emission
      (gasm asm --format goobj) is proven end-to-end by linking the object
      into a cross-compiled go build.
    • GOOBJ DWARF symbols. The GOOBJ emitters now write the per-function
      DWARF symbols the linker requires (the subprogram DIE and the .debug_line
      program, byte-identical to cmd/asm's), and the pc-value table deltas are
      in the architecture's MinLC units as the runtime expects — the amd64 link
      test now genuinely substitutes the gasm object, and the amd64/loong64
      end-to-end GOOBJ link tests pass.
    • RISC-V GOOBJ emission via the shared emitter. RISC-V GOOBJ output is
      now written by the same shared emitter as amd64 and LoongArch, modelling
      each AUIPC + second-instruction pair as a single R_RISCV_PCREL_ITYPE/STYPE
      relocation (the layout cmd/asm writes, not the ELF HI20/LO12 pair), so the
      object links into a cross-compiled go build for GOARCH=riscv64. An
      end-to-end link test substitutes the gasm object and reads the symbol back
      with go tool nm; the rewrite also corrects the relocation after field.

    Fixed

    • RISC-V frame model and RVC encodings. The riscv64 frame layout now
      matches go tool asm: the prologue/epilogue save and restore the link
      register (LR) instead of S0, with the correct autosize (locals + 8) and the
      RVC-compressed prologue/epilogue instructions; RET emits the uncompressed
      JALR X0, 0(X1) the toolchain writes; the C.ADDI/C.LI/C.LUI/C.ADDIW
      opcode bit and the C.ADD CR-type encoding are fixed; and the LR/TMP
      register aliases now resolve to X1 and X31. The pcsp/pcfile/pcline tables
      are populated from the recorded stack-adjustment and source-line data, and
      a byte-exact ground-truth test compares framed and leaf functions against
      GOARCH=riscv64 go tool asm.
    • RISC-V operand ordering and RVC compression. R-type instructions now
      take rs2, rs1, rd and I-type arithmetic instructions take imm12, rs1, rd, matching the Go assembler's documented operand order (previously both
      were reversed, so non-commutative R-type instructions such as SUB encoded
      the wrong operation). The two-operand ternary forms (ADD rs2, rd,
      ADDI $imm, rd, SLLI $shamt, rd) are now accepted. RVC compression is
      completed for C.ADDI16SP, C.SLLI, C.SRLI, C.SRAI, C.ANDI,
      C.NOP, C.EBREAK, C.MV (from ADDI/ADD) and the commutative
      AND/OR/XOR forms; the byte-exact ground-truth test now covers these.
    • RISC-V compressed loads/stores and word arithmetic. RVC compression
      now also covers the register-relative C.LW/C.SW/C.LD/C.SD/
      C.FLD/C.FSD forms (in addition to the stack-relative C.LWSP/C.SWSP/
      C.LDSP/C.SDSP), plus C.ADDI4SPN, C.ADDW and C.SUBW. The
      byte-exact ground-truth test exercises these against GOARCH=riscv64 go tool asm.
    • RISC-V large-immediate materialisation. ADDI/ANDI/ORI/XORI
      with a 32-bit immediate that does not fit 12 bits now expand exactly as
      cmd/asm: two ADDIs for the small ADDI split range, and
      LUI+ADDIW+<op> otherwise, with the LUI and ADDIW compressed to
      C.LUI/C.ADDIW when their immediate fits six signed bits. The
      byte-exact ground-truth test covers positive, negative, and out-of-range
      immediates against GOARCH=riscv64 go tool asm.
    • RISC-V MOV $imm, rd materialisation. The immediate-loading
      pseudo-instruction now uses the toolchain's Split32BitImmediate split
      (previously it rounded the upper 20 bits, producing wrong results for
      negative and bit-11-set immediates) and compresses the emitted
      ADDI/LUI/ADDIW to C.LI/C.LUI/C.ADDIW when their immediate
      fits six signed bits. A byte-exact ground-truth test covers zero, small,
      negative, and 32-bit immediates against GOARCH=riscv64 go tool asm.
    • RISC-V branch/jump compression. JMP/JAL were being compressed to
      C.J and BEQ/BNE (with X0) to C.BEQZ/C.BNEZ, but go tool asm
      never emits these compressed forms. They now emit the 32-bit JAL and
      branch encodings the toolchain writes; the dead C.J/C.BEQZ/C.BNEZ
      encoders were removed, and the C.LUI direct-instruction compression now
      uses the correct six-bit signed range. A byte-exact ground-truth test
      covers the branch family and jumps against GOARCH=riscv64 go tool asm.
    • RISC-V CALL sym(SB). The call pseudo-instruction now emits the
      toolchain's JAL X1, sym(SB) with a single R_RISCV_JAL relocation
      (previously it emitted an AUIPC+JALR pair against a local branch
      label, a form go tool asm rejects). The GOOBJ and ELF emitters now map
      that relocation (Go objabi 59 / ELF R_RISCV_JAL 17, a 4-byte field), and
      relocation offsets are recorded relative to the function start (including
      the prologue). A byte-exact ground-truth test covers a call against
      GOARCH=riscv64 go tool asm.
    • Debugger watchpoint slots. gasm debug's watch command always used
      hardware watchpoint slot 0, so a second watch call silently overwrote
      the first. Watchpoint slots are now tracked in the Session (DR0–DR3);
      watch picks the first free slot and reports an error if all four are in
      use, and unwatch <slot> clears one (no argument clears all).

    Changed

    • Linux only. The toolkit, its CI and the released binaries are now
      Linux-only; cross-compiled to linux/{amd64,arm64,riscv64,loong64}.
    • Phase 4 closed. README's "Remaining" list for the debugger is gone;
      disassembly at PC, memory-write, watchpoints, and source-line mapping are
      all shipped.
    Downloads